(* translate.sml * * COPYRIGHT (c) 2010 The Diderot Project (http://diderot.cs.uchicago.edu) * All rights reserved. * * Translate Simple-AST code into the IL representation. *) structure Translate : sig val translate : Simple.program -> HighIL.program end = struct structure S = Simple structure VMap = Var.Map structure VSet = Var.Set structure IL = HighIL fun lookup env x = (case VMap.find (env, x) of SOME x' => x' | NONE => raise Fail(concat[ "no binding for ", Var.uniqueNameOf x, " in environment" ]) (* end case *)) (* create a new instance of a variable *) fun newVar x = IL.Var.new (Var.nameOf x) (* expression translation *) fun cvtExp (env, lhs, exp) = (case exp of S.E_Var x => [(lhs, IL.VAR(lookup env x))] | S.E_Lit lit => [(lhs, IL.LIT lit)] | S.E_Tuple xs => raise Fail "E_Tuple not implemeted" | S.E_Apply(f, tyArgs, args, ty) => let val args' = List.map (lookup env) args in TranslateBasis.translate (lhs, f, tyArgs, args') end | S.E_Cons args => [(lhs, IL.CONS(List.map (lookup env) args))] | S.E_Input(_, name, NONE) => [(lhs, IL.OP(HighOps.Input name, []))] | S.E_Input(_, name, SOME dflt) => [(lhs, IL.OP(HighOps.InputWithDefault name, [lookup env dflt]))] | S.E_Field fld => [(lhs, IL.OP(HighOps.Field fld, []))] | S.E_LoadImage info => [(lhs, IL.OP(HighOps.LoadImage info, []))] (* end case *)) (* convert a Simple AST block to an IL statement. We return the statement that represents the * block, plus the environment mapping Simple AST variables to their current SSA representations * and the set of Simple AST variables that were assigned to in the block. *) fun cvtBlock (env, S.Block stms) = let fun toBlock (env, assigned, [], assignments) = (IL.mkBLOCK{succ=IL.dummy, body=List.rev assignments}, env, assigned) | toBlock (env, assigned, S.S_Assign(x, e)::rest, assignments) = let val x' = newVar x val stms = cvtExp(env, x', e) val assigned = VSet.add(assigned, x) val env = VMap.insert(env, x, x') in toBlock (env, assigned, rest, stms@assignments) end | toBlock (env, assigned, stms, assignments) = let val (succ, env, assigned) = toStmt (env, assigned, stms) val blk = IL.mkBLOCK{succ=succ, body=List.rev assignments} in IL.addPred (succ, blk); (blk, env, assigned) end and toStmt (env, assigned, []) = (IL.mkBLOCK{succ=IL.dummy, body=[]}, env, assigned) | toStmt (env, assigned, stms as stm::rest) = (case stm of S.S_Assign _ => toBlock (env, assigned, stms, []) | S.S_IfThenElse(x, b1, b2) => let val x' = lookup env x val (s1, env1, assigned1) = cvtBlock(env, b1) val (s2, env2, assigned2) = cvtBlock(env, b2) val assigned = VSet.union(assigned1, assigned2) (* PROBLEM: what about variables that are assigned for the first time in one branch * and not the other? This situation should only occur for variables who's scope is * the branch of the if. Short-term solution is to ignore variables that are defined * in only one branch. *) val (env, phis) = let fun mkPhi (x, (env, phis)) = ( case (VMap.find(env1, x), VMap.find(env2, x)) of (SOME x1, SOME x2) => let val x' = newVar x in (VMap.insert(env, x, x'), (x', [x1, x2])::phis) end | _ => (env, phis) (* end case *)) in VSet.foldl mkPhi (env, []) assigned end val stm = IL.mkIF{cond=x', thenBranch=s1, elseBranch=s2} in case rest of [] => (stm, env, assigned) | _ => let val (join, env, assigned) = toStmt (env, assigned, rest) in IL.addPred (join, stm); IL.setSucc (stm, join); (stm, env, assigned) end (* end case *) end | S.S_New(name, xs) => let val xs' = List.map (lookup env) xs in case rest of [] => (IL.mkNEW{actor=name, args=xs', succ=IL.dummy}, env, assigned) | _ => let val (succ, env, assigned) = toStmt (env, assigned, rest) val stm = IL.mkNEW{actor=name, args=xs', succ=succ} in IL.addPred (succ, stm); (stm, env, assigned) end end | S.S_Die => (IL.mkDIE(), env, assigned) | S.S_Stabilize => (IL.mkSTABILIZE(), env, assigned) (* end case *)) in toStmt (env, VSet.empty, stms) end fun translate (S.Program{globals, globalInit, actors}) = let val (globalInit, env, _) = cvtBlock (VMap.empty, globalInit) (* get the SSA names for the globals and a reduced environment *) val (env, globs) = let val lookup = lookup env fun cvtVar (x, (env, globs)) = let val x' = lookup x in (VMap.insert(env, x, x'), x'::globs) end val (env, globs) = List.foldl cvtVar (VMap.empty, []) globals in (env, List.rev globs) end fun cvtActor (S.Actor{name, params, state, stateInit, methods}) = let val (env, params) = let fun cvtParam (x, (env, xs)) = let val x' = newVar x in (VMap.insert(env, x, x'), x'::xs) end val (env, params) = List.foldl cvtParam (env, []) params in (env, List.rev params) end val (stateInit, env, _) = cvtBlock (env, stateInit) val state = List.map (lookup env) state fun cvtMethod (S.Method(name, blk)) = let val (body, _, _) = cvtBlock (env, blk) in IL.Method(name, body) end in IL.Actor{ name = name, params = params, state = state, stateInit = stateInit, methods = List.map cvtMethod methods } end in IL.Program{ globals = globs, globalInit = globalInit, actors = List.map cvtActor actors } end end
Click to toggle
does not end with </html> tag
does not end with </body> tag
The output has ended thus: obals = globs, globalInit = globalInit, actors = List.map cvtActor actors } end end