300 likes | 463 Views
CS412/413. Introduction to Compilers and Translators Spring ’99 Lecture 10: More Type Checking. Administration. Homework 2 due Friday. Review. During type checking, associate types from a type system with expressions and variables in program
E N D
CS412/413 Introduction to Compilers and Translators Spring ’99 Lecture 10: More Type Checking
Administration • Homework 2 due Friday CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Review • During type checking, associate types from a type system with expressions and variables in program • Types: primitive types, type constructors, pseudo-types (e.g. void, error) • Type constructors: • Arrays: array(T) • Records/structs: {id1 : T1, id2 : T2, … } • Functions: T1T2 T1T2 ... Tn Tr CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Review • Formally symbol table is map from identifiers to types, referred to as type-checking environment A = { id1 : T1, id2 : T2, … } • Type checking is attempt to make typejudgments A |– E : T means “ in the environment A, expression E has type T ” CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Review • Type inference rules allow precise, compact expression of type-checking process • Semantic analysis corresponds to working backwards through inference rules A |– E : bool A |– !E : bool ! bool? E What if can’t get desired type judgment? CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Function-checking rule • Notation: A|– [ F ] means F is type-safe • Create an environment A containing all the argument variables • Check the body E in this environment • Type of E must match declared return type of function A { ..., ai : Ti, ...} |–E : T A|– [ id ( ..., ai : Ti, ...) : T = E ] CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Example fact(x: int) : int = { if (x==0) 1; else x * fact(x - 1); } A |–[fact(x: int) : int = {…} ] A {x : int} |– if (x==0) ...; else ... : int A {x : int} |– x==0 : bool A {x : int} |– x : T1 (T1 = int) A {x : int} |– 0 : int A {x : int} |– 1 : T2 (T2 = int) A {x : int} |– x * fact(x-1) : int CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Remainder of proof A {x : int} |– x * fact(x-1) : int A {x : int} |– x : int A {x : int} |– fact(x-1) : int A {x : int} |– x-1 : int A {x : int} |– x : int A {x : int} |– 1 : int A {x : int} |– fact : intint CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Sequence • Rule: A sequence of statements is type-safe if the first statement is type-safe, and the remaining are type-safe too: A |– S1: T1 A |– S2 S3 ...Sn : T A |–S1 S2 ...Sn : T • What about variable declarations ? CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Declarations A |– id: T1 [ = E ] : T1 A { id : T1} |– S2 ...Sn : T A |– id : T1 [ = E ]; S2 ...Sn : Tn • This formally describes the type-checking code from two lectures ago! CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Implementation class Block { Stmt stmts[]; Type typeCheck(SymTab s) { Type t; for (int i = 0; i < stmts.length; i++) { t = stmts[i].typeCheck(s); if (stmts[i] instanceof Decl) s = s.add(Decl.id, Decl.typeExpr.evaluate()); } return t; } } A |– S1: T1 S1 not a decl. A |– S2 S3...Sn : T A |– S1 S2 ...Sn : T A |– id: T1 [ = E ] : T1 A { id : T1} |– S2 ...Sn : T A |– id : T1 [ = E ]; S2 ...Sn : T CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Completing static semantics • Rest of static semantics can be written in this style • Provides complete recipe (inductively) for how to show a program type-safe • Induction: • have rules for atoms: A |– true : bool • for every valid syntactic construct in language, have a rule showing how to prove it type-safe • Therefore, have rules for checking all syntactically valid programs for type safety CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Implementing Rules • Start from goal judgments for each function A |– [ id ( ..., ai : Ti, ...) : T = E ] • Work backward applying inference rules to sub-trees of abstract syntax trees • Same recursive traversal described earlier • Need efficient way to create new environments , e.g. for A { id : T1} |– S2 ...Sn : T CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Implementing Types • How do we represent types during type checking? Need a data structure. • Types need operations: • creation from type expressions in the program interpretType(AST_node n, SymTab s); • ability to be checked for equivalence • application of type constructors CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Type Class abstract class Type { boolean equals(Type t); // type equivalence void unparse(OutputStream o) // for debugging } CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Primitive Types class PrimitiveType extends Type { string name; boolean equals(Type t) { return this == t; } void unparse(OutputStream o){ o.print(name); } } CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Type Constructor: Array class ArrayType extends Type { Type T; // represents the type array[T] Array(Type t) { T = t; } boolean equals(Type t) { if (t instanceof ArrayType && ((ArrayType)t).T.equals(T)) return true; else return false; } CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Type Equivalence • Structural equivalence vs. name equivalence • Record types in C: struct Point { int x,y; }; struct Range { int low, int high; } struct Point2 { int x, y; } struct Point3 { int y, x; } • Name equivalence: all different since created by different constructor invocations • Structural equivalence: depends on structure • possibilities: all same, Point=Point2, =Point3 CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Type Equivalence, Formally • Add a new kind of judgment: A |– T1 = T2 • Meaning: types T1 and T2 are equivalent in environment A • Axioms: A |– int = int, A |– bool = bool • Arrays: A |– T1 = T2 A |– array(T1) = array(T2) CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Record Equivalence • Name equivalence: record type has a name generated (or assigned) at declaration n1 = n2 A |– n1{id1 : T1…} = n2{id1 : T1…} • Structural equivalence: field names & types must match m = n idi = id’iA |– Ti = T’i A |– {id1:T1...idn:Tn} = {id’1:T’1… id’m: T’m} CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Interpreting Types • Iota: type ::= id | array[ type ] • Suppose type : TypeExpr class TypeId extends TypeExpr class ArrayTypeExpr extends TypeExpr CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Interpreting Types abstract class TypeExpr { Type interpret(SymTab A); } class TypeId { string name; Type interpret(SymTab A) { if (name.equals(“int”)) return Int; if (name.equals(“string”)) return Str; ... CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Interpreting Arrays class ArrayTypeExpr extends TypeExpr { TypeExpr te; Type interpret(SymTab A) { return new ArrayType(te.interpret()); } } CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
More language features • Recursive definitions & forward decls • Returns and exceptions • Subtyping • Classes • Inheritance • Parametric polymorphism CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Handling Recursion A |–[ fact(x: int) : int = { if (x==0) 1; else x * fact(x - 1); } ] • To type-check this, A must contain entry fact : int int • Java, Iota: functions (methods, classes) may be mutually recursive. f(x: int) : int = {if (x<1) 1; else g(f(x-1)); } g(x: int) : int = {if (x<1) 2; else f(g(x-1)); } CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Handling Recursion • Need environment containing at least {f: int int, g: int int} when checking both f and g • Two-step approach: • Scan top level of AST picking up all function signatures and creating an environment binding all global identifiers • Type-check each function individually using this global environment CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Non-local control flow • How to check non-local control transfers? • return, throw, break, continue • Fits into existing framework for type checking (mostly) • Question: what is the type of a return statement? A |– returnE : ? CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
How to check return? A |– E : T A |– returnE : void • A return statement has no value, so its type is void • But… how do make sure the return type of the current function is T ? CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Answer: put it in the symbol table • Add entry {return : int } when we start checking the function, look up this entry when we hit a return statement. A’ = A { ..., ai : Ti, ...} {return : T} A { ..., ai : Ti, ...} |–E : T A|– [ id ( ..., ai : Ti, ...) : T = E ] A |– E : T {return : T} A A |– returnE : void CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers
Summary • Type systems and static semantics • Type-checking functions • How bindings are added to environment • local variables • global definitions (possibly recursive) • Representing, interpreting types • Type equivalence • return statement CS 412/413 Introduction to Compilers and Translators -- Spring '99 Andrew Myers