Scope of Variable Scope and visibility n n
Scope of Variable
Scope and visibility n n Scope (visibility) of identifier = portion of program where identifier can be referred to Lexical scope = textual region in the program n n n Statement block Method body Class body Module / package / file Whole program (multiple modules) 2
Scope example class Foo { int value; int test() { int b = 3; return value + b; } void set. Value(int c) { value = c; { int d = c; c = c + d; scope of local variable in statement block d value = c; } } } class Bar extends Foo { int value; void set. Value(int c) { value = c; test(); } } scope of local variable b scope of field value scope of formal parameter c scope of method test scope of value 3
Scope nesting n n Scopes may be enclosed in other scopes void foo() { int a; … {int a; } } Name disambiguation Generally scope hierarchy forms a tree Scope of subclass enclosed in scope of its superclass same name but different symbol n Subtype relation must be acyclic 4
Scope hierarchy in IC n Global scope n n Class scope n n Instance scope: all fields and methods of the class Static scope: all static methods Scope of subclass nested in scope of its superclass Method scope n n The names of all classes defined in the program Formal parameters and local variables in code block of body method Code block scope n Variables defined in block 5
Scope rules in IC n n n “When resolving an identifier at a certain point in the program, the enclosing scopes are searched for that identifier. ” “local variables and method parameters can only be used after they are defined in one of the enclosing block or method scopes. ” “Fields and virtual methods can be used in expressions of the form e. f or e. m() when e has class type C and the instance scope of C contains those fields and methods. ” “static methods can be used in expressions of the form C. m() if the static scope of C contains m. ” … (Section 10 in IC specification) How do we check these rules? 6
Symbol Table Basics
Symbol table n n n An environment that stores information about identifiers A data structure that captures scope information Each entry in symbol table contains n n n The name of an identifier Its kind (variable/method/field…) Type Additional properties, e. g. , final, public (not needed for IC) One symbol table for each scope 8
Scope nesting in IC Scope nesting mirrored in hierarchy of symbol tables Symbol Kind Type Properties Global names of all classes Symbol Kind Type Properties Class fields and methods Symbol Kind Type Properties Method formals + locals Symbol Kind Type Properties Block variables defined in block 9
Symbol table example block 1 class Foo { int value; int test() { int b = 3; scope of b return value + b; } void set. Value(int c) { value = c; { int d = c; c = c + d; scope of d value = c; } } } class Bar { int value; void set. Value(int c) { value = c; } } scope of value scope of c scope of value 10
Symbol table example cont. … (Foo) Symbol Kind Type Properties value field int … test method -> int set. Value method int -> void (test) (set. Value) Symbol Kind Type Properties b var int … c var int … (block 1) Symbol Kind Type Properties d var int … 11
Checking scope rules (Foo) Symbol Kind Type Properties value field int … test method -> int set. Value method int -> void (test) (set. Value) Symbol Kind Type Properties b var int … c var int … (block 1) void set. Value(int c) { value = c; { int d = c; c = c + d; value = c; } } lookup(value) Symbol Kind Type Properties d var int … 12
Catching semantic errors Error ! (Foo) Symbol Kind Type Properties value field int … test method -> int set. Value method int -> void (test) undefined symbol (set. Value) Symbol Kind Type Properties b var int … c var int … (block 1) void set. Value(int c) { value = c; { int d = c; c = c + d; my. Value = c; } } lookup(my. Value) Symbol Kind Type Properties d var int … 13
Symbol table operations n insert n n lookup n n Insert new symbol (to current scope) Try to find a symbol in the table May cause lookup in parent tables Report an error when symbol not found How do we check illegal re-definitions? 14
Symbol table construction via AST traversal globals Symbol root Foo Class. Decl kind class Foo name=Foo Symbol kind test method set. Value method Method. Decl name=set. Value name=test set. Value Symbol b Var. Decl Stmt var c block 1 Block Symbol id=b d Var. Decl Stmt var Stmt id=d 15
Linking AST nodes to enclosing table globals Symbol root Foo Class. Decl kind class Foo name=Foo Symbol kind test method set. Value method Method. Decl name=set. Value name=test set. Value Symbol b Var. Decl Stmt var c block 1 Block Symbol id=b d Var. Decl Stmt var Stmt id=d 16
Symbol table implementation n Each table in the hierarchy could be implemented using java. util. Hash. Map Implement a hierarchy of symbol tables Can implement a Symbol class n n Use in subsequent phases instead of id name A programming note: n n Hash. Map keys should obey equals/hashcode contracts Safe when key is symbol name (String) 17
Implementing table structure n Hierarchy of symbol tables n n n Pointer to enclosing table Can also keep list of sub-tables Symbol table key should include id and kind n n Can implement using 2 -level maps (kind->id->entry) Separating table in advance according to kinds also acceptable 18
Forward references class A { void foo() { bar(); } void bar() { … } } globals bar used before encountered declaration Symbol root A kind class A Program Symbol foo bar kind method Class. Decl id=A Method. Decl id=foo ret. Type=void id=bar ret. Type=void Call id=bar() Undefined identifier bar() How do we handle forward references? We will see two solutions 19
Solution 1 – multiple phases n Multiple phase solution n Building visitor Checking visitor Building visitor n On visit to node – build corresponding symbol table n n Can maintain stack of symbol tables n n class, method, block (and possibly nested blocks) Push new table when entering scope Pop when exiting scope Link AST node to symbol table of corresponding scope Do not perform any checks 20
Building and checking n Building visitor n A propagating visitor Propagates reference to the symbol table of the current scope (or use table stack) In some cases have to use type information (extends) n Populate tables with declarations/definitions n n n Class definitions, method definitions, field definitions, variable declarations, formal arguments class A {void foo(){int B; int[] C; }}; Checking visitor n On visit to node – perform check using symbol tables n n Resolve identifiers Look for symbol in table hierarchy 21
Building phase globals Symbol root Foo Class. Decl kind class Foo name=Foo Symbol kind test method set. Value method Method. Decl name=set. Value name=test Symbol b set. Value Kind var Symbol c kind var block 1 Var. Decl Stmt Block Symbol id=b d unresolved symbol Var. Decl id=d Stmt test() kind var Stmt 22
Checking phase globals Symbol root foo Class. Decl kind class foo name=Foo Symbol kind test method set. Value method Method. Decl name=set. Value name=test Symbol b set. Value Kind var Symbol c kind var block 1 Var. Decl Stmt Block Symbol id=b resolved symbols d Var. Decl id=d Stmt test() kind var Stmt 23
Forward references – solution 2 n n n Use forward reference marker (flag) Optimistically assume that symbol will be eventually defined Update symbol table when symbol defined n n n Remove forward-reference marker Count unresolved symbols and upon exit check that #unresolved=0 And/or construct some of the symbol table during parsing 24
Forward reference flag example globals class A { void foo() { car(); } void car() { … } } Symbol root A kind class A Program Symbol foo car kind FREF method true Class. Decl id=A Method. Decl id=foo ret. Type=void id=car ret. Type=void Call id=car() 25
Next-Symbol Table representation
- Slides: 26