Cse 321 Programming Languages and Compilers Lecture 16

  • Slides: 26
Download presentation
Cse 321, Programming Languages and Compilers Lecture #16, March 7, 2007 • Mutual Recursion

Cse 321, Programming Languages and Compilers Lecture #16, March 7, 2007 • Mutual Recursion • Symbol Tables • Class Hierarchies • Type checkers that rebuild code 9/9/2020 1

Cse 321, Programming Languages and Compilers Assignments • Reading – Finish Chapter 4. Sections

Cse 321, Programming Languages and Compilers Assignments • Reading – Finish Chapter 4. Sections 4. 4, 4. 5, and 4. 6 pages 188 -208 – Read Section 5. 7 on Symbol tables page 238 -248 – Possible Quiz next Monday. • Project 3 is due Monday March 19 9/9/2020 2

Cse 321, Programming Languages and Compilers Mutual Recursion • Mutual recursion is found in

Cse 321, Programming Languages and Compilers Mutual Recursion • Mutual recursion is found in almost all real languages • Mutual recursion requires different techniques – Multiple passes. – One pass to build a temporary table with just the information about the mutually recursive entities – Second pass to type the recursive entities where the current scope is extended with the temporary table. » Inside this pass, the table is often extended even more to capture information about entities declared in a single one of the mutually recursive entities. – Finally, the temporary table is exported to the scope in which the mutually recursive entities exist. 9/9/2020 3

Cse 321, Programming Languages and Compilers Example in ML x: int val x =

Cse 321, Programming Languages and Compilers Example in ML x: int val x = 56; fun f x = x + 5; fun even n = if n=0 then true else odd (n-1) and odd n = if n=0 then false else if n=1 then true else even (n-1); val main = even(f x) 9/9/2020 f: int -> int x: int f: int -> int even: int->bool odd: int->bool n: int x: int f: int -> int even: int->bool odd: int->bool main: bool 4

Cse 321, Programming Languages and Compilers Concrete Example and = | | Dec Valdec

Cse 321, Programming Languages and Compilers Concrete Example and = | | Dec Valdec of (string*MLtype)*Exp Fundec of (string*MLtype)*string*Exp Mutdec of Dec list • Assume we represent declarations as above. • Every val and fun declaration contains explicit information about their types (as is true in Mini-Java) • Then the concrete syntax may look like: val (x: int) = 56; fun (f: int->int) (x: int) = x + 5; 9/9/2020 5

Cse 321, Programming Languages and Compilers Type Checking Declarations • Type checking will depend

Cse 321, Programming Languages and Compilers Type Checking Declarations • Type checking will depend upon two attribute computations. • Checking declarations will map an environment to a delta environment. • New environment will be the old one plus the delta. TCExp: Exp ->(string * MLtype)list ->MLtype TCDec: Dec ->(string * MLtype)list ->(string * MLtype) list fun (even: int ->bool) (n: int) = if n=0 then true else odd (n-1) and (odd: int -> bool) (n: int) = if n=0 then false else if n=1 then true else even (n-1); 9/9/2020 x: int even: int -> bool f: int -> int odd: int -> bool 6

Cse 321, Programming Languages and Compilers Non mutually recursive cases fun TCDec (Valdec((nm, t),

Cse 321, Programming Languages and Compilers Non mutually recursive cases fun TCDec (Valdec((nm, t), exp)) cntxt = let val bodyt = TCExp exp cntxt in if typeeq(t, bodyt) then [(nm, t)] else unexpected exp bodyt t end | TCDec (Fundec((f, dom, rng), x, body)) cntxt = let val ft = Arrow(dom, rng) val bodyt = TCExp body((x, dom): : cntxt) (* f is not recursive unless inside a Mutdec *) in if typeeq(bodyt, rng) then [(f, ft)] else unexpected bodyt rng end 9/9/2020 7

Cse 321, Programming Languages and Compilers Mutually recursive case | TCDec (Mutdec ds) cntxt

Cse 321, Programming Languages and Compilers Mutually recursive case | TCDec (Mutdec ds) cntxt = let fun pass 1 [] cntxt = cntxt | pass 1 (Valdec(p, b): : ds) cntxt = pass 1 ds (p: : cntxt) | pass 1 (Fundec((f, d, r), x, b): : ds) cntxt = pass 1 ds ((f, Arrow(d, r)): : cntxt) val temp = pass 1 ds cntxt val pass 2 = map (fn d => TCDec d temp) ds in List. concat pass 2 end; cntxt temp pass 2 result x: int odd: int->bool even: int->bool f: int -> int even: int->bool x: int f: int -> int odd: int->bool 9/9/2020 8

Cse 321, Programming Languages and Compilers Symbol Tables • Symbol Tables map names to

Cse 321, Programming Languages and Compilers Symbol Tables • Symbol Tables map names to information • Many kinds of Names – – – Variables Procedure and function names Labels Data Structure names (Constructors in ML or named Struct in C) Types • Many kinds of information – – – 9/9/2020 Type Physical location in source (line number) Size Storage class Lexical location (Inside what class) Location in memory in the translation 9

Cse 321, Programming Languages and Compilers Multiple symbol tables • Compilers might use one

Cse 321, Programming Languages and Compilers Multiple symbol tables • Compilers might use one big table, or many smaller ones. • Multiple tables have advantages – Each table stores uniform items – Tables might have limited scope and can be recycled – Each table can use different implementation » Hash Table » Linked List » Balanced Tree – Each table probably has different access patterns » Create Once, then read only » Block Structured, so stack allocation is possible » Insertions only » Both insertions and deletions • Tables can have mutable or non-mutable data • Language may have multiple name spaces – Types, labels, variables, selectors, . . . 9/9/2020 10

Cse 321, Programming Languages and Compilers Nested Scope • Many tables record information with

Cse 321, Programming Languages and Compilers Nested Scope • Many tables record information with block structure or nested scope. • Stack allocation is possible • Easy to implement in a functional language like ML – Use inherited attribute computation – Table becomes a parameter to the function – Entering new block means a new call to function with the parameter augmented. – Exiting scope means restoring the old parameter » Natural in a functional style since the old parameter is always still around. 9/9/2020 11

Cse 321, Programming Languages and Compilers Operations on nested scope • • Initialize Scope

Cse 321, Programming Languages and Compilers Operations on nested scope • • Initialize Scope Insert name value Scope Lookup name Scope Finalize Scope type ('name, 'value)table = ('name * 'value) list; type ('name, 'value)Scope = (('name, 'value)table) list ; More sophisticated kinds of tables can be used here rather than a linked list of pairs. Hash Tables, Balanced trees, etc. fun initialize scope = [ ] : : scope fun insert name value (table: : scope) = ((name, value): : table): : scope fun Lookup name (table: : scope) = case List. find (fn (x, y) => x=name) table of NONE => error | SOME (x, y) => y fun finalize (table: : scope) = scope 9/9/2020 12

Cse 321, Programming Languages and Compilers Data Structures for the Mini. Java Type Checker

Cse 321, Programming Languages and Compilers Data Structures for the Mini. Java Type Checker • Scope in object oriented languages like mini-java is attached to the class structure. • Each class has its own symbol table – Usually this table is an ordinary nested scope table • Each class must link to the symbol table for its super -class. • The Class hierarchy is a tree of symbol tables. • The set of operations on the tables can be found by inspecting the type rules. 9/9/2020 13

Cse 321, Programming Languages and Compilers Judgments from the type rules Th, C, TE

Cse 321, Programming Languages and Compilers Judgments from the type rules Th, C, TE |- exp : type Th, R, C, TE |= stmt C |~ t 1 ≤ t 2 t 1 = t 2 C defines x In C p has method f In C p has variable x Op <+> : (t 1, t 2) -> t 3 t is basic 9/9/2020 14

Cse 321, Programming Languages and Compilers Data Structure datatype CTab = Node of Id

Cse 321, Programming Languages and Compilers Data Structure datatype CTab = Node of Id * (* Class Name (Id * Type)list * (* Class Variables (Id * Type list * Type)list * (* Methods CTab ref * (* Parent Class CTab list (* Sub Classes | Null. Class; *) *) *) val root = Node("object", [], ref Null. Class, []); CTab for class table is an n-way branching tree. object point colorpoint 9/9/2020 numeric int boolean void double 15

Cse 321, Programming Languages and Compilers new. Class fun new. Class name vars methods

Cse 321, Programming Languages and Compilers new. Class fun new. Class name vars methods parent Null. Class = Null. Class | new. Class name vars methods parent (n as Node(nm, vs, ms, p, subs)) = if parent=nm then let val p 1 = ref n val new = Node(name, vars, methods, p 1, []) val new. P = Node(nm, vs, ms, p, new : : subs) val _ = p 1 : = new. P in new. P end else Node(nm, vs, ms, p, map (new. Class name vars methods parent) subs) • new. Class creates a new class hierarchy from the old one. The old one is unchanged. 9/9/2020 16

Cse 321, Programming Languages and Compilers val t 1 = new. Class "point" []

Cse 321, Programming Languages and Compilers val t 1 = new. Class "point" [] [] "object" root; root Node(“object”, [ ], ref Null. Class, [ ]) new Node(“point”, [ ], ref _ , [ ]) new. P Node(“object”, [ ], ref Null. Class, [Node(“point”, [ ], ref _ , [ ])]) • The final step is to overwrite the pointer to root with new. P, and then return new. P • new. Class rebuilds the part of the tree that are unchanged 9/9/2020 • The references make cyclic structures 17

Cse 321, Programming Languages and Compilers val t 1 = new. Class "point" []

Cse 321, Programming Languages and Compilers val t 1 = new. Class "point" [] [] "object" root; val t 2 = new. Class "colorpoint" [] [] "point" t 1; t 2 Node(“object”, [ ], ref Null. Class , [ _ ]) Node(“point”, [ ], ref _ , [ _ ]) Node(“colorpoint”, [ ], ref _ , [ ]) 9/9/2020 18

Cse 321, Programming Languages and Compilers val t 1 = new. Class "point" []

Cse 321, Programming Languages and Compilers val t 1 = new. Class "point" [] [] "object" root; val t 2 = new. Class "colorpoint" [] [] "point" t 1; val t 3 = new. Class "person" [] [] "object" t 2 t 3 Node(“object”, [ ], ref Null. Class , [ _ , _ ]) Node(“point”, [ ], ref _ , [ _ ]) Node(“colorpoint”, [ ], ref _ , [ ]) Node(“person”, [ ], ref _ , [ ]) 9/9/2020 19

Cse 321, Programming Languages and Compilers C defines x fun defines name Null. Class

Cse 321, Programming Languages and Compilers C defines x fun defines name Null. Class = false | defines name (Node(n, vs, ms, p, ss)) = if name=n then true else List. exists (defines name) ss; 9/9/2020 20

Cse 321, Programming Languages and Compilers t 1 = t 2 fun basiceq (x,

Cse 321, Programming Languages and Compilers t 1 = t 2 fun basiceq (x, y) = case (x, y) of (Real, Real) => true | (Int, Int) => true | (Bool, Bool) => true | (_, _) => false fun typeeq (x, y) = case (x, y) of (Basic. Type x, Basic. Type y) => basiceq(x, y) | (Array. Type x, Array. Type y) => basiceq(x, y) | (Obj. Type x, Obj. Type y) => x=y | (Void. Type, Void. Type) => true | (_, _) => false 9/9/2020 21

Cse 321, Programming Languages and Compilers C |~ t 1 ≤ t 2 fun

Cse 321, Programming Languages and Compilers C |~ t 1 ≤ t 2 fun use. Tree Null. Class (x, y) = false | use. Tree (Node(nm, vs, ms, p, ss)) (x, y) = if nm = y then List. exists (defines x) ss else List. exists (fn t => use. Tree t (x, y)) ss fun subtype class. H (x, y) = case (x, y) of (x, Obj. Type "object") => true | (Basic. Type Int, Obj. Type "numeric") => true | (Basic. Type Real, Obj. Type "numeric") => true | (Obj. Type x, Obj. Type y) => use. Tree class. H (x, y) | (_, _) => typeeq(x, y) 9/9/2020 22

Cse 321, Programming Languages and Compilers Type checkers that rebuild the syntax tree •

Cse 321, Programming Languages and Compilers Type checkers that rebuild the syntax tree • Some type checkers use inference to add things to the syntax tree that are missing. – Coercions » 3 + 5. 6 -> to. Float 3 + 5. 6 – Implicit class information » X. f(3, 5) -> X. ffrompoint(2, 5) – Implicit type information » (fn x => x + 1) -> (fn (x: Int) => x + 1) • Such type checkers return a tuple. – The tuple includes the synthesized attributes and a new syntax tree. Compare the two types – TCExp 2: Exp -> (string * MLtype) list -> MLtype * Exp – TCExp: Exp -> (string * MLtype) list -> MLtype 9/9/2020 23

Cse 321, Programming Languages and Compilers TCExp 2 fun TCExp 2 x cntxt =

Cse 321, Programming Languages and Compilers TCExp 2 fun TCExp 2 x cntxt = When a term has no sub terms, the old term can case x of usually be returned Lit c => (TCConstant c, x) | Var s => (case List. find (fn (nm, t) => nm=s) cntxt of SOME(nm, t) => (t, x) | NONE => error x "Undeclared variable") | Infix(l, x, r) => let val (ltype, l 2) = TCExp 2 l cntxt val (rtype, r 2) = TCExp 2 r cntxt val (lneed, result) = TCOp x in case (typeeq(ltype, lneed), typeeq(rtype, rneed)) of (true, true) => (result, Infix(l 2, x, r 2) ) | (true, false) => unexpected r rtype rneed | (false, true) => unexpected l ltype lneed Sub terms are | (false, false) => unexpected l ltype lneed rebuilt and the returned term is end constructed from these. 9/9/2020 24

Cse 321, Programming Languages and Compilers Why Bother • If all we ever do

Cse 321, Programming Languages and Compilers Why Bother • If all we ever do is return the same tree, why bother? • We use type (or other) information to add little bits of syntax. Infix(l, x, r) => let val (ltype, l 2) = TCExp 2 l cntxt val (rtype, r 2) = TCExp 2 r cntxt val (lneed, result) = TCOp x in case (typeeq(ltype, lneed), typeeq(rtype, rneed)) of (true, true) => Fix result (x, ltype, rtype) l 2 r 2 | (true, false) => unexpected r rtype rneed | (false, true) => unexpected l ltype lneed | (false, false) => unexpected l ltype lneed end fun Fix result info left right = case info of (Plus, Int, Real) => (result, Infix( Int 2 Real left , Plus, right)) | (Plus, Real, Int) => (result, Infix(left, Plus, Int 2 Real right )) | (oper, _ ) => (result, Infix(left, oper, right)) 9/9/2020 25

Cse 321, Programming Languages and Compilers Class exercise • As an in class exercise,

Cse 321, Programming Languages and Compilers Class exercise • As an in class exercise, lets continue the function on the previous pages. • Start with an non rebuilding type-checker – Make a copy of it. • Rename every call to a new name (so it doesn’t conflict) • For each returned expression add a another value to the tuple. • For each recursive call, accept (or pattern match against) an additional value. 9/9/2020 26