Principles of Programming Languages h"p://www.di.unipi.it/~andrea/Dida2ca/PLP-16/ Prof. Andrea Corradini Department of Computer Science, Pisa Lesson 19 � • Sta:c Scoping – Declara:ons and Defini:ons – Modules – Local symbol tables during compila:on – Syntax-Directed Transla:on of three-address code in Scope – LeBlanc & Cook data structure and lookup func:on
Declara:on order and use of bindings Scope of a binding • 1) In the whole block where it is defined 2) From the declara:on to the end of the block Use of binding • a) Only aNer declara:on b) In the scope of declara:on Many languages use 2–a . Java uses 1–b for methods in a class. Modula • uses 1–b also for variables! Some combina:ons produce strange effects: Pascal uses 1) – a) . • const N = 10; ... procedure foo; const M = N; (* static semantic error! *) var A : array [1..M] of integer; N : real; (* hiding declaration *) Reported errors: “N used before declara:on” “N is not a constant” 2
Declara:ons and defini:ons • “Use aNer declara:on” would forbid mutually recursive defini:ons (procedures, data types) • The problem is solved dis:nguishing declara'on and defini'on of a name, as in C • DeclaraEon : introduces a name • DefiniEon : defines the binding struct manager; // Declaration only struct employee { struct manager *boss; struct employee *next_employee; ... }; struct manager { // Definition struct employee *first_employee; ... }; 3
Nested Blocks In several languages local • { int t = a; variables are declared in a block a = b; C or compound statement b = t; } – At the beginning of the block (Pascal, ADA, …) declare t:integer – Anywhere (C/C++, Java, …) begin Blocks can be considered as • t := a; Ada a := b; subrou:nes that are called where b := t; they are defined end; Local variables declared in nested • { int a,b; blocks in a single func:on are all ... stored in the subrou:ne frame C++ int t; for that func:on (most Java t=a; programming languages, e.g. C/C a=b; C# ++, Ada, Java) b=t; ... } 4
Out of Scope • Non-local objects can be hidden by local name- to-object bindings • The scope is said to have a hole in which the non- local binding is temporarily inac:ve but not destroyed • Some languages, like Ada, C++ and Java, use qualifiers or scope resolu:on operators to access non-local objects that are hidden – P1.X in Ada to access variable X of P1 – ::X to access global variable X in C++ – this.x or super.x in Java 5
Out of Scope Example • P2 is nested in P1 • P1 has a local variable X • P2 has a local variable X that hides X in P1 procedure P1; • When P2 is called, no extra var X:real; code is executed to inactivate procedure P2; the binding of X to P1 var X:integer begin ... (* X of P1 is hidden *) end; begin ... end 6
Modules • Modules are the main feature of a programming language that supports the construc:on of large applica:ons – Support informa,on hiding through encapsula,on : explicit import and export lists – Reduce risks of name conflicts; support integrity of data abstrac,on • Teams of programmers can work on separate modules in a project • No language support for modules in C and Pascal – Modula-2 modules , Ada packages , C++ namespaces – Java packages 7
Module Scope • Scoping: modules encapsulate variables, data types, and subrou:nes in a package – Objects inside are visible to each other – Objects inside are not visible outside unless exported – Objects outside are visible [ open scopes ], or are not visible inside unless imported [ closed scopes ], or are visible with “qualified name” [ selec,vely open scopes ] (eg: B.x ) • A module interface specifies exported variables, data types and subrou:nes • The module implementa:on is compiled separately and implementa:on details are hidden from the user of the module 8
Module Types, towards Classes • Modules as abstrac:on mechanism: collec:on of data with opera:ons defined on them (sort of abstract data type) • Various mechanism to get module instances : – Modules as manager: instance as addi:onal arguments to subrou:nes ( Modula-2 ) – Modules as types ( Simula , ML ) • Object-Oriented: Modules (classes) + inheritance • Many OO languages support a no:on of Module (packages) independent from classes 9
Syntax-directed transla:on of three- address code with names and scopes • The three-address code generated by the syntax- directed defini:ons shown in a previous lesson is simplis:c • It assumes that the names of variables can be resolved by the back-end in global or local variables, which is unrealis:c • We need local symbol tables to record global declara:ons as well as local declara:ons in procedures, blocks, and records (structs) to resolve names 10
Implemen:ng Sta:c Scoping • The language implementa:on must keep trace of current bindings with suitable data structures: – Sta:c scoping: symbol tables at compile Eme • Symbol table main opera:ons: insert , lookup – because of nested scopes, the compiler must handle several bindings for the same name with LIFO policy – new scopes (not LIFO) should be created for records and classes – Other opera:ons: enter_scope , leave_scope • The symbol table might be needed at run:me for symbolic debugging – The debugger must resolve names in high-level commands by the user – Symbol table are saved in por:on of the target program code 11
Symbol Tables for Scoping We need a symbol table struct S { int a; for the fields of struct S int b; } s; Need symbol table for global variables void swap(int& a, int& b) and func:ons { int t; t = a; a = b; b = t; Need symbol table for arguments } and locals for each func:on void somefunc() Check: s is global and has fields a and b { … swap(s.a, s.b); Using symbol tables we can generate … code to access s and its fields 12 }
Offset and Width for Run:me Alloca:on struct S The fields a and b of struct S { int a; are located at offsets 0 and 4 int b; } s; from the start of S a (0) void swap(int& a, int& b) The width of S is 8 { int t; b (4) t = a; Subrou:ne frame holds a = b; b = t; arguments a and b and Subroutine � } local t at offsets 0, 4, and 8 frame fp[0]= void somefunc() a (0) { … fp[4]= b (4) swap(s.a, s.b); fp[8]= t (8) The width of the frame is 12 … 13 }
Symbol Tables for Scoping globals struct S prev=nil [8] Trec S { int a; s (0) int b; prev=nil [8] swap } s; a (0) foo b (4) void swap(int& a, int& b) { int t; Tfun swap Tref t = a; a = b; prev [12] Tint b = t; a (0) } b (4) t (8) void foo() Table nodes � { … type nodes � Tfun foo swap(s.a, s.b); ( offset ) � … [ width ] 14 prev [0] }
Hierarchical Symbol Table Opera:ons • mktable ( previous ) returns a pointer to a new (empty) table that is linked to a previous table in the outer scope • enter ( table , name , type , offset ) creates a new entry in table • addwidth ( table , width ) accumulates the total width of all entries in table • enterproc ( table , name , newtable ) creates a new entry in table for procedure with local scope newtable • lookup ( table , name ) returns a pointer to the entry in the table for name by following linked tables 15
Syntax-Directed Transla:on: Grammar and Aoributes ProducEons ProducEons (cont’d) P → D ; S E → E + E D → D ; D | E * E Synthesized attributes: � | id : T | - E T .type pointer to type (ex.: ‘integer’, | proc id ; D ; S | ( E ) array(2, ‘real’), pointer(record(Table)) , …) T → integer | id T .width storage width of type (bytes) � | real | E ^ E .place name of temp holding value of E | array [ num ] of T | & E | ^ T | E . id | record D end A → A , E S → S ; S | E Global data to implement scoping: | id := E tblptr stack of pointers to tables � | call id ( A ) offset stack of offset values 16
Syntax-Directed Transla:on of Declara:ons in Scope P → { t := mktable (nil); push ( t , tblptr ); push (0, offset ) } D ; S enter ( table , name , type , offset ) D → id : T { enter ( top ( tblptr) , id .name, T .type, top ( offset )); top ( offset ) := top ( offset ) + T .width } D → proc id ; { t := mktable ( top ( tblptr )); push ( t , tblptr ); push (0, offset ) } D 1 ; S { t := top ( tblptr ); addwidth ( t , top ( offset )); pop ( tblptr ); pop ( offset ); enterproc ( table , name , newtable ) enterproc ( top ( tblptr ), id .name, t ) } D → D 1 ; D 2 17
Syntax-Directed Transla:on of Declara:ons in Scope (cont’d) T → integer { T .type := ‘ integer ’ ; T .width := 4 } T → real { T .type := ‘ real ’ ; T .width := 8 } T → array [ num ] of T 1 { T .type := array ( num .val, T 1 .type); T .width := num .val * T 1 .width } T → ^ T 1 { T .type := pointer ( T 1 .type); T .width := 4 } T → record { t := mktable (nil); push ( t , tblptr ); push (0, offset ) } D end { T .type := record ( top ( tblptr )); T .width := top ( offset ); addwidth ( top ( tblptr ), top ( offset )); pop ( tblptr ); pop ( offset ) } 18
Example globals struct S prev=nil [8] Trec { int a; int b; s (0) prev=nil [8] } s; swap a (0) foo void swap(int& a, int& b) b (4) { int t; Tfun swap t = a; Tptr a = b; prev [12] b = t; Tint a (0) } b (4) void foo() t (8) Table nodes � { … type nodes � swap(s.a, s.b); Tfun foo … ( offset ) � } [ width ] 19 prev [0]
Recommend
More recommend