The Compiler So Far • Scanner ‐ Lexical analysis CSC 4181 – Detects inputs with illegal tokens • e.g.: main 5 (); Compiler Construction • Parser ‐ Syntactic analysis – Detects inputs with ill ‐ formed parse trees • e.g.: missing semicolons Semantic Analysis • Semantic analysis – Last “front end” analysis phase – Catches all remaining errors Semantic Analysis 1 0 1 Semantic Analysis Beyond Syntax • Source code W hat’s w rong foo(int a, char * s){ … } lexical w ith this code? Lexical Analysis errors int bar() { tokens int f[3]; (Note: it parses syntax int i, j, k; Syntactic Analysis perfectly) char *p; errors float k; AST foo(f[6], 10, j); semantic break; Semantic Analysis errors i->val = 5; AST’ j = i + k; printf(“%s,%s.\n”,p,q); Intermediate Code Gen goto label23; } Semantic Analysis 2 Semantic Analysis 3 2 3 Goals of a Semantic Analyzer Kinds of Checks • Compiler must do more than recognize whether a • Uniqueness checks sentence belongs to the language… – Certain names must be unique – Many languages require variable declarations • • Find remaining errors that would make program invalid • undefined variables, types • Flow ‐ of ‐ control checks • type errors that can be caught statically – Match control ‐ flow operators with structures • • Figure out useful information for later phases – Example: break applies to innermost loop/switch • types of all expressions • data layout • Type checks • Terminology – Check compatibility of operators and operands • Static checks – done by the compiler Logical checks – Program is syntactically and semantically correct, but does not • Dynamic checks – done at run time do the “correct” thing Semantic Analysis 4 Semantic Analysis 5 4 5 1
Examples of Reported Errors Program Checking • Why do we care? • Undeclared identifier • Multiply declared identifier • Obvious: • Index out of bounds – Report mistakes to programmer – Avoid bugs: f[6] will cause a run ‐ time failure • Wrong number or types of args to call – Help programmer verify intent • Incompatible types for operation • How do these checks help compilers? • Break statement outside switch/loop – Allocate right amount of space for variables • Goto with no label – Select right machine operations – Proper implementation of control structures Semantic Analysis 6 Semantic Analysis 7 6 7 Can We Catch Everything? gcc reports warnings… • Try compiling this code: example.c: In function "main": example.c:4:2: warning: incompatible implicit declaration of built-in function "printf" [enabled by default] printf("Hello World\n"); • void main() ^ example.c:5:2: warning: format "%d" expects a matching "int" argument [-Wformat=] • { printf("Hello World, N=%d\n"); ^ • int i=21, j=42; example.c:6:2: warning: too many arguments for format [-Wformat-extra-args] printf("Hello World\n", i, j); • printf(“Hello World\n”); ^ example.c:7:2: warning: format "%d" expects a matching "int" argument [-Wformat=] • printf(“Hello World, N=%d\n”); printf("Hello World, N=%d\n"); ^ • printf(“Hello World\n”, i, j); example.c:8:2: warning: format "%d" expects a matching "int" argument [-Wformat=] printf("Hello World, N=%d\n"); • printf(“Hello World, N=%d\n”); ^ • printf(“Hello World, N=%d\n”); • } Semantic Analysis 8 Semantic Analysis 9 8 9 Typical Semantic Errors Scoping • In most languages, the same name can be declared • Multiple declarations: a variable should be multiple times declared (in the same scope) at most once – if its declarations occur in different scopes, and/or – involve different kinds of names • Undeclared variable: a variable should not be • Java: can use same name for – a class used before being declared – field of the class – a method of the class • Type mismatch: type of the LHS of an – a local variable of the method assignment should match the type of the RHS class Test { • Wrong arguments: methods should be called int Test; void Test( ) { double Test; } with the right number and types of arguments } Semantic Analysis 10 Semantic Analysis 11 10 11 2
Scoping: Overloading Scoping: General Rules • The scope rules of a language: • Java and C++ (but not in Pascal or C): – Determine which declaration of a named object corresponds to – can use the same name for more than one method each use of the object – as long as the number and/or types of parameters are – Scoping rules map uses of objects to their declarations unique • C++ and Java use static scoping : int add(int a, int b); – Mapping from uses to declarations at compile time float add(float a, float b); – C++ uses the "most closely nested" rule • a use of variable x matches the declaration in the most closely enclosing scope • such that the declaration precedes the use Semantic Analysis 12 Semantic Analysis 13 12 13 Scope levels Checkpoint #1 • Each function has two or more scopes: – Match each use to its declaration, or say why it is a use of an undeclared variable. One for the function body – • Sometimes parameters are separate scope! int k=10, x=20; void foo(int k) { • (Not true in C) int a = x; int x = k; int b = x; void f( int k ) { // k is a parameter while (...) { int k = 0; // also a local variable while (k) { int x; int k = 1; // another local var, in a loop if (x == k) { } int k, y; } k = y = x; – Additional scopes in the function } if (x == k) { int x = y; } • each for loop and } • each nested block (delimited by curly braces) } Semantic Analysis 14 Semantic Analysis 15 14 15 Dynamic Scoping Example • For example, consider the following code: • Not all languages use static scoping • Lisp, APL, and Snobol use dynamic scoping int i = 1; void func() { cout << i << endl; • Dynamic scoping: } If C+ + used – A use of a variable that has no corresponding declaration int main () { dynamic scoping, in the same function corresponds to the declaration in the int i = 2; this would print out most ‐ recently ‐ called still active function func(); 2, not 1 return 0; } Semantic Analysis 16 Semantic Analysis 17 16 17 3
Checkpoint #2 Keeping Track • Need a way to keep track of all identifier types in scope – Assuming that dynamic scoping is used, what is output by the following program? i int n int void main() { int x = 0; f1(); g(); { f2(); } int i, n = …; i int void f1() { int x = 10; g(); } for (i=0; i < n; i++) n int b boolean boolean b= … void f2() { int x = 20; f1(); g(); } void g() { print(x); } ? } Semantic Analysis 18 Semantic Analysis 19 18 19 How Symbol Tables Work (1) Symbol Tables int x; char y; • Purpose: void p(void) { double x; – keep track of names declared in the program … • Symbol table entry: { int y[10]; … – associates a name with a set of attributes , e.g.: } • kind of name (variable, class, field, method, …) … } • type (int, float, …) • nesting level void q(void) • mem location (where will it be found at runtime) { int y; • Functions: … } • Type Lookup(String id) main() • Void Add(String id, Type binding) { char x; • Bindings: name type pairs {a string, b int} … } Semantic Analysis Semantic Analysis 20 21 20 21 How Symbol Tables Work (2) How Symbol Tables Work (3) int x; int x; char y; char y; void p(void) void p(void) { double x; { double x; … … { int y[10]; { int y[10]; … … } } … … } } void q(void) void q(void) { int y; { int y; … … } } main() main() { char x; { char x; … … } } Semantic Analysis Semantic Analysis 22 23 22 23 4
How Symbol Tables Work (4) How Symbol Tables Work (5) int x; int x; char y; char y; void p(void) void p(void) { double x; { double x; … … { int y[10]; { int y[10]; … … } } … … } } void q(void) void q(void) { int y; { int y; … … } } main() main() { char x; { char x; … … } } Semantic Analysis Semantic Analysis 24 25 24 25 How Symbol Tables Work (6) Semantic Analysis Summary int x; char y; void p(void) • Compiler must do more than recognize { double x; … whether a sentence belongs to the language { int y[10]; … } • • Checks of all kinds … } • undefined variables, types void q(void) • type errors that can be caught statically { int y; … • • Store useful information for later phases } main() • types of all expressions { char x; … } Semantic Analysis 26 Semantic Analysis 27 26 27 5
Recommend
More recommend