Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 Mooly Sagiv and Greta Yorsh School of Computer Science Tel-Aviv University Modern Compiler Design.

Similar presentations


Presentation on theme: "1 Mooly Sagiv and Greta Yorsh School of Computer Science Tel-Aviv University Modern Compiler Design."— Presentation transcript:

1 1 Mooly Sagiv and Greta Yorsh School of Computer Science Tel-Aviv University gretay@post.tau.ac.il http://www.cs.tau.ac.il/~gretay Modern Compiler Design T8 – Semantic Analysis: Type Checking

2 2 Example “drive” + “drink” 12 + “Rumster” String string Int String ERROR (in Java ) in Cool ?

3 3 Today COOL code txt Executable code exe Lexical Analysis Syntax Analysis Parsing ASTSymbol Table etc. Inter. Rep. (IR) Code Gen. Goals  Implementing Type Checking for Cool  Cool Type Rules Coming up: MIPS tutorial

4 4 Inheritance Graph What do we put in it?  all predefined classes: Int, String, Bool, Object, IO  all user-defined classes Why do we put it there ?  to be able to check that something is a type  to be able to compare types (for type checking) Implementation  mapping class names to nodes in the graph  node points to its superclass node

5 5 Major Semantic Tasks Inheritance graph construction and checking Symbol table construction  construct symbol table for features using inheritance tree  assign enclosing scope for each AST node Scope checking  check program using symbol tables Check for Main class and main method Type checking  uses inheritance graph and symbol tables  assign type for each AST node

6 6 Semantic Checks Scope rules  identifiers are defined  no multiple definition of same identifier  local variables are defined before used  … Type rules  which types can be combined with certain operator  assignment of expression to variable  formal and actual parameters of a method call  …

7 7 Notation for Inference Rules By tradition inference rules are written  Hypothesis 1  Hypothesis 2...  Hypothesis n  Conclusion  means “it is provable that...” Cool type rules have hypothesis and conclusion O,M,C  e: T [ NAME] conditions type environment

8 8 Type Checking - Implementation Single traversal over AST Types passed up the tree Type environment passed down the tree

9 9 Example (45 + x) < (~32) plus neg lt … int_const val=45 object name=x int_const val=32 : Int O,M,C  int_const : Int O,M,C  x : Int O(x) = Int classFoo kindSymbol globals Foo Intc Symbol test Intx Int->Inttest kindSymbol lookup(x)

10 10 Example (45 + x) < (~32) plus neg lt … int_const val=45 object name=x int_const val=32 : Int : Bool O,M,C  int_const : Int O,M,C  E1 : Int O,M,C  E2 : Int O,M,C  E1 < E2 : Bool O,M,C  E1 : Int O,M,C  E2 : Int O,M,C  E1 + E2 : Int O,M,C  E1 : Int O,M,C  ~E1 : Int O,M,C  x : Int O(x) = Int

11 11 Cool Types How types are represented ?  AbstractSymbol  compare types by comparing AbstractSymbols When are types are created?  during lexer/parsing  predefined types

12 12 Cool Types The types are  Class Names  SELF_TYPE The user declares types for identifiers The semantic analysis infers types for expressions  Every expression has a unique type A language’s type system specifies which operations are valid for which types The goal of type checking is to ensure that operations are used with the correct types  Enforces intended interpretation of values Cool is statically typed: type checking during compilation

13 13 Cool Types Environment O, M, K  e: T  gives types to free identifiers in the current scope  information about the formal parameters and return type of methods  the class in which an expression e appears Why separate object/methods?  In Cool, the method and object identifiers live in different name spaces type environment

14 14 Cool Types Environment O, M, K  e: T O --- mapping Object Id’s to types  symbol table - current scope  O(x) = T M --- mapping methods to method signatures  M(C, f) = (A, B, D)  means there is a method f(a:A, b:B): D defined in class C (or its ancestor) K --- the class in which expression e appears  when SELF_TYPE is involved type environment

15 15 Type rules O, M, K  e1 : Int O, M, K  e2 : Int O, M, K  e1 + e2 : Int Rules give templates describing how to type expressions By filling the templates, we can produce complete typings for expressions O,M,C  int_const : Int O,M,C  x : T O(x) = T

16 16 Example 1 +2 Templates: Inference: 2 is an integer O,M,C  2: Int [Int] O,M,C  1+2: Int [Add] 1 is an integer O,M,C  1 : Int [Int] O,M,C  int_const : Int O,M,C  E1 : Int O,M,C  E2 : Int O,M,C  E1 + E2 : Int

17 17 Subtyping Define a relation  on classes  X  X  X  Y if X inherits from Y  X  Z if X  Y and Y  Z A  C B  Object E  D and D  E AB C D Object E IO

18 18 Least Upper Bounds Z is the least upper bound of X and Y lub(X, Y)=Z  X  Z and Y  Z Z is upper bound  X  Z’ and Y  Z’  Z  Z’ Z is the least upper bound

19 19 Least Upper Bounds lub(A,B) = C lub(C,D) = D lub(C,E) = Object In Cool, the least upper bound of two types is their least common ancestor in the inheritance tree AB C D Object E IO

20 20 Dynamic and Static Types in Cool A variable of static type A can hold the value of static type B if B  A class A {... } class B inherits A {... } class Main ( x: A  new A ;... x  new B ; } dynamic type of x is A dynamic type of x is B static type of x is A

21 21 Dynamic and Static Types The dynamic type of an object is the class that is used in the new expression  a runtime notion  even languages that are statically typed have dynamic types The static type of an expression captures all the dynamic types that the expression could have  a compile-time notion

22 22 Static vs. Dynamic Typing Static typing proponents say:  Static checking catches many programming errors  Prove properties of your code  Avoids the overhead of runtime type checks x C, Java, Cool, ML Dynamic typing proponents say:  Static type systems are restrictive  Rapid prototyping difficult with type systems  Complicates the programming language and the compiler  Compiler optimizations can hide costs x machine code In practice, most code is written in statically typed languages with escape mechanisms  Unsafe casts in C, Java  union in C

23 23 Soundness A type system is sound if  e. dynamic_type(e)  static_type(e)  whenever the inferred type of e is T ( denoted by O,M,C  e : T )  Then e evaluates to a value of type  T in all executions of the program We only want sound rules But some sound rules are better than others

24 24 Assign O (x) = T 0 O,M,K  e 1 : T 1 T 1  T 0 O,M,K  x  e 1 : T 1 [Assign] class A { foo() : A { … } }; class B inherits A { };... let x:B in x  (new B).foo(); let x:A in x  (new B).foo(); let x:Object in x  (new B).foo(); ERROR OK A

25 25 Let Rule with Initialization Both rules are sound but more programs typecheck with the second one  uses subtyping O,M,K  e 0 : T O(T/x)  e 1 : T 1 O,M,K  let x: T  e 0 in e 1 : T 1 Weak rule O,M,K  e 0 : T O(T 0 /x)  e 1 : T 1 T  T 0 O,M,K  let x: T 0  e 0 in e 1 : T 1 class A { foo():C { … } }; class B inherits A { };... let x:A  new B in x.foo();

26 26 If-Then-Else O,M,K  e 0 :Bool O,M,K  e 1 : T 1 O,M,K  e 2 : T 2 O,M,K  if e 0 then e 1 else e 2 fi : lub(T 1, T 2 ) AB C D Object E IO foo(a:A, b:B, c:C, e:E) : D { if (a < b) then e else c fi } lub(E,C) = Object Is Object  D ? ERROR

27 27 foo(d:D) : D { case d of x : IO => let a:A  (new A) in x; y : E => (new B); z : C => z; esac }; lub(IO,B,C) = Object and Object  D Case O,M,K  e : T O[X/x],M,K  e 1 : E O[Y/y],M,K  e 2 : F O[Z/z],M,K  e 3 : G O,M,K  case e of x: X =>e 1 ; y:Y =>e 2 ; z:Z=>e 3 esac : lub(E,F,G) AB C D Object E IO ERROR IO

28 28 foo(d:D) : D { case d of x : IO => let a:A  (new A) in a; y : E => (new B); z : C => z; esac }; lub(A,B,C) = C and C  D Case O,M,K  e : T O[X/x],M,K  e 1 : E O[Y/y],M,K  e 2 : F O[Z/z],M,K  e 3 : G O,M,K  case e of x: X =>e 1 ; y:Y =>e 2 ; z:Z=>e 3 esac : lub(E,F,G) AB C D Object E IO OK A

29 29 Dispatch O, M  c : C O, M  a : A O, M  b : B M(C, f) = (A1, B1, D1) A  A1, B  B1 O, M, K  c.f(a, b): D1 [Dispatch] class C1 { foo(a:A1, b:B1) : D1 {new D1 ; }; }; … (new C).foo( (new A), (new B) );

30 30 Static Dispatch [StaticDispatch] O, M, K  c : C O, M, K  a : A O, M, K  b : B M(C, f) = (A1, B1, D1) A  A1, B  B1, C  C1 O, M, K  c@C1.f(a, b): D1 class C1 { foo(a:A1, b:B1) : D1 {new D1 ; }; }; … (new C)@C1.foo( (new A), (new B) );

31 31 SELF_TYPE Example What can be a dynamic type of object returned by foo() ?  any subtype of A class A { foo() : A { self } ; }; class B inherits A {... }; class Main { B x  (new B).foo(); }; class A { foo() : SELF_TYPE { self } ; }; class B inherits A {... }; class Main { B x  (new B).foo(); }; ERROROK

32 32 SELF_TYPE Research idea Helps type checker to accept more correct programs C,M,K  (new A).foo() : A C,M,K  (new B).foo() : B SELF_TYPE is NOT a dynamic type Meaning of SELF_TYPE depends on where it appears textually

33 33 Where can SELF_TYPE appear ? Parser checks that SELF_TYPE appears only where a type is expected  How ? But SELF_TYPE is not allowed everywhere a type can appear

34 34 Where can SELF_TYPE appear ? class T1 inherits T2 { … }  T1, T2 cannot be SELF_TYPE x : SELF_TYPE  attribute  let  case new SELF_TYPE  creates an object of the same type as self foo@T(e)  T cannot be SELF_TYPE foo(x:T1):T2 {…}  only T2 can be SELF_TYPE

35 35 new Example class A { foo() : A { new SELF_TYPE }; }; class B inherits A { … } … (new A).foo(); (new B).foo(); creates A object creates B object

36 36 Subtyping for SELF_TYPE SELF_TYPE c  SELF_TYPE c SELF_TYPE c  C It is always safe to replace SELF_TYPE c with C SELF_TYPE c  T if C  T T  SELF_TYPE c is always false  because SELF_TYPE c can denote any subtype of C

37 37 lub(T,T’) for SELF_TYPE lub(SELF_TYPE c, SELF_TYPE c ) = SELF_TYPE c lub(T, SELF_TYPE c ) = lub(T,C)  the best we can do

38 38 New Rules O, M, K  self : SELF_TYPE k O, M, K  new SELF_TYPE : SELF_TYPE k

39 39 Other rules A use of SELF_TYPE refers to any subtype of the current class Except in dispatch  because the method return type of SELF_TYPE might have nothing to do with the current class

40 40 Dispatch O, M  c : C O, M  a : A O, M  b : B M(C, foo) = (A1, B1, D1) A  A1, B  B1, D1  SELF_TYPE O, M, K  c.foo(a, b) : D1 O, M  c : C O, M  a : A O, M  b : B M(C, foo) = (A1, B1, SELF_TYPE) A  A1, B  B1 O, M, K  c.foo(a, b): C which class is used to find the declaration of foo() ?

41 41 Example class A { foo() : A { self }; }; class B inherits A { … } … (new A).foo(); (new B).foo(); returns A object returns B object

42 42 Static Dispatch O, M, K  c : C O, M, K  a : A O, M, K  b : B M(C, f) = (A1, B1, D1) A  A1, B  B1, C  C1, D1  SELF_TYPE O, M, K  c.f@C1(a, b): D1 O, M, K  c : C O, M, K  a : A O, M, K  b : B M(C, f) = (A1, B1, SELF_TYPE) A  A1, B  B1, C  C1 O, M, K  c@C1.f@(a, b): C if we dispatch a method returning SELF_TYPE in class C1, do we get back C1 ? No. SELF_TYPE is the type of self, which may be a subtype of the class in which the method appears

43 43 SELF_TYPE Example class A { deligate : B; callMe() : ??? { deligate.callMe(); } ; }; class B { callMe() : SELF_TYPE { self }; }; class Main { A a  (new A).callMe(); }; ERROR SELF_TYPE

44 44 Error Handling Error detection is easy Error recovery: what type is assigned to an expression with no legitimate type ?  influences type of enclosing expressions  cascading errors let y : Int  x + 2 in y + 3  Better solution: special type No_Type  inheritance graph can be cyclic

45 45 Summary Type is a set of values Type rules are logical rules of inference Soundness of (static) type systems  for every expression e, for every value v of e at runtime v  values_of(static_type(e))  static_type(e) may actually describe more values  can reject correct programs Becomes more complicated with subtyping (inheritance)

46 46 Major Semantic Tasks Inheritance graph construction and checking Symbol table construction  construct symbol table for features using inheritance tree  assign enclosing scope for each AST node Scope checking  check program using symbol tables Check for Main class and main method Type checking  uses inheritance graph and symbol tables  assign type for each AST node Remaining Semantic Checks  checks that require type + symbol table information combined Disclaimer: This is a naïve phase ordering. Phases could be mixed, combined, optimized, re-ordered etc.


Download ppt "1 Mooly Sagiv and Greta Yorsh School of Computer Science Tel-Aviv University Modern Compiler Design."

Similar presentations


Ads by Google