Presentation is loading. Please wait.

Presentation is loading. Please wait.

Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

Similar presentations


Presentation on theme: "Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together."— Presentation transcript:

1 Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together.

2 Symbols and symbol tables Given code implements structure Symbol. Symbol.symbol : string -> Symbol.symbol Symbol.name : Symbol.symbol -> string empty :'a table enter :'a table * symbol * 'a -> 'a table look :'a table * symbol -> 'a option

3 Symbols and symbol tables (2) When to convert a string to a symbol? What to put in the symbol table? Depends on the use of the symbol table. For type checking one could associate: Type of the symbol. Nesting level with each symbol.

4 Semantic Analysis The goal of the semantic analysis is to determine whether a program is semantically correct. That is, find errors that has to do with the meaning of the program (as opposed to the syntax of the program). For example, check that the program is correctly typed, e.g. don’t let the programmer write: True + 42;

5 Semantic Analysis in Bar (1) What to detect. –Undefined symbols –Multiply defined symbols –Type errors –etc... (see definition and example files.) How to detect it. –By recursion over the Absyn structure.

6 Semantic Analysis in Bar (2) Example: MINI-Float Goal: To detect undefined variables. Absyn: datatype expr = FloatE of real | IdE of Symbol.symbol * pos | AddE of expr * expr * pos datatype stmnt = AssS of Symbol.symbol * expr * pos | PrintS of expr * pos datatype prog = BarProg of stmnt list

7 structure Env = struct structure S = Symbol type environment = {ok:bool, table: bool S.table} val empty = {ok=true, table=S.empty} fun enter({ok,table}, id) = {ok=ok, table = S.enter(table,id,true)} fun set_ok({table,ok}:environment,newok) = {ok=ok andalso newok, table=table} fun isok({ok,...}:environment) = ok fun isDefined(id, {ok,table}) = case S.look(table, id) of SOME _ => true | NONE => false end Environment for semantic analysis of MINI-Float

8 fun msg_undef (id, pos) = (ErrorMsg.error pos ("Variable " ^ S.name(id) ^ " not defined."); false) fun expr(A.FloatE(f), env) = true | expr(A.IdE(id, pos), env) = Env.isDefined(id, env) orelse (msg_undef (id,pos)) | expr(A.AddE(e1, e2, pos), env) = expr(e1, env) andalso expr(e2, env) fun stmnt(A.AssS(id, e, pos), env) = Env.set_ok(Env.enter(env, id), expr(e, env)) | stmnt(A.PrintS(e, pos), env) = Env.set_ok(env, expr(e, env)) fun program(A.BarProg(statements)) = Env.isok(foldl stmnt Env.empty statements) Semantic analysis of MINI-Float

9 Notes on semantic analysis of Bar The analysis of Bar will be much more complex. The type of expressions needs to be returned. Nested scopes needs to be handled. Return types of functions need to be handled. One-pass is OK, two-pass is optional.

10 Translation to intermediate code Turn the abstract synatax tree into a tree representing the instructions to be executed by the program. Also solved by recursion over the Absyn structure.

11 Given code: IR-Tree: The tree structure you are to translate to. Frames: A signature for the frame structure is given. (To implement the frame structure you will have to read up about calling conventions in the SPIM manual.) Backend: Names of runtime functions (such as PRINTBOOL) are given.

12 datatype etype = INT | FLOAT (* Expresion types *) datatype cond = LT | LE | EQ | NE | GE | GT datatype unop = ILOAD (* load integer ( *expr ) *) | FLOAD (* load float *) | IMOVE of temp (* reg := expr *) | FMOVE of ftemp (* freg := expr *) | ITOF of ftemp (* freg := integer-expr *) datatype binop = IADD | ISUB | IMUL | IDIV (* int * int -> int *) | FADD | FSUB | FMUL | FDIV (* float * float -> float *) | AND | OR (* int * int -> int *) | ICMP of cond (* int * int -> int *) | FCMP of cond (* float * float -> int *) | ISTORE (* MEM[exp1] := exp2 *) | FSTORE (* MEM[exp1] := exp2 *) | RNGCHK (* if (0 <= exp1 < exp2) then exp1 else error *) datatype exp = TEMP of temp (* Temporary value in reg *) | FTEMP of ftemp (* Temporary value in reg *) | ICON of int (* Integer constant *) | UNARY of unop * exp | BINARY of binop * exp * exp | LABREF of label | CALL of etype * label * ((etype * exp) list) IR Tree (1)

13 datatype insn = LABDEF of label (* Label *) | JUMP of label (* GOTO *) | CJUMP of exp * label (* Conditional branch e=1 *) | IGNORE of etype * exp (* Expression used for side-effects only *) datatype dec = PROC of (* Function and procs *) {label: label, localsSize: int, insns: insn list} | DATA of (* Uninitialised data *) {label: label, size: int} | FCONST of (* Initialised fp-data *) {label: label, float: real} datatype program = PROGRAM of dec list IR Tree (2)

14 structure Env = struct type bindings = I.label type environment = {env: bindings S.table, globals: I.dec list} val empty = {env = S.empty, globals=[]}:environment fun enter_gvar({env, globals}, name, loc) = {env = S.enter(env, name, loc), globals= (I.DATA{label = loc, size = 2})::globals}:environment fun enter_float({env, globals}, f, lab) = {env = env, globals = (I.FCONST{label = lab, float = f}) ::globals}:environment fun var({env,...}:environment, id) = case S.look(env, id) of SOME loc => loc | _ => ErrorMsg.impossible("Trying to ref a nonvar.") fun globals({globals,...}:environment) = globals end Environment for translation to IR of MINI-Float

15 fun expr2icode(A.FloatE(f), env) = let val name = R.new_label() in (Env.enter_float(env,f,name), I.UNARY(I.FLOAD, I.LABREF name)) end | expr2icode(A.IdE(id,pos),env) = (env,I.UNARY(I.FLOAD, I.LABREF(Env.var(env,id)))) | expr2icode(A.AddE(e1,e2,pos),env) = let val (env1,icode1) = expr2icode(e1,env) val (env2,icode2) = expr2icode(e2,env1) in (env2, I.BINARY(I.FADD, icode1, icode2)) end Translation of expressions in MINI-Float

16 fun stmnt2icode(A.AssS(id, e, pos), env) = let val (env1, expricode) = expr2icode(e, env) val lab = R.varLabel id val newenv = Env.enter_gvar(env1, id, lab) in (newenv, I.IGNORE(I.FLOAT, I.BINARY(I.FSTORE, I.LABREF lab, expricode))) end | stmnt2icode(A.PrintS(e, pos),env) = let val (env1,expricode) = expr2icode(e, env) in (env1, I.IGNORE(I.INT, I.CALL(I.INT, R.labPrintFloat, [(I.FLOAT,expricode)]))) end and stmnts2icode(s::statements, env) = let val (newenv,icode) = stmnt2icode(s,env) val (finalenv,moreicode) = stmnts2icode(statements,newenv) in (finalenv, icode::moreicode) end | stmnts2icode([],env) = (env,[]) Translation of statements in MINI-Float

17 fun syn2icode(A.BarProg(stmnts)) = let val (env, insns) = stmnts2icode(stmnts, Env.empty) in I.PROGRAM(I.PROC{label=R.labMain, localsSize=0, insns=insns}::Env.globals(env)) end Translation of programs in MINI-Float

18 Translation to intermediate code The Bar language will be much more complicated. Function calls has to be handled. Locations of parameters, local-, static- and globalvaraibles has to be handled. Conversions between int and floats has to be handled.

19 The frame siganture (1) val wordSize : int (* Locations for formals, locals, and the return value.*) type temp = int type ftemp = int datatype vtype = INT | FLOAT datatype location = TEMP of temp | FTEMP of ftemp | OFF of temp * int val RV : location val FRV : location

20 The frame siganture (2) (* Locations of formal parameters. *) type formals val initFormals : unit -> formals val nextFormal : formals * vtype -> formals * location val formalsStackNeed : formals -> int (* Locations of local variables. *) type locals val initLocals : unit -> locals val nextScalar : locals * vtype -> locals * location val nextArray : locals * vtype * int -> locals * location

21 Runtime support fun procLabel id = Symbol.symbol("P_" ^ (Symbol.name id)) fun varLabel id = Symbol.symbol("V_" ^ (Symbol.name id)) val labMain = Symbol.symbol "main" val labPrintInt = Symbol.symbol "PRINTINT" val labPrintBool = Symbol.symbol "PRINTBOOL" val labPrintFloat = Symbol.symbol "PRINTFLOAT" val labTrunc = Symbol.symbol "TRUNC" val labRead = Symbol.symbol "READINT" val labReadBool = Symbol.symbol "READBOOL" val labReadFloat = Symbol.symbol "READFLOAT" val labRangeError = Symbol.symbol "RANGEERROR" local val labnr = ref 0 in fun new_label () = (labnr := !labnr + 1; Symbol.symbol("Label_" ^ (Int.toString (!labnr)))) end


Download ppt "Lesson 3 Two topics 1. Semantic Analysis 2. Translation to intermediate code Presented as separated topics but can be implemented together."

Similar presentations


Ads by Google