(* tr_env.ml: handling of the translation environment. *) open List Fnlib Mixture Const Prim Lambda Globals Units Types Asynt Asyntfn; type RenEnv = (string * int) list; datatype AccessPath = Path_rec of int | Path_local of int | Path_global of (QualifiedIdent * int) | Path_son of int * AccessPath | Path_virtual_son of int * AccessPath ; type TranslEnv = (Const.Id, AccessPath) Env * int; fun lookupRenEnv asId q = let val {qual, id = lid} = q val id = (longIdentAsIdent lid "lookupRenEnv") val mangled_id = mangle (asId id) in (* cvr: TODO treat lond ids *) if qual = "" then fatalError ("lookupRenEnv: empty qualifier for "^id) else (); if qual = currentUnitName() then (mkUniqueGlobalName (mangled_id, Hasht.find (!currentRenEnv) (mangled_id)) handle Subscript => fatalError ("lookupRenEnv: unknown variable: " ^ showQualId q)) else ({qual=qual,id = [mangled_id]}, 0) end ; fun updateCurrentRenEnv RE = app (fn (x,y) => Hasht.insert (!currentRenEnv) x y) (rev RE) ; fun renameId id = (id, newValStamp()); (* Generating lambda expressions from access pahts *) local (* cvr: TODO copied from Front.sml ---- code should be shared *) fun mkDynexn exnname = Lprim(Pmakeblock (CONtag(0,1)), [exnname, Lconst constUnit]) val bindExn = mkDynexn (Lprim(Pget_global ({qual="General", id=["exn_bind"]}, 0), [])); val bindRaiser = Lprim(Praise, [bindExn]) in fun translatePath depth = fn Path_rec i => Llet([Lprim(Pfield 0,[Lvar (depth-(i+1))])], Lswitch(2,Lvar 0, [(CONtag(0,2),bindRaiser), (CONtag(1,2),Lprim(Pfield 0,[Lvar 0]))])) | Path_local i => Lvar (depth-(i+1)) | Path_global uid => Lprim(Pget_global uid, []) | Path_virtual_son(arity, p) => translatePath depth p | Path_son(n, p) => Lprim(Pfield n, [translatePath depth p]) end fun translateTopOfPath depth = fn Path_virtual_son(arity, Path_local i) => let val lvar = Lvar (depth-(i+1)) in Lprim(Pmakeblock(CONtag(0,1)), tabulate(arity, (fn n => Lprim(Pfield n, [lvar])))) end | Path_virtual_son(arity, p) => Llet([translatePath depth p], Lprim(Pmakeblock(CONtag(0,1)), tabulate(arity, (fn n => Lprim(Pfield n, [Lvar 0]))))) | p => translatePath depth p ; fun translateLocalAccess asId (rho, depth) id = translateTopOfPath depth (lookupEnv rho (asId id)) handle Subscript => fatalError ("translateLocalAccess"^id) ; fun lookupInLocalEnv asId env q = let val {qual,id} = q in (* cvr: TODO handle long ids *) if qual = "" orelse qual = currentUnitName() then lookupEnv env (asId (longIdentAsIdent id "lookupInLocalEnv")) else raise Subscript end ; fun translateAccess asId (rho, depth) q = translateTopOfPath depth (lookupInLocalEnv asId rho q) handle Subscript => Lprim(Pget_global (lookupRenEnv asId q), []) ; (* cvr: added *) fun translateLongAccess asId env (ii:IdInfo) = let val {info={idKind,idFields,...}, ...} = ii val {qualid, ...} = !idKind in case qualid of {qual,id=[]} => Lstruct [] | {qual,id=[_]} => translateAccess asId env qualid | {qual,id} => let fun trLongAccess [id] _ = translateAccess ModId env {qual = qual,id = [id]} | trLongAccess (id::ids) (field::fields) = Lprim(Pfield field, [trLongAccess ids fields]) | trLongAccess _ _ = fatalError "trLongAccess" in trLongAccess id (!idFields) end end; fun translateExName env (ii : IdInfo) = let val {qualid, info} = ii in case #info(!(#idKind info)) of EXCONik _ => translateLongAccess ValId env ii | _ => fatalError "translateExName" end; fun pair x y = (x, y); fun pathsOfPatAcc path ((loc, pat') : Pat) acc = case pat' of SCONpat _ => acc | VARpat ii => bindInEnv acc (ValId (hd(#id(#qualid ii)))) path | WILDCARDpat => acc | NILpat _ => acc | CONSpat(ii, p) => let val ci = getConInfo ii in if #conSpan(!ci) = 1 then pathsOfPatAcc path p acc else if #conIsGreedy(!ci) then (if #conTag(!ci) = 0 then pathsOfPatAcc path p acc else pathsOfPatAcc (Path_virtual_son(#conArity(!ci), path)) p acc) else pathsOfPatAcc (Path_son(0, path)) p acc end | EXNILpat _ => acc | EXCONSpat(ii, p) => pathsOfPatAcc (Path_son(1, path)) p acc | EXNAMEpat _ => fatalError "pathsOfPatAcc" | REFpat p => pathsOfPatAcc (Path_son(0, path)) p acc | RECpat(ref (TUPLErp ps)) => foldR (fn(i,p) => fn acc => pathsOfPatAcc (Path_son(i,path)) p acc) acc (mapFrom pair 0 ps) | RECpat(ref (RECrp _)) => fatalError "pathsOfPatAcc: unresolved record pattern" | VECpat ps => foldR (fn(i,p) => fn acc => pathsOfPatAcc (Path_son(i,path)) p acc) acc (mapFrom pair 0 ps) | INFIXpat _ => fatalError "pathsOfPatAcc" | PARpat p => pathsOfPatAcc path p acc | TYPEDpat(p, _) => pathsOfPatAcc path p acc | LAYEREDpat(p1, p2) => pathsOfPatAcc path p1 (pathsOfPatAcc path p2 acc) ; fun pathsOfPat path pat = pathsOfPatAcc path pat NILenv; fun mutableVarsOfPatAcc ((loc, pat') : Pat) acc = case pat' of SCONpat _ => acc | VARpat _ => acc | WILDCARDpat => acc | NILpat _ => acc | CONSpat(_, p) => mutableVarsOfPatAcc p acc | EXNILpat _ => acc | EXCONSpat(ii, p) => mutableVarsOfPatAcc p acc | EXNAMEpat _ => fatalError "mutableVarsOfPatAcc" | REFpat p => domPatAcc p acc | RECpat(ref (TUPLErp ps)) => foldR mutableVarsOfPatAcc acc ps | RECpat(ref (RECrp _)) => fatalError "mutableVarsOfPatAcc: unresolved record pattern" | VECpat ps => foldR mutableVarsOfPatAcc acc ps | INFIXpat _ => fatalError "mutableVarsOfPatAcc" | PARpat p => mutableVarsOfPatAcc p acc | TYPEDpat(p, _) => mutableVarsOfPatAcc p acc | LAYEREDpat(p1, p2) => mutableVarsOfPatAcc p1 (mutableVarsOfPatAcc p2 acc) ; (* Since the program is supposed to be well-typed, *) (* the patterns in a `val rec' can't contain mutable variables. *) (* Thus there's no danger in accessing variable values via *) (* their access paths... *) fun mkEnvOfRecPats depth pats = foldL (fn pat => fn (rho, depth) => (pathsOfPatAcc (Path_local depth) pat rho, depth+1)) (NILenv, depth) pats ; (* If a `val' declaration isn't recursive, the mutable variables *) (* appearing in its patterns must be taken special care of... *) fun mutableVarsOfPat pat = mutableVarsOfPatAcc pat []; fun addLetsToEnv varlist (env as (rho, depth)) = case varlist of [] => env | var::rest => addLetsToEnv rest (bindInEnv rho (ValId var) (Path_local depth), depth+1) ; fun addLetsToExp varlist (rho, depth) exp = case varlist of [] => exp | _ => Llet(mapFrom (fn i => fn var => translateLocalAccess ValId (rho, i) var) depth varlist, exp) ; fun mkEnvOfPats depth pats = let val env' = mkEnvOfRecPats depth pats val mut_vars = foldR mutableVarsOfPatAcc [] pats in (addLetsToEnv mut_vars env', addLetsToExp mut_vars env') end ;