230 likes | 397 Views
Semantic Analysis II. x86 executable. exe. IC Program. ic. IC compiler. Compiler. We saw: Scope Symbol tables. Lexical Analysis. Syntax Analysis Parsing. AST. Symbol Table etc. Inter. Rep. (IR). Code Generation. Today: Type checking. assigned type doesn’t match declared type.
E N D
x86 executable exe ICProgram ic IC compiler Compiler We saw: • Scope • Symbol tables LexicalAnalysis Syntax Analysis Parsing AST SymbolTableetc. Inter.Rep.(IR) CodeGeneration Today: • Type checking
assigned type doesn’t match declared type relational operator applied to non-int type a is not a subtype of b argument list doesn’t match formal parameters Examples of type errors 1 < true int a; a = true; class A {…}class B extends A { void foo() { A a; B b; b = a; }} void foo(int x) { int y; foo(5,7);}
Types • Type • Set of possible values (and operations) • boolean = {true,false} • int = {-231..231-1} • void = {} • Type safety • Type usage adheres to formally defined typing rules
Type judgments • e : T • e is a well-typed expression of type T • Examples • 2 : int • 2 * (3 + 4) : int • true : bool • “Hello” : string
Type judgments • E e : T • In the context E,e is a well-typed expression of T • Examples: • b:bool, x:int b:bool • x:int 1 + x < 4:bool • foo:int->string, x:int foo(x) : string
Typing rules Premise [Name] Conclusion [Name] Conclusion
Typing rules for expressions E e1 : int E e2 : int [+] E e1+e2 : int
Expression rules E true : bool E false : bool E int-literal : int E string-literal : string E e1 : int E e2 : int op { +, -, /, *, %} E e1 op e2 : int E e1 : int E e2 : int rop { <=,<, >, >=} E e1 rop e2 : bool
More expression rules E e1 : bool E e2 : bool lop { &&,|| } E e1 lop e2 : bool E e1 : int E e1 : bool E - e1 : int E ! e1 : bool E e1 : T[] E e1 : T[] E e2 : int E e1 : int E e1[e2] : T E e1.length : int E new T[e1] : T[] E e:C (id : T) C E e.id : T E new T() : T
Subtyping • Inheritance induces subtyping relation ≤ • S ≤ T values(S) values(T) • “A value of type S may be used wherever a value of type T is expected”
Subtyping • For all types: • For reference types: A ≤ A A extends B {…} A ≤ B B ≤ C A ≤ B A ≤ C null ≤ A
Examples • int ≤ int ? • null ≤ A ? • null ≤ string ? • string ≤ null ? • null ≤ boolean ? • null ≤ boolean[] ? • A[] ≤ B[] ?
Examples • int ≤ int ? • null ≤ A ? • null ≤ string ? • string ≤ null ? • null ≤ boolean ? • null ≤ boolean[] ? • A[] ≤ B[] ? “Subtyping is not covariant for array types: if A is a subtype of B then A[ ] is not a subtype of B[ ]. Instead, array subtyping is type invariant, which means that each array type is only a subtype of itself.”
Expression rules with subtyping E e1 : T1 E e2 : T2 T1 ≤ T2 or T2 ≤ T1op {==,!=} E e1 op e2 : bool
Rules for method invocations E e0 : T1 … Tn Tr E ei : T’i T’i ≤ Ti for all i=1..n E e0(e1, … ,en): Tr (m : static T1 … Tn Tr) CE ei : T’i T’i ≤ Ti for all i=1..n E C.m(e1, … ,en): Tr
E e:bool E S1 E S2 E e:bool E e:bool E S E S E if (e) S1 else S2 E while (e) S E if (e) S E break E continue Statement rules • Statements have type void • Judgments of the form E S • In environment E, S is well typed
Return statements • ret:Tr represents return type of current method E e:T ret:T’E T≤T’ ret:void E E return e; E return;
More IC Rules • Declarations • Method • Class • Program • …
Type-checking algorithm • Construct types • Add basic types to a “type table” • Traverse AST looking for user-defined types (classes,methods,arrays) and store in table • Bind all symbols to types
Type-checking algorithm • Traverse AST bottom-up (using visitor) • For each AST node find corresponding rule(there is only one for each kind of node) • Check if rule holds • Yes: assign type to node according to consequent • No: report error
E e1 : bool E e2 : bool E e1 && e2 : bool E e1 : bool E e1 : int E e2 : int E !e1 : bool E e1 > e2 : bool E false : bool intLiteral intLiteral boolLiteral E int-literal : int val=45 val=32 val=false Algorithm example … BinopExpr : bool op=AND : bool : bool BinopExpr UnopExpr op=GT op=NEG : int : int : bool 45 > 32 && !false
Semantic analysis flow • Parsing and AST construction • Combine library AST with IC program AST • Construct and initialize global type table • Construct class hierarchy and verify the hierarchy is tree • Phase 1: Symbol table construction • Assign enclosing-scope for each AST node • Phase 2: Scope checking • Resolve names • Check scope rules using symbol table • Phase 3: Type checking • Assign type for each AST node • Phase 4: Remaining semantic checks