Upload
others
View
8
Download
0
Embed Size (px)
Citation preview
Semantic AnalysisLecture 10
February 20, 2018
Scoping Review
▶ Programs have many symbols declaredthroughout▶ Class names▶ Attribute names▶ Method names▶ bound identifiers (e.g., let in Cool)
▶ Language determines scoping rules▶ Static vs. Dynamic scope
▶ Almost always static...
▶ Globals?▶ Most-closely-nested?
Compiler Construction 2/1
Symbol Table and Maps▶ You love tables and maps
▶ We use maps for tracking class attributes andclass methods▶ These are both global inside each class!
▶ We use a map of stacks to implementmost-closely-nested rule!▶ When we enter a new scope (e.g., through let), we
push new copies of bound symbols on the stackmapped by each symbol!
Compiler Construction 3/1
Class and Implementation Maps
▶ Classes contains lists of features▶ Attributes (data)▶ Methods (operations on the data)
▶ Attributes are global within a class
Compiler Construction 4/1
Scoping Reminder1 class Main inherits IO {2 a : Int <- 1;3 b : Int <- 2;4 c : Int <- 3;5 a() : Int { a };6 main () : Object {{7 out_int (a) -- 18 let a : Int <- 5 in9 out_int (a) ; -- 5
10 let a : Int <- 10 in11 out_int (b) ; -- 212 let a : Int <- 5 in13 let b : Int <- 6, c : Int <- 7 in14 let a : String <- "8", d : Int <- 8 in15 let c : Int <- 7, a : Int <- 9 in16 out_int (a+b+c+d+self.a());17 }};18 };
Compiler Construction 5/1
Scoping Reminder1 class Main inherits IO {2 a : Int <- 1;3 b : Int <- 2;4 c : Int <- 3;5 a() : Int { a };6 main () : Object {{7 out_int (a) -- 18 let a : Int <- 5 in9 out_int (a) ; -- 5
10 let a : Int <- 10 in11 out_int (b) ; -- 212 let a : Int <- 5 in13 let b : Int <- 6, c : Int <- 7 in14 let a : String <- "8", d : Int <- 8 in15 let c : Int <- 7, a : Int <- 9 in16 out_int (a+b+c+d+self.a());17 }};18 };
Class MapMaina Intb Intc Int
Compiler Construction 5/1
Scoping Reminder1 class Main inherits IO {2 a : Int <- 1;3 b : Int <- 2;4 c : Int <- 3;5 a() : Int { a };6 main () : Object {{7 out_int (a) -- 18 let a : Int <- 5 in9 out_int (a) ; -- 5
10 let a : Int <- 10 in11 out_int (b) ; -- 212 let a : Int <- 5 in13 let b : Int <- 6, c : Int <- 7 in14 let a : String <- "8", d : Int <- 8 in15 let c : Int <- 7, a : Int <- 9 in16 out_int (a+b+c+d+self.a());17 }};18 };
Class MapMaina Intb Intc Int
Symbol Tablea Int
Compiler Construction 5/1
Scoping Reminder1 class Main inherits IO {2 a : Int <- 1;3 b : Int <- 2;4 c : Int <- 3;5 a() : Int { a };6 main () : Object {{7 out_int (a) -- 18 let a : Int <- 5 in9 out_int (a) ; -- 5
10 let a : Int <- 10 in11 out_int (b) ; -- 212 let a : Int <- 5 in13 let b : Int <- 6, c : Int <- 7 in14 let a : String <- "8", d : Int <- 8 in15 let c : Int <- 7, a : Int <- 9 in16 out_int (a+b+c+d+self.a());17 }};18 };
Class MapMaina Intb Intc Int
Symbol Table
Compiler Construction 5/1
Scoping Reminder1 class Main inherits IO {2 a : Int <- 1;3 b : Int <- 2;4 c : Int <- 3;5 a() : Int { a };6 main () : Object {{7 out_int (a) -- 18 let a : Int <- 5 in9 out_int (a) ; -- 5
10 let a : Int <- 10 in11 out_int (b) ; -- 212 let a : Int <- 5 in13 let b : Int <- 6, c : Int <- 7 in14 let a : String <- "8", d : Int <- 8 in15 let c : Int <- 7, a : Int <- 9 in16 out_int (a+b+c+d+self.a());17 }};18 };
Class MapMaina Intb Intc Int
Symbol Tablea Int
Compiler Construction 5/1
Scoping Reminder1 class Main inherits IO {2 a : Int <- 1;3 b : Int <- 2;4 c : Int <- 3;5 a() : Int { a };6 main () : Object {{7 out_int (a) -- 18 let a : Int <- 5 in9 out_int (a) ; -- 5
10 let a : Int <- 10 in11 out_int (b) ; -- 212 let a : Int <- 5 in13 let b : Int <- 6, c : Int <- 7 in14 let a : String <- "8", d : Int <- 8 in15 let c : Int <- 7, a : Int <- 9 in16 out_int (a+b+c+d+self.a());17 }};18 };
Class MapMaina Intb Intc Int
Symbol Table
Compiler Construction 5/1
Scoping Reminder1 class Main inherits IO {2 a : Int <- 1;3 b : Int <- 2;4 c : Int <- 3;5 a() : Int { a };6 main () : Object {{7 out_int (a) -- 18 let a : Int <- 5 in9 out_int (a) ; -- 5
10 let a : Int <- 10 in11 out_int (b) ; -- 212 let a : Int <- 5 in13 let b : Int <- 6, c : Int <- 7 in14 let a : String <- "8", d : Int <- 8 in15 let c : Int <- 7, a : Int <- 9 in16 out_int (a+b+c+d+self.a());17 }};18 };
Class MapMaina Intb Intc Int
Symbol Tablea Int
Compiler Construction 5/1
Scoping Reminder1 class Main inherits IO {2 a : Int <- 1;3 b : Int <- 2;4 c : Int <- 3;5 a() : Int { a };6 main () : Object {{7 out_int (a) -- 18 let a : Int <- 5 in9 out_int (a) ; -- 5
10 let a : Int <- 10 in11 out_int (b) ; -- 212 let a : Int <- 5 in13 let b : Int <- 6, c : Int <- 7 in14 let a : String <- "8", d : Int <- 8 in15 let c : Int <- 7, a : Int <- 9 in16 out_int (a+b+c+d+self.a());17 }};18 };
Class MapMaina Intb Intc Int
Symbol Tablea Intb Intc Int
Compiler Construction 5/1
Scoping Reminder1 class Main inherits IO {2 a : Int <- 1;3 b : Int <- 2;4 c : Int <- 3;5 a() : Int { a };6 main () : Object {{7 out_int (a) -- 18 let a : Int <- 5 in9 out_int (a) ; -- 5
10 let a : Int <- 10 in11 out_int (b) ; -- 212 let a : Int <- 5 in13 let b : Int <- 6, c : Int <- 7 in14 let a : String <- "8", d : Int <- 8 in15 let c : Int <- 7, a : Int <- 9 in16 out_int (a+b+c+d+self.a());17 }};18 };
Class MapMaina Intb Intc Int
Symbol Tablea Int; Stringb Intc Intd Int
Compiler Construction 5/1
Scoping Reminder1 class Main inherits IO {2 a : Int <- 1;3 b : Int <- 2;4 c : Int <- 3;5 a() : Int { a };6 main () : Object {{7 out_int (a) -- 18 let a : Int <- 5 in9 out_int (a) ; -- 5
10 let a : Int <- 10 in11 out_int (b) ; -- 212 let a : Int <- 5 in13 let b : Int <- 6, c : Int <- 7 in14 let a : String <- "8", d : Int <- 8 in15 let c : Int <- 7, a : Int <- 9 in16 out_int (a+b+c+d+self.a());17 }};18 };
Class MapMaina Intb Intc Int
Symbol Tablea Int; String; Intb Intc Int; Intd Int
Compiler Construction 5/1
Formal Parameters
We must track formal parameters1 class Main inherits IO{2 a : Int <- 5;3 main () : Object {{4 stuff (9);5 out_int (a) --outputs 56 }};7 stuff ( a : Int ) : Int {{8 out_int (a); --outputs 99 a;
10 }};11 };
Class Mapa Int
Symbol Table (main)
Compiler Construction 6/1
Formal Parameters
We must track formal parameters1 class Main inherits IO{2 a : Int <- 5;3 main () : Object {{4 stuff (9);5 out_int (a) --outputs 56 }};7 stuff ( a : Int ) : Int {{8 out_int (a); --outputs 99 a;
10 }};11 };
Class Mapa Int
Symbol Table (stuff)a Int
Compiler Construction 6/1
Class Map▶ Class attributes are private in Cool
1 class Main inherits IO {2 a : A <- new A;3 main () : Object {{4 out_int (a.field );5 -- not allowed6 out_int (field );7 --nothing in8 -- symbol table or class map!9 out_int (a);
10 -- totally Cool11 }};12 };13 class A {14 field : Int <- 5;15 };
Class Map
Maina A
Afield Int
Compiler Construction 7/1
Implementation Map
▶ Class methods are public in Cool
1 class Main inherits IO {2 method () : Int { 5 };3 method2 () : Int { 5 };4 main () : Object {{5 out_int ( method ());6 out_int (7 (new A). method2 ()8 );9 }};
10 };11 class A inherits Main {12 method2 () : Int { 10 };13 method3 () : Int { 5 };14 };
Compiler Construction 8/1
Implementation Map
▶ Class methods are public in Cool
1 class Main inherits IO {2 method () : Int { 5 };3 method2 () : Int { 5 };4 main () : Object {{5 out_int ( method ());6 out_int (7 (new A). method2 ()8 );9 }};
10 };11 class A inherits Main {12 method2 () : Int { 10 };13 method3 () : Int { 5 };14 };
Implementation Map
Main1 Object.abort2 Object.type_name... ...
Afield loc(2)
Compiler Construction 8/1
Implementation Map
▶ Class methods are public in Cool
1 class Main inherits IO {2 method () : Int { 5 };3 method2 () : Int { 5 };4 main () : Object {{5 out_int ( method ());6 out_int (7 (new A). method2 ()8 );9 }};
10 };11 class A inherits Main {12 method2 () : Int { 10 };13 method3 () : Int { 5 };14 };
Implementation Map
Main1 Object.abort2 Object.type_name... ...8 Main.method9 Main.method210 Main.main
Afield loc(2)
Compiler Construction 8/1
Implementation Map
▶ Class methods are public in Cool
1 class Main inherits IO {2 method () : Int { 5 };3 method2 () : Int { 5 };4 main () : Object {{5 out_int ( method ());6 out_int (7 (new A). method2 ()8 );9 }};
10 };11 class A inherits Main {12 method2 () : Int { 10 };13 method3 () : Int { 5 };14 };
Implementation Map
Main1 Object.abort2 Object.type_name... ...8 Main.method9 Main.method210 Main.main
A1 Object.abort2 Object.type_name... ...8 Main.method9 Main.method210 Main.main
Compiler Construction 8/1
Implementation Map
▶ Class methods are public in Cool
1 class Main inherits IO {2 method () : Int { 5 };3 method2 () : Int { 5 };4 main () : Object {{5 out_int ( method ());6 out_int (7 (new A). method2 ()8 );9 }};
10 };11 class A inherits Main {12 method2 () : Int { 10 };13 method3 () : Int { 5 };14 };
Implementation Map
Main1 Object.abort2 Object.type_name... ...8 Main.method9 Main.method210 Main.main
A1 Object.abort2 Object.type_name... ...8 Main.method9 A.method210 Main.main11 A.method3
Compiler Construction 8/1
Validating Identifiers in Expressions▶ Your program is a list of classes
▶ Each class is a list of features▶ Each feature could be a method (with an AST!)
▶ Use the AST to determine valid uses ofidentifiers▶ We’re not checking the types yet; just whether
variables are in scope!
▶ Introduce new bindings to symbol table whenencountering let expressions (what else?)▶ Restore old bindings after leaving a node (why?)
Compiler Construction 9/1
Validating Identifiers in Expressions (2)For each method:
1. Start with a symbol table containing the classmap!▶ Class map tells us starting symbols globally
available
2. Add in entries for parameters3. Recurse through child expression
(there is only one per method!)▶ On let expressions (or case expressions), introduce
new bindings▶ On identifier expressions, check if it exists in the
symbol table!▶ If not, complain to user
Compiler Construction 10/1
Rules of InferenceYou have survived formal languages in specifyingparts of the compiler▶ Regular expressions (lexer)▶ Context-free grammars (parser)
We uselogical rules of inferenceas a formalism for type in-ference
Compiler Construction 11/1
Rules of Inference?
Inference rules have the form
If Hypothesis is true, then Conclusion is true
Type checking computes via reasoning:
If E1 and E2 have certain types,then E3 has a certain type
Rules of inference are a compact notation for“If-then” statements
Compiler Construction 12/1
From English to Inference Rules
Start with a simplified system and gradually addfeatures...
Building blocks
▶ Symbol “∧” is “and”▶ Symbol “⇒” is “if-then”▶ x:T is “x has type T”
Compiler Construction 13/1
English to Inference Rules (2)
If e1 has type Int and e2 has type Int,then e1+ e2 has type Int
(e1 has type Int ∧ e2 has type Int)⇒e1+ e2 has type Int
(e1 : Int∧ e2 : Int)⇒ e1+ e2 : Int
This is an inference rule!▶ e1 : Int∧ e2 : Int are two hypotheses,
e1+ e2 : Int is a conclusion!
Compiler Construction 14/1
Notation for Inference RulesBy tradition, inference rules are written
⊢Hypothesis1... ⊢Hypothesisn
⊢Conclusion
Cool type rules have hypotheses and conclusions ofthe form:
⊢ e : T
⊢means “we can prove that...”
Compiler Construction 15/1
Examples
⊢ i : Int Int
(i is an Integer)
⊢ e1 : Int⊢ e2 : Int⊢ e1+ e2 : Int Add
(the result of adding to Ints is an Int)
Compiler Construction 16/1
Examples (2)
⊢ e1 : Int⊢ e2 : Int⊢ e1+ e2 : Int Add
▶ These rules give templates describing how totype integers and + expressions...▶ We can fill in the templates, producing a
complete typing for any expression!
⊢ false : Int⊢ true : Int
⊢ true+ false : IntCompiler Construction 17/1
Example: 1+2
⊢ 1 : Int⊢ 2 : Int⊢ 1+ 2 : Int
Compiler Construction 18/1