home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Moscow ML 1.31 / source code / mosml / src / compiler / Front.sml < prev    next >
Encoding:
Text File  |  1996-07-03  |  27.6 KB  |  787 lines  |  [TEXT/R*ch]

  1. (* front.ml : translation abstract syntax -> extended lambda-calculus. *)
  2.  
  3. open Misc List Obj Fnlib Config Mixture Const Smlexc Prim Lambda Smlprim;
  4. open Globals Location Units Types Asynt Asyntfn Tr_env Match;
  5.  
  6. datatype SMLPrimImpl =
  7.     GVprim of QualifiedIdent
  8.   | VMprim of int * primitive
  9.   | VMPprim of int * primitive
  10.   | GVTprim of QualifiedIdent * obj
  11. ;
  12.  
  13. val getPrimImpl = fn
  14.     MLPeq =>         VMPprim(1, Pccall("sml_equal", 2))
  15.   | MLPnoteq =>      VMPprim(1, Pccall("sml_not_equal", 2))
  16.   | MLPeq_c =>       VMprim (2, Pccall("sml_equal", 2))
  17.   | MLPnoteq_c =>    VMprim (2, Pccall("sml_not_equal", 2))
  18.   | MLPref =>        VMprim (1, Pmakeblock (CONtag(refTag, 1)))
  19.   | MLPsetref =>     VMPprim(1, Psetfield 0)
  20.   | MLPsetref_c  =>  VMprim (2, Psetfield 0)
  21.   | MLPadd_int   =>  VMPprim(1, Psmladdint)
  22.   | MLPsub_int   =>  VMPprim(1, Psmlsubint)
  23.   | MLPmul_int   =>  VMPprim(1, Psmlmulint)
  24.   | MLPdiv_int   =>  VMPprim(1, Psmldivint)
  25.   | MLPmod_int   =>  VMPprim(1, Psmlmodint)
  26.   | MLPquot_int  =>  VMPprim(1, Psmlquotint)
  27.   | MLPrem_int   =>  VMPprim(1, Psmlremint)
  28.   | MLPlt_int    =>  VMPprim(1, Ptest(Pint_test PTlt))
  29.   | MLPgt_int    =>  VMPprim(1, Ptest(Pint_test PTgt))
  30.   | MLPle_int    =>  VMPprim(1, Ptest(Pint_test PTle))
  31.   | MLPge_int    =>  VMPprim(1, Ptest(Pint_test PTge))
  32.   | MLPadd_int_c =>  VMprim (2, Psmladdint)
  33.   | MLPsub_int_c =>  VMprim (2, Psmlsubint)
  34.   | MLPmul_int_c =>  VMprim (2, Psmlmulint)
  35.   | MLPdiv_int_c =>  VMprim (2, Psmldivint)
  36.   | MLPmod_int_c =>  VMprim (2, Psmlmodint)
  37.   | MLPquot_int_c => VMprim (2, Psmlquotint)
  38.   | MLPrem_int_c =>  VMprim (2, Psmlremint)
  39.   | MLPlt_int_c =>   VMprim (2, Ptest(Pint_test PTlt))
  40.   | MLPgt_int_c =>   VMprim (2, Ptest(Pint_test PTgt))
  41.   | MLPle_int_c =>   VMprim (2, Ptest(Pint_test PTle))
  42.   | MLPge_int_c =>   VMprim (2, Ptest(Pint_test PTge))
  43.   | MLPadd_real =>   VMPprim(1, Pfloatprim Psmladdfloat)
  44.   | MLPsub_real =>   VMPprim(1, Pfloatprim Psmlsubfloat)
  45.   | MLPmul_real =>   VMPprim(1, Pfloatprim Psmlmulfloat)
  46.   | MLPdiv_real =>   VMPprim(1, Pfloatprim Psmldivfloat)
  47.   | MLPlt_real =>    VMPprim(1, Ptest(Pfloat_test PTlt))
  48.   | MLPgt_real =>    VMPprim(1, Ptest(Pfloat_test PTgt))
  49.   | MLPle_real =>    VMPprim(1, Ptest(Pfloat_test PTle))
  50.   | MLPge_real =>    VMPprim(1, Ptest(Pfloat_test PTge))
  51.   | MLPadd_real_c => VMprim (2, Pfloatprim Psmladdfloat)
  52.   | MLPsub_real_c => VMprim (2, Pfloatprim Psmlsubfloat)
  53.   | MLPmul_real_c => VMprim (2, Pfloatprim Psmlmulfloat)
  54.   | MLPdiv_real_c => VMprim (2, Pfloatprim Psmldivfloat)
  55.   | MLPlt_real_c =>  VMprim (2, Ptest(Pfloat_test PTlt))
  56.   | MLPgt_real_c =>  VMprim (2, Ptest(Pfloat_test PTgt))
  57.   | MLPle_real_c =>  VMprim (2, Ptest(Pfloat_test PTle))
  58.   | MLPge_real_c =>  VMprim (2, Ptest(Pfloat_test PTge))
  59.   | MLPlt_string =>  VMPprim(1, Ptest(Pstring_test PTlt))
  60.   | MLPgt_string =>  VMPprim(1, Ptest(Pstring_test PTgt))
  61.   | MLPle_string =>  VMPprim(1, Ptest(Pstring_test PTle))
  62.   | MLPge_string =>  VMPprim(1, Ptest(Pstring_test PTge))
  63.   | MLPconcat =>     VMPprim(1, Pccall("sml_concat", 2))
  64.   | MLPlt_string_c =>   VMprim (2, Ptest(Pstring_test PTlt))
  65.   | MLPgt_string_c =>   VMprim (2, Ptest(Pstring_test PTgt))
  66.   | MLPle_string_c =>   VMprim (2, Ptest(Pstring_test PTle))
  67.   | MLPge_string_c =>   VMprim (2, Ptest(Pstring_test PTge))
  68.   | MLPconcat_c =>   VMprim(2, Pccall("sml_concat", 2))
  69.   | MLPprim(arity, prim)  => VMprim(arity, prim)
  70.   | MLPccall(arity, name) => VMprim(arity, Pccall(name, arity))
  71.   | MLPgv qualid         => GVprim qualid
  72.   | MLPgvt(qualid, ref sc) =>   GVTprim(qualid, sc)
  73. ;
  74.  
  75. val curriedPrimVersion = fn
  76.     MLPeq       =>    SOME MLPeq_c
  77.   | MLPnoteq    =>    SOME MLPnoteq_c
  78.   | MLPsetref   =>    SOME MLPsetref_c
  79.   | MLPadd_int  =>    SOME MLPadd_int_c
  80.   | MLPsub_int  =>    SOME MLPsub_int_c
  81.   | MLPmul_int  =>    SOME MLPmul_int_c
  82.   | MLPdiv_int  =>    SOME MLPdiv_int_c
  83.   | MLPmod_int  =>    SOME MLPmod_int_c
  84.   | MLPquot_int =>    SOME MLPquot_int_c
  85.   | MLPrem_int  =>    SOME MLPrem_int_c
  86.   | MLPlt_int   =>    SOME MLPlt_int_c
  87.   | MLPgt_int   =>    SOME MLPgt_int_c
  88.   | MLPle_int   =>    SOME MLPle_int_c
  89.   | MLPge_int   =>    SOME MLPge_int_c
  90.   | MLPadd_real =>    SOME MLPadd_real_c
  91.   | MLPsub_real =>    SOME MLPsub_real_c
  92.   | MLPmul_real =>    SOME MLPmul_real_c
  93.   | MLPdiv_real =>    SOME MLPdiv_real_c
  94.   | MLPlt_real  =>    SOME MLPlt_real_c
  95.   | MLPgt_real  =>    SOME MLPgt_real_c
  96.   | MLPle_real  =>    SOME MLPle_real_c
  97.   | MLPge_real  =>    SOME MLPge_real_c
  98.   | MLPlt_string =>   SOME MLPlt_string_c
  99.   | MLPgt_string =>   SOME MLPgt_string_c
  100.   | MLPle_string =>   SOME MLPle_string_c
  101.   | MLPge_string =>   SOME MLPge_string_c
  102.   | MLPconcat   =>    SOME MLPconcat_c
  103.   | _           =>    NONE
  104. ;
  105.  
  106. (* Translation of expressions *)
  107.  
  108. exception Not_constant;
  109.  
  110. fun extractConstant (Lconst cst) = cst
  111.   | extractConstant _ = raise Not_constant
  112. ;
  113.  
  114. val bindConst  = Lconst(BLOCKsc(EXNtag bindTagName,  []));
  115. val matchConst = Lconst(BLOCKsc(EXNtag matchTagName, []));
  116. val bindRaiser  = Lprim(Praise, [bindConst]);
  117. val matchRaiser = Lprim(Praise, [matchConst]);
  118.  
  119. fun partial_fun (loc as Loc(start,stop)) (tsb : ThreeValuedLogic) =
  120.   case tsb of
  121.     True =>
  122.       (msgIBlock 0;
  123.        errLocation loc;
  124.        errPrompt "Warning: pattern matching is not exhaustive";
  125.        msgEOL(); msgEOL();
  126.        msgEBlock();
  127.        matchRaiser)
  128.   | _ =>
  129.       matchRaiser
  130. ;
  131.  
  132. fun partial_let (onTop : bool) (loc as Loc(start,stop))
  133.                 (tsb : ThreeValuedLogic) =
  134.   case tsb of
  135.     True =>
  136.       (if not onTop then
  137.          (msgIBlock 0;
  138.           errLocation loc;
  139.           errPrompt "Warning: pattern matching is not exhaustive";
  140.           msgEOL(); msgEOL();
  141.           msgEBlock())
  142.        else ();
  143.        bindRaiser)
  144.   | _ =>
  145.       bindRaiser
  146. ;
  147.  
  148. fun partial_try (tsb : ThreeValuedLogic) =
  149.   Lprim(Praise, [Lvar 0])
  150. ;
  151.  
  152. val smlExnTag = EXNtag exnTagName;
  153.  
  154. fun extract_fields arity =
  155.   let fun loop i =
  156.     if i >= arity then []
  157.     else
  158.       Lprim(Pfield i, [Lvar 0]) :: loop (i+1)
  159.   in loop 0 end
  160. ;
  161.  
  162. fun normApp (func as (_, func')) args =
  163.   case func' of
  164.       PARexp e        => normApp e args
  165.     | TYPEDexp(e,_)   => normApp e args
  166.     | APPexp(e1,e2)   => normApp e1 (e2 :: args)
  167.     | _               => (func, args)
  168. ;
  169.  
  170. fun extractPairArg (_, exp') =
  171.   case exp' of
  172.       PARexp e                       => extractPairArg e
  173.     | TYPEDexp(e,_)                  => extractPairArg e
  174.     | RECexp(ref (TUPLEre [e1,e2]))  => SOME (e1, e2)
  175.     | _                              => NONE
  176. ;
  177.  
  178. fun canSplitFirstArg (Lvar n :: args) = true
  179.   | canSplitFirstArg (Lprim(Pget_global _, []) :: args) = true
  180.   | canSplitFirstArg _ = false
  181. ;
  182.  
  183. fun splitFirstArg (arg :: args) =
  184.       Lprim(Pfield 0, [arg]) :: Lprim(Pfield 1, [arg]) :: args
  185.   | splitFirstArg _ = fatalError "splitFirstArg"
  186. ;
  187.  
  188. (* An expression is "safe", if evaluating it can't produce *)
  189. (* side-effects, i.e. I/O, exceptions, etc. *)
  190. (* The following is a crude approximation... *)
  191.  
  192. fun isSafe (_, exp') =
  193.   case exp' of
  194.     SCONexp _ => true
  195.   | VARexp _ => true
  196.   | FNexp _ => true
  197.   | APPexp(e1,e2) => false
  198.   | RECexp(ref (RECre fs)) =>
  199.       all (fn (_, e) => isSafe e) fs
  200.   | RECexp(ref (TUPLEre es)) =>
  201.       all isSafe es
  202.   | VECexp es =>
  203.       all isSafe es
  204.   | PARexp e => isSafe e
  205.   | LETexp (dec,exp) => false
  206.   | INFIXexp es => fatalError "isSafe"
  207.   | TYPEDexp(e,ty) => isSafe e
  208.   | ANDALSOexp(e1,e2) =>
  209.       isSafe e1 andalso isSafe e2
  210.   | ORELSEexp(e1,e2) =>
  211.       isSafe e1 andalso isSafe e2
  212.   | HANDLEexp(e, mrules) => false
  213.   | RAISEexp e => false
  214.   | IFexp(e0,e1,e2) =>
  215.       isSafe e0 andalso isSafe e1 andalso isSafe e2
  216.   | WHILEexp(e1,e2) =>
  217.       isSafe e1 andalso isSafe e2
  218.   | SEQexp(e1,e2) =>
  219.       isSafe e1 andalso isSafe e2
  220. ;
  221.  
  222. (* All unsafe arguments must be lifted, except the rightmost one, *)
  223. (* in order to preserve the evaluation order. *)
  224.  
  225. datatype AppArgs =
  226.     SAFEarg of Exp
  227.   | CONSTarg of Lambda
  228.   | UNSAFEarg
  229. ;
  230.  
  231. fun trConVar (ci : ConInfo) =
  232.   let val {conArity, conIsGreedy, conTag, conSpan, ...} = !ci in
  233.     case (conIsGreedy, conArity, conSpan) of
  234.         (true,  _, _) =>
  235.           Lfn(Lprim(
  236.             Pmakeblock(CONtag(conTag,conSpan)), extract_fields conArity))
  237.       | (false, 0, _) =>
  238.           Lconst(BLOCKsc(CONtag(conTag,conSpan), []))
  239.       | (false, _, 1) =>
  240.           Lfn(Lvar 0)
  241.       | (false, _, _) =>
  242.           Lfn(Lprim(Pmakeblock(CONtag(conTag,conSpan)), [(Lvar 0)]))
  243.   end;
  244.  
  245. fun trStaticExConVar isGreedy arity tag =
  246.   case (isGreedy, arity) of
  247.       (true,  _) =>
  248.         Lfn(Lprim(Pmakeblock(EXNtag tag), extract_fields arity))
  249.     | (false, 0) =>
  250.         Lconst(BLOCKsc(EXNtag tag, []))
  251.     | (false, _) =>
  252.         Lfn(Lprim(Pmakeblock (EXNtag tag), [Lvar 0]))
  253. ;
  254.  
  255. fun trExConVar (env as (rho, depth)) q (ei : ExConInfo) =
  256.   let val {qual, id} = q
  257.       val {exconArity, exconIsGreedy, exconTag, ...} = !ei
  258.   in
  259.     case exconTag of
  260.         NONE =>
  261.           if exconArity = 0 then
  262.             let val en = translateLocalAccess env id
  263.             in Lprim(Pmakeblock smlExnTag, [en]) end
  264.           else
  265.             let val en = translateLocalAccess (rho, depth+1) id
  266.             in Lfn(Lprim(Pmakeblock smlExnTag, [en, Lvar 0])) end
  267.      | SOME tag =>
  268.          trStaticExConVar exconIsGreedy exconArity tag
  269.   end;
  270.  
  271. fun trTopExConVar (ei : ExConInfo) =
  272.   let val {exconArity, exconIsGreedy, exconTag, ...} = !ei in
  273.     case exconTag of
  274.         NONE => fatalError "trTopExConVar"
  275.       | SOME tag =>
  276.          trStaticExConVar exconIsGreedy exconArity tag
  277.   end;
  278.  
  279. fun trPrimVar prim =
  280.   case getPrimImpl prim of
  281.       GVprim globalName =>
  282.         Lprim(Pget_global (globalName, 0), [])
  283.     | VMprim(arity, p) =>
  284.         let fun make_fn n args =
  285.           if n >= arity
  286.           then Lprim(p, args)
  287.           else Lfn(make_fn (n+1) (Lvar n :: args))
  288.         in make_fn 0 [] end
  289.     | VMPprim(arity, p) =>
  290.         let fun make_fn n args =
  291.           if n >= arity
  292.           then Lprim(p, splitFirstArg args)
  293.           else Lfn(make_fn (n+1) (Lvar n :: args))
  294.         in make_fn 0 [] end
  295.     | GVTprim(globalName, sc) =>
  296.         Lfn(Lapply(
  297.               Lprim(Pget_global (globalName, 0), []),
  298.               [Lconst(QUOTEsc (ref sc)), Lvar 0]))
  299. ;
  300.  
  301. fun trVar (env as (rho, depth)) (ii : IdInfo) =
  302.   let val {info={idKind, ...}, ...} = ii
  303.       val {qualid, info} = !idKind
  304.   in
  305.     case info of
  306.         VARik =>
  307.           translateAccess env qualid
  308.       | PRIMik pi =>
  309.           trPrimVar (#primOp pi)
  310.       | CONik ci =>
  311.           trConVar ci
  312.       | EXCONik ei =>
  313.           trExConVar env qualid ei
  314.   end;
  315.  
  316. fun trExp (env as (rho, depth)) (exp as (loc, exp')) =
  317.   case exp' of
  318.     SCONexp scon =>
  319.       Lconst (ATOMsc scon)
  320.   | VARexp(ref (RESve ii)) =>
  321.       trVar env ii
  322.   | VARexp(ref (OVLve _)) => fatalError "trExp"
  323.   | FNexp [] =>
  324.       fatalError "trExp: empty fun"
  325.   | FNexp(mrules as MRule(pats,_)::_) =>
  326.       foldR (fn pat => fn lam => Lfn lam)
  327.             (trMatch loc env (partial_fun loc) mrules)
  328.             pats
  329.   | APPexp(e1,e2) =>
  330.       (case normApp e1 [e2] of
  331.            (func as (loc, FNexp mrules), args) =>
  332.              if curriedness mrules = List.length args then
  333.                Llet(trLetArgs env args,
  334.                     trMatch loc env (partial_fun loc) mrules)
  335.              else
  336.                let val (env', tr_args, envelope) = trArgs env args
  337.                in envelope(Lapply(trExp env' func, tr_args)) end
  338.           | (func as (_, VARexp(ref (RESve ii))), args) =>
  339.               trVarApp env ii args
  340.           | (func, args) =>
  341.               let val (env', tr_args, envelope) = trArgs env (func :: args)
  342.               in envelope(Lapply(hd tr_args, tl tr_args)) end)
  343.   | RECexp(ref (RECre fs)) =>
  344.       trRec env (CONtag(0,1)) fs
  345.   | RECexp(ref (TUPLEre es)) =>
  346.       trTuple env (CONtag(0,1)) es
  347.   | VECexp es =>
  348.       trTuple env (CONtag(0,1)) es
  349.   | PARexp e => trExp env e
  350.   | LETexp (dec,exp) =>
  351.       let val ((rho', depth'), envelope) = trDec env dec
  352.           val env'' = (plusEnv rho rho', depth')
  353.       in envelope(trExp env'' exp) end
  354.   | INFIXexp es => fatalError "trExp"
  355.   | TYPEDexp(e,ty) => trExp env e
  356.   | ANDALSOexp(e1,e2) =>
  357.       Landalso(trExp env e1, trExp env e2)
  358.   | ORELSEexp(e1,e2) =>
  359.       Lorelse(trExp env e1, trExp env e2)
  360.   | HANDLEexp(e, mrules) =>
  361.       Lhandle(trExp env e, trMatch loc env partial_try mrules)
  362.   | RAISEexp e =>
  363.       Lprim(Praise, [trExp env e])
  364.   | IFexp(e0,e1,e2) =>
  365.       Lif(trExp env e0, trExp env e1, trExp env e2)
  366.   | WHILEexp(e1,e2) =>
  367.       Lwhile(trExp env e1, trExp env e2)
  368.   | SEQexp(e1,e2) =>
  369.       Lseq(trExp env e1, trExp env e2)
  370.  
  371. and trVarApp env (ii : IdInfo) args =
  372.   let val {qualid={id, ...}, info={idKind, ...}} = ii in
  373.     case #info(!idKind) of
  374.         VARik =>
  375.           let val (env', tr_args, envelope) = trArgs env args
  376.           in envelope(Lapply(trVar env' ii, tr_args)) end
  377.       | PRIMik pi =>
  378.           let val {primOp, ...} = pi in
  379.             case curriedPrimVersion primOp of
  380.                 NONE => trPrimApp env primOp args
  381.               | SOME prim_c =>
  382.                   (case extractPairArg (hd args) of
  383.                         NONE => trPrimApp env primOp args
  384.                       | SOME(arg', arg'') =>
  385.                           trPrimApp env prim_c (arg'::arg''::(tl args)))
  386.           end
  387.       | CONik ci =>
  388.           let val {conArity, conIsGreedy, conTag, conSpan, ...} = !ci in
  389.             if List.length args <> 1 then
  390.               fatalError "trVarApp: unary con requires 1 arg"
  391.             else ();
  392.             case (conIsGreedy, conArity, conSpan) of
  393.                 (true,  _, _) =>
  394.                   (case (hd args) of
  395.                       (_, RECexp(ref (RECre fs))) =>
  396.                         trRec env (CONtag(conTag,conSpan)) fs
  397.                     | (_, RECexp(ref (TUPLEre es))) =>
  398.                         trTuple env (CONtag(conTag,conSpan)) es
  399.                     | _ =>
  400.                         Llet([trExp env (hd args)],
  401.                               Lprim(Pmakeblock(CONtag(conTag,conSpan)),
  402.                                     extract_fields conArity)))
  403.               | (false, 0, _) =>
  404.                   fatalError "trVarApp: nullary con in app"
  405.               | (false, _, 1) =>
  406.                   trExp env (hd args)
  407.               | (false, _, _) =>
  408.                   (* Normal unary con, in the end... *)
  409.                   let val tr_arg = trExp env (hd args) in
  410.                     Lconst(BLOCKsc(CONtag(conTag,conSpan),
  411.                                     [extractConstant tr_arg]))
  412.                     handle Not_constant =>
  413.                         Lprim(Pmakeblock(CONtag(conTag,conSpan)), [tr_arg])
  414.                   end
  415.           end
  416.       | EXCONik ei =>
  417.           let val {exconArity, exconIsGreedy, exconTag, ...} = !ei in
  418.             if List.length args <> 1 then
  419.               fatalError "trVarApp: unary excon requires 1 arg"
  420.             else ();
  421.             case exconTag of
  422.                 NONE =>
  423.                   let val () =
  424.                         if exconArity = 0 then
  425.                           fatalError "trVarApp: nullary excon in app"
  426.                         else ();
  427.                       val en = translateLocalAccess env id
  428.                       val tr_arg = trExp env (hd args)
  429.                   in Lprim(Pmakeblock smlExnTag, [en, tr_arg]) end
  430.               | SOME tag =>
  431.                  (case (exconIsGreedy, exconArity) of
  432.                     (true,  _) =>
  433.                       (case (hd args) of
  434.                           (_, RECexp(ref (RECre fs))) =>
  435.                             trRec env (EXNtag tag) fs
  436.                         | (_, RECexp(ref (TUPLEre es))) =>
  437.                             trTuple env (EXNtag tag) es
  438.                         | _ =>
  439.                             Llet([trExp env (hd args)],
  440.                                   Lprim(Pmakeblock(EXNtag tag),
  441.                                         extract_fields exconArity)))
  442.                   | (false, 0) =>
  443.                       fatalError "trVarApp: nullary excon in app"
  444.                   | (false, _) =>
  445.                       let val tr_arg = trExp env (hd args)
  446.                       in Lprim(Pmakeblock (EXNtag tag), [tr_arg]) end)
  447.           end
  448.   end
  449.  
  450. and trPrimApp env prim args =
  451.   let val (env', tr_args, envelope) = trArgs env args in
  452.     case getPrimImpl prim of
  453.         GVprim globalName =>
  454.           envelope(Lapply(trPrimVar prim, tr_args))
  455.       | VMprim(arity, p) =>
  456.           if arity <> List.length tr_args
  457.           then envelope(Lapply(trPrimVar prim, tr_args))
  458.           else envelope(Lprim(p, tr_args))
  459.       | VMPprim(arity, p) =>
  460.           if (arity <> List.length tr_args) then
  461.             envelope(Lapply(trPrimVar prim, tr_args))
  462.           else if canSplitFirstArg tr_args then
  463.             envelope(Lprim(p, splitFirstArg tr_args))
  464.           else if arity = 1 then
  465.             Llet(tr_args, Lprim(p, splitFirstArg [Lvar 0]))
  466.           else
  467.             envelope(Lapply(trPrimVar prim, tr_args))
  468.       | GVTprim(globalName, sc) =>
  469.           envelope(Lapply(Lprim(Pget_global (globalName, 0), []),
  470.                           Lconst(QUOTEsc (ref sc))::tr_args))
  471.   end
  472.  
  473. and trRec env tag fs =
  474.   let val labs = map fst fs and es = map snd fs
  475.       val (env', tr_es, envelope) = trArgs env es
  476.       val tr_es' = map snd (sortRow (zip2 labs tr_es))
  477.   in
  478.     (case tag of CONtag _ => () | EXNtag _ => raise Not_constant;
  479.      envelope(Lconst(BLOCKsc(tag, map extractConstant tr_es'))))
  480.     handle Not_constant =>
  481.            envelope(Lprim(Pmakeblock tag, tr_es'))
  482.   end
  483.  
  484. and trTuple env tag es =
  485.   let val (env', tr_es, envelope) = trArgs env es in
  486.     (case tag of CONtag _ => () | EXNtag _ => raise Not_constant;
  487.      envelope(Lconst(BLOCKsc(tag, map extractConstant tr_es))))
  488.     handle Not_constant =>
  489.            envelope(Lprim(Pmakeblock tag, tr_es))
  490.   end
  491.  
  492. (* We recognize constant arguments only upon translating them, *)
  493. (* to avoid repeated traversals of the abstract syntax tree. *)
  494.  
  495. and classifyArgs (env as (rho, depth)) unsafe safe = fn
  496.     [] => (unsafe, safe)
  497.   | arg :: args =>
  498.       if isSafe arg then
  499.         classifyArgs env unsafe ((SAFEarg arg) :: safe) args
  500.       else
  501.         let val lam = trExp env arg in
  502.           case lam of
  503.               Lconst _ =>
  504.                 classifyArgs env unsafe ((CONSTarg lam) :: safe) args
  505.             | _ =>
  506.                 classifyArgs (rho, depth+1) (lam :: unsafe)
  507.                              (UNSAFEarg :: safe) args
  508.         end
  509.  
  510. and adjustHeadArgs env pos acc = fn
  511.     [] => acc
  512.   | SAFEarg exp :: rest =>
  513.       adjustHeadArgs env pos (trExp env exp :: acc) rest
  514.   | CONSTarg lam :: rest =>
  515.       adjustHeadArgs env pos (lam :: acc) rest
  516.   | UNSAFEarg :: rest =>
  517.       adjustHeadArgs env (pos+1) (Lvar pos :: acc) rest
  518.  
  519. (* The rightmost unsafe expression needn't be lifted, *)
  520. (* as it can't do any harm. *)
  521.  
  522. and adjustArgs env quasisafe acc = fn
  523.     [] => fatalError "adjustArgs"
  524.   | SAFEarg exp :: rest =>
  525.       adjustArgs env quasisafe (trExp env exp :: acc) rest
  526.   | CONSTarg lam :: rest =>
  527.       adjustArgs env quasisafe (lam :: acc) rest
  528.   | UNSAFEarg :: rest =>
  529.       adjustHeadArgs env 0 (quasisafe :: acc) rest
  530.  
  531. and trArgs (env as (rho, depth)) args =
  532.   case classifyArgs env [] [] args of
  533.       ([], safe) => (env, adjustHeadArgs env 0 [] safe, fn lam => lam)
  534.     | (quasisafe :: unsafe, safe) =>
  535.         let val num = List.length unsafe
  536.             val env' = (rho, depth + num)
  537.         in
  538.           (env',
  539.            adjustArgs env' quasisafe [] safe,
  540.            if num = 0 then fn lam => lam
  541.                       else fn lam => Llet(rev unsafe, lam))
  542.         end
  543.  
  544. and trValDec onTop (env as (rho, depth)) pvbs rvbs =
  545.   let val ((rho',  depth'),  envelope' ) =
  546.         trValBind onTop env pvbs
  547.       val ((rho'', depth''), envelope'') =
  548.         trRecValBind (rho, depth') rvbs
  549.   in
  550.     ((plusEnv rho' rho'', depth''), envelope' o envelope'')
  551.   end
  552.  
  553. and trDec (env as (rho, depth)) (loc, dec') =
  554.   case dec' of
  555.     VALdec (pvbs, rvbs) =>
  556.       trValDec false env pvbs rvbs
  557.   | PRIM_VALdec _ => ((NILenv, depth), fn lam => lam)
  558.   | FUNdec _ => fatalError "trDec"
  559.   | TYPEdec _ => ((NILenv, depth), fn lam => lam)
  560.   | PRIM_TYPEdec _ => ((NILenv, depth), fn lam => lam)
  561.   | DATATYPEdec(dbs, _) => ((NILenv, depth), fn lam => lam)
  562.   | ABSTYPEdec(dbs, _, dec2) =>
  563.       trDec env dec2
  564.   | EXCEPTIONdec ebs =>
  565.       trExBindList env ebs
  566.   | LOCALdec(dec1,dec2) =>
  567.       let val ((rho', depth'), envelope') =
  568.                               trDec env dec1
  569.           val ((rho'', depth''), envelope'') =
  570.                               trDec ((plusEnv rho rho'), depth') dec2
  571.       in ((rho'', depth''), envelope' o envelope'') end
  572.   | OPENdec _ => ((NILenv, depth), fn lam => lam)
  573.   | EMPTYdec => ((NILenv, depth), fn lam => lam)
  574.   | SEQdec(dec1,dec2) =>
  575.       let val ((rho', depth'), envelope') =
  576.                               trDec env dec1
  577.           val ((rho'', depth''), envelope'') =
  578.                               trDec ((plusEnv rho rho'), depth') dec2
  579.       in ((plusEnv rho' rho'', depth''), envelope' o envelope'') end
  580.   | FIXITYdec  _ =>  ((NILenv, depth), fn lam => lam)
  581.  
  582. and tr1ValBind onTop (env as (rho, depth)) (ValBind(pat, arg)) =
  583.   let val (env', add_lets) = mkEnvOfPats depth [pat]
  584.       val tr_arg = trExp env arg
  585.       val m_env = (rho, depth+1)
  586.       val loc = xLR pat
  587.       fun envelope lam =
  588.             Llet([tr_arg],
  589.               translateMatch m_env (partial_let onTop loc) loc
  590.                              [([pat], add_lets lam)])
  591.   in (env', envelope) end
  592.  
  593. and trValBind onTop (env as (rho, depth)) = fn
  594.     [] => ((NILenv, depth), fn lam => lam)
  595.   | [vb] =>
  596.       tr1ValBind onTop env vb
  597.   | vb :: vbs =>
  598.       let val (env' as (rho', depth'),  envelope') =
  599.              tr1ValBind onTop env vb
  600.           val (env'' as (rho'', depth''), envelope'') =
  601.              trValBind onTop (rho, depth') vbs
  602.       in ((plusEnv rho' rho'', depth''), envelope' o envelope'') end
  603.  
  604. and trRecValBind (env as (rho, depth)) = fn
  605.     [] => ((NILenv, depth), fn lam => lam)
  606.   | vbs =>
  607.       let val pats = map (fn ValBind(p, _) => p) vbs
  608.           val args = map (fn ValBind(_, e) => e) vbs
  609.           val (env' as (rho', depth')) = mkEnvOfRecPats depth pats
  610.           val new_env = (plusEnv rho rho', depth')
  611.           val tr_bindings = map (trExp new_env) args
  612.           fun envelope lam = Lletrec(tr_bindings, lam)
  613.       in (env', envelope) end
  614.  
  615. and trMatch loc (env as (rho, depth)) failure_code mrules =
  616.   let val m_env = (rho, depth + curriedness mrules)
  617.       fun trMRule (MRule(pats, exp)) =
  618.         let val ((rho', depth'), add_lets) = mkEnvOfPats depth pats
  619.             val new_env = (plusEnv rho rho', depth')
  620.         in (pats, add_lets (trExp new_env exp)) end
  621.   in translateMatch m_env failure_code loc (map trMRule mrules) end
  622.  
  623. and trLetArgs (env as (rho, depth)) = fn
  624.     [] =>  []
  625.   | exp :: exps =>
  626.       trExp env exp :: trLetArgs (rho, depth+1) exps
  627.  
  628. and trBindings (env as (rho, depth)) = fn
  629.     [] => []
  630.   | (pat, exp) :: rest =>
  631.       trExp env exp :: trBindings (rho, depth+1) rest
  632.  
  633. and trExBindList (env as (rho, depth)) ebs =
  634.   let val id_path_list =
  635.         mapFrom (fn depth =>
  636.                  fn
  637.                     (EXDECexbind(ii, _))   =>
  638.                               (#id(#qualid ii), Path_local depth)
  639.                   | (EXEQUALexbind(ii, _)) =>
  640.                               (#id (#qualid ii), Path_local depth))
  641.                 depth ebs
  642.       and len = List.length ebs
  643.       and args = mapFrom (fn i => fn eb => trExBind (rho, i) eb) depth ebs
  644.       val rho' = foldR (fn (id, path) => fn rho => bindInEnv rho id path)
  645.                        NILenv id_path_list
  646.   in ((rho', depth+len), fn lam => Llet(args, lam)) end
  647.  
  648. and trExBind env = fn
  649.     EXDECexbind(ii, _) =>
  650.       let val () =
  651.             if isExConStatic(getExConInfo ii) then fatalError "trExBind"
  652.             else ()
  653.           val uname = ATOMsc(STRINGscon(currentUnitName()))
  654.           val exid  = ATOMsc(STRINGscon (#id (#qualid ii)))
  655.           val en = BLOCKsc(CONtag(0,1), [exid, uname])
  656.       in Lprim(Pmakeblock(CONtag(refTag, 1)), [Lconst en]) end
  657.   | EXEQUALexbind(ii, ii') =>
  658.       (if isExConStatic(getExConInfo ii') then fatalError "trExBind"
  659.        else ();
  660.        translateExName env ii')
  661. ;
  662.  
  663. (* Translation of toplevel declarations *)
  664.  
  665. fun makeSeq f [] = Lunspec
  666.   | makeSeq f [x] = f x
  667.   | makeSeq f (x::rest) = Lseq(f x, makeSeq f rest)
  668. ;
  669.  
  670. fun lookupLocalRenEnv renEnv id =
  671.   mkUniqueGlobalName (id, (lookup id renEnv))
  672.   handle Subscript => fatalError "lookupLocalRenEnv"
  673. ;
  674.  
  675. fun storeGlobal renEnv env var =
  676.   Lprim(Pset_global (lookupLocalRenEnv renEnv var),
  677.           [translateLocalAccess env var])
  678. ;
  679.  
  680. fun equGlobal renEnv var0 var =
  681.   Lprim(Pset_global (lookupLocalRenEnv renEnv var),
  682.     [Lprim(Pget_global (lookupLocalRenEnv renEnv var0), [])])
  683. ;
  684.  
  685. fun tr1ToplevelRecValBind renEnv rho = fn
  686.     ([], exp) => Lunspec
  687.   | ([var], exp) =>
  688.       Lprim(Pset_global (lookupLocalRenEnv renEnv var), [trExp (rho, 0) exp])
  689.   | (var :: vars, exp) =>
  690.       Lseq(Lprim(Pset_global (lookupLocalRenEnv renEnv var),
  691.                  [trExp (rho, 0) exp]),
  692.         makeSeq (equGlobal renEnv var) vars)
  693. ;
  694.  
  695. fun revWithoutDuplicates [] acc = acc
  696.   | revWithoutDuplicates (x :: xs) acc =
  697.       if member x acc then
  698.         revWithoutDuplicates xs acc
  699.       else
  700.         revWithoutDuplicates xs (x :: acc)
  701. ;
  702.  
  703. datatype TopLambda =
  704.     NILtlam
  705.   | SEQtlam of TopLambda * TopLambda
  706.   | LAMtlam of bool * Lambda
  707. ;
  708.  
  709. fun flattenTLam tlam acc =
  710.   case tlam of
  711.       NILtlam => acc
  712.     | SEQtlam(tlam1, tlam2) =>
  713.         flattenTLam tlam1 (flattenTLam tlam2 acc)
  714.     | LAMtlam(is_pure, lam) => (is_pure, lam) :: acc
  715. ;
  716.  
  717. fun trToplevelDec rho (dec as (_, dec')) =
  718.   case dec' of
  719.       VALdec ([ValBind((_, VARpat ii), exp)], []) =>
  720.         let val id = #id(#qualid ii)
  721.             val id' = mkUniqueGlobalName (renameId id)
  722.         in
  723.           (mk1Env id (Path_global id'),
  724.             LAMtlam(isSafe exp,
  725.               Lprim(Pset_global id', [trExp (rho, 0) exp])))
  726.         end
  727.     | VALdec ([], rvbs) =>
  728.         let val ves = map (fn ValBind(p, e) => (domPat p, e)) rvbs
  729.             val vars = foldL (fn (vs, _) => fn acc => vs @ acc) [] ves
  730.             val renEnv = map renameId vars
  731.             val rho' =
  732.               foldR (fn (id' as (id, _)) => fn rho =>
  733.                        bindInEnv rho id (Path_global (mkUniqueGlobalName id')))
  734.                     NILenv renEnv
  735.         in
  736.           (rho',
  737.            LAMtlam(true,
  738.              makeSeq (tr1ToplevelRecValBind renEnv (plusEnv rho rho')) ves))
  739.         end
  740.     | VALdec (pvbs, rvbs) =>
  741.         let val (env as (rho', depth'), envelope) =
  742.                trValDec true (rho, 0) pvbs rvbs
  743.             val vars = foldEnv (fn id => fn _ => fn vars => id :: vars)
  744.                                [] rho'
  745.             val renEnv = map renameId vars
  746.         in
  747.           (foldR (fn (id' as (id,_)) => fn rho =>
  748.                     bindInEnv rho id (Path_global (mkUniqueGlobalName id')))
  749.                  NILenv renEnv,
  750.            LAMtlam(
  751.              all (fn ValBind(_, e) => isSafe e) pvbs,
  752.              envelope (makeSeq (storeGlobal renEnv env)
  753.                                (revWithoutDuplicates vars []))))
  754.         end
  755.     | PRIM_VALdec _ => (NILenv, NILtlam)
  756.     | FUNdec _ => fatalError "trToplevelDec"
  757.     | TYPEdec _ => (NILenv, NILtlam)
  758.     | PRIM_TYPEdec _ => (NILenv, NILtlam)
  759.     | DATATYPEdec(dbs, _) => (NILenv, NILtlam)
  760.     | ABSTYPEdec(dbs, _, dec2) =>
  761.         trToplevelDec rho dec2
  762.     | EXCEPTIONdec ebs => (NILenv, NILtlam)
  763.     | LOCALdec(dec1,dec2) =>
  764.         let val (rho' , tlam')  = trToplevelDec rho dec1
  765.             val (rho'', tlam'') = trToplevelDec (plusEnv rho rho') dec2
  766.         in (rho'', SEQtlam(tlam', tlam'')) end
  767.     | OPENdec _ => (NILenv, NILtlam)
  768.     | EMPTYdec => (NILenv, NILtlam)
  769.     | SEQdec(dec1,dec2) =>
  770.         let val (rho' , tlam')  = trToplevelDec rho dec1
  771.             val (rho'', tlam'') = trToplevelDec (plusEnv rho rho') dec2
  772.         in (plusEnv rho' rho'', SEQtlam(tlam', tlam'')) end
  773.     | FIXITYdec  _ =>  (NILenv, NILtlam)
  774. ;
  775.  
  776. fun REofRho1 id (Path_global (_, stamp)) re = (id, stamp) :: re
  777.   | REofRho1 _  _            _              = fatalError "REofRho1"
  778.  
  779. fun REofRho rho =
  780.   foldEnv REofRho1 [] rho
  781. ;
  782.  
  783. fun translateToplevelDec dec =
  784.   let val (rho, tlam) = trToplevelDec NILenv dec
  785.   in (REofRho rho, flattenTLam tlam []) end
  786. ;
  787.