320 likes | 435 Views
Lecture #6, April 17, 2007. Project #1 description, Changes to Program Types, IR1 intermediate language, Embedded statements in expressions, Handling variables, Syntax directed translation, The project template, What to hand in. Assignments.
E N D
Lecture #6, April 17, 2007 • Project #1 description, • Changes to Program Types, • IR1 intermediate language, • Embedded statements in expressions, • Handling variables, • Syntax directed translation, • The project template, • What to hand in.
Assignments • Project #1 is now available on the class website under the projects link. Due in 2 weeks. May 3, 2007 • Recall Midterm Exam on Tuesday May 1, 2007. In class, 1.5 hours, two days before Project 1 is due.
Project 1 Description • Project #1 is to translate the abstract datatypes found in ProjectTypes.sml into the first of a number of Intermediate languages.
Features of ProgramTypes.sml • locations are arguments to some of the constructors. This supports better error messages • type loc = (int * int) • Added functions that print Exp and Stmt and also code that computes the (loc option) of Exp and Stmt
Recall datatype Exp = Literal of loc * Constant (* 5, 6.3, true *) | Binop of BINOP * Exp * Exp (* x + 3 *) | Relop of RELOP * Exp * Exp (* x < 7.7 *) | Not of Exp (* ! x *) | ArrayElm of Exp * Exp * (Basic TC) (* x[3] *) | ArrayLen of Exp (* x.length() *) | Call of Exp * Id *(Id TC)* Exp list (* x.f(1,z) *) | NewArray of Basic * Exp (* new int[3] *) | NewObject of loc * Id (* new point() *) (* Coerce is used only in type checking *) | Coerce of Exp | Member of loc * Exp * Id * Id | Var of loc * Id | This of loc A string, which is the name of the class the member comes from. Filled in by type checking
locations in declarations datatype VarDecl = VarDecl of loc * Type * Id * Exp option; datatype Formal = Formal of Type * Id; datatype MetDecl = MetDecl of loc * Type * Id * Formal list * VarDecl list * Stmt list; datatype ClassDec = ClassDec of loc * Id * Id * VarDecl list * MetDecl list;
Locations • Locations are a pair of ints (lineno, columnno) • We place locations on the terminal leafs of the parse tree. Variables, members, new, and this. • Given an expression we can compute a • (loc option) • When reporting an error, if we can compute (SOME pos) we can use pos to report the line and column number.
Computing Locations • We can only compute (loc option) because we might not find a location tag in some expressions or statements. • If a construct has two or more locations, we prefer the left most one, since this is the one closest to the beginning of the construct. • Left most preference: fun or (SOME x) _ = SOME x | or NONE x = x; fun orL [] = NONE | orL (x::xs) = or x (orL xs)
Locations of expressions fun posE exp = case exp of Literal (pos,x) => SOME pos | Binop (oper,x,y) => or (posE x) (posE y) | Relop (oper,x,y) => or (posE x) (posE y) | Not x => posE x | ArrayElm (x,n,NONE) => or (posE x) (posE n) | ArrayElm (x,n,SOME t) => or (posE x) (posE n) | ArrayLen x => posE x | Call (e,f,_,xs) => or (posE e) (orL (map posE xs)) | NewArray (t,x) => posE x | NewObject(pos,x) => SOME pos | Coerce e => posE e | Var(pos,x) => SOME pos | Member(pos,_,_,x) => SOME pos | This pos => SOME pos
Locations of statements fun posS stmt = case stmt of Block ss => orL (map posS ss) | Assign (SOME e, x, SOME n, v) => or (posE e) (or (posE n) (posE v)) | Assign (SOME e, x, NONE, v) => or (posE e) (posE v) | Assign (NONE, x, SOME n, v) => or (posE n) (posE v) | Assign (NONE, x, NONE, v) => posE v | CallStmt (e,f,_,xs) => or (posE e) (orL (map posE xs)) | If (g,x,y) => or (posE g) (or (posS x) (posS y)) | While (g,b) => or (posE g) (posS b) | PrintE e => posE e | PrintT t => NONE | Return NONE => NONE | Return (SOME e) => posE e;
Parser and type checker • I have created a parser and type checker that you may use. group is ProgramTypes.sml Mini.lex Mini.grm Driver.sml TypeChecker.sml IR1.sml Phase1.sml $/basis.cm $/smlnj-lib.cm $/ml-yacc-lib.cm A program template for you to fill in.
Distribution • I will distribute the code for the parser and typechecker if you want it. • You do not need it to do the project • But it may help in the testing phase. • I will not post it to the class web page. • I will zip it up and email it to you • On the condition that you do not distribute it • That you do not make changes to it • You must program to it verbatim so my drivers will be able to automatically test your project. • That you swear not to give it out to anyone else. • I have it on a key drive tonight if you want it.
The first intermediate language • The first IR is called IR1 • It is some where between the ProgramTypes and the IR from the last few lectures. • Important ideas • It abstracts away from variables (turns them into integers which are offsets) • It allows statements to be included in expressions (this makes it possible to emit code with out using side effects, i.e. using emit). • It introduces temporaries (an infinite set of registers)
IR #1 datatype EXP = BINOP of ProgramTypes.BINOP * EXP * EXP | RELOP of ProgramTypes.RELOP * EXP * EXP | CALL of EXP * EXP list | MEM of EXP | NAME of string (* method names *) | TEMP of int (* registers *) | PARAM of int (* method parameters *) | MEMBER of EXP * int (* instance variables *) | VAR of int (* local vars of methods *) | CONST of string | STRING of string | ESEQ of STMT list * EXP
IR #1 continued and STMT = MOVE of EXP * EXP | JUMP of LABEL | CJUMP of ProgramTypes.RELOP * EXP * EXP * LABEL | LABEL of LABEL | CALLST of EXP * EXP list | RETURN of EXP | STMTlist of STMT list; datatype FUNC = FUNC of string * ProgramTypes.Type list * ProgramTypes.Type list * STMT list type TEMP = int type LABEL = int
Translating Variables • Variables occur in 4 places • Method names • Method parameters • Method local variables • Instance variables • These come in two forms • X which is shorthand for this.x • Exp.x class teste24 { int age; public int f(int i) { int height; return (height + i + age + this.f(i) ) } }
Tracking variables datatype Vkind = Vparam of int | Vlocal of int | Vmember of int • An environment maps strings to Vkind type env = (string * Vkind) list E.g. val env0 = [("x",Vlocal 1) ,("y",Vlocal 2) ,("z",Vparam 1)]
Translating variables fun pass1Var env s = case List.find (fn (x,t) => x=s) env of NONE => bad ("Variable: "^s^" not found.") | SOME(_,Vparam n) => (MEM(PARAM n)) | SOME(_,Vlocal n) => (MEM(VAR n)) | SOME(_,Vmember n) => (MEMBER(MEM(PARAM 0),n))
Translating Member lookup fun pass1Member env object s = case List.find (fn (x,t) => x=s) env of NONE => bad ("Variable: "^s^" not found.") | SOME(_,Vparam n) => bad ("Variable: "^s^" is a parameter, not a member.") | SOME(_,Vlocal n) => bad ("Variable: "^s^" is a local, not a member.") | SOME(_,Vmember n) => (MEMBER(object,n))
Simple constants val TRUE = CONST "1“ val FALSE = CONST "0“ fun not x = CALL(NAME("Bool_not"),[x])
The phase 1 template file • I will post the phase one template file. • It will have several missing and unfinished functions. • You should read Jenke Li’s • IR code Generation (Part I) • IR code Generation (Part II) • Both are posted on the class web site, under todays notes and under project #1. • The goal is to translate a (ProgramTypes.Program) into a (IR1.Func list)
Class Declarations • Each class declaration is translated into a (Func list) • A program is the appending of all the lists. • The order shouldn’t matter.
Methods • Each method is translated into a Func • To translate you need to • Create a proper name. Classname_methodname • You may need to track the current class so the classname is available • Translate the method’s variable declarations into a (possibly empty) STMT list • Translate the methods body into a STMT list • Merge the two STMT list. Put the variable one first. • As you do this you will need to prepare the correct environment that tracks the Vkind of variables. • Return a FUNC object. Be sure and get the (ProgramTypes.Type list) right in the Func node as these will needed in the second phase.
Statements • Assignments • Translate into MOVE • Method Calls • Translated into CALLST • Note obj.f(x1,x2) -> CALLST(f’, [obj, x1,x2]) • See the template file • Note that the Class name placed in ProgramTypes.Call is needed to get the correct name for f’ • If and While • Translate to a list of STMT with CJUMP nodes • Print Statements • Translate into a CALLST node with name “prInt” or “prString”
Expressions • Variables • Method names are translated into NAME • Instance variables into MEMBER • Local variables into VAR • Parameters into PARAM • See the template file • Arithmetic into BINOP and RELOP • RELOP into a short circuit evaluation • See the template file • New Array – Allocate space and initialize elements • A CALL node to “malloc” space (1 extra cell for length field) • A statement to save the length into the correct field • A loop to initialize elements • Use an ESEQ to glue it all together
Expressions continued • Array elements – Translate into MEM node where the expression inside the MEM node is address calculation. xA[i] MEM( addressA + (I – lowbound + 1) * element size) Array length – Translate into a MEM node (first element of the array) NewObject – translate into a Malloc with a synthetic argument (NAME classname_object_size) Member – into a MEMBER node This – into (PARAM 0) Text in print – translate into a STRING node
Structure of the Template structure Phase1 = struct open IR1; open ProgramTypes; fun pass1E env exp = . . . fun pass1S env stmt = . . . fun pass1M env methoddecl = . . . fun pass1C env classdecl = . . . fun pass1P env program = . . . end;
Translating Expressions fun pass1E env exp = case exp of Var(pos,s) => pass1Var env s | Literal(pos,Cint n) => CONST n | This pos => MEM(PARAM 0) | Call(object,mName,SOME cName,arglist) => let val objT = pass1E env object val argsT = map (pass1E env) arglist in CALL(NAME(cName^"_"^mName),objT::argsT) end
fun pass1E env exp = case exp of . . . | Binop((AND | OR), x, y) => let val start = newLabel() val thenL = newLabel() val elseL = newLabel() val doneL = newLabel() val result = newTemp() val stmtT = short env exp start thenL elseL in ESEQ(stmtT @ [LABEL thenL ,MOVE(result,TRUE) ,JUMP doneL ,LABEL elseL ,MOVE(result,FALSE) ,LABEL doneL],result) end | . . . The strategy of an ESEQ is to generate some statement that will set up some temporaries, which are used in the expression part of the ESEQ
Translating Statements fun pass1S env stmt = case stmt of Block ss => List.concat(map (pass1S env) ss) | If(test,tstmt,estmt) => let val thenL = newLabel() val elseL = newLabel() val startL = newLabel() in (short env test startL thenL elseL) @ (label env thenL tstmt) @ (label env elseL estmt) end | . . .
Short Circuit Evaluation and short env (Relop(m,x,y)) start trueL falseL = let val xT = pass1E env x val yT = pass1E env y in [ LABEL start , CJUMP(m,xT,yT,trueL) , JUMP falseL] end | short env (Binop(AND,r1,r2)) start trueL falseL = let val start2 = newLabel() in short env r1 start start2 falseL @ short env r2 start2 trueL falseL end | short env (Binop(OR,r1,r2)) start trueL falseL = let val start2 = newLabel() in short env r1 start trueL start2 @ short env r2 start2 trueL falseL end | short env (Not x) start trueL falseL = short env x start falseL trueL | short env x start trueL falseL = let val xT = pass1E env x in [ LABEL start , CJUMP(EQ,xT,TRUE,trueL) , JUMP falseL] end
What to hand in • You should download • ProgramTypes.sml • IR1.sml • Phase1.sml • You may also obtain for testing purposes • Mini.lex • Mini.grm • Driver.sml • TypeChecker.sml • You should email me a copy of “Phase1.sml” • Put your name on it in a comment • Mail it as an attachment. Use your name as the file name, I’ll rename it as Phase1.sml • I will run it in my test harness • It should have a function pass1P:: env -> ProgramTypes.Program -> IR1.Func list