adamc@1191: (* Copyright (c) 2008-2010, Adam Chlipala adamc@25: * All rights reserved. adamc@25: * adamc@25: * Redistribution and use in source and binary forms, with or without adamc@25: * modification, are permitted provided that the following conditions are met: adamc@25: * adamc@25: * - Redistributions of source code must retain the above copyright notice, adamc@25: * this list of conditions and the following disclaimer. adamc@25: * - Redistributions in binary form must reproduce the above copyright notice, adamc@25: * this list of conditions and the following disclaimer in the documentation adamc@25: * and/or other materials provided with the distribution. adamc@25: * - The names of contributors may not be used to endorse or promote products adamc@25: * derived from this software without specific prior written permission. adamc@25: * adamc@25: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" adamc@25: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE adamc@25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE adamc@25: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE adamc@25: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR adamc@25: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF adamc@25: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS adamc@25: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN adamc@25: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) adamc@25: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE adamc@25: * POSSIBILITY OF SUCH DAMAGE. adamc@25: *) adamc@25: adamc@25: structure Monoize :> MONOIZE = struct adamc@25: adamc@25: structure E = ErrorMsg adamc@25: structure Env = CoreEnv adamc@25: adamc@25: structure L = Core adamc@25: structure L' = Mono adamc@25: adamc@196: structure IM = IntBinaryMap adamc@735: structure IS = IntBinarySet adamc@196: adamc@984: structure SS = BinarySetFn(struct adamc@984: type ord_key = string adamc@984: val compare = String.compare adamc@984: end) adamc@984: adamc@984: val singletons = SS.addList (SS.empty, adamc@984: ["link", adamc@984: "br", adamc@984: "p", adamc@984: "hr", adamc@984: "input", adamc@1129: "button", adamc@1129: "img"]) adamc@984: adamc@196: val dummyTyp = (L'.TDatatype (0, ref (L'.Enum, [])), E.dummySpan) adamc@25: adamc@252: structure U = MonoUtil adamc@252: adamc@252: val liftExpInExp = adamc@252: U.Exp.mapB {typ = fn t => t, adamc@252: exp = fn bound => fn e => adamc@252: case e of adamc@252: L'.ERel xn => adamc@252: if xn < bound then adamc@252: e adamc@252: else adamc@252: L'.ERel (xn + 1) adamc@252: | _ => e, adamc@252: bind = fn (bound, U.Exp.RelE _) => bound + 1 adamc@252: | (bound, _) => bound} adamc@252: adamc@25: fun monoName env (all as (c, loc)) = adamc@25: let adamc@25: fun poly () = adamc@25: (E.errorAt loc "Unsupported name constructor"; adamc@25: Print.eprefaces' [("Constructor", CorePrint.p_con env all)]; adamc@25: "") adamc@25: in adamc@25: case c of adamc@25: L.CName s => s adamc@25: | _ => poly () adamc@25: end adamc@25: adamc@877: fun lowercaseFirst "" = "" adamc@877: | lowercaseFirst s = String.str (Char.toLower (String.sub (s, 0))) adamc@877: ^ String.extract (s, 1, NONE) adamc@877: adamc@877: fun monoNameLc env c = lowercaseFirst (monoName env c) adamc@877: adamc@292: fun readType' (t, loc) = (L'.TFun ((L'.TFfi ("Basis", "string"), loc), adamc@292: (L'.TOption t, loc)), loc) adamc@292: fun readErrType (t, loc) = (L'.TFun ((L'.TFfi ("Basis", "string"), loc), adamc@292: t), loc) adamc@292: fun readType (t, loc) = adamc@292: (L'.TRecord [("Read", readType' (t, loc)), adamc@292: ("ReadError", readErrType (t, loc))], adamc@292: loc) adamc@292: adamc@196: fun monoType env = adamc@25: let adamc@196: fun mt env dtmap (all as (c, loc)) = adamc@196: let adamc@196: fun poly () = adamc@196: (E.errorAt loc "Unsupported type constructor"; adamc@196: Print.eprefaces' [("Constructor", CorePrint.p_con env all)]; adamc@196: dummyTyp) adamc@196: in adamc@196: case c of adamc@196: L.TFun (c1, c2) => (L'.TFun (mt env dtmap c1, mt env dtmap c2), loc) adamc@196: | L.TCFun _ => poly () adamc@196: | L.TRecord (L.CRecord ((L.KType, _), xcs), _) => adamc@905: let adamc@905: val xcs = map (fn (x, t) => (monoName env x, mt env dtmap t)) xcs adamc@905: val xcs = ListMergeSort.sort (fn ((x, _), (y, _)) => String.compare (x, y) = GREATER) xcs adamc@905: in adamc@905: (L'.TRecord xcs, loc) adamc@905: end adamc@196: | L.TRecord _ => poly () adamc@196: adamc@288: | L.CApp ((L.CFfi ("Basis", "option"), _), t) => adamc@288: (L'.TOption (mt env dtmap t), loc) adamc@757: | L.CApp ((L.CFfi ("Basis", "list"), _), t) => adamc@757: (L'.TList (mt env dtmap t), loc) adamc@288: adamc@820: | L.CApp ((L.CFfi ("Basis", "monad"), _), _) => adamc@820: (L'.TRecord [], loc) adamc@820: adamc@387: | L.CApp ((L.CFfi ("Basis", "eq"), _), t) => adamc@387: let adamc@387: val t = mt env dtmap t adamc@387: in adamc@387: (L'.TFun (t, (L'.TFun (t, (L'.TFfi ("Basis", "bool"), loc)), loc)), loc) adamc@387: end adamc@389: | L.CApp ((L.CFfi ("Basis", "num"), _), t) => adamc@389: let adamc@389: val t = mt env dtmap t adamc@389: in adamc@417: (L'.TRecord [("Zero", t), adamc@417: ("Neg", (L'.TFun (t, t), loc)), adamc@389: ("Plus", (L'.TFun (t, (L'.TFun (t, t), loc)), loc)), adamc@389: ("Minus", (L'.TFun (t, (L'.TFun (t, t), loc)), loc)), adamc@389: ("Times", (L'.TFun (t, (L'.TFun (t, t), loc)), loc)), adamc@389: ("Div", (L'.TFun (t, (L'.TFun (t, t), loc)), loc)), adamc@389: ("Mod", (L'.TFun (t, (L'.TFun (t, t), loc)), loc))], adamc@389: loc) adamc@389: end adamc@391: | L.CApp ((L.CFfi ("Basis", "ord"), _), t) => adamc@391: let adamc@391: val t = mt env dtmap t adamc@391: in adamc@391: (L'.TRecord [("Lt", (L'.TFun (t, (L'.TFun (t, (L'.TFfi ("Basis", "bool"), loc)), loc)), loc)), adamc@391: ("Le", (L'.TFun (t, (L'.TFun (t, (L'.TFfi ("Basis", "bool"), loc)), loc)), loc))], adamc@391: loc) adamc@391: end adamc@286: | L.CApp ((L.CFfi ("Basis", "show"), _), t) => adamc@286: (L'.TFun (mt env dtmap t, (L'.TFfi ("Basis", "string"), loc)), loc) adamc@290: | L.CApp ((L.CFfi ("Basis", "read"), _), t) => adamc@292: readType (mt env dtmap t, loc) adamc@286: adamc@1176: | L.CFfi ("Basis", "unit") => (L'.TRecord [], loc) adamc@1176: | L.CFfi ("Basis", "page") => (L'.TFfi ("Basis", "string"), loc) adamc@1176: | L.CFfi ("Basis", "xbody") => (L'.TFfi ("Basis", "string"), loc) adamc@1176: | L.CFfi ("Basis", "xtr") => (L'.TFfi ("Basis", "string"), loc) adamc@1176: | L.CFfi ("Basis", "xform") => (L'.TFfi ("Basis", "string"), loc) adamc@1176: adamc@717: | L.CFfi ("Basis", "url") => (L'.TFfi ("Basis", "string"), loc) adamc@741: | L.CFfi ("Basis", "mimeType") => (L'.TFfi ("Basis", "string"), loc) adamc@720: | L.CApp ((L.CApp ((L.CApp ((L.CFfi ("Basis", "xml"), _), _), _), _), _), _) => adamc@196: (L'.TFfi ("Basis", "string"), loc) adamc@196: | L.CApp ((L.CApp ((L.CFfi ("Basis", "xhtml"), _), _), _), _) => adamc@196: (L'.TFfi ("Basis", "string"), loc) adamc@721: | L.CFfi ("Basis", "css_class") => (L'.TFfi ("Basis", "string"), loc) adamc@196: adamc@1104: | L.CApp ((L.CFfi ("Basis", "serialized"), _), _) => adamc@1104: (L'.TFfi ("Basis", "string"), loc) adamc@1104: adamc@251: | L.CApp ((L.CFfi ("Basis", "transaction"), _), t) => adamc@252: (L'.TFun ((L'.TRecord [], loc), mt env dtmap t), loc) adamc@565: | L.CApp ((L.CFfi ("Basis", "source"), _), t) => adamc@577: (L'.TSource, loc) adamc@568: | L.CApp ((L.CFfi ("Basis", "signal"), _), t) => adamc@568: (L'.TSignal (mt env dtmap t), loc) adamc@462: | L.CApp ((L.CFfi ("Basis", "http_cookie"), _), _) => adamc@462: (L'.TFfi ("Basis", "string"), loc) adamc@705: | L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_table"), _), _), _), _) => adamc@252: (L'.TFfi ("Basis", "string"), loc) adamc@823: | L.CApp ((L.CFfi ("Basis", "sql_view"), _), _) => adamc@823: (L'.TFfi ("Basis", "string"), loc) adamc@338: | L.CFfi ("Basis", "sql_sequence") => adamc@338: (L'.TFfi ("Basis", "string"), loc) adamc@1191: | L.CApp ((L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_query"), _), _), _), _), _), _) => adamc@252: (L'.TFfi ("Basis", "string"), loc) adamc@1191: | L.CApp ((L.CApp ((L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_query1"), _), _), _), _), _), _), _), _) => adamc@252: (L'.TFfi ("Basis", "string"), loc) adamc@1191: | L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_from_items"), _), _), _), _) => adamc@748: (L'.TFfi ("Basis", "string"), loc) adamc@252: | L.CApp ((L.CApp ((L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_exp"), _), _), _), _), _), _), _), _) => adamc@252: (L'.TFfi ("Basis", "string"), loc) adamc@707: | L.CApp ((L.CApp ((L.CFfi ("Basis", "primary_key"), _), _), _), _) => adamc@707: (L'.TFfi ("Basis", "string"), loc) adamc@704: | L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_constraints"), _), _), _), _) => adamc@704: (L'.TFfi ("Basis", "sql_constraints"), loc) adamc@705: | L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_constraint"), _), _), _), _) => adamc@704: (L'.TFfi ("Basis", "string"), loc) adamc@712: | L.CApp ((L.CApp ((L.CFfi ("Basis", "linkable"), _), _), _), _) => adamc@712: (L'.TRecord [], loc) adamc@709: | L.CApp ((L.CApp ((L.CFfi ("Basis", "matching"), _), _), _), _) => adamc@709: let adamc@709: val string = (L'.TFfi ("Basis", "string"), loc) adamc@709: in adamc@709: (L'.TRecord [("1", string), ("2", string)], loc) adamc@709: end adamc@709: | L.CApp ((L.CFfi ("Basis", "propagation_mode"), _), _) => adamc@709: (L'.TFfi ("Basis", "string"), loc) adamc@252: adamc@252: | L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_subset"), _), _), _), _) => adamc@252: (L'.TRecord [], loc) adamc@252: | L.CFfi ("Basis", "sql_relop") => adamc@252: (L'.TFfi ("Basis", "string"), loc) adamc@252: | L.CFfi ("Basis", "sql_direction") => adamc@252: (L'.TFfi ("Basis", "string"), loc) adamc@252: | L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_order_by"), _), _), _), _) => adamc@252: (L'.TFfi ("Basis", "string"), loc) adamc@252: | L.CFfi ("Basis", "sql_limit") => adamc@252: (L'.TFfi ("Basis", "string"), loc) adamc@252: | L.CFfi ("Basis", "sql_offset") => adamc@252: (L'.TFfi ("Basis", "string"), loc) adamc@753: | L.CApp ((L.CApp ((L.CFfi ("Basis", "fieldsOf"), _), _), _), _) => adamc@753: (L'.TRecord [], loc) adamc@252: adamc@676: | L.CApp ((L.CFfi ("Basis", "sql_injectable_prim"), _), t) => adamc@676: (L'.TFun (mt env dtmap t, (L'.TFfi ("Basis", "string"), loc)), loc) adamc@252: | L.CApp ((L.CFfi ("Basis", "sql_injectable"), _), t) => adamc@252: (L'.TFun (mt env dtmap t, (L'.TFfi ("Basis", "string"), loc)), loc) adamc@750: | L.CApp ((L.CApp ((L.CFfi ("Basis", "nullify"), _), _), _), _) => adamc@750: (L'.TRecord [], loc) adamc@252: | L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_unary"), _), _), _), _) => adamc@252: (L'.TFfi ("Basis", "string"), loc) adamc@252: | L.CApp ((L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_binary"), _), _), _), _), _), _) => adamc@252: (L'.TFfi ("Basis", "string"), loc) adamc@1187: | L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_aggregate"), _), _), _), _) => adamc@252: (L'.TFfi ("Basis", "string"), loc) adamc@252: | L.CApp ((L.CFfi ("Basis", "sql_summable"), _), _) => adamc@252: (L'.TRecord [], loc) adamc@252: | L.CApp ((L.CFfi ("Basis", "sql_maxable"), _), _) => adamc@252: (L'.TRecord [], loc) adamc@559: | L.CApp ((L.CFfi ("Basis", "sql_arith"), _), _) => adamc@559: (L'.TRecord [], loc) adamc@441: | L.CApp ((L.CFfi ("Basis", "sql_nfunc"), _), _) => adamc@441: (L'.TFfi ("Basis", "string"), loc) adamc@746: | L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_ufunc"), _), _), _), _) => adamc@746: (L'.TFfi ("Basis", "string"), loc) adamc@251: adamc@668: | L.CApp ((L.CFfi ("Basis", "channel"), _), _) => adamc@668: (L'.TFfi ("Basis", "channel"), loc) adamc@668: adamc@196: | L.CRel _ => poly () adamc@196: | L.CNamed n => adamc@196: (case IM.find (dtmap, n) of adamc@196: SOME r => (L'.TDatatype (n, r), loc) adamc@196: | NONE => adamc@196: let adamc@196: val r = ref (L'.Default, []) adamc@196: val (_, xs, xncs) = Env.lookupDatatype env n adamc@196: adamc@196: val dtmap' = IM.insert (dtmap, n, r) adamc@196: adamc@196: val xncs = map (fn (x, n, to) => (x, n, Option.map (mt env dtmap') to)) xncs adamc@196: in adamc@196: case xs of adamc@198: [] =>(r := (ElabUtil.classifyDatatype xncs, xncs); adamc@196: (L'.TDatatype (n, r), loc)) adamc@196: | _ => poly () adamc@196: end) adamc@196: | L.CFfi mx => (L'.TFfi mx, loc) adamc@196: | L.CApp _ => poly () adamc@196: | L.CAbs _ => poly () adamc@196: adamc@196: | L.CName _ => poly () adamc@196: adamc@196: | L.CRecord _ => poly () adamc@196: | L.CConcat _ => poly () adamc@621: | L.CMap _ => poly () adamc@196: | L.CUnit => poly () adamc@214: adamc@214: | L.CTuple _ => poly () adamc@214: | L.CProj _ => poly () adamc@626: adamc@626: | L.CKAbs _ => poly () adamc@626: | L.CKApp _ => poly () adamc@626: | L.TKFun _ => poly () adamc@196: end adamc@25: in adamc@196: mt env IM.empty adamc@25: end adamc@25: adamc@25: val dummyExp = (L'.EPrim (Prim.Int 0), E.dummySpan) adamc@25: adamc@179: structure IM = IntBinaryMap adamc@179: adamc@179: datatype foo_kind = adamc@179: Attr adamc@179: | Url adamc@179: adamc@179: fun fk2s fk = adamc@179: case fk of adamc@179: Attr => "attr" adamc@179: | Url => "url" adamc@179: adamc@179: structure Fm :> sig adamc@179: type t adamc@179: adamc@179: val empty : int -> t adamc@179: adamc@179: val lookup : t -> foo_kind -> int -> (int -> t -> L'.decl * t) -> t * int adamc@758: val lookupList : t -> foo_kind -> L'.typ -> (int -> t -> L'.decl * t) -> t * int adamc@179: val enter : t -> t adamc@179: val decls : t -> L'.decl list adamc@683: adamc@683: val freshName : t -> int * t adamc@179: end = struct adamc@179: adamc@179: structure M = BinaryMapFn(struct adamc@179: type ord_key = foo_kind adamc@179: fun compare x = adamc@179: case x of adamc@179: (Attr, Attr) => EQUAL adamc@179: | (Attr, _) => LESS adamc@179: | (_, Attr) => GREATER adamc@179: adamc@179: | (Url, Url) => EQUAL adamc@179: end) adamc@179: adamc@758: structure TM = BinaryMapFn(struct adamc@758: type ord_key = L'.typ adamc@758: val compare = MonoUtil.Typ.compare adamc@758: end) adamc@758: adamc@179: type t = { adamc@179: count : int, adamc@179: map : int IM.map M.map, adamc@758: listMap : int TM.map M.map, adamc@179: decls : L'.decl list adamc@179: } adamc@179: adamc@179: fun empty count = { adamc@179: count = count, adamc@179: map = M.empty, adamc@758: listMap = M.empty, adamc@179: decls = [] adamc@179: } adamc@179: adamc@758: fun enter ({count, map, listMap, ...} : t) = {count = count, map = map, listMap = listMap, decls = []} adamc@758: fun freshName {count, map, listMap, decls} = (count, {count = count + 1, map = map, listMap = listMap, decls = decls}) adamc@179: fun decls ({decls, ...} : t) = decls adamc@179: adamc@758: fun lookup (t as {count, map, listMap, decls}) k n thunk = adamc@120: let adamc@179: val im = Option.getOpt (M.find (map, k), IM.empty) adamc@179: in adamc@179: case IM.find (im, n) of adamc@179: NONE => adamc@179: let adamc@179: val n' = count adamc@758: val (d, {count, map, listMap, decls}) = adamc@758: thunk count {count = count + 1, adamc@758: map = M.insert (map, k, IM.insert (im, n, n')), adamc@758: listMap = listMap, adamc@758: decls = decls} adamc@179: in adamc@179: ({count = count, adamc@179: map = map, adamc@758: listMap = listMap, adamc@758: decls = d :: decls}, n') adamc@758: end adamc@758: | SOME n' => (t, n') adamc@758: end adamc@758: adamc@758: fun lookupList (t as {count, map, listMap, decls}) k tp thunk = adamc@758: let adamc@758: val tm = Option.getOpt (M.find (listMap, k), TM.empty) adamc@758: in adamc@758: case TM.find (tm, tp) of adamc@758: NONE => adamc@758: let adamc@758: val n' = count adamc@758: val (d, {count, map, listMap, decls}) = adamc@758: thunk count {count = count + 1, adamc@758: map = map, adamc@758: listMap = M.insert (listMap, k, TM.insert (tm, tp, n')), adamc@758: decls = decls} adamc@758: in adamc@758: ({count = count, adamc@758: map = map, adamc@758: listMap = listMap, adamc@179: decls = d :: decls}, n') adamc@179: end adamc@179: | SOME n' => (t, n') adamc@179: end adamc@179: adamc@179: end adamc@185: adamc@185: adamc@185: fun capitalize s = adamc@185: if s = "" then adamc@185: s adamc@185: else adamc@185: str (Char.toUpper (String.sub (s, 0))) ^ String.extract (s, 1, NONE) adamc@179: adamc@179: fun fooifyExp fk env = adamc@179: let adamc@179: fun fooify fm (e, tAll as (t, loc)) = adamc@120: case #1 e of adamc@120: L'.EClosure (fnam, [(L'.ERecord [], _)]) => adamc@120: let adamc@120: val (_, _, _, s) = Env.lookupENamed env fnam adamc@120: in adamc@764: ((L'.EPrim (Prim.String (Settings.getUrlPrefix () ^ s)), loc), fm) adamc@120: end adamc@120: | L'.EClosure (fnam, args) => adamc@120: let adamc@120: val (_, ft, _, s) = Env.lookupENamed env fnam adamc@120: val ft = monoType env ft adamc@111: adamc@179: fun attrify (args, ft, e, fm) = adamc@120: case (args, ft) of adamc@179: ([], _) => (e, fm) adamc@120: | (arg :: args, (L'.TFun (t, ft), _)) => adamc@179: let adamc@179: val (arg', fm) = fooify fm (arg, t) adamc@179: in adamc@179: attrify (args, ft, adamc@179: (L'.EStrcat (e, adamc@179: (L'.EStrcat ((L'.EPrim (Prim.String "/"), loc), adamc@179: arg'), loc)), loc), adamc@179: fm) adamc@179: end adamc@120: | _ => (E.errorAt loc "Type mismatch encoding attribute"; adamc@179: (e, fm)) adamc@120: in adamc@764: attrify (args, ft, (L'.EPrim (Prim.String (Settings.getUrlPrefix () ^ s)), loc), fm) adamc@120: end adamc@120: | _ => adamc@120: case t of adamc@1109: L'.TFfi ("Basis", "unit") => ((L'.EPrim (Prim.String ""), loc), fm) adamc@1109: | L'.TFfi (m, x) => ((L'.EFfiApp (m, fk2s fk ^ "ify" ^ capitalize x, [e]), loc), fm) adamc@200: adamc@179: | L'.TRecord [] => ((L'.EPrim (Prim.String ""), loc), fm) adamc@200: | L'.TRecord ((x, t) :: xts) => adamc@200: let adamc@200: val (se, fm) = fooify fm ((L'.EField (e, x), loc), t) adamc@200: in adamc@200: foldl (fn ((x, t), (se, fm)) => adamc@200: let adamc@200: val (se', fm) = fooify fm ((L'.EField (e, x), loc), t) adamc@200: in adamc@200: ((L'.EStrcat (se, adamc@200: (L'.EStrcat ((L'.EPrim (Prim.String "/"), loc), adamc@200: se'), loc)), loc), adamc@200: fm) adamc@200: end) (se, fm) xts adamc@200: end adamc@111: adamc@196: | L'.TDatatype (i, ref (dk, _)) => adamc@179: let adamc@179: fun makeDecl n fm = adamc@179: let adamc@193: val (x, _, xncs) = Env.lookupDatatype env i adamc@179: adamc@179: val (branches, fm) = adamc@179: ListUtil.foldlMap adamc@179: (fn ((x, n, to), fm) => adamc@179: case to of adamc@179: NONE => adamc@188: (((L'.PCon (dk, L'.PConVar n, NONE), loc), adamc@179: (L'.EPrim (Prim.String x), loc)), adamc@179: fm) adamc@179: | SOME t => adamc@179: let adamc@182: val t = monoType env t adamc@182: val (arg, fm) = fooify fm ((L'.ERel 0, loc), t) adamc@179: in adamc@188: (((L'.PCon (dk, L'.PConVar n, SOME (L'.PVar ("a", t), loc)), loc), adamc@179: (L'.EStrcat ((L'.EPrim (Prim.String (x ^ "/")), loc), adamc@179: arg), loc)), adamc@179: fm) adamc@179: end) adamc@179: fm xncs adamc@179: adamc@179: val dom = tAll adamc@179: val ran = (L'.TFfi ("Basis", "string"), loc) adamc@179: in adamc@179: ((L'.DValRec [(fk2s fk ^ "ify_" ^ x, adamc@179: n, adamc@179: (L'.TFun (dom, ran), loc), adamc@179: (L'.EAbs ("x", adamc@179: dom, adamc@179: ran, adamc@179: (L'.ECase ((L'.ERel 0, loc), adamc@179: branches, adamc@182: {disc = dom, adamc@182: result = ran}), loc)), loc), adamc@179: "")], loc), adamc@179: fm) adamc@179: end adamc@179: adamc@179: val (fm, n) = Fm.lookup fm fk i makeDecl adamc@179: in adamc@179: ((L'.EApp ((L'.ENamed n, loc), e), loc), fm) adamc@179: end adamc@164: adamc@471: | L'.TOption t => adamc@471: let adamc@471: val (body, fm) = fooify fm ((L'.ERel 0, loc), t) adamc@471: in adamc@471: ((L'.ECase (e, adamc@471: [((L'.PNone t, loc), adamc@471: (L'.EPrim (Prim.String "None"), loc)), adamc@471: adamc@471: ((L'.PSome (t, (L'.PVar ("x", t), loc)), loc), adamc@471: (L'.EStrcat ((L'.EPrim (Prim.String "Some/"), loc), adamc@471: body), loc))], adamc@471: {disc = tAll, adamc@471: result = (L'.TFfi ("Basis", "string"), loc)}), loc), adamc@471: fm) adamc@471: end adamc@471: adamc@758: | L'.TList t => adamc@758: let adamc@758: fun makeDecl n fm = adamc@758: let adamc@758: val rt = (L'.TRecord [("1", t), ("2", (L'.TList t, loc))], loc) adamc@758: val (arg, fm) = fooify fm ((L'.ERel 0, loc), rt) adamc@758: adamc@758: val branches = [((L'.PNone rt, loc), adamc@758: (L'.EPrim (Prim.String "Nil"), loc)), adamc@758: ((L'.PSome (rt, (L'.PVar ("a", rt), loc)), loc), adamc@758: (L'.EStrcat ((L'.EPrim (Prim.String "Cons/"), loc), adamc@758: arg), loc))] adamc@758: adamc@758: val dom = tAll adamc@758: val ran = (L'.TFfi ("Basis", "string"), loc) adamc@758: in adamc@758: ((L'.DValRec [(fk2s fk ^ "ify_list", adamc@758: n, adamc@758: (L'.TFun (dom, ran), loc), adamc@758: (L'.EAbs ("x", adamc@758: dom, adamc@758: ran, adamc@758: (L'.ECase ((L'.ERel 0, loc), adamc@758: branches, adamc@758: {disc = dom, adamc@758: result = ran}), loc)), loc), adamc@758: "")], loc), adamc@758: fm) adamc@758: end adamc@758: adamc@758: val (fm, n) = Fm.lookupList fm fk t makeDecl adamc@758: in adamc@758: ((L'.EApp ((L'.ENamed n, loc), e), loc), fm) adamc@758: end adamc@758: adamc@490: | _ => (E.errorAt loc "Don't know how to encode attribute/URL type"; adamc@120: Print.eprefaces' [("Type", MonoPrint.p_typ MonoEnv.empty tAll)]; adamc@179: (dummyExp, fm)) adamc@120: in adamc@120: fooify adamc@120: end adamc@120: adamc@179: val attrifyExp = fooifyExp Attr adamc@179: val urlifyExp = fooifyExp Url adamc@105: adamc@143: datatype 'a failable_search = adamc@143: Found of 'a adamc@143: | NotFound adamc@143: | Error adamc@143: adamc@153: structure St :> sig adamc@153: type t adamc@153: adamc@153: val empty : t adamc@153: adamc@153: val radioGroup : t -> string option adamc@153: val setRadioGroup : t * string -> t adamc@153: end = struct adamc@153: adamc@153: type t = { adamc@153: radioGroup : string option adamc@153: } adamc@153: adamc@153: val empty = {radioGroup = NONE} adamc@153: adamc@153: fun radioGroup (t : t) = #radioGroup t adamc@153: adamc@153: fun setRadioGroup (t : t, x) = {radioGroup = SOME x} adamc@153: adamc@153: end adamc@153: adamc@186: fun monoPatCon env pc = adamc@178: case pc of adamc@178: L.PConVar n => L'.PConVar n adamc@188: | L.PConFfi {mod = m, datatyp, con, arg, ...} => L'.PConFfi {mod = m, datatyp = datatyp, con = con, adamc@188: arg = Option.map (monoType env) arg} adamc@178: adamc@193: val dummyPat = (L'.PPrim (Prim.Int 0), ErrorMsg.dummySpan) adamc@193: adamc@757: adamc@757: fun listify t = (L'.TRecord [("1", t), ("2", (L'.TList t, #2 t))], #2 t) adamc@757: adamc@193: fun monoPat env (all as (p, loc)) = adamc@193: let adamc@193: fun poly () = adamc@193: (E.errorAt loc "Unsupported pattern"; adamc@193: Print.eprefaces' [("Pattern", CorePrint.p_pat env all)]; adamc@193: dummyPat) adamc@193: in adamc@193: case p of adamc@193: L.PWild => (L'.PWild, loc) adamc@193: | L.PVar (x, t) => (L'.PVar (x, monoType env t), loc) adamc@193: | L.PPrim p => (L'.PPrim p, loc) adamc@193: | L.PCon (dk, pc, [], po) => (L'.PCon (dk, monoPatCon env pc, Option.map (monoPat env) po), loc) adamc@757: | L.PCon (L.Option, L.PConFfi {mod = "Basis", datatyp = "list", ...}, [t], NONE) => adamc@757: (L'.PNone (listify (monoType env t)), loc) adamc@757: | L.PCon (L.Option, L.PConFfi {mod = "Basis", datatyp = "list", ...}, [t], SOME p) => adamc@757: (L'.PSome (listify (monoType env t), monoPat env p), loc) adamc@288: | L.PCon (L.Option, _, [t], NONE) => (L'.PNone (monoType env t), loc) adamc@757: | L.PCon (L.Option, pc, [t], SOME p) => (L'.PSome (monoType env t, monoPat env p), loc) adamc@193: | L.PCon _ => poly () adamc@193: | L.PRecord xps => (L'.PRecord (map (fn (x, p, t) => (x, monoPat env p, monoType env t)) xps), loc) adamc@193: end adamc@178: adamc@252: fun strcat loc es = adamc@252: case es of adamc@252: [] => (L'.EPrim (Prim.String ""), loc) adamc@252: | [e] => e adamc@252: | _ => adamc@252: let adamc@252: val e2 = List.last es adamc@252: val es = List.take (es, length es - 1) adamc@252: val e1 = List.last es adamc@252: val es = List.take (es, length es - 1) adamc@252: in adamc@252: foldr (fn (e, e') => (L'.EStrcat (e, e'), loc)) adamc@252: (L'.EStrcat (e1, e2), loc) es adamc@252: end adamc@252: adamc@252: fun strcatComma loc es = adamc@252: case es of adamc@252: [] => (L'.EPrim (Prim.String ""), loc) adamc@252: | [e] => e adamc@252: | _ => adamc@252: let adamc@252: val e1 = List.last es adamc@252: val es = List.take (es, length es - 1) adamc@252: in adamc@252: foldr (fn (e, e') => adamc@265: case (e, e') of adamc@265: ((L'.EPrim (Prim.String ""), _), _) => e' adamc@265: | (_, (L'.EPrim (Prim.String ""), _)) => e adamc@252: | _ => adamc@252: (L'.EStrcat (e, adamc@252: (L'.EStrcat ((L'.EPrim (Prim.String ", "), loc), e'), loc)), loc)) adamc@252: e1 es adamc@252: end adamc@252: adamc@252: fun strcatR loc e xs = strcatComma loc (map (fn (x, _) => (L'.EField (e, x), loc)) xs) adamc@252: adamc@735: val readCookie = ref IS.empty adamc@735: adamc@877: fun isBlobby (t : L.con) = adamc@877: case #1 t of adamc@877: L.CFfi ("Basis", "string") => true adamc@877: | L.CFfi ("Basis", "blob") => true adamc@877: | _ => false adamc@877: adamc@179: fun monoExp (env, st, fm) (all as (e, loc)) = adamc@25: let adamc@598: val strcat = strcat loc adamc@598: val strcatComma = strcatComma loc adamc@598: fun str s = (L'.EPrim (Prim.String s), loc) adamc@598: adamc@25: fun poly () = adamc@25: (E.errorAt loc "Unsupported expression"; adamc@25: Print.eprefaces' [("Expression", CorePrint.p_exp env all)]; adamc@179: (dummyExp, fm)) adamc@389: adamc@389: fun numTy t = adamc@417: (L'.TRecord [("Zero", t), adamc@417: ("Neg", (L'.TFun (t, t), loc)), adamc@389: ("Plus", (L'.TFun (t, (L'.TFun (t, t), loc)), loc)), adamc@389: ("Minus", (L'.TFun (t, (L'.TFun (t, t), loc)), loc)), adamc@389: ("Times", (L'.TFun (t, (L'.TFun (t, t), loc)), loc)), adamc@389: ("Div", (L'.TFun (t, (L'.TFun (t, t), loc)), loc)), adamc@389: ("Mod", (L'.TFun (t, (L'.TFun (t, t), loc)), loc))], loc) adamc@417: fun numEx (t, zero, neg, plus, minus, times, dv, md) = adamc@417: ((L'.ERecord [("Zero", (L'.EPrim zero, loc), t), adamc@417: ("Neg", neg, (L'.TFun (t, t), loc)), adamc@389: ("Plus", plus, (L'.TFun (t, (L'.TFun (t, t), loc)), loc)), adamc@389: ("Minus", minus, (L'.TFun (t, (L'.TFun (t, t), loc)), loc)), adamc@389: ("Times", times, (L'.TFun (t, (L'.TFun (t, t), loc)), loc)), adamc@389: ("Div", dv, (L'.TFun (t, (L'.TFun (t, t), loc)), loc)), adamc@389: ("Mod", md, (L'.TFun (t, (L'.TFun (t, t), loc)), loc))], loc), fm) adamc@391: adamc@391: fun ordTy t = adamc@391: (L'.TRecord [("Lt", (L'.TFun (t, (L'.TFun (t, (L'.TFfi ("Basis", "bool"), loc)), loc)), loc)), adamc@391: ("Le", (L'.TFun (t, (L'.TFun (t, (L'.TFfi ("Basis", "bool"), loc)), loc)), loc))], loc) adamc@391: fun ordEx (t, lt, le) = adamc@391: ((L'.ERecord [("Lt", lt, (L'.TFun (t, (L'.TFun (t, (L'.TFfi ("Basis", "bool"), loc)), loc)), loc)), adamc@391: ("Le", le, (L'.TFun (t, (L'.TFun (t, (L'.TFfi ("Basis", "bool"), loc)), loc)), loc))], adamc@391: loc), fm) adamc@750: adamc@750: fun outerRec xts = adamc@750: (L'.TRecord (map (fn ((L.CName x, _), (L.CRecord (_, xts), _)) => adamc@750: (x, (L'.TRecord (map (fn (x', _) => (x, (L'.TRecord [], loc))) xts), loc)) adamc@750: | (x, all as (_, loc)) => adamc@750: (E.errorAt loc "Unsupported record field constructor"; adamc@750: Print.eprefaces' [("Name", CorePrint.p_con env x), adamc@750: ("Constructor", CorePrint.p_con env all)]; adamc@750: ("", dummyTyp))) xts), loc) adamc@25: in adamc@25: case e of adamc@179: L.EPrim p => ((L'.EPrim p, loc), fm) adamc@179: | L.ERel n => ((L'.ERel n, loc), fm) adamc@179: | L.ENamed n => ((L'.ENamed n, loc), fm) adamc@193: | L.ECon (dk, pc, [], eo) => adamc@193: let adamc@179: val (eo, fm) = adamc@179: case eo of adamc@179: NONE => (NONE, fm) adamc@179: | SOME e => adamc@179: let adamc@179: val (e, fm) = monoExp (env, st, fm) e adamc@179: in adamc@179: (SOME e, fm) adamc@179: end adamc@179: in adamc@188: ((L'.ECon (dk, monoPatCon env pc, eo), loc), fm) adamc@193: end adamc@757: | L.ECon (L.Option, L.PConFfi {mod = "Basis", datatyp = "list", ...}, [t], NONE) => adamc@757: ((L'.ENone (listify (monoType env t)), loc), fm) adamc@757: | L.ECon (L.Option, L.PConFfi {mod = "Basis", datatyp = "list", ...}, [t], SOME e) => adamc@757: let adamc@757: val (e, fm) = monoExp (env, st, fm) e adamc@757: in adamc@757: ((L'.ESome (listify (monoType env t), e), loc), fm) adamc@757: end adamc@297: | L.ECon (L.Option, _, [t], NONE) => adamc@297: ((L'.ENone (monoType env t), loc), fm) adamc@297: | L.ECon (L.Option, _, [t], SOME e) => adamc@297: let adamc@297: val (e, fm) = monoExp (env, st, fm) e adamc@297: in adamc@297: ((L'.ESome (monoType env t, e), loc), fm) adamc@297: end adamc@193: | L.ECon _ => poly () adamc@94: adamc@387: | L.ECApp ((L.EFfi ("Basis", "eq"), _), t) => adamc@387: let adamc@387: val t = monoType env t adamc@387: val b = (L'.TFfi ("Basis", "bool"), loc) adamc@387: val dom = (L'.TFun (t, (L'.TFun (t, b), loc)), loc) adamc@387: in adamc@387: ((L'.EAbs ("f", dom, dom, adamc@387: (L'.ERel 0, loc)), loc), fm) adamc@387: end adamc@387: | L.ECApp ((L.EFfi ("Basis", "ne"), _), t) => adamc@387: let adamc@387: val t = monoType env t adamc@387: val b = (L'.TFfi ("Basis", "bool"), loc) adamc@387: val dom = (L'.TFun (t, (L'.TFun (t, b), loc)), loc) adamc@387: in adamc@387: ((L'.EAbs ("f", dom, dom, adamc@387: (L'.EAbs ("x", t, (L'.TFun (t, b), loc), adamc@387: (L'.EAbs ("y", t, b, adamc@387: (L'.EUnop ("!", (L'.EApp ((L'.EApp ((L'.ERel 2, loc), adamc@387: (L'.ERel 1, loc)), loc), adamc@387: (L'.ERel 0, loc)), loc)), loc)), adamc@387: loc)), adamc@387: loc)), adamc@387: loc), fm) adamc@387: end adamc@387: | L.EFfi ("Basis", "eq_int") => adamc@387: ((L'.EAbs ("x", (L'.TFfi ("Basis", "int"), loc), adamc@387: (L'.TFun ((L'.TFfi ("Basis", "int"), loc), (L'.TFfi ("Basis", "bool"), loc)), loc), adamc@387: (L'.EAbs ("y", (L'.TFfi ("Basis", "int"), loc), adamc@387: (L'.TFfi ("Basis", "bool"), loc), adamc@387: (L'.EBinop ("==", (L'.ERel 1, loc), (L'.ERel 0, loc)), loc)), loc)), loc), adamc@387: fm) adamc@394: | L.EFfi ("Basis", "eq_float") => adamc@394: ((L'.EAbs ("x", (L'.TFfi ("Basis", "float"), loc), adamc@394: (L'.TFun ((L'.TFfi ("Basis", "float"), loc), (L'.TFfi ("Basis", "bool"), loc)), loc), adamc@394: (L'.EAbs ("y", (L'.TFfi ("Basis", "float"), loc), adamc@394: (L'.TFfi ("Basis", "bool"), loc), adamc@394: (L'.EBinop ("==", (L'.ERel 1, loc), (L'.ERel 0, loc)), loc)), loc)), loc), adamc@394: fm) adamc@388: | L.EFfi ("Basis", "eq_bool") => adamc@388: ((L'.EAbs ("x", (L'.TFfi ("Basis", "bool"), loc), adamc@388: (L'.TFun ((L'.TFfi ("Basis", "bool"), loc), (L'.TFfi ("Basis", "bool"), loc)), loc), adamc@388: (L'.EAbs ("y", (L'.TFfi ("Basis", "bool"), loc), adamc@388: (L'.TFfi ("Basis", "bool"), loc), adamc@388: (L'.EBinop ("==", (L'.ERel 1, loc), (L'.ERel 0, loc)), loc)), loc)), loc), adamc@388: fm) adamc@388: | L.EFfi ("Basis", "eq_string") => adamc@388: ((L'.EAbs ("x", (L'.TFfi ("Basis", "string"), loc), adamc@388: (L'.TFun ((L'.TFfi ("Basis", "string"), loc), (L'.TFfi ("Basis", "bool"), loc)), loc), adamc@388: (L'.EAbs ("y", (L'.TFfi ("Basis", "string"), loc), adamc@388: (L'.TFfi ("Basis", "bool"), loc), adamc@388: (L'.EBinop ("!strcmp", (L'.ERel 1, loc), (L'.ERel 0, loc)), loc)), loc)), loc), adamc@388: fm) adamc@821: | L.EFfi ("Basis", "eq_char") => adamc@821: ((L'.EAbs ("x", (L'.TFfi ("Basis", "char"), loc), adamc@821: (L'.TFun ((L'.TFfi ("Basis", "char"), loc), (L'.TFfi ("Basis", "bool"), loc)), loc), adamc@821: (L'.EAbs ("y", (L'.TFfi ("Basis", "char"), loc), adamc@821: (L'.TFfi ("Basis", "bool"), loc), adamc@821: (L'.EBinop ("==", (L'.ERel 1, loc), (L'.ERel 0, loc)), loc)), loc)), loc), adamc@821: fm) adamc@437: | L.EFfi ("Basis", "eq_time") => adamc@437: ((L'.EAbs ("x", (L'.TFfi ("Basis", "time"), loc), adamc@437: (L'.TFun ((L'.TFfi ("Basis", "time"), loc), (L'.TFfi ("Basis", "bool"), loc)), loc), adamc@437: (L'.EAbs ("y", (L'.TFfi ("Basis", "time"), loc), adamc@437: (L'.TFfi ("Basis", "bool"), loc), adamc@437: (L'.EBinop ("==", (L'.ERel 1, loc), (L'.ERel 0, loc)), loc)), loc)), loc), adamc@437: fm) adamc@844: adamc@422: | L.ECApp ((L.EFfi ("Basis", "mkEq"), _), t) => adamc@422: let adamc@422: val t = monoType env t adamc@422: val b = (L'.TFfi ("Basis", "bool"), loc) adamc@422: val dom = (L'.TFun (t, (L'.TFun (t, b), loc)), loc) adamc@422: in adamc@422: ((L'.EAbs ("f", dom, dom, adamc@422: (L'.ERel 0, loc)), loc), fm) adamc@422: end adamc@387: adamc@417: | L.ECApp ((L.EFfi ("Basis", "zero"), _), t) => adamc@417: let adamc@417: val t = monoType env t adamc@417: in adamc@417: ((L'.EAbs ("r", numTy t, t, adamc@417: (L'.EField ((L'.ERel 0, loc), "Zero"), loc)), loc), fm) adamc@417: end adamc@389: | L.ECApp ((L.EFfi ("Basis", "neg"), _), t) => adamc@389: let adamc@389: val t = monoType env t adamc@389: in adamc@389: ((L'.EAbs ("r", numTy t, (L'.TFun (t, t), loc), adamc@389: (L'.EField ((L'.ERel 0, loc), "Neg"), loc)), loc), fm) adamc@389: end adamc@389: | L.ECApp ((L.EFfi ("Basis", "plus"), _), t) => adamc@389: let adamc@389: val t = monoType env t adamc@389: in adamc@389: ((L'.EAbs ("r", numTy t, (L'.TFun (t, (L'.TFun (t, t), loc)), loc), adamc@389: (L'.EField ((L'.ERel 0, loc), "Plus"), loc)), loc), fm) adamc@389: end adamc@389: | L.ECApp ((L.EFfi ("Basis", "minus"), _), t) => adamc@389: let adamc@389: val t = monoType env t adamc@389: in adamc@389: ((L'.EAbs ("r", numTy t, (L'.TFun (t, (L'.TFun (t, t), loc)), loc), adamc@389: (L'.EField ((L'.ERel 0, loc), "Minus"), loc)), loc), fm) adamc@389: end adamc@389: | L.ECApp ((L.EFfi ("Basis", "times"), _), t) => adamc@389: let adamc@389: val t = monoType env t adamc@389: in adamc@389: ((L'.EAbs ("r", numTy t, (L'.TFun (t, (L'.TFun (t, t), loc)), loc), adamc@389: (L'.EField ((L'.ERel 0, loc), "Times"), loc)), loc), fm) adamc@389: end adamc@775: | L.ECApp ((L.EFfi ("Basis", "divide"), _), t) => adamc@389: let adamc@389: val t = monoType env t adamc@389: in adamc@389: ((L'.EAbs ("r", numTy t, (L'.TFun (t, (L'.TFun (t, t), loc)), loc), adamc@389: (L'.EField ((L'.ERel 0, loc), "Div"), loc)), loc), fm) adamc@389: end adamc@389: | L.ECApp ((L.EFfi ("Basis", "mod"), _), t) => adamc@389: let adamc@389: val t = monoType env t adamc@389: in adamc@389: ((L'.EAbs ("r", numTy t, (L'.TFun (t, (L'.TFun (t, t), loc)), loc), adamc@389: (L'.EField ((L'.ERel 0, loc), "Mod"), loc)), loc), fm) adamc@389: end adamc@389: | L.EFfi ("Basis", "num_int") => adamc@389: let adamc@389: fun intBin s = adamc@389: (L'.EAbs ("x", (L'.TFfi ("Basis", "int"), loc), adamc@389: (L'.TFun ((L'.TFfi ("Basis", "int"), loc), (L'.TFfi ("Basis", "int"), loc)), loc), adamc@389: (L'.EAbs ("y", (L'.TFfi ("Basis", "int"), loc), adamc@389: (L'.TFfi ("Basis", "int"), loc), adamc@389: (L'.EBinop (s, (L'.ERel 1, loc), (L'.ERel 0, loc)), loc)), loc)), loc) adamc@389: in adamc@389: numEx ((L'.TFfi ("Basis", "int"), loc), adamc@417: Prim.Int (Int64.fromInt 0), adamc@389: (L'.EAbs ("x", (L'.TFfi ("Basis", "int"), loc), adamc@389: (L'.TFfi ("Basis", "int"), loc), adamc@389: (L'.EUnop ("-", (L'.ERel 0, loc)), loc)), loc), adamc@389: intBin "+", adamc@389: intBin "-", adamc@389: intBin "*", adamc@389: intBin "/", adamc@389: intBin "%") adamc@389: end adamc@390: | L.EFfi ("Basis", "num_float") => adamc@390: let adamc@390: fun floatBin s = adamc@390: (L'.EAbs ("x", (L'.TFfi ("Basis", "float"), loc), adamc@390: (L'.TFun ((L'.TFfi ("Basis", "float"), loc), (L'.TFfi ("Basis", "float"), loc)), loc), adamc@390: (L'.EAbs ("y", (L'.TFfi ("Basis", "float"), loc), adamc@390: (L'.TFfi ("Basis", "float"), loc), adamc@390: (L'.EBinop (s, (L'.ERel 1, loc), (L'.ERel 0, loc)), loc)), loc)), loc) adamc@390: in adamc@390: numEx ((L'.TFfi ("Basis", "float"), loc), adamc@417: Prim.Float 0.0, adamc@390: (L'.EAbs ("x", (L'.TFfi ("Basis", "float"), loc), adamc@390: (L'.TFfi ("Basis", "float"), loc), adamc@390: (L'.EUnop ("-", (L'.ERel 0, loc)), loc)), loc), adamc@390: floatBin "+", adamc@390: floatBin "-", adamc@390: floatBin "*", adamc@390: floatBin "/", adamc@390: floatBin "fmod") adamc@390: end adamc@391: adamc@391: | L.ECApp ((L.EFfi ("Basis", "lt"), _), t) => adamc@391: let adamc@391: val t = monoType env t adamc@391: in adamc@391: ((L'.EAbs ("r", ordTy t, (L'.TFun (t, (L'.TFun (t, (L'.TFfi ("Basis", "bool"), loc)), loc)), loc), adamc@391: (L'.EField ((L'.ERel 0, loc), "Lt"), loc)), loc), fm) adamc@391: end adamc@391: | L.ECApp ((L.EFfi ("Basis", "le"), _), t) => adamc@391: let adamc@391: val t = monoType env t adamc@391: in adamc@391: ((L'.EAbs ("r", ordTy t, (L'.TFun (t, (L'.TFun (t, (L'.TFfi ("Basis", "bool"), loc)), loc)), loc), adamc@391: (L'.EField ((L'.ERel 0, loc), "Le"), loc)), loc), fm) adamc@391: end adamc@392: | L.ECApp ((L.EFfi ("Basis", "gt"), _), t) => adamc@392: let adamc@392: val t = monoType env t adamc@392: val b = (L'.TFfi ("Basis", "bool"), loc) adamc@392: in adamc@392: ((L'.EAbs ("f", ordTy t, (L'.TFun (t, (L'.TFun (t, b), loc)), loc), adamc@392: (L'.EAbs ("x", t, (L'.TFun (t, b), loc), adamc@392: (L'.EAbs ("y", t, b, adamc@392: (L'.EUnop ("!", adamc@392: (L'.EApp ((L'.EApp ((L'.EField ((L'.ERel 2, loc), adamc@392: "Le"), loc), adamc@392: (L'.ERel 1, loc)), loc), adamc@392: (L'.ERel 0, loc)), loc)), loc)), loc)), adamc@392: loc)), adamc@392: loc), fm) adamc@392: end adamc@392: | L.ECApp ((L.EFfi ("Basis", "ge"), _), t) => adamc@392: let adamc@392: val t = monoType env t adamc@392: val b = (L'.TFfi ("Basis", "bool"), loc) adamc@392: in adamc@392: ((L'.EAbs ("f", ordTy t, (L'.TFun (t, (L'.TFun (t, b), loc)), loc), adamc@392: (L'.EAbs ("x", t, (L'.TFun (t, b), loc), adamc@392: (L'.EAbs ("y", t, b, adamc@392: (L'.EUnop ("!", adamc@392: (L'.EApp ((L'.EApp ((L'.EField ((L'.ERel 2, loc), adamc@392: "Lt"), loc), adamc@392: (L'.ERel 1, loc)), loc), adamc@392: (L'.ERel 0, loc)), loc)), loc)), loc)), adamc@392: loc)), adamc@392: loc), fm) adamc@392: end adamc@391: | L.EFfi ("Basis", "ord_int") => adamc@391: let adamc@391: fun intBin s = adamc@391: (L'.EAbs ("x", (L'.TFfi ("Basis", "int"), loc), adamc@391: (L'.TFun ((L'.TFfi ("Basis", "int"), loc), (L'.TFfi ("Basis", "bool"), loc)), loc), adamc@391: (L'.EAbs ("y", (L'.TFfi ("Basis", "int"), loc), adamc@391: (L'.TFfi ("Basis", "bool"), loc), adamc@391: (L'.EBinop (s, (L'.ERel 1, loc), (L'.ERel 0, loc)), loc)), loc)), loc) adamc@391: in adamc@391: ordEx ((L'.TFfi ("Basis", "int"), loc), adamc@391: intBin "<", adamc@391: intBin "<=") adamc@391: end adamc@394: | L.EFfi ("Basis", "ord_float") => adamc@394: let adamc@394: fun floatBin s = adamc@394: (L'.EAbs ("x", (L'.TFfi ("Basis", "float"), loc), adamc@394: (L'.TFun ((L'.TFfi ("Basis", "float"), loc), (L'.TFfi ("Basis", "bool"), loc)), loc), adamc@394: (L'.EAbs ("y", (L'.TFfi ("Basis", "float"), loc), adamc@394: (L'.TFfi ("Basis", "bool"), loc), adamc@394: (L'.EBinop (s, (L'.ERel 1, loc), (L'.ERel 0, loc)), loc)), loc)), loc) adamc@394: in adamc@394: ordEx ((L'.TFfi ("Basis", "float"), loc), adamc@394: floatBin "<", adamc@394: floatBin "<=") adamc@394: end adamc@394: | L.EFfi ("Basis", "ord_bool") => adamc@394: let adamc@394: fun boolBin s = adamc@394: (L'.EAbs ("x", (L'.TFfi ("Basis", "bool"), loc), adamc@394: (L'.TFun ((L'.TFfi ("Basis", "bool"), loc), (L'.TFfi ("Basis", "bool"), loc)), loc), adamc@394: (L'.EAbs ("y", (L'.TFfi ("Basis", "bool"), loc), adamc@394: (L'.TFfi ("Basis", "bool"), loc), adamc@394: (L'.EBinop (s, (L'.ERel 1, loc), (L'.ERel 0, loc)), loc)), loc)), loc) adamc@394: in adamc@394: ordEx ((L'.TFfi ("Basis", "bool"), loc), adamc@394: boolBin "<", adamc@394: boolBin "<=") adamc@394: end adamc@395: | L.EFfi ("Basis", "ord_string") => adamc@395: let adamc@395: fun boolBin s = adamc@395: (L'.EAbs ("x", (L'.TFfi ("Basis", "string"), loc), adamc@395: (L'.TFun ((L'.TFfi ("Basis", "string"), loc), (L'.TFfi ("Basis", "bool"), loc)), loc), adamc@395: (L'.EAbs ("y", (L'.TFfi ("Basis", "string"), loc), adamc@395: (L'.TFfi ("Basis", "bool"), loc), adamc@395: (L'.EBinop (s, adamc@395: (L'.EBinop ("strcmp", adamc@395: (L'.ERel 1, loc), adamc@395: (L'.ERel 0, loc)), loc), adamc@395: (L'.EPrim (Prim.Int (Int64.fromInt 0)), loc)), loc)), loc)), loc) adamc@395: in adamc@395: ordEx ((L'.TFfi ("Basis", "string"), loc), adamc@395: boolBin "<", adamc@395: boolBin "<=") adamc@395: end adamc@821: | L.EFfi ("Basis", "ord_char") => adamc@821: let adamc@821: fun charBin s = adamc@821: (L'.EAbs ("x", (L'.TFfi ("Basis", "char"), loc), adamc@821: (L'.TFun ((L'.TFfi ("Basis", "char"), loc), (L'.TFfi ("Basis", "bool"), loc)), loc), adamc@821: (L'.EAbs ("y", (L'.TFfi ("Basis", "char"), loc), adamc@821: (L'.TFfi ("Basis", "bool"), loc), adamc@821: (L'.EBinop (s, (L'.ERel 1, loc), (L'.ERel 0, loc)), loc)), loc)), loc) adamc@821: in adamc@821: ordEx ((L'.TFfi ("Basis", "char"), loc), adamc@821: charBin "<", adamc@821: charBin "<=") adamc@821: end adamc@437: | L.EFfi ("Basis", "ord_time") => adamc@437: let adamc@437: fun boolBin s = adamc@437: (L'.EAbs ("x", (L'.TFfi ("Basis", "time"), loc), adamc@437: (L'.TFun ((L'.TFfi ("Basis", "time"), loc), (L'.TFfi ("Basis", "bool"), loc)), loc), adamc@437: (L'.EAbs ("y", (L'.TFfi ("Basis", "time"), loc), adamc@437: (L'.TFfi ("Basis", "bool"), loc), adamc@437: (L'.EBinop (s, (L'.ERel 1, loc), (L'.ERel 0, loc)), loc)), loc)), loc) adamc@437: in adamc@437: ordEx ((L'.TFfi ("Basis", "time"), loc), adamc@437: boolBin "<", adamc@437: boolBin "<=") adamc@437: end adamc@961: | L.ECApp ((L.EFfi ("Basis", "mkOrd"), _), t) => adamc@961: let adamc@961: val t = monoType env t adamc@961: val b = (L'.TFfi ("Basis", "bool"), loc) adamc@961: val dom = ordTy t adamc@961: in adamc@961: ((L'.EAbs ("f", dom, dom, adamc@961: (L'.ERel 0, loc)), loc), fm) adamc@961: end adamc@389: adamc@286: | L.ECApp ((L.EFfi ("Basis", "show"), _), t) => adamc@286: let adamc@286: val t = monoType env t adamc@286: val s = (L'.TFfi ("Basis", "string"), loc) adamc@286: in adamc@286: ((L'.EAbs ("f", (L'.TFun (t, s), loc), (L'.TFun (t, s), loc), adamc@286: (L'.ERel 0, loc)), loc), fm) adamc@286: end adamc@286: | L.EFfi ("Basis", "show_int") => adamc@286: ((L'.EFfi ("Basis", "intToString"), loc), fm) adamc@286: | L.EFfi ("Basis", "show_float") => adamc@286: ((L'.EFfi ("Basis", "floatToString"), loc), fm) adamc@286: | L.EFfi ("Basis", "show_string") => adamc@286: let adamc@286: val s = (L'.TFfi ("Basis", "string"), loc) adamc@286: in adamc@286: ((L'.EAbs ("s", s, s, (L'.ERel 0, loc)), loc), fm) adamc@286: end adamc@1065: | L.EFfi ("Basis", "show_url") => adamc@1065: let adamc@1065: val s = (L'.TFfi ("Basis", "string"), loc) adamc@1065: in adamc@1065: ((L'.EAbs ("s", s, s, (L'.ERel 0, loc)), loc), fm) adamc@1065: end adamc@821: | L.EFfi ("Basis", "show_char") => adamc@821: ((L'.EFfi ("Basis", "charToString"), loc), fm) adamc@286: | L.EFfi ("Basis", "show_bool") => adamc@286: ((L'.EFfi ("Basis", "boolToString"), loc), fm) adamc@436: | L.EFfi ("Basis", "show_time") => adamc@436: ((L'.EFfi ("Basis", "timeToString"), loc), fm) adamc@727: | L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "show_xml"), _), _),_), _), _), _) => adamc@727: let adamc@727: val s = (L'.TFfi ("Basis", "string"), loc) adamc@727: in adamc@727: ((L'.EAbs ("s", s, s, (L'.ERel 0, loc)), loc), fm) adamc@727: end adamc@452: | L.ECApp ((L.EFfi ("Basis", "mkShow"), _), t) => adamc@452: let adamc@452: val t = monoType env t adamc@452: val b = (L'.TFfi ("Basis", "string"), loc) adamc@452: val dom = (L'.TFun (t, b), loc) adamc@452: in adamc@452: ((L'.EAbs ("f", dom, dom, adamc@452: (L'.ERel 0, loc)), loc), fm) adamc@452: end adamc@286: adamc@290: | L.ECApp ((L.EFfi ("Basis", "read"), _), t) => adamc@290: let adamc@290: val t = monoType env t adamc@290: val s = (L'.TFfi ("Basis", "string"), loc) adamc@290: in adamc@292: ((L'.EAbs ("f", readType (t, loc), readType' (t, loc), adamc@292: (L'.EField ((L'.ERel 0, loc), "Read"), loc)), loc), fm) adamc@292: end adamc@292: | L.ECApp ((L.EFfi ("Basis", "readError"), _), t) => adamc@292: let adamc@292: val t = monoType env t adamc@292: val s = (L'.TFfi ("Basis", "string"), loc) adamc@292: in adamc@292: ((L'.EAbs ("f", readType (t, loc), readErrType (t, loc), adamc@292: (L'.EField ((L'.ERel 0, loc), "ReadError"), loc)), loc), fm) adamc@290: end adamc@777: | L.ECApp ((L.EFfi ("Basis", "mkRead"), _), t) => adamc@777: let adamc@777: val t = monoType env t adamc@777: val b = (L'.TFfi ("Basis", "string"), loc) adamc@777: val b' = (L'.TOption b, loc) adamc@777: val dom = (L'.TFun (t, b), loc) adamc@777: val dom' = (L'.TFun (t, b'), loc) adamc@777: in adamc@777: ((L'.EAbs ("f", dom, (L'.TFun (dom', readType (t, loc)), loc), adamc@777: (L'.EAbs ("f'", dom', readType (t, loc), adamc@777: (L'.ERecord [("Read", (L'.ERel 0, loc), dom), adamc@777: ("ReadError", (L'.ERel 1, loc), dom')], loc)), loc)), loc), adamc@777: fm) adamc@777: end adamc@290: | L.EFfi ("Basis", "read_int") => adamc@292: let adamc@292: val t = (L'.TFfi ("Basis", "int"), loc) adamc@292: in adamc@292: ((L'.ERecord [("Read", (L'.EFfi ("Basis", "stringToInt"), loc), readType' (t, loc)), adamc@292: ("ReadError", (L'.EFfi ("Basis", "stringToInt_error"), loc), readErrType (t, loc))], adamc@292: loc), adamc@292: fm) adamc@292: end adamc@290: | L.EFfi ("Basis", "read_float") => adamc@292: let adamc@292: val t = (L'.TFfi ("Basis", "float"), loc) adamc@292: in adamc@292: ((L'.ERecord [("Read", (L'.EFfi ("Basis", "stringToFloat"), loc), readType' (t, loc)), adamc@292: ("ReadError", (L'.EFfi ("Basis", "stringToFloat_error"), loc), readErrType (t, loc))], adamc@292: loc), adamc@292: fm) adamc@292: end adamc@290: | L.EFfi ("Basis", "read_string") => adamc@290: let adamc@290: val s = (L'.TFfi ("Basis", "string"), loc) adamc@290: in adamc@292: ((L'.ERecord [("Read", (L'.EAbs ("s", s, (L'.TOption s, loc), adamc@292: (L'.ESome (s, (L'.ERel 0, loc)), loc)), loc), readType' (s, loc)), adamc@292: ("ReadError", (L'.EAbs ("s", s, s, (L'.ERel 0, loc)), loc), readErrType (s, loc))], loc), adamc@292: fm) adamc@290: end adamc@821: | L.EFfi ("Basis", "read_char") => adamc@821: let adamc@821: val t = (L'.TFfi ("Basis", "char"), loc) adamc@821: in adamc@821: ((L'.ERecord [("Read", (L'.EFfi ("Basis", "stringToChar"), loc), readType' (t, loc)), adamc@821: ("ReadError", (L'.EFfi ("Basis", "stringToChar_error"), loc), readErrType (t, loc))], adamc@821: loc), adamc@821: fm) adamc@821: end adamc@290: | L.EFfi ("Basis", "read_bool") => adamc@292: let adamc@292: val t = (L'.TFfi ("Basis", "bool"), loc) adamc@292: in adamc@292: ((L'.ERecord [("Read", (L'.EFfi ("Basis", "stringToBool"), loc), readType' (t, loc)), adamc@292: ("ReadError", (L'.EFfi ("Basis", "stringToBool_error"), loc), readErrType (t, loc))], adamc@292: loc), adamc@292: fm) adamc@292: end adamc@436: | L.EFfi ("Basis", "read_time") => adamc@436: let adamc@436: val t = (L'.TFfi ("Basis", "time"), loc) adamc@436: in adamc@436: ((L'.ERecord [("Read", (L'.EFfi ("Basis", "stringToTime"), loc), readType' (t, loc)), adamc@436: ("ReadError", (L'.EFfi ("Basis", "stringToTime_error"), loc), readErrType (t, loc))], adamc@436: loc), adamc@436: fm) adamc@436: end adamc@290: adamc@820: | L.EFfi ("Basis", "transaction_monad") => ((L'.ERecord [], loc), fm) adamc@820: | L.ECApp ((L.ECApp ((L.EFfi ("Basis", "return"), _), (L.CFfi ("Basis", "transaction"), _)), _), t) => adamc@252: let adamc@252: val t = monoType env t adamc@252: in adamc@820: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFun (t, (L'.TFun ((L'.TRecord [], loc), t), loc)), loc), adamc@820: (L'.EAbs ("x", t, adamc@820: (L'.TFun ((L'.TRecord [], loc), t), loc), adamc@820: (L'.EAbs ("_", (L'.TRecord [], loc), t, adamc@820: (L'.ERel 1, loc)), loc)), loc)), loc), adamc@820: fm) adamc@252: end adamc@820: | L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "bind"), _), (L.CFfi ("Basis", "transaction"), _)), _), adamc@820: t1), _), t2) => adamc@251: let adamc@251: val t1 = monoType env t1 adamc@251: val t2 = monoType env t2 adamc@251: val un = (L'.TRecord [], loc) adamc@252: val mt1 = (L'.TFun (un, t1), loc) adamc@252: val mt2 = (L'.TFun (un, t2), loc) adamc@251: in adamc@820: ((L'.EAbs ("_", un, adamc@820: (L'.TFun (mt1, (L'.TFun ((L'.TFun (t1, mt2), loc), (L'.TFun (un, un), loc)), loc)), loc), adamc@820: (L'.EAbs ("m1", mt1, (L'.TFun ((L'.TFun (t1, mt2), loc), (L'.TFun (un, un), loc)), loc), adamc@820: (L'.EAbs ("m2", (L'.TFun (t1, mt2), loc), (L'.TFun (un, un), loc), adamc@820: (L'.EAbs ("_", un, un, adamc@820: (L'.ELet ("r", t1, (L'.EApp ((L'.ERel 2, loc), adamc@820: (L'.ERecord [], loc)), loc), adamc@820: (L'.EApp ( adamc@820: (L'.EApp ((L'.ERel 2, loc), (L'.ERel 0, loc)), loc), adamc@820: (L'.ERecord [], loc)), adamc@820: loc)), loc)), loc)), loc)), loc)), loc), adamc@251: fm) adamc@251: end adamc@697: adamc@1021: | L.EApp ((L.ECApp ((L.EFfi ("Basis", "recv"), _), t1), _), ch) => adamc@670: let adamc@1021: val un = (L'.TRecord [], loc) adamc@670: val t1 = monoType env t1 adamc@670: val (ch, fm) = monoExp (env, st, fm) ch adamc@670: in adamc@1021: ((L'.EAbs ("_", un, un, (L'.ERecv (liftExpInExp 0 ch, t1), loc)), loc), fm) adamc@670: end adamc@697: | L.EFfiApp ("Basis", "recv", _) => poly () adamc@697: adamc@1021: | L.EFfiApp ("Basis", "sleep", [n]) => adamc@695: let adamc@695: val (n, fm) = monoExp (env, st, fm) n adamc@695: in adamc@1021: ((L'.ESleep n, loc), fm) adamc@695: end adamc@697: | L.EFfiApp ("Basis", "sleep", _) => poly () adamc@251: adamc@565: | L.ECApp ((L.EFfi ("Basis", "source"), _), t) => adamc@565: let adamc@565: val t = monoType env t adamc@565: in adamc@577: ((L'.EAbs ("x", t, (L'.TFun ((L'.TRecord [], loc), (L'.TSource, loc)), loc), adamc@577: (L'.EAbs ("_", (L'.TRecord [], loc), (L'.TSource, loc), adamc@577: (L'.EFfiApp ("Basis", "new_client_source", adamc@815: [(L'.EJavaScript (L'.Source t, (L'.ERel 1, loc)), loc)]), adamc@578: loc)), loc)), adamc@565: loc), adamc@565: fm) adamc@565: end adamc@575: | L.ECApp ((L.EFfi ("Basis", "set"), _), t) => adamc@575: let adamc@575: val t = monoType env t adamc@575: in adamc@577: ((L'.EAbs ("src", (L'.TSource, loc), adamc@575: (L'.TFun (t, (L'.TFun ((L'.TRecord [], loc), (L'.TRecord [], loc)), loc)), loc), adamc@575: (L'.EAbs ("v", t, (L'.TFun ((L'.TRecord [], loc), (L'.TRecord [], loc)), loc), adamc@575: (L'.EAbs ("_", (L'.TRecord [], loc), (L'.TRecord [], loc), adamc@575: (L'.EFfiApp ("Basis", "set_client_source", adamc@577: [(L'.ERel 2, loc), adamc@590: (L'.EJavaScript (L'.Source t, adamc@815: (L'.ERel 1, loc)), loc)]), adamc@575: loc)), loc)), loc)), loc), adamc@575: fm) adamc@575: end adamc@601: | L.ECApp ((L.EFfi ("Basis", "get"), _), t) => adamc@601: let adamc@601: val t = monoType env t adamc@601: in adamc@601: ((L'.EAbs ("src", (L'.TSource, loc), adamc@601: (L'.TFun ((L'.TRecord [], loc), t), loc), adamc@601: (L'.EAbs ("_", (L'.TRecord [], loc), t, adamc@601: (L'.EFfiApp ("Basis", "get_client_source", adamc@601: [(L'.ERel 1, loc)]), adamc@601: loc)), loc)), loc), adamc@601: fm) adamc@601: end adamc@841: | L.ECApp ((L.EFfi ("Basis", "current"), _), t) => adamc@841: let adamc@841: val t = monoType env t adamc@841: in adamc@841: ((L'.EAbs ("src", (L'.TSource, loc), adamc@841: (L'.TFun ((L'.TRecord [], loc), t), loc), adamc@841: (L'.EAbs ("_", (L'.TRecord [], loc), t, adamc@841: (L'.EFfiApp ("Basis", "current", adamc@841: [(L'.ERel 1, loc)]), adamc@841: loc)), loc)), loc), adamc@841: fm) adamc@841: end adamc@565: adamc@694: | L.EFfiApp ("Basis", "spawn", [e]) => adamc@694: let adamc@694: val (e, fm) = monoExp (env, st, fm) e adamc@694: in adamc@1021: ((L'.ESpawn e, loc), fm) adamc@694: end adamc@694: adamc@820: | L.EFfi ("Basis", "signal_monad") => ((L'.ERecord [], loc), fm) adamc@820: | L.ECApp ((L.ECApp ((L.EFfi ("Basis", "return"), _), (L.CFfi ("Basis", "signal"), _)), _), t) => adamc@568: let adamc@568: val t = monoType env t adamc@568: in adamc@820: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFun (t, (L'.TSignal t, loc)), loc), adamc@820: (L'.EAbs ("x", t, (L'.TSignal t, loc), adamc@820: (L'.ESignalReturn (L'.ERel 0, loc), loc)), loc)), loc), adamc@568: fm) adamc@568: end adamc@820: | L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "bind"), _), (L.CFfi ("Basis", "signal"), _)), _), adamc@820: t1), _), t2) => adamc@572: let adamc@572: val t1 = monoType env t1 adamc@572: val t2 = monoType env t2 adamc@572: val un = (L'.TRecord [], loc) adamc@572: val mt1 = (L'.TSignal t1, loc) adamc@572: val mt2 = (L'.TSignal t2, loc) adamc@572: in adamc@820: ((L'.EAbs ("_", un, (L'.TFun (mt1, (L'.TFun ((L'.TFun (t1, mt2), loc), mt2), loc)), loc), adamc@820: (L'.EAbs ("m1", mt1, (L'.TFun ((L'.TFun (t1, mt2), loc), mt2), loc), adamc@820: (L'.EAbs ("m2", (L'.TFun (t1, mt2), loc), mt2, adamc@820: (L'.ESignalBind ((L'.ERel 1, loc), (L'.ERel 0, loc)), loc)), loc)), loc)), adamc@820: loc), adamc@572: fm) adamc@572: end adamc@574: | L.ECApp ((L.EFfi ("Basis", "signal"), _), t) => adamc@574: let adamc@574: val t = monoType env t adamc@574: in adamc@574: ((L'.EAbs ("x", (L'.TFfi ("Basis", "int"), loc), (L'.TSignal t, loc), adamc@574: (L'.ESignalSource (L'.ERel 0, loc), loc)), loc), adamc@574: fm) adamc@574: end adamc@568: adamc@462: | L.ECApp ((L.EFfi ("Basis", "getCookie"), _), t) => adamc@462: let adamc@462: val s = (L'.TFfi ("Basis", "string"), loc) adamc@462: val un = (L'.TRecord [], loc) adamc@462: val t = monoType env t adamc@462: in adamc@462: ((L'.EAbs ("c", s, (L'.TFun (un, s), loc), adamc@462: (L'.EAbs ("_", un, s, adamc@463: (L'.EUnurlify ((L'.EFfiApp ("Basis", "get_cookie", [(L'.ERel 1, loc)]), loc), adamc@1112: t, true), adamc@463: loc)), loc)), loc), adamc@462: fm) adamc@462: end adamc@462: adamc@462: | L.ECApp ((L.EFfi ("Basis", "setCookie"), _), t) => adamc@462: let adamc@462: val s = (L'.TFfi ("Basis", "string"), loc) adamc@462: val un = (L'.TRecord [], loc) adamc@462: val t = monoType env t adamc@1050: val rt = (L'.TRecord [("Value", t), adamc@1050: ("Expires", (L'.TOption (L'.TFfi ("Basis", "time"), adamc@1050: loc), loc)), adamc@1050: ("Secure", (L'.TFfi ("Basis", "bool"), loc))], loc) adamc@1050: adamc@1050: fun fd x = (L'.EField ((L'.ERel 1, loc), x), loc) adamc@1050: val (e, fm) = urlifyExp env fm (fd "Value", t) adamc@462: in adamc@1050: ((L'.EAbs ("c", s, (L'.TFun (rt, (L'.TFun (un, un), loc)), loc), adamc@1050: (L'.EAbs ("r", rt, (L'.TFun (un, un), loc), adamc@462: (L'.EAbs ("_", un, un, adamc@764: (L'.EFfiApp ("Basis", "set_cookie", [(L'.EPrim (Prim.String adamc@764: (Settings.getUrlPrefix ())), adamc@466: loc), adamc@466: (L'.ERel 2, loc), adamc@1050: e, adamc@1050: fd "Expires", adamc@1050: fd "Secure"]) adamc@1050: , loc)), loc)), loc)), loc), adamc@1050: fm) adamc@1050: end adamc@1050: adamc@1050: | L.ECApp ((L.EFfi ("Basis", "clearCookie"), _), t) => adamc@1050: let adamc@1050: val s = (L'.TFfi ("Basis", "string"), loc) adamc@1050: val un = (L'.TRecord [], loc) adamc@1050: in adamc@1050: ((L'.EAbs ("c", s, (L'.TFun (un, un), loc), adamc@1050: (L'.EAbs ("_", un, un, adamc@1050: (L'.EFfiApp ("Basis", "clear_cookie", adamc@1050: [(L'.EPrim (Prim.String adamc@1050: (Settings.getUrlPrefix ())), adamc@1050: loc), adamc@1050: (L'.ERel 1, loc)]), adamc@462: loc)), loc)), loc), adamc@462: fm) adamc@1050: end adamc@462: adamc@668: | L.ECApp ((L.EFfi ("Basis", "channel"), _), t) => adamc@668: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFfi ("Basis", "channel"), loc), adamc@668: (L'.EFfiApp ("Basis", "new_channel", [(L'.ERecord [], loc)]), loc)), loc), adamc@668: fm) adamc@668: | L.ECApp ((L.EFfi ("Basis", "send"), _), t) => adamc@668: let adamc@668: val t = monoType env t adamc@668: val (e, fm) = urlifyExp env fm ((L'.ERel 1, loc), t) adamc@668: in adamc@668: ((L'.EAbs ("ch", (L'.TFfi ("Basis", "channel"), loc), adamc@668: (L'.TFun (t, (L'.TFun ((L'.TRecord [], loc), (L'.TRecord [], loc)), loc)), loc), adamc@668: (L'.EAbs ("v", t, (L'.TFun ((L'.TRecord [], loc), (L'.TRecord [], loc)), loc), adamc@668: (L'.EAbs ("_", (L'.TRecord [], loc), (L'.TRecord [], loc), adamc@668: (L'.EFfiApp ("Basis", "send", adamc@668: [(L'.ERel 2, loc), adamc@668: e]), adamc@668: loc)), loc)), loc)), loc), adamc@668: fm) adamc@668: end adamc@668: adamc@707: | L.ECApp ((L.EFfi ("Basis", "no_primary_key"), _), _) => adamc@707: ((L'.EPrim (Prim.String ""), loc), adamc@707: fm) adamc@707: | L.ECApp ( adamc@707: (L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "primary_key"), _), _), _), t), _), adamc@707: nm), _), adamc@707: (L.CRecord (_, unique), _)) => adamc@707: let adamc@707: val unique = (nm, t) :: unique adamc@707: val witnesses = (L'.TRecord (map (fn (nm, _) => (monoName env nm, (L'.TRecord [], loc))) unique), loc) adamc@707: in adamc@707: ((L'.EAbs ("_", witnesses, (L'.TFfi ("Basis", "string"), loc), adamc@707: (L'.EPrim (Prim.String adamc@707: (String.concatWith ", " adamc@877: (map (fn (x, _) => adamc@877: "uw_" ^ monoNameLc env x adamc@877: ^ (if #textKeysNeedLengths (Settings.currentDbms ()) adamc@877: andalso isBlobby t then adamc@877: "(767)" adamc@877: else adamc@877: "")) unique))), adamc@707: loc)), loc), adamc@707: fm) adamc@707: end adamc@707: adamc@704: | L.ECApp ((L.EFfi ("Basis", "no_constraint"), _), _) => adamc@704: ((L'.ERecord [], loc), adamc@704: fm) adamc@705: | L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "one_constraint"), _), _), _), _), _), (L.CName name, _)) => adamc@704: ((L'.EAbs ("c", adamc@704: (L'.TFfi ("Basis", "string"), loc), adamc@704: (L'.TFfi ("Basis", "sql_constraints"), loc), adamc@704: (L'.ERecord [(name, (L'.ERel 0, loc), (L'.TFfi ("Basis", "string"), loc))], loc)), loc), adamc@704: fm) adamc@705: | L.ECApp ( adamc@705: (L.ECApp ( adamc@705: (L.ECApp ( adamc@705: (L.EFfi ("Basis", "join_constraints"), _), adamc@705: _), _), adamc@705: _), _), adamc@705: _) => adamc@704: let adamc@704: val constraints = (L'.TFfi ("Basis", "sql_constraints"), loc) adamc@704: in adamc@704: ((L'.EAbs ("cs1", constraints, (L'.TFun (constraints, constraints), loc), adamc@704: (L'.EAbs ("cs2", constraints, constraints, adamc@704: (L'.EStrcat ((L'.ERel 1, loc), (L'.ERel 0, loc)), loc)), loc)), loc), adamc@704: fm) adamc@704: end adamc@704: adamc@705: | L.ECApp ( adamc@705: (L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "unique"), _), _), _), t), _), adamc@705: nm), _), adamc@705: (L.CRecord (_, unique), _)) => adamc@705: let adamc@705: val unique = (nm, t) :: unique adamc@705: in adamc@705: ((L'.EPrim (Prim.String ("UNIQUE (" adamc@877: ^ String.concatWith ", " adamc@877: (map (fn (x, t) => "uw_" ^ monoNameLc env x adamc@877: ^ (if #textKeysNeedLengths (Settings.currentDbms ()) adamc@877: andalso isBlobby t then adamc@877: "(767)" adamc@877: else adamc@877: "")) unique) adamc@705: ^ ")")), loc), adamc@705: fm) adamc@705: end adamc@704: adamc@712: | L.ECApp ((L.EFfi ("Basis", "linkable_same"), loc), _) => adamc@712: ((L'.ERecord [], loc), fm) adamc@712: | L.ECApp ((L.EFfi ("Basis", "linkable_from_nullable"), loc), _) => adamc@712: ((L'.ERecord [], loc), fm) adamc@712: | L.ECApp ((L.EFfi ("Basis", "linkable_to_nullable"), loc), _) => adamc@712: ((L'.ERecord [], loc), fm) adamc@712: adamc@709: | L.EFfi ("Basis", "mat_nil") => adamc@709: let adamc@709: val string = (L'.TFfi ("Basis", "string"), loc) adamc@709: val stringE = (L'.EPrim (Prim.String ""), loc) adamc@709: in adamc@709: ((L'.ERecord [("1", stringE, string), adamc@709: ("2", stringE, string)], loc), fm) adamc@709: end adamc@709: | L.ECApp ( adamc@709: (L.ECApp ( adamc@709: (L.ECApp ( adamc@709: (L.ECApp ( adamc@709: (L.ECApp ( adamc@712: (L.ECApp ( adamc@712: (L.EFfi ("Basis", "mat_cons"), _), adamc@712: _), _), adamc@709: _), _), adamc@709: _), _), adamc@709: _), _), adamc@709: (L.CName nm1, _)), _), adamc@709: (L.CName nm2, _)) => adamc@709: let adamc@709: val string = (L'.TFfi ("Basis", "string"), loc) adamc@709: val mat = (L'.TRecord [("1", string), ("2", string)], loc) adamc@709: in adamc@712: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFun (mat, mat), loc), adamc@712: (L'.EAbs ("m", mat, mat, adamc@712: (L'.ECase ((L'.EField ((L'.ERel 0, loc), "1"), loc), adamc@712: [((L'.PPrim (Prim.String ""), loc), adamc@877: (L'.ERecord [("1", (L'.EPrim (Prim.String ("uw_" ^ lowercaseFirst nm1)), adamc@712: loc), string), adamc@877: ("2", (L'.EPrim (Prim.String ("uw_" ^ lowercaseFirst nm2)), adamc@712: loc), string)], loc)), adamc@712: ((L'.PWild, loc), adamc@712: (L'.ERecord [("1", (L'.EStrcat ( adamc@877: (L'.EPrim (Prim.String ("uw_" ^ lowercaseFirst nm1 adamc@877: ^ ", ")), adamc@712: loc), adamc@712: (L'.EField ((L'.ERel 0, loc), "1"), loc)), adamc@712: loc), string), adamc@712: ("2", (L'.EStrcat ( adamc@877: (L'.EPrim (Prim.String ("uw_" ^ lowercaseFirst nm2 adamc@877: ^ ", ")), loc), adamc@712: (L'.EField ((L'.ERel 0, loc), "2"), loc)), adamc@712: loc), string)], adamc@712: loc))], adamc@712: {disc = string, adamc@712: result = mat}), loc)), loc)), loc), adamc@709: fm) adamc@709: end adamc@709: adamc@709: | L.ECApp ((L.EFfi ("Basis", "restrict"), _), _) => ((L'.EPrim (Prim.String "RESTRICT"), loc), fm) adamc@709: | L.ECApp ((L.EFfi ("Basis", "cascade"), _), _) => ((L'.EPrim (Prim.String "CASCADE"), loc), fm) adamc@709: | L.ECApp ((L.EFfi ("Basis", "no_action"), _), _) => ((L'.EPrim (Prim.String "NO ACTION"), loc), fm) adamc@709: | L.ECApp ((L.EFfi ("Basis", "set_null"), _), _) => ((L'.EPrim (Prim.String "SET NULL"), loc), fm) adamc@709: adamc@709: | L.ECApp ( adamc@709: (L.ECApp ( adamc@709: (L.ECApp ( adamc@709: (L.ECApp ( adamc@709: (L.ECApp ( adamc@709: (L.ECApp ( adamc@709: (L.ECApp ( adamc@709: (L.ECApp ( adamc@709: (L.EFfi ("Basis", "foreign_key"), _), adamc@709: _), _), adamc@709: _), _), adamc@709: _), _), adamc@709: _), _), adamc@709: _), _), adamc@709: _), _), adamc@709: _), _), adamc@709: _) => adamc@709: let adamc@709: val unit = (L'.TRecord [], loc) adamc@709: val string = (L'.TFfi ("Basis", "string"), loc) adamc@709: val mat = (L'.TRecord [("1", string), ("2", string)], loc) adamc@709: val recd = (L'.TRecord [("OnDelete", string), adamc@709: ("OnUpdate", string)], loc) adamc@709: adamc@709: fun strcat [] = raise Fail "Monoize.strcat" adamc@709: | strcat [e] = e adamc@709: | strcat (e1 :: es) = (L'.EStrcat (e1, strcat es), loc) adamc@709: adamc@709: fun prop (fd, kw) = adamc@709: (L'.ECase ((L'.EField ((L'.ERel 0, loc), fd), loc), adamc@709: [((L'.PPrim (Prim.String "NO ACTION"), loc), adamc@709: (L'.EPrim (Prim.String ""), loc)), adamc@709: ((L'.PWild, loc), adamc@709: strcat [(L'.EPrim (Prim.String (" ON " ^ kw ^ " ")), loc), adamc@709: (L'.EField ((L'.ERel 0, loc), fd), loc)])], adamc@709: {disc = string, adamc@709: result = string}), loc) adamc@709: in adamc@709: ((L'.EAbs ("m", mat, (L'.TFun (string, (L'.TFun (recd, string), loc)), loc), adamc@709: (L'.EAbs ("tab", string, (L'.TFun (recd, string), loc), adamc@709: (L'.EAbs ("pr", recd, string, adamc@709: strcat [(L'.EPrim (Prim.String "FOREIGN KEY ("), loc), adamc@709: (L'.EField ((L'.ERel 2, loc), "1"), loc), adamc@709: (L'.EPrim (Prim.String ") REFERENCES "), loc), adamc@709: (L'.ERel 1, loc), adamc@709: (L'.EPrim (Prim.String " ("), loc), adamc@709: (L'.EField ((L'.ERel 2, loc), "2"), loc), adamc@709: (L'.EPrim (Prim.String ")"), loc), adamc@709: prop ("OnDelete", "DELETE"), adamc@709: prop ("OnUpdate", "UPDATE")]), loc)), loc)), loc), adamc@709: fm) adamc@709: end adamc@709: adamc@1072: | L.ECApp ( adamc@1072: (L.ECApp ( adamc@1072: (L.ECApp ( adamc@1072: (L.ECApp ( adamc@1072: (L.ECApp ( adamc@1072: (L.ECApp ( adamc@1072: (L.ECApp ( adamc@1072: (L.EFfi ("Basis", "sql_exp_weaken"), _), adamc@1072: _), _), adamc@1072: _), _), adamc@1072: _), _), adamc@1072: _), _), adamc@1072: _), _), adamc@1072: _), _), adamc@1072: _) => adamc@1072: let adamc@1072: val string = (L'.TFfi ("Basis", "string"), loc) adamc@1072: in adamc@1072: ((L'.EAbs ("e", string, string, (L'.ERel 0, loc)), loc), adamc@1072: fm) adamc@1072: end adamc@1072: adamc@714: | L.ECApp ((L.EFfi ("Basis", "check"), _), _) => adamc@714: let adamc@714: val string = (L'.TFfi ("Basis", "string"), loc) adamc@714: in adamc@714: ((L'.EAbs ("e", string, string, adamc@714: (L'.EStrcat ((L'.EPrim (Prim.String "CHECK "), loc), adamc@714: (L'.EFfiApp ("Basis", "checkString", adamc@714: [(L'.ERel 0, loc)]), loc)), loc)), loc), adamc@714: fm) adamc@714: end adamc@714: adamc@307: | L.EFfiApp ("Basis", "dml", [e]) => adamc@307: let adamc@307: val (e, fm) = monoExp (env, st, fm) e adamc@307: in adamc@468: ((L'.EDml e, loc), adamc@307: fm) adamc@307: end adamc@308: adamc@705: | L.ECApp ((L.ECApp ((L.EFfi ("Basis", "insert"), _), fields), _), _) => adamc@307: (case monoType env (L.TRecord fields, loc) of adamc@307: (L'.TRecord fields, _) => adamc@307: let adamc@307: val s = (L'.TFfi ("Basis", "string"), loc) adamc@307: val fields = map (fn (x, _) => (x, s)) fields adamc@307: val rt = (L'.TRecord fields, loc) adamc@307: fun sc s = (L'.EPrim (Prim.String s), loc) adamc@307: in adamc@307: ((L'.EAbs ("tab", s, (L'.TFun (rt, s), loc), adamc@307: (L'.EAbs ("fs", rt, s, adamc@598: strcat [sc "INSERT INTO ", adamc@598: (L'.ERel 1, loc), adamc@598: sc " (", adamc@598: strcatComma (map (fn (x, _) => sc ("uw_" ^ x)) fields), adamc@598: sc ") VALUES (", adamc@598: strcatComma (map (fn (x, _) => adamc@598: (L'.EField ((L'.ERel 0, loc), adamc@598: x), loc)) fields), adamc@598: sc ")"]), loc)), loc), adamc@307: fm) adamc@307: end adamc@307: | _ => poly ()) adamc@307: adamc@705: | L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "update"), _), _), _), _), _), changed) => adamc@308: (case monoType env (L.TRecord changed, loc) of adamc@308: (L'.TRecord changed, _) => adamc@308: let adamc@308: val s = (L'.TFfi ("Basis", "string"), loc) adamc@308: val changed = map (fn (x, _) => (x, s)) changed adamc@308: val rt = (L'.TRecord changed, loc) adamc@308: fun sc s = (L'.EPrim (Prim.String s), loc) adamc@308: in adamc@308: ((L'.EAbs ("fs", rt, (L'.TFun (s, (L'.TFun (s, s), loc)), loc), adamc@308: (L'.EAbs ("tab", s, (L'.TFun (s, s), loc), adamc@308: (L'.EAbs ("e", s, s, adamc@886: if #supportsUpdateAs (Settings.currentDbms ()) then adamc@886: strcat [sc "UPDATE ", adamc@886: (L'.ERel 1, loc), adamc@986: sc " AS T_T SET ", adamc@886: strcatComma (map (fn (x, _) => adamc@886: strcat [sc ("uw_" ^ x adamc@886: ^ " = "), adamc@886: (L'.EField adamc@886: ((L'.ERel 2, adamc@886: loc), adamc@886: x), loc)]) adamc@886: changed), adamc@886: sc " WHERE ", adamc@886: (L'.ERel 0, loc)] adamc@886: else adamc@886: strcat [sc "UPDATE ", adamc@886: (L'.ERel 1, loc), adamc@886: sc " SET ", adamc@886: strcatComma (map (fn (x, _) => adamc@886: strcat [sc ("uw_" ^ x adamc@886: ^ " = "), adamc@886: (L'.EField adamc@886: ((L'.ERel 2, adamc@886: loc), adamc@886: x), loc)]) adamc@886: changed), adamc@886: sc " WHERE ", adamc@886: (L'.EFfiApp ("Basis", "unAs", [(L'.ERel 0, loc)]), loc)]), adamc@886: loc)), loc)), loc), adamc@308: fm) adamc@308: end adamc@308: | _ => poly ()) adamc@308: adamc@705: | L.ECApp ((L.ECApp ((L.EFfi ("Basis", "delete"), _), _), _), _) => adamc@309: let adamc@309: val s = (L'.TFfi ("Basis", "string"), loc) adamc@309: fun sc s = (L'.EPrim (Prim.String s), loc) adamc@309: in adamc@309: ((L'.EAbs ("tab", s, (L'.TFun (s, s), loc), adamc@309: (L'.EAbs ("e", s, s, adamc@874: if #supportsDeleteAs (Settings.currentDbms ()) then adamc@874: strcat [sc "DELETE FROM ", adamc@874: (L'.ERel 1, loc), adamc@986: sc " AS T_T WHERE ", adamc@874: (L'.ERel 0, loc)] adamc@874: else adamc@874: strcat [sc "DELETE FROM ", adamc@874: (L'.ERel 1, loc), adamc@874: sc " WHERE ", adamc@874: (L'.EFfiApp ("Basis", "unAs", [(L'.ERel 0, loc)]), loc)]), loc)), loc), adamc@309: fm) adamc@309: end adamc@309: adamc@252: | L.ECApp ( adamc@252: (L.ECApp ( adamc@252: (L.ECApp ((L.EFfi ("Basis", "query"), _), (L.CRecord (_, tables), _)), _), adamc@252: exps), _), adamc@252: state) => adamc@252: (case monoType env (L.TRecord exps, loc) of adamc@252: (L'.TRecord exps, _) => adamc@252: let adamc@252: val tables = map (fn ((L.CName x, _), xts) => adamc@252: (case monoType env (L.TRecord xts, loc) of adamc@252: (L'.TRecord xts, _) => SOME (x, xts) adamc@252: | _ => NONE) adamc@252: | _ => NONE) tables adamc@252: in adamc@252: if List.exists (fn x => x = NONE) tables then adamc@252: poly () adamc@252: else adamc@252: let adamc@252: val tables = List.mapPartial (fn x => x) tables adamc@252: val state = monoType env state adamc@252: val s = (L'.TFfi ("Basis", "string"), loc) adamc@252: val un = (L'.TRecord [], loc) adamc@252: adamc@252: val rt = exps @ map (fn (x, xts) => (x, (L'.TRecord xts, loc))) tables adamc@252: val ft = (L'.TFun ((L'.TRecord rt, loc), adamc@252: (L'.TFun (state, adamc@252: (L'.TFun (un, state), loc)), adamc@252: loc)), loc) adamc@252: adamc@267: val body' = (L'.EApp ( adamc@267: (L'.EApp ( adamc@267: (L'.EApp ((L'.ERel 4, loc), adamc@267: (L'.ERel 1, loc)), loc), adamc@267: (L'.ERel 0, loc)), loc), adamc@267: (L'.ERecord [], loc)), loc) adamc@252: adamc@252: val body = (L'.EQuery {exps = exps, adamc@252: tables = tables, adamc@252: state = state, adamc@252: query = (L'.ERel 3, loc), adamc@252: body = body', adamc@252: initial = (L'.ERel 1, loc)}, adamc@252: loc) adamc@252: in adamc@252: ((L'.EAbs ("q", s, (L'.TFun (ft, (L'.TFun (state, (L'.TFun (un, state), loc)), loc)), loc), adamc@252: (L'.EAbs ("f", ft, (L'.TFun (state, (L'.TFun (un, state), loc)), loc), adamc@252: (L'.EAbs ("i", state, (L'.TFun (un, state), loc), adamc@252: (L'.EAbs ("_", un, state, adamc@252: body), loc)), loc)), loc)), loc), fm) adamc@252: end adamc@252: end adamc@252: | _ => poly ()) adamc@252: adamc@1191: | L.ECApp ((L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sql_query"), _), _), _), _), _), _), _), _) => adamc@252: let adamc@252: fun sc s = (L'.EPrim (Prim.String s), loc) adamc@252: val s = (L'.TFfi ("Basis", "string"), loc) adamc@252: fun gf s = (L'.EField ((L'.ERel 0, loc), s), loc) adamc@252: in adamc@252: ((L'.EAbs ("r", adamc@252: (L'.TRecord [("Rows", s), ("OrderBy", s), ("Limit", s), ("Offset", s)], loc), adamc@252: s, adamc@598: strcat [gf "Rows", adamc@598: (L'.ECase (gf "OrderBy", adamc@598: [((L'.PPrim (Prim.String ""), loc), sc ""), adamc@598: ((L'.PWild, loc), adamc@598: strcat [sc " ORDER BY ", adamc@598: gf "OrderBy"])], adamc@598: {disc = s, result = s}), loc), adamc@598: gf "Limit", adamc@598: gf "Offset"]), loc), fm) adamc@252: end adamc@252: adamc@252: | L.ECApp ( adamc@252: (L.ECApp ( adamc@252: (L.ECApp ( adamc@252: (L.ECApp ( adamc@1070: (L.ECApp ( adamc@1191: (L.ECApp ( adamc@1191: (L.EFfi ("Basis", "sql_query1"), _), adamc@1191: _), _), adamc@1070: (L.CRecord (_, tables), _)), _), adamc@1070: (L.CRecord (_, grouped), _)), _), adamc@1070: (L.CRecord (_, stables), _)), _), adamc@1070: sexps), _), adamc@1070: _) => adamc@252: let adamc@252: fun sc s = (L'.EPrim (Prim.String s), loc) adamc@252: val s = (L'.TFfi ("Basis", "string"), loc) adamc@993: val b = (L'.TFfi ("Basis", "bool"), loc) adamc@252: val un = (L'.TRecord [], loc) adamc@252: fun gf s = (L'.EField ((L'.ERel 0, loc), s), loc) adamc@252: adamc@252: fun doTables tables = adamc@252: let adamc@252: val tables = map (fn ((L.CName x, _), xts) => adamc@252: (case monoType env (L.TRecord xts, loc) of adamc@252: (L'.TRecord xts, _) => SOME (x, xts) adamc@252: | _ => NONE) adamc@252: | _ => NONE) tables adamc@252: in adamc@252: if List.exists (fn x => x = NONE) tables then adamc@252: NONE adamc@252: else adamc@260: let adamc@260: val tables = List.mapPartial (fn x => x) tables adamc@260: val tables = ListMergeSort.sort adamc@260: (fn ((x, _), (y, _)) => String.compare (x, y) = GREATER) adamc@260: tables adamc@260: val tables = map (fn (x, xts) => adamc@260: (x, ListMergeSort.sort adamc@260: (fn ((x, _), (y, _)) => String.compare (x, y) = GREATER) adamc@260: xts)) tables adamc@260: in adamc@260: SOME tables adamc@260: end adamc@252: end adamc@252: in adamc@252: case (doTables tables, doTables grouped, doTables stables, monoType env (L.TRecord sexps, loc)) of adamc@252: (SOME tables, SOME grouped, SOME stables, (L'.TRecord sexps, _)) => adamc@441: let adamc@441: val sexps = ListMergeSort.sort adamc@441: (fn ((x, _), (y, _)) => String.compare (x, y) = GREATER) sexps adamc@441: in adamc@441: ((L'.EAbs ("r", adamc@993: (L'.TRecord [("Distinct", b), adamc@993: ("From", s), adamc@441: ("Where", s), adamc@441: ("GroupBy", un), adamc@441: ("Having", s), adamc@441: ("SelectFields", un), adamc@441: ("SelectExps", (L'.TRecord (map (fn (x, _) => (x, s)) sexps), loc))], adamc@441: loc), adamc@441: s, adamc@598: strcat [sc "SELECT ", adamc@993: (L'.ECase (gf "Distinct", adamc@993: [((L'.PCon (L'.Enum, adamc@993: L'.PConFfi {mod = "Basis", adamc@993: datatyp = "bool", adamc@993: con = "True", adamc@993: arg = NONE}, adamc@993: NONE), loc), adamc@993: (L'.EPrim (Prim.String "DISTINCT "), loc)), adamc@993: ((L'.PCon (L'.Enum, adamc@993: L'.PConFfi {mod = "Basis", adamc@993: datatyp = "bool", adamc@993: con = "False", adamc@993: arg = NONE}, adamc@993: NONE), loc), adamc@993: (L'.EPrim (Prim.String ""), loc))], adamc@993: {disc = b, result = s}), loc), adamc@598: strcatComma (map (fn (x, t) => adamc@598: strcat [ adamc@598: (L'.EField (gf "SelectExps", x), loc), adamc@1192: sc (" AS uw_" ^ x) adamc@598: ]) sexps adamc@598: @ map (fn (x, xts) => adamc@598: strcatComma adamc@598: (map (fn (x', _) => adamc@986: sc ("T_" ^ x adamc@986: ^ ".uw_" adamc@986: ^ x')) adamc@598: xts)) stables), adamc@1195: (L'.ECase (gf "From", adamc@1195: [((L'.PPrim (Prim.String ""), loc), adamc@1195: sc ""), adamc@1195: ((L'.PVar ("x", s), loc), adamc@1195: strcat [sc " FROM ", adamc@1195: (L'.ERel 0, loc)])], adamc@1195: {disc = s, adamc@1195: result = s}), loc), adamc@598: (L'.ECase (gf "Where", adamc@598: [((L'.PPrim (Prim.String "TRUE"), loc), adamc@598: sc ""), adamc@598: ((L'.PWild, loc), adamc@598: strcat [sc " WHERE ", gf "Where"])], adamc@598: {disc = s, adamc@598: result = s}), loc), adamc@598: adamc@598: if List.all (fn (x, xts) => adamc@598: case List.find (fn (x', _) => x' = x) grouped of adamc@598: NONE => List.null xts adamc@598: | SOME (_, xts') => adamc@598: List.all (fn (x, _) => adamc@598: List.exists (fn (x', _) => x' = x) adamc@598: xts') xts) tables then adamc@598: sc "" adamc@598: else adamc@598: strcat [ adamc@598: sc " GROUP BY ", adamc@598: strcatComma (map (fn (x, xts) => adamc@598: strcatComma adamc@598: (map (fn (x', _) => adamc@986: sc ("T_" ^ x adamc@986: ^ ".uw_" adamc@986: ^ x')) adamc@598: xts)) grouped) adamc@598: ], adamc@259: adamc@598: (L'.ECase (gf "Having", adamc@1014: [((L'.PPrim (Prim.String adamc@1014: (#trueString (Settings.currentDbms ()))), loc), adamc@598: sc ""), adamc@598: ((L'.PWild, loc), adamc@598: strcat [sc " HAVING ", gf "Having"])], adamc@598: {disc = s, adamc@598: result = s}), loc) adamc@441: ]), loc), adamc@441: fm) adamc@441: end adamc@252: | _ => poly () adamc@252: end adamc@252: adamc@252: | L.ECApp ( adamc@252: (L.ECApp ( adamc@252: (L.ECApp ( adamc@252: (L.ECApp ( adamc@252: (L.EFfi ("Basis", "sql_inject"), _), adamc@252: _), _), adamc@252: _), _), adamc@252: _), _), adamc@252: t) => adamc@252: let adamc@252: val t = monoType env t adamc@252: val s = (L'.TFfi ("Basis", "string"), loc) adamc@252: in adamc@252: ((L'.EAbs ("f", (L'.TFun (t, s), loc), (L'.TFun (t, s), loc), adamc@252: (L'.ERel 0, loc)), loc), fm) adamc@252: end adamc@252: adamc@253: | L.EFfi ("Basis", "sql_int") => adamc@253: ((L'.EAbs ("x", (L'.TFfi ("Basis", "int"), loc), (L'.TFfi ("Basis", "string"), loc), adamc@253: (L'.EFfiApp ("Basis", "sqlifyInt", [(L'.ERel 0, loc)]), loc)), loc), adamc@253: fm) adamc@253: | L.EFfi ("Basis", "sql_float") => adamc@253: ((L'.EAbs ("x", (L'.TFfi ("Basis", "float"), loc), (L'.TFfi ("Basis", "string"), loc), adamc@253: (L'.EFfiApp ("Basis", "sqlifyFloat", [(L'.ERel 0, loc)]), loc)), loc), adamc@253: fm) adamc@253: | L.EFfi ("Basis", "sql_bool") => adamc@253: ((L'.EAbs ("x", (L'.TFfi ("Basis", "bool"), loc), (L'.TFfi ("Basis", "string"), loc), adamc@253: (L'.EFfiApp ("Basis", "sqlifyBool", [(L'.ERel 0, loc)]), loc)), loc), adamc@253: fm) adamc@253: | L.EFfi ("Basis", "sql_string") => adamc@253: ((L'.EAbs ("x", (L'.TFfi ("Basis", "string"), loc), (L'.TFfi ("Basis", "string"), loc), adamc@253: (L'.EFfiApp ("Basis", "sqlifyString", [(L'.ERel 0, loc)]), loc)), loc), adamc@253: fm) adamc@1011: | L.EFfi ("Basis", "sql_char") => adamc@1011: ((L'.EAbs ("x", (L'.TFfi ("Basis", "char"), loc), (L'.TFfi ("Basis", "string"), loc), adamc@1011: (L'.EFfiApp ("Basis", "sqlifyChar", [(L'.ERel 0, loc)]), loc)), loc), adamc@1011: fm) adamc@439: | L.EFfi ("Basis", "sql_time") => adamc@439: ((L'.EAbs ("x", (L'.TFfi ("Basis", "time"), loc), (L'.TFfi ("Basis", "string"), loc), adamc@439: (L'.EFfiApp ("Basis", "sqlifyTime", [(L'.ERel 0, loc)]), loc)), loc), adamc@439: fm) adamc@737: | L.EFfi ("Basis", "sql_blob") => adamc@737: ((L'.EAbs ("x", (L'.TFfi ("Basis", "blob"), loc), (L'.TFfi ("Basis", "string"), loc), adamc@737: (L'.EFfiApp ("Basis", "sqlifyBlob", [(L'.ERel 0, loc)]), loc)), loc), adamc@737: fm) adamc@678: | L.ECApp ((L.EFfi ("Basis", "sql_channel"), _), _) => adamc@678: ((L'.EAbs ("x", (L'.TFfi ("Basis", "channel"), loc), (L'.TFfi ("Basis", "string"), loc), adamc@678: (L'.EFfiApp ("Basis", "sqlifyChannel", [(L'.ERel 0, loc)]), loc)), loc), adamc@678: fm) adamc@682: | L.EFfi ("Basis", "sql_client") => adamc@682: ((L'.EAbs ("x", (L'.TFfi ("Basis", "client"), loc), (L'.TFfi ("Basis", "string"), loc), adamc@682: (L'.EFfiApp ("Basis", "sqlifyClient", [(L'.ERel 0, loc)]), loc)), loc), adamc@682: fm) adamc@1104: | L.ECApp ((L.EFfi ("Basis", "sql_serialized"), _), _) => adamc@1104: ((L'.EAbs ("x", (L'.TFfi ("Basis", "string"), loc), (L'.TFfi ("Basis", "string"), loc), adamc@1104: (L'.EFfiApp ("Basis", "sqlifyString", [(L'.ERel 0, loc)]), loc)), loc), adamc@1104: fm) adamc@676: | L.ECApp ((L.EFfi ("Basis", "sql_prim"), _), t) => adamc@676: let adamc@676: val t = monoType env t adamc@676: val tf = (L'.TFun (t, (L'.TFfi ("Basis", "string"), loc)), loc) adamc@676: in adamc@676: ((L'.EAbs ("f", tf, tf, (L'.ERel 0, loc)), loc), adamc@676: fm) adamc@676: end adamc@676: | L.ECApp ((L.EFfi ("Basis", "sql_option_prim"), _), t) => adamc@676: let adamc@676: val t = monoType env t adamc@676: val s = (L'.TFfi ("Basis", "string"), loc) adamc@676: in adamc@676: ((L'.EAbs ("f", adamc@676: (L'.TFun (t, s), loc), adamc@676: (L'.TFun ((L'.TOption t, loc), s), loc), adamc@676: (L'.EAbs ("x", adamc@676: (L'.TOption t, loc), adamc@676: s, adamc@676: (L'.ECase ((L'.ERel 0, loc), adamc@676: [((L'.PNone t, loc), adamc@676: (L'.EPrim (Prim.String "NULL"), loc)), adamc@676: ((L'.PSome (t, (L'.PVar ("y", t), loc)), loc), adamc@676: (L'.EApp ((L'.ERel 2, loc), (L'.ERel 0, loc)), loc))], adamc@676: {disc = (L'.TOption t, loc), adamc@676: result = s}), loc)), loc)), loc), adamc@676: fm) adamc@676: end adamc@253: adamc@750: | L.ECApp ((L.EFfi ("Basis", "nullify_option"), _), _) => adamc@750: ((L'.ERecord [], loc), fm) adamc@750: | L.ECApp ((L.EFfi ("Basis", "nullify_prim"), _), _) => adamc@750: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TRecord [], loc), adamc@750: (L'.ERecord [], loc)), loc), adamc@750: fm) adamc@750: adamc@252: | L.ECApp ((L.EFfi ("Basis", "sql_subset"), _), _) => adamc@252: ((L'.ERecord [], loc), fm) adamc@252: | L.ECApp ((L.EFfi ("Basis", "sql_subset_all"), _), _) => adamc@252: ((L'.ERecord [], loc), fm) adamc@1072: | L.ECApp ((L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sql_subset_concat"), adamc@1072: _), _), _), _), _), _), _), _) => adamc@1072: let adamc@1072: val un = (L'.TRecord [], loc) adamc@1072: in adamc@1072: ((L'.EAbs ("_", un, (L'.TFun (un, un), loc), adamc@1072: (L'.EAbs ("_", un, un, adamc@1072: (L'.ERecord [], loc)), loc)), loc), adamc@1072: fm) adamc@1072: end adamc@252: adamc@753: | L.ECApp ((L.ECApp ((L.EFfi ("Basis", "fieldsOf_table"), _), _), _), _) => adamc@753: ((L'.ERecord [], loc), fm) adamc@753: | L.ECApp ((L.EFfi ("Basis", "fieldsOf_view"), _), _) => adamc@753: ((L'.ERecord [], loc), fm) adamc@753: adamc@1195: | L.ECApp ((L.EFfi ("Basis", "sql_from_nil"), _), _) => adamc@1195: ((L'.EPrim (Prim.String ""), loc), fm) adamc@1191: | L.ECApp ((L.EApp ((L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sql_from_table"), _), _), adamc@1191: _), _), _), _), _), _), _), adamc@753: (L.CName name, _)) => adamc@748: let adamc@748: val s = (L'.TFfi ("Basis", "string"), loc) adamc@748: in adamc@748: ((L'.EAbs ("tab", s, s, adamc@748: strcat [(L'.ERel 0, loc), adamc@986: (L'.EPrim (Prim.String (" AS T_" ^ name)), loc)]), loc), adamc@748: fm) adamc@748: end adamc@1192: | L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sql_from_query"), _), _), adamc@1192: _), _), _), adamc@1192: (L.CName name, _)) => adamc@1192: let adamc@1192: val s = (L'.TFfi ("Basis", "string"), loc) adamc@1192: fun sc s = (L'.EPrim (Prim.String s), loc) adamc@1192: in adamc@1192: ((L'.EAbs ("q", s, s, adamc@1192: strcat [sc "(", adamc@1192: (L'.ERel 0, loc), adamc@1192: sc (") AS T_" ^ name)]), loc), adamc@1192: fm) adamc@1192: end adamc@1191: | L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sql_from_comma"), _), _), _), _), _), _) => adamc@748: let adamc@748: val s = (L'.TFfi ("Basis", "string"), loc) adamc@748: in adamc@748: ((L'.EAbs ("tab1", s, (L'.TFun (s, s), loc), adamc@748: (L'.EAbs ("tab2", s, s, adamc@1195: (L'.ECase ((L'.ERecord [("1", (L'.ERel 1, loc), s), adamc@1195: ("2", (L'.ERel 0, loc), s)], loc), adamc@1195: [((L'.PRecord [("1", (L'.PPrim (Prim.String ""), loc), s)], loc), adamc@1195: (L'.ERel 0, loc)), adamc@1195: ((L'.PRecord [("2", (L'.PPrim (Prim.String ""), loc), s)], loc), adamc@1195: (L'.ERel 1, loc)), adamc@1195: ((L'.PWild, loc), adamc@1195: strcat [(L'.ERel 1, loc), adamc@1195: (L'.EPrim (Prim.String ", "), loc), adamc@1195: (L'.ERel 0, loc)])], adamc@1195: {disc = (L'.TRecord [("1", s), ("2", s)], loc), adamc@1195: result = s}), loc)), loc)), loc), adamc@748: fm) adamc@748: end adamc@1191: | L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sql_inner_join"), _), _), _), _), _), _) => adamc@749: let adamc@749: val s = (L'.TFfi ("Basis", "string"), loc) adamc@749: in adamc@749: ((L'.EAbs ("tab1", s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc), adamc@749: (L'.EAbs ("tab2", s, (L'.TFun (s, s), loc), adamc@749: (L'.EAbs ("on", s, s, adamc@1195: (L'.ECase ((L'.ERecord [("1", (L'.ERel 2, loc), s), adamc@1195: ("2", (L'.ERel 1, loc), s)], loc), adamc@1195: [((L'.PRecord [("1", (L'.PPrim (Prim.String ""), loc), s)], loc), adamc@1195: (L'.ERel 1, loc)), adamc@1195: ((L'.PRecord [("2", (L'.PPrim (Prim.String ""), loc), s)], loc), adamc@1195: (L'.ERel 2, loc)), adamc@1195: ((L'.PWild, loc), adamc@1195: strcat [(L'.EPrim (Prim.String "("), loc), adamc@1195: (L'.ERel 2, loc), adamc@1195: (L'.EPrim (Prim.String " JOIN "), loc), adamc@1195: (L'.ERel 1, loc), adamc@1195: (L'.EPrim (Prim.String " ON "), loc), adamc@1195: (L'.ERel 0, loc), adamc@1195: (L'.EPrim (Prim.String ")"), loc)])], adamc@1195: {disc = (L'.TRecord [("1", s), ("2", s)], loc), adamc@1195: result = s}), loc)), loc)), loc)), loc), adamc@749: fm) adamc@749: end adamc@1191: | L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sql_left_join"), _), _), _), _), _), adamc@1191: (L.CRecord (_, right), _)) => adamc@750: let adamc@750: val s = (L'.TFfi ("Basis", "string"), loc) adamc@750: in adamc@750: ((L'.EAbs ("_", outerRec right, adamc@750: (L'.TFun (s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc)), loc), adamc@750: (L'.EAbs ("tab1", s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc), adamc@750: (L'.EAbs ("tab2", s, (L'.TFun (s, s), loc), adamc@750: (L'.EAbs ("on", s, s, adamc@1195: (L'.ECase ((L'.ERecord [("1", (L'.ERel 2, loc), s), adamc@1195: ("2", (L'.ERel 1, loc), s)], loc), adamc@1195: [((L'.PRecord [("1", (L'.PPrim (Prim.String ""), adamc@1195: loc), s)], loc), adamc@1195: (L'.ERel 1, loc)), adamc@1195: ((L'.PRecord [("2", (L'.PPrim (Prim.String ""), adamc@1195: loc), s)], loc), adamc@1195: (L'.ERel 2, loc)), adamc@1195: ((L'.PWild, loc), adamc@1195: strcat [(L'.EPrim (Prim.String "("), loc), adamc@1195: (L'.ERel 2, loc), adamc@1195: (L'.EPrim (Prim.String " LEFT JOIN "), loc), adamc@1195: (L'.ERel 1, loc), adamc@1195: (L'.EPrim (Prim.String " ON "), loc), adamc@1195: (L'.ERel 0, loc), adamc@1195: (L'.EPrim (Prim.String ")"), loc)])], adamc@1195: {disc = (L'.TRecord [("1", s), ("2", s)], loc), adamc@1195: result = s}), loc)), loc)), loc)), loc)), loc), adamc@750: fm) adamc@750: end adamc@1191: | L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sql_right_join"), _), (L.CRecord (_, left), _)), adamc@1191: _), _), _), _) => adamc@751: let adamc@751: val s = (L'.TFfi ("Basis", "string"), loc) adamc@751: in adamc@751: ((L'.EAbs ("_", outerRec left, adamc@751: (L'.TFun (s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc)), loc), adamc@751: (L'.EAbs ("tab1", s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc), adamc@751: (L'.EAbs ("tab2", s, (L'.TFun (s, s), loc), adamc@751: (L'.EAbs ("on", s, s, adamc@1195: (L'.ECase ((L'.ERecord [("1", (L'.ERel 2, loc), s), adamc@1195: ("2", (L'.ERel 1, loc), s)], loc), adamc@1195: [((L'.PRecord [("1", (L'.PPrim (Prim.String ""), adamc@1195: loc), s)], loc), adamc@1195: (L'.ERel 1, loc)), adamc@1195: ((L'.PRecord [("2", (L'.PPrim (Prim.String ""), adamc@1195: loc), s)], loc), adamc@1195: (L'.ERel 2, loc)), adamc@1195: ((L'.PWild, loc), adamc@1195: strcat [(L'.EPrim (Prim.String "("), loc), adamc@1195: (L'.ERel 2, loc), adamc@1195: (L'.EPrim (Prim.String " RIGHT JOIN "), loc), adamc@1195: (L'.ERel 1, loc), adamc@1195: (L'.EPrim (Prim.String " ON "), loc), adamc@1195: (L'.ERel 0, loc), adamc@1195: (L'.EPrim (Prim.String ")"), loc)])], adamc@1195: {disc = (L'.TRecord [("1", s), ("2", s)], loc), adamc@1195: result = s}), loc)), loc)), loc)), loc)), loc), adamc@751: fm) adamc@751: end adamc@1191: | L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sql_full_join"), _), (L.CRecord (_, left), _)), _), adamc@1191: (L.CRecord (_, right), _)), _), _) => adamc@751: let adamc@751: val s = (L'.TFfi ("Basis", "string"), loc) adamc@751: in adamc@751: ((L'.EAbs ("_", outerRec (left @ right), adamc@751: (L'.TFun (s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc)), loc), adamc@751: (L'.EAbs ("tab1", s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc), adamc@751: (L'.EAbs ("tab2", s, (L'.TFun (s, s), loc), adamc@751: (L'.EAbs ("on", s, s, adamc@1195: (L'.ECase ((L'.ERecord [("1", (L'.ERel 2, loc), s), adamc@1195: ("2", (L'.ERel 1, loc), s)], loc), adamc@1195: [((L'.PRecord [("1", (L'.PPrim (Prim.String ""), adamc@1195: loc), s)], loc), adamc@1195: (L'.ERel 1, loc)), adamc@1195: ((L'.PRecord [("2", (L'.PPrim (Prim.String ""), adamc@1195: loc), s)], loc), adamc@1195: (L'.ERel 2, loc)), adamc@1195: ((L'.PWild, loc), adamc@1195: strcat [(L'.EPrim (Prim.String "("), loc), adamc@1195: (L'.ERel 2, loc), adamc@1195: (L'.EPrim (Prim.String " FULL JOIN "), loc), adamc@1195: (L'.ERel 1, loc), adamc@1195: (L'.EPrim (Prim.String " ON "), loc), adamc@1195: (L'.ERel 0, loc), adamc@1195: (L'.EPrim (Prim.String ")"), loc)])], adamc@1195: {disc = (L'.TRecord [("1", s), ("2", s)], loc), adamc@1195: result = s}), loc)), loc)), loc)), loc)), loc), adamc@751: fm) adamc@751: end adamc@748: adamc@252: | L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sql_order_by_Nil"), _), _), _), _) => adamc@252: ((L'.EPrim (Prim.String ""), loc), fm) adamc@261: | L.ECApp ( adamc@261: (L.ECApp ( adamc@261: (L.ECApp ( adamc@261: (L.EFfi ("Basis", "sql_order_by_Cons"), _), adamc@261: _), _), adamc@261: _), _), adamc@261: _) => adamc@261: let adamc@261: val s = (L'.TFfi ("Basis", "string"), loc) adamc@261: fun sc s = (L'.EPrim (Prim.String s), loc) adamc@261: in adamc@268: ((L'.EAbs ("e1", s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc), adamc@268: (L'.EAbs ("d", s, (L'.TFun (s, s), loc), adamc@268: (L'.EAbs ("e2", s, s, adamc@268: (L'.ECase ((L'.ERel 0, loc), adamc@268: [((L'.PPrim (Prim.String ""), loc), adamc@598: strcat [(L'.ERel 2, loc), adamc@598: (L'.ERel 1, loc)]), adamc@268: ((L'.PWild, loc), adamc@598: strcat [(L'.ERel 2, loc), adamc@598: (L'.ERel 1, loc), adamc@598: sc ", ", adamc@598: (L'.ERel 0, loc)])], adamc@268: {disc = s, result = s}), loc)), loc)), loc)), loc), adamc@261: fm) adamc@261: end adamc@252: adamc@252: | L.EFfi ("Basis", "sql_no_limit") => adamc@252: ((L'.EPrim (Prim.String ""), loc), fm) adamc@262: | L.EFfiApp ("Basis", "sql_limit", [e]) => adamc@262: let adamc@262: val (e, fm) = monoExp (env, st, fm) e adamc@262: in adamc@598: (strcat [ adamc@262: (L'.EPrim (Prim.String " LIMIT "), loc), adamc@262: (L'.EFfiApp ("Basis", "sqlifyInt", [e]), loc) adamc@262: ], adamc@262: fm) adamc@262: end adamc@262: adamc@252: | L.EFfi ("Basis", "sql_no_offset") => adamc@252: ((L'.EPrim (Prim.String ""), loc), fm) adamc@263: | L.EFfiApp ("Basis", "sql_offset", [e]) => adamc@263: let adamc@263: val (e, fm) = monoExp (env, st, fm) e adamc@263: in adamc@598: (strcat [ adamc@263: (L'.EPrim (Prim.String " OFFSET "), loc), adamc@263: (L'.EFfiApp ("Basis", "sqlifyInt", [e]), loc) adamc@263: ], adamc@263: fm) adamc@263: end adamc@253: adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_eq"), _), _) => adamc@253: ((L'.EPrim (Prim.String "="), loc), fm) adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_ne"), _), _) => adamc@253: ((L'.EPrim (Prim.String "<>"), loc), fm) adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_lt"), _), _) => adamc@253: ((L'.EPrim (Prim.String "<"), loc), fm) adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_le"), _), _) => adamc@253: ((L'.EPrim (Prim.String "<="), loc), fm) adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_gt"), _), _) => adamc@253: ((L'.EPrim (Prim.String ">"), loc), fm) adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_ge"), _), _) => adamc@253: ((L'.EPrim (Prim.String ">="), loc), fm) adamc@253: adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_plus"), _), _) => adamc@559: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc), adamc@559: (L'.EPrim (Prim.String "+"), loc)), loc), fm) adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_minus"), _), _) => adamc@559: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc), adamc@559: (L'.EPrim (Prim.String "-"), loc)), loc), fm) adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_times"), _), _) => adamc@559: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc), adamc@559: (L'.EPrim (Prim.String "*"), loc)), loc), fm) adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_div"), _), _) => adamc@559: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc), adamc@559: (L'.EPrim (Prim.String "/"), loc)), loc), fm) adamc@559: | L.EFfi ("Basis", "sql_mod") => adamc@559: ((L'.EPrim (Prim.String "%"), loc), fm) adamc@559: adamc@253: | L.ECApp ( adamc@253: (L.ECApp ( adamc@253: (L.ECApp ( adamc@253: (L.ECApp ( adamc@254: (L.ECApp ( adamc@264: (L.EFfi ("Basis", "sql_unary"), _), adamc@264: _), _), adamc@264: _), _), adamc@264: _), _), adamc@264: _), _), adamc@264: _) => adamc@264: let adamc@264: val s = (L'.TFfi ("Basis", "string"), loc) adamc@264: fun sc s = (L'.EPrim (Prim.String s), loc) adamc@264: in adamc@264: ((L'.EAbs ("c", s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc), adamc@264: (L'.EAbs ("e1", s, (L'.TFun (s, s), loc), adamc@598: strcat [sc "(", adamc@598: (L'.ERel 1, loc), adamc@598: sc " ", adamc@598: (L'.ERel 0, loc), adamc@598: sc ")"]), loc)), loc), adamc@264: fm) adamc@264: end adamc@264: | L.EFfi ("Basis", "sql_not") => ((L'.EPrim (Prim.String "NOT"), loc), fm) adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_neg"), _), _) => adamc@559: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc), adamc@559: (L'.EPrim (Prim.String "-"), loc)), loc), fm) adamc@264: adamc@264: | L.ECApp ( adamc@264: (L.ECApp ( adamc@264: (L.ECApp ( adamc@264: (L.ECApp ( adamc@264: (L.ECApp ( adamc@254: (L.ECApp ( adamc@254: (L.EFfi ("Basis", "sql_binary"), _), adamc@254: _), _), adamc@254: _), _), adamc@254: _), _), adamc@254: _), _), adamc@254: _), _), adamc@254: _) => adamc@254: let adamc@254: val s = (L'.TFfi ("Basis", "string"), loc) adamc@254: fun sc s = (L'.EPrim (Prim.String s), loc) adamc@254: in adamc@254: ((L'.EAbs ("c", s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc), adamc@254: (L'.EAbs ("e1", s, (L'.TFun (s, s), loc), adamc@254: (L'.EAbs ("e2", s, s, adamc@598: strcat [sc "(", adamc@598: (L'.ERel 1, loc), adamc@598: sc " ", adamc@598: (L'.ERel 2, loc), adamc@598: sc " ", adamc@598: (L'.ERel 0, loc), adamc@598: sc ")"]), loc)), loc)), loc), adamc@254: fm) adamc@254: end adamc@254: | L.EFfi ("Basis", "sql_and") => ((L'.EPrim (Prim.String "AND"), loc), fm) adamc@254: | L.EFfi ("Basis", "sql_or") => ((L'.EPrim (Prim.String "OR"), loc), fm) adamc@254: adamc@254: | L.ECApp ( adamc@254: (L.ECApp ( adamc@254: (L.ECApp ( adamc@254: (L.ECApp ( adamc@253: (L.ECApp ( adamc@253: (L.ECApp ( adamc@253: (L.ECApp ( adamc@253: (L.EFfi ("Basis", "sql_field"), _), adamc@253: _), _), adamc@253: _), _), adamc@253: _), _), adamc@253: _), _), adamc@253: _), _), adamc@253: (L.CName tab, _)), _), adamc@986: (L.CName field, _)) => ((L'.EPrim (Prim.String ("T_" ^ tab ^ ".uw_" ^ lowercaseFirst field)), loc), fm) adamc@260: adamc@260: | L.ECApp ( adamc@260: (L.ECApp ( adamc@260: (L.ECApp ( adamc@260: (L.ECApp ( adamc@261: (L.ECApp ( adamc@261: (L.EFfi ("Basis", "sql_exp"), _), adamc@261: _), _), adamc@261: _), _), adamc@261: _), _), adamc@261: _), _), adamc@1192: (L.CName nm, _)) => ((L'.EPrim (Prim.String ("uw_" ^ lowercaseFirst nm)), loc), fm) adamc@261: adamc@261: | L.ECApp ( adamc@261: (L.ECApp ( adamc@261: (L.ECApp ( adamc@261: (L.ECApp ( adamc@1191: (L.ECApp ( adamc@1191: (L.EFfi ("Basis", "sql_relop"), _), adamc@1191: _), _), adamc@260: _), _), adamc@260: _), _), adamc@260: _), _), adamc@260: _) => adamc@260: let adamc@260: val s = (L'.TFfi ("Basis", "string"), loc) adamc@260: fun sc s = (L'.EPrim (Prim.String s), loc) adamc@260: in adamc@1196: (if #nestedRelops (Settings.currentDbms ()) then adamc@1196: (L'.EAbs ("c", s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc), adamc@1196: (L'.EAbs ("e1", s, (L'.TFun (s, s), loc), adamc@1196: (L'.EAbs ("e2", s, s, adamc@1196: strcat [sc "((", adamc@1196: (L'.ERel 1, loc), adamc@1196: sc ") ", adamc@1196: (L'.ERel 2, loc), adamc@1196: sc " (", adamc@1196: (L'.ERel 0, loc), adamc@1196: sc "))"]), loc)), loc)), loc) adamc@1196: else adamc@1196: (L'.EAbs ("c", s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc), adamc@1196: (L'.EAbs ("e1", s, (L'.TFun (s, s), loc), adamc@1196: (L'.EAbs ("e2", s, s, adamc@1196: strcat [(L'.ERel 1, loc), adamc@1196: sc " ", adamc@1196: (L'.ERel 2, loc), adamc@1196: sc " ", adamc@1196: (L'.ERel 0, loc)]), loc)), loc)), loc), adamc@260: fm) adamc@260: end adamc@1071: | L.ECApp ( adamc@1071: (L.ECApp ( adamc@1071: (L.ECApp ( adamc@1191: (L.ECApp ( adamc@1191: (L.EFfi ("Basis", "sql_forget_tables"), _), adamc@1191: _), _), adamc@1071: _), _), adamc@1071: _), _), adamc@1071: _) => adamc@1071: let adamc@1071: val s = (L'.TFfi ("Basis", "string"), loc) adamc@1071: fun sc s = (L'.EPrim (Prim.String s), loc) adamc@1071: in adamc@1071: ((L'.EAbs ("x", s, s, (L'.ERel 0, loc)), loc), adamc@1071: fm) adamc@1071: end adamc@260: adamc@260: | L.EFfi ("Basis", "sql_union") => ((L'.EPrim (Prim.String "UNION"), loc), fm) adamc@1196: | L.EFfi ("Basis", "sql_intersect") => adamc@1196: (if #onlyUnion (Settings.currentDbms ()) then adamc@1196: ErrorMsg.errorAt loc "The DBMS you've selected doesn't support INTERSECT." adamc@1196: else adamc@1196: (); adamc@1196: ((L'.EPrim (Prim.String "INTERSECT"), loc), fm)) adamc@1196: | L.EFfi ("Basis", "sql_except") => adamc@1196: (if #onlyUnion (Settings.currentDbms ()) then adamc@1196: ErrorMsg.errorAt loc "The DBMS you've selected doesn't support EXCEPT." adamc@1196: else adamc@1196: (); adamc@1196: ((L'.EPrim (Prim.String "EXCEPT"), loc), fm)) adamc@260: adamc@265: | L.ECApp ( adamc@265: (L.ECApp ( adamc@265: (L.ECApp ( adamc@265: (L.EFfi ("Basis", "sql_count"), _), adamc@265: _), _), adamc@265: _), _), adamc@1168: _) => ((L'.EPrim (Prim.String "COALESCE(COUNT(*),0)"), loc), adamc@265: fm) adamc@266: adamc@266: | L.ECApp ( adamc@266: (L.ECApp ( adamc@266: (L.ECApp ( adamc@266: (L.ECApp ( adamc@1187: (L.ECApp ( adamc@1187: (L.EFfi ("Basis", "sql_aggregate"), _), adamc@1187: _), _), adamc@266: _), _), adamc@266: _), _), adamc@266: _), _), adamc@1168: t) => adamc@266: let adamc@1168: val default = adamc@1168: case #1 t of adamc@1168: L.CFfi ("Basis", s) => adamc@1168: (case s of adamc@1168: "int" => "0" adamc@1168: | "float" => "0.0" adamc@1168: | "string" => "''" adamc@1168: | "time" => "0" adamc@1168: | _ => raise Fail "Illegal type of sql_aggregate [1]") adamc@1168: | _ => raise Fail "Illegal type of sql_aggregate [2]" adamc@1168: adamc@266: val s = (L'.TFfi ("Basis", "string"), loc) adamc@266: fun sc s = (L'.EPrim (Prim.String s), loc) adamc@266: in adamc@266: ((L'.EAbs ("c", s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc), adamc@266: (L'.EAbs ("e1", s, (L'.TFun (s, s), loc), adamc@1168: strcat [sc "COALESCE(", adamc@1168: (L'.ERel 1, loc), adamc@598: sc "(", adamc@598: (L'.ERel 0, loc), adamc@1168: sc (")," ^ default ^ ")")]), loc)), loc), adamc@266: fm) adamc@266: end adamc@266: adamc@1187: | L.ECApp ((L.EFfi ("Basis", "sql_count_col"), _), _) => adamc@1187: ((L'.EPrim (Prim.String "COUNT"), loc), adamc@1187: fm) adamc@1187: adamc@266: | L.EFfi ("Basis", "sql_summable_int") => ((L'.ERecord [], loc), fm) adamc@266: | L.EFfi ("Basis", "sql_summable_float") => ((L'.ERecord [], loc), fm) adamc@266: | L.ECApp ((L.EFfi ("Basis", "sql_avg"), _), _) => adamc@266: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc), adamc@266: (L'.EPrim (Prim.String "AVG"), loc)), loc), adamc@266: fm) adamc@266: | L.ECApp ((L.EFfi ("Basis", "sql_sum"), _), _) => adamc@266: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc), adamc@266: (L'.EPrim (Prim.String "SUM"), loc)), loc), adamc@266: fm) adamc@266: adamc@559: | L.EFfi ("Basis", "sql_arith_int") => ((L'.ERecord [], loc), fm) adamc@559: | L.EFfi ("Basis", "sql_arith_float") => ((L'.ERecord [], loc), fm) adamc@559: adamc@266: | L.EFfi ("Basis", "sql_maxable_int") => ((L'.ERecord [], loc), fm) adamc@266: | L.EFfi ("Basis", "sql_maxable_float") => ((L'.ERecord [], loc), fm) adamc@266: | L.EFfi ("Basis", "sql_maxable_string") => ((L'.ERecord [], loc), fm) adamc@266: | L.ECApp ((L.EFfi ("Basis", "sql_max"), _), _) => adamc@266: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc), adamc@266: (L'.EPrim (Prim.String "MAX"), loc)), loc), adamc@266: fm) adamc@266: | L.ECApp ((L.EFfi ("Basis", "sql_min"), _), _) => adamc@266: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc), adamc@266: (L'.EPrim (Prim.String "MIN"), loc)), loc), adamc@266: fm) adamc@266: adamc@268: | L.EFfi ("Basis", "sql_asc") => ((L'.EPrim (Prim.String ""), loc), fm) adamc@268: | L.EFfi ("Basis", "sql_desc") => ((L'.EPrim (Prim.String " DESC"), loc), fm) adamc@268: adamc@441: | L.ECApp ( adamc@441: (L.ECApp ( adamc@441: (L.ECApp ( adamc@441: (L.ECApp ( adamc@441: (L.EFfi ("Basis", "sql_nfunc"), _), adamc@441: _), _), adamc@441: _), _), adamc@441: _), _), adamc@441: _) => adamc@441: let adamc@441: val s = (L'.TFfi ("Basis", "string"), loc) adamc@441: fun sc s = (L'.EPrim (Prim.String s), loc) adamc@441: in adamc@441: ((L'.EAbs ("s", s, s, (L'.ERel 0, loc)), loc), adamc@441: fm) adamc@441: end adamc@441: | L.EFfi ("Basis", "sql_current_timestamp") => ((L'.EPrim (Prim.String "CURRENT_TIMESTAMP"), loc), fm) adamc@441: adamc@746: | L.ECApp ( adamc@746: (L.ECApp ( adamc@746: (L.ECApp ( adamc@746: (L.ECApp ( adamc@746: (L.ECApp ( adamc@746: (L.EFfi ("Basis", "sql_ufunc"), _), adamc@746: _), _), adamc@746: _), _), adamc@746: _), _), adamc@746: _), _), adamc@746: _) => adamc@746: let adamc@746: val s = (L'.TFfi ("Basis", "string"), loc) adamc@746: fun sc s = (L'.EPrim (Prim.String s), loc) adamc@746: in adamc@746: ((L'.EAbs ("f", s, (L'.TFun (s, s), loc), adamc@746: (L'.EAbs ("x", s, s, adamc@746: strcat [(L'.ERel 1, loc), adamc@746: sc "(", adamc@746: (L'.ERel 0, loc), adamc@746: sc ")"]), loc)), loc), adamc@746: fm) adamc@746: end adamc@890: | L.EFfi ("Basis", "sql_octet_length") => adamc@890: ((L'.EPrim (Prim.String (if #supportsOctetLength (Settings.currentDbms ()) then adamc@890: "octet_length" adamc@890: else adamc@890: "length")), loc), fm) adamc@1207: | L.ECApp ((L.EFfi ("Basis", "sql_known"), _), _) => adamc@1207: ((L'.EFfi ("Basis", "sql_known"), loc), fm) adamc@746: adamc@470: | (L.ECApp ( adamc@470: (L.ECApp ( adamc@470: (L.ECApp ( adamc@470: (L.ECApp ( adamc@470: (L.EFfi ("Basis", "sql_is_null"), _), _), adamc@470: _), _), adamc@470: _), _), adamc@470: _), _)) => adamc@470: let adamc@470: val s = (L'.TFfi ("Basis", "string"), loc) adamc@470: fun sc s = (L'.EPrim (Prim.String s), loc) adamc@470: in adamc@470: ((L'.EAbs ("s", s, s, adamc@598: strcat [sc "(", adamc@598: (L'.ERel 0, loc), adamc@598: sc " IS NULL)"]), loc), adamc@470: fm) adamc@470: end adamc@470: adamc@1081: | L.ECApp ( adamc@1081: (L.ECApp ( adamc@1081: (L.ECApp ( adamc@1081: (L.ECApp ( adamc@1081: (L.EFfi ("Basis", "sql_nullable"), _), adamc@1081: _), _), adamc@1081: _), _), adamc@1081: _), _), adamc@1081: _) => adamc@1081: let adamc@1081: val s = (L'.TFfi ("Basis", "string"), loc) adamc@1081: fun sc s = (L'.EPrim (Prim.String s), loc) adamc@1081: in adamc@1081: ((L'.EAbs ("u", (L'.TRecord [], loc), (L'.TFun (s, s), loc), adamc@1081: (L'.EAbs ("x", s, s, adamc@1081: (L'.ERel 0, loc)), loc)), loc), adamc@1081: fm) adamc@1081: end adamc@1191: adamc@1191: | L.ECApp ( adamc@1191: (L.ECApp ( adamc@1191: (L.ECApp ( adamc@1191: (L.ECApp ( adamc@1191: (L.ECApp ( adamc@1191: (L.EFfi ("Basis", "sql_subquery"), _), adamc@1191: _), _), adamc@1191: _), _), adamc@1191: _), _), adamc@1191: _), _), adamc@1191: _) => adamc@1191: let adamc@1191: val s = (L'.TFfi ("Basis", "string"), loc) adamc@1191: fun sc s = (L'.EPrim (Prim.String s), loc) adamc@1191: in adamc@1191: ((L'.EAbs ("x", s, s, adamc@1191: strcat [sc "(", adamc@1191: (L'.ERel 0, loc), adamc@1191: sc ")"]), loc), adamc@1191: fm) adamc@1191: end adamc@1081: adamc@338: | L.EFfiApp ("Basis", "nextval", [e]) => adamc@338: let adamc@338: val (e, fm) = monoExp (env, st, fm) e adamc@338: in adamc@465: ((L'.ENextval e, loc), fm) adamc@338: end adamc@1073: | L.EFfiApp ("Basis", "setval", [e1, e2]) => adamc@1073: let adamc@1073: val (e1, fm) = monoExp (env, st, fm) e1 adamc@1073: val (e2, fm) = monoExp (env, st, fm) e2 adamc@1073: in adamc@1073: ((L'.ESetval (e1, e2), loc), fm) adamc@1073: end adamc@338: adamc@139: | L.EApp ( adamc@139: (L.ECApp ( adamc@720: (L.ECApp ((L.EFfi ("Basis", "cdata"), _), _), _), adamc@139: _), _), adamc@179: se) => adamc@179: let adamc@179: val (se, fm) = monoExp (env, st, fm) se adamc@179: in adamc@179: ((L'.EFfiApp ("Basis", "htmlifyString", [se]), loc), fm) adamc@179: end adamc@179: adamc@95: | L.EApp ( adamc@95: (L.EApp ( adamc@720: (L.ECApp ( adamc@720: (L.ECApp ( adamc@95: (L.ECApp ( adamc@139: (L.ECApp ( adamc@720: (L.EFfi ("Basis", "join"), adamc@720: _), _), _), adamc@139: _), _), adamc@720: _), _), adamc@720: _), _), adamc@720: xml1), _), adamc@720: xml2) => adamc@179: let adamc@179: val (xml1, fm) = monoExp (env, st, fm) xml1 adamc@179: val (xml2, fm) = monoExp (env, st, fm) xml2 adamc@179: in adamc@179: ((L'.EStrcat (xml1, xml2), loc), fm) adamc@179: end adamc@95: adamc@95: | L.EApp ( adamc@95: (L.EApp ( adamc@104: (L.EApp ( adamc@721: (L.EApp ( adamc@720: (L.ECApp ( adamc@104: (L.ECApp ( adamc@104: (L.ECApp ( adamc@139: (L.ECApp ( adamc@139: (L.ECApp ( adamc@139: (L.ECApp ( adamc@139: (L.ECApp ( adamc@721: (L.ECApp ( adamc@721: (L.EFfi ("Basis", "tag"), adamc@721: _), _), _), _), _), _), _), _), _), _), _), _), _), _), _), _), _), adamc@721: class), _), adamc@720: attrs), _), adamc@720: tag), _), adamc@95: xml) => adamc@95: let adamc@140: fun getTag' (e, _) = adamc@140: case e of adamc@143: L.EFfi ("Basis", tag) => (tag, []) adamc@143: | L.ECApp (e, t) => let adamc@143: val (tag, ts) = getTag' e adamc@143: in adamc@143: (tag, ts @ [t]) adamc@143: end adamc@140: | _ => (E.errorAt loc "Non-constant XML tag"; adamc@140: Print.eprefaces' [("Expression", CorePrint.p_exp env tag)]; adamc@143: ("", [])) adamc@140: adamc@95: fun getTag (e, _) = adamc@95: case e of adamc@143: L.EFfiApp ("Basis", tag, [(L.ERecord [], _)]) => (tag, []) adamc@140: | L.EApp (e, (L.ERecord [], _)) => getTag' e adamc@95: | _ => (E.errorAt loc "Non-constant XML tag"; adamc@95: Print.eprefaces' [("Expression", CorePrint.p_exp env tag)]; adamc@143: ("", [])) adamc@95: adamc@143: val (tag, targs) = getTag tag adamc@95: adamc@179: val (attrs, fm) = monoExp (env, st, fm) attrs adamc@598: val attrs = case #1 attrs of adamc@598: L'.ERecord xes => xes adamc@598: | _ => raise Fail "Non-record attributes!" adamc@104: adamc@717: val attrs = adamc@717: if List.exists (fn ("Link", _, _) => true adamc@717: | _ => false) attrs then adamc@717: List.filter (fn ("Href", _, _) => false adamc@717: | _ => true) attrs adamc@717: else adamc@717: attrs adamc@717: adamc@1042: fun findOnload (attrs, onload, onunload, acc) = adamc@668: case attrs of adamc@1042: [] => (onload, onunload, acc) adamc@1042: | ("Onload", e, _) :: rest => findOnload (rest, SOME e, onunload, acc) adamc@1042: | ("Onunload", e, _) :: rest => findOnload (rest, onload, SOME e, acc) adamc@1042: | x :: rest => findOnload (rest, onload, onunload, x :: acc) adamc@679: adamc@1042: val (onload, onunload, attrs) = findOnload (attrs, NONE, NONE, []) adamc@668: adamc@721: val (class, fm) = monoExp (env, st, fm) class adamc@721: adamc@143: fun tagStart tag = adamc@598: let adamc@721: val t = (L'.TFfi ("Basis", "string"), loc) adamc@598: val s = (L'.EPrim (Prim.String (String.concat ["<", tag])), loc) adamc@721: adamc@721: val s = (L'.ECase (class, adamc@721: [((L'.PNone t, loc), adamc@721: s), adamc@721: ((L'.PSome (t, (L'.PVar ("x", t), loc)), loc), adamc@721: (L'.EStrcat (s, adamc@721: (L'.EStrcat ((L'.EPrim (Prim.String " class=\""), loc), adamc@721: (L'.EStrcat ((L'.ERel 0, loc), adamc@721: (L'.EPrim (Prim.String "\""), loc)), adamc@721: loc)), loc)), loc))], adamc@721: {disc = (L'.TOption t, loc), adamc@721: result = t}), loc) adamc@598: in adamc@598: foldl (fn (("Action", _, _), acc) => acc adamc@598: | (("Source", _, _), acc) => acc adamc@598: | ((x, e, t), (s, fm)) => adamc@598: case t of adamc@598: (L'.TFfi ("Basis", "bool"), _) => adamc@598: let adamc@598: val s' = " " ^ lowercaseFirst x adamc@598: in adamc@598: ((L'.ECase (e, adamc@598: [((L'.PCon (L'.Enum, adamc@598: L'.PConFfi {mod = "Basis", adamc@598: datatyp = "bool", adamc@598: con = "True", adamc@598: arg = NONE}, adamc@598: NONE), loc), adamc@598: (L'.EStrcat (s, adamc@598: (L'.EPrim (Prim.String s'), loc)), loc)), adamc@598: ((L'.PCon (L'.Enum, adamc@598: L'.PConFfi {mod = "Basis", adamc@598: datatyp = "bool", adamc@598: con = "False", adamc@598: arg = NONE}, adamc@598: NONE), loc), adamc@598: s)], adamc@598: {disc = (L'.TFfi ("Basis", "bool"), loc), adamc@598: result = (L'.TFfi ("Basis", "string"), loc)}), loc), adamc@598: fm) adamc@598: end adamc@895: | (L'.TFun (dom, _), _) => adamc@598: let adamc@598: val s' = " " ^ lowercaseFirst x ^ "='" adamc@970: val (e, s') = adamc@970: case #1 dom of adamc@970: L'.TRecord [] => ((L'.EApp (e, (L'.ERecord [], loc)), loc), s') adamc@970: | _ => ((L'.EApp ((L'.EApp (e, (L'.EFfiApp ("Basis", "kc", []), loc)), adamc@970: loc), (L'.ERecord [], loc)), loc), adamc@970: s' ^ "uwe=event;") adamc@970: val s' = s' ^ "exec(" adamc@598: in adamc@598: ((L'.EStrcat (s, adamc@598: (L'.EStrcat ( adamc@598: (L'.EPrim (Prim.String s'), loc), adamc@598: (L'.EStrcat ( adamc@815: (L'.EJavaScript (L'.Attribute, e), loc), adamc@970: (L'.EPrim (Prim.String ");return false'"), loc)), loc)), adamc@598: loc)), loc), adamc@598: fm) adamc@598: end adamc@598: | _ => adamc@598: let adamc@598: val fooify = adamc@598: case x of adamc@717: "Link" => urlifyExp adamc@717: | "Action" => urlifyExp adamc@598: | _ => attrifyExp adamc@120: adamc@724: val x = adamc@724: case x of adamc@724: "Typ" => "Type" adamc@907: | "Link" => "Href" adamc@724: | _ => x adamc@598: val xp = " " ^ lowercaseFirst x ^ "=\"" adamc@179: adamc@598: val (e, fm) = fooify env fm (e, t) adamc@598: in adamc@598: ((L'.EStrcat (s, adamc@598: (L'.EStrcat ((L'.EPrim (Prim.String xp), loc), adamc@598: (L'.EStrcat (e, adamc@598: (L'.EPrim (Prim.String "\""), adamc@598: loc)), adamc@598: loc)), adamc@598: loc)), loc), adamc@598: fm) adamc@598: end) adamc@598: (s, fm) attrs adamc@598: end adamc@104: adamc@143: fun input typ = adamc@143: case targs of adamc@155: [_, (L.CName name, _)] => adamc@179: let adamc@179: val (ts, fm) = tagStart "input" adamc@179: in adamc@179: ((L'.EStrcat (ts, adamc@802: (L'.EPrim (Prim.String (" type=\"" ^ typ ^ "\" name=\"" ^ name ^ "\" />")), adamc@179: loc)), loc), fm) adamc@179: end adamc@143: | _ => (Print.prefaces "Targs" (map (fn t => ("T", CorePrint.p_con env t)) targs); adamc@153: raise Fail "No name passed to input tag") adamc@104: adamc@565: fun normal (tag, extra, extraInner) = adamc@143: let adamc@179: val (tagStart, fm) = tagStart tag adamc@152: val tagStart = case extra of adamc@152: NONE => tagStart adamc@152: | SOME extra => (L'.EStrcat (tagStart, extra), loc) adamc@152: adamc@143: fun normal () = adamc@179: let adamc@179: val (xml, fm) = monoExp (env, st, fm) xml adamc@916: adamc@916: val xml = case extraInner of adamc@916: NONE => xml adamc@916: | SOME ei => (L'.EStrcat (ei, xml), loc) adamc@179: in adamc@179: ((L'.EStrcat ((L'.EStrcat (tagStart, (L'.EPrim (Prim.String ">"), loc)), loc), adamc@179: (L'.EStrcat (xml, adamc@179: (L'.EPrim (Prim.String (String.concat ["", tag, ">"])), adamc@179: loc)), loc)), adamc@179: loc), adamc@179: fm) adamc@179: end adamc@984: adamc@984: fun isSingleton () = adamc@984: let adamc@984: val (bef, aft) = Substring.splitl (not o Char.isSpace) (Substring.full tag) adamc@984: in adamc@984: SS.member (singletons, if Substring.isEmpty aft then adamc@984: tag adamc@984: else adamc@984: Substring.string bef) adamc@984: end adamc@143: in adamc@143: case xml of adamc@143: (L.EApp ((L.ECApp ( adamc@143: (L.ECApp ((L.EFfi ("Basis", "cdata"), _), adamc@143: _), _), adamc@143: _), _), adamc@143: (L.EPrim (Prim.String s), _)), _) => adamc@984: if CharVector.all Char.isSpace s andalso isSingleton () then adamc@802: ((L'.EStrcat (tagStart, (L'.EPrim (Prim.String " />"), loc)), loc), fm) adamc@143: else adamc@143: normal () adamc@143: | _ => normal () adamc@143: end adamc@606: adamc@606: fun setAttrs jexp = adamc@606: let adamc@606: val s = (L'.EPrim (Prim.String (String.concat ["<", tag])), loc) adamc@606: adamc@606: val assgns = List.mapPartial adamc@606: (fn ("Source", _, _) => NONE adamc@800: | ("Onchange", e, _) => adamc@970: SOME (strcat [str "addOnChange(d,exec(", adamc@815: (L'.EJavaScript (L'.Script, e), loc), adamc@970: str "))"]) adamc@606: | (x, e, _) => adamc@970: SOME (strcat [str ("d." ^ lowercaseFirst x ^ "=exec("), adamc@815: (L'.EJavaScript (L'.Script, e), loc), adamc@970: str ");"])) adamc@606: attrs adamc@1173: adamc@1173: val t = (L'.TFfi ("Basis", "string"), loc) adamc@1173: val setClass = (L'.ECase (class, adamc@1173: [((L'.PNone t, loc), adamc@1173: str ""), adamc@1173: ((L'.PSome (t, (L'.PVar ("x", t), loc)), loc), adamc@1173: (L'.EStrcat ((L'.EPrim (Prim.String "d.className=\""), loc), adamc@1173: (L'.EStrcat ((L'.ERel 0, loc), adamc@1173: (L'.EPrim (Prim.String "\";"), loc)), loc)), adamc@1173: loc))], adamc@1173: {disc = (L'.TOption t, loc), adamc@1173: result = t}), loc) adamc@606: in adamc@606: case assgns of adamc@1173: [] => strcat [str "var d=", adamc@1173: jexp, adamc@1173: str ";", adamc@1173: setClass] adamc@606: | _ => strcat (str "var d=" adamc@606: :: jexp adamc@606: :: str ";" adamc@1173: :: setClass adamc@606: :: assgns) adamc@606: end adamc@1042: adamc@1042: fun execify e = adamc@1042: case e of adamc@1042: NONE => (L'.EPrim (Prim.String ""), loc) adamc@1042: | SOME e => adamc@1042: let adamc@1042: val e = (L'.EApp (e, (L'.ERecord [], loc)), loc) adamc@1042: in adamc@1042: (L'.EStrcat ((L'.EPrim (Prim.String "exec("), loc), adamc@1042: (L'.EStrcat ((L'.EJavaScript (L'.Attribute, e), loc), adamc@1042: (L'.EPrim (Prim.String ")"), loc)), loc)), loc) adamc@1042: end adamc@152: in adamc@1065: (case tag of adamc@1065: "body" => let adamc@1065: val onload = execify onload adamc@1065: val onunload = execify onunload adamc@1065: in adamc@1065: normal ("body", adamc@1065: SOME (L'.EStrcat ((L'.EFfiApp ("Basis", "maybe_onload", adamc@1065: [(L'.EStrcat ((L'.EFfiApp ("Basis", "get_settings", adamc@1065: [(L'.ERecord [], loc)]), loc), adamc@1065: onload), loc)]), adamc@1065: loc), adamc@1065: (L'.EFfiApp ("Basis", "maybe_onunload", adamc@1065: [onunload]), adamc@1065: loc)), loc), adamc@1065: SOME (L'.EFfiApp ("Basis", "get_script", [(L'.ERecord [], loc)]), loc)) adamc@1065: end adamc@568: adamc@1065: | "dyn" => adamc@1065: let adamc@1065: fun inTag tag = case targs of adamc@1065: (L.CRecord (_, ctx), _) :: _ => adamc@1065: List.exists (fn ((L.CName tag', _), _) => tag' = tag adamc@1065: | _ => false) ctx adamc@1065: | _ => false adamc@1065: adamc@1065: val tag = if inTag "Tr" then adamc@1065: "tr" adamc@1065: else if inTag "Table" then adamc@1065: "table" adamc@1065: else adamc@1065: "span" adamc@1065: in adamc@1065: case attrs of adamc@1065: [("Signal", e, _)] => adamc@1065: ((L'.EStrcat adamc@1065: ((L'.EPrim (Prim.String ("")), loc)), loc)), loc), adamc@1065: fm) adamc@1065: | _ => raise Fail "Monoize: Bad dyn attributes" adamc@1065: end adamc@1065: adamc@1065: | "submit" => normal ("input type=\"submit\"", NONE, NONE) adamc@1065: | "button" => normal ("input type=\"submit\"", NONE, NONE) adamc@1065: | "hidden" => input "hidden" adamc@152: adamc@1065: | "textbox" => adamc@1065: (case targs of adamc@1065: [_, (L.CName name, _)] => adamc@1065: (case List.find (fn ("Source", _, _) => true | _ => false) attrs of adamc@1065: NONE => adamc@1065: let adamc@1065: val (ts, fm) = tagStart "input" adamc@1065: in adamc@1065: ((L'.EStrcat (ts, adamc@1065: (L'.EPrim (Prim.String (" name=\"" ^ name ^ "\" />")), adamc@1065: loc)), loc), fm) adamc@1065: end adamc@1065: | SOME (_, src, _) => adamc@1065: (strcat [str ""], adamc@1065: fm)) adamc@1065: | _ => (Print.prefaces "Targs" (map (fn t => ("T", CorePrint.p_con env t)) targs); adamc@1065: raise Fail "No name passed to textbox tag")) adamc@1065: | "password" => input "password" adamc@1065: | "textarea" => adamc@1065: (case targs of adamc@1065: [_, (L.CName name, _)] => adamc@1065: let adamc@1065: val (ts, fm) = tagStart "textarea" adamc@1065: val (xml, fm) = monoExp (env, st, fm) xml adamc@1065: in adamc@1065: ((L'.EStrcat ((L'.EStrcat (ts, adamc@1065: (L'.EPrim (Prim.String (" name=\"" ^ name ^ "\">")), loc)), loc), adamc@1065: (L'.EStrcat (xml, adamc@1065: (L'.EPrim (Prim.String ""), adamc@1065: loc)), loc)), adamc@1065: loc), fm) adamc@1065: end adamc@1065: | _ => (Print.prefaces "Targs" (map (fn t => ("T", CorePrint.p_con env t)) targs); adamc@1065: raise Fail "No name passed to ltextarea tag")) adamc@153: adamc@1065: | "checkbox" => input "checkbox" adamc@1065: | "upload" => input "file" adamc@190: adamc@1065: | "radio" => adamc@1065: (case targs of adamc@1065: [_, (L.CName name, _)] => adamc@1065: monoExp (env, St.setRadioGroup (st, name), fm) xml adamc@1065: | _ => (Print.prefaces "Targs" (map (fn t => ("T", CorePrint.p_con env t)) targs); adamc@1065: raise Fail "No name passed to radio tag")) adamc@1065: | "radioOption" => adamc@1065: (case St.radioGroup st of adamc@1065: NONE => raise Fail "No name for radioGroup" adamc@1065: | SOME name => adamc@1065: normal ("input", adamc@1065: SOME (L'.EPrim (Prim.String (" type=\"radio\" name=\"" ^ name ^ "\"")), loc), adamc@1065: NONE)) adamc@152: adamc@1065: | "select" => adamc@1065: (case targs of adamc@1065: [_, (L.CName name, _)] => adamc@1065: let adamc@1065: val (ts, fm) = tagStart "select" adamc@1065: val (xml, fm) = monoExp (env, st, fm) xml adamc@1065: in adamc@1065: ((L'.EStrcat ((L'.EStrcat (ts, adamc@1065: (L'.EPrim (Prim.String (" name=\"" ^ name ^ "\">")), adamc@1065: loc)), loc), adamc@1065: (L'.EStrcat (xml, adamc@1065: (L'.EPrim (Prim.String ""), adamc@1065: loc)), loc)), adamc@1065: loc), adamc@1065: fm) adamc@1065: end adamc@1065: | _ => (Print.prefaces "Targs" (map (fn t => ("T", CorePrint.p_con env t)) targs); adamc@1065: raise Fail "No name passed to lselect tag")) adamc@154: adamc@1065: | "ctextbox" => adamc@1065: (case List.find (fn ("Source", _, _) => true | _ => false) attrs of adamc@1065: NONE => adamc@1065: let adamc@1065: val (ts, fm) = tagStart "input" adamc@1065: in adamc@1065: ((L'.EStrcat (ts, adamc@1065: (L'.EPrim (Prim.String " />"), loc)), adamc@1065: loc), fm) adamc@1065: end adamc@1065: | SOME (_, src, _) => adamc@1065: let adamc@1065: val sc = strcat [str "inp(exec(", adamc@1065: (L'.EJavaScript (L'.Script, src), loc), adamc@1065: str "))"] adamc@1065: val sc = setAttrs sc adamc@1065: in adamc@1065: (strcat [str ""], adamc@1065: fm) adamc@1065: end) adamc@797: adamc@1065: | "ccheckbox" => adamc@1065: (case List.find (fn ("Source", _, _) => true | _ => false) attrs of adamc@1065: NONE => adamc@1065: let adamc@1065: val (ts, fm) = tagStart "input type=\"checkbox\"" adamc@1065: in adamc@1065: ((L'.EStrcat (ts, adamc@1065: (L'.EPrim (Prim.String " />"), loc)), adamc@1065: loc), fm) adamc@1065: end adamc@1065: | SOME (_, src, _) => adamc@1065: let adamc@1065: val sc = strcat [str "chk(exec(", adamc@1065: (L'.EJavaScript (L'.Script, src), loc), adamc@1065: str "))"] adamc@1065: val sc = setAttrs sc adamc@1065: in adamc@1065: (strcat [str ""], adamc@1065: fm) adamc@1065: end) adamc@817: adamc@1065: | "cselect" => adamc@1065: (case List.find (fn ("Source", _, _) => true | _ => false) attrs of adamc@1065: NONE => adamc@1065: let adamc@1065: val (xml, fm) = monoExp (env, st, fm) xml adamc@1065: val (ts, fm) = tagStart "select" adamc@1065: in adamc@1065: (strcat [ts, adamc@1065: str ">", adamc@1065: xml, adamc@1065: str ""], adamc@1065: fm) adamc@1065: end adamc@1065: | SOME (_, src, _) => adamc@1065: let adamc@1065: val (xml, fm) = monoExp (env, st, fm) xml adamc@797: adamc@1065: val sc = strcat [str "sel(exec(", adamc@1065: (L'.EJavaScript (L'.Script, src), loc), adamc@1065: str "),exec(", adamc@1065: (L'.EJavaScript (L'.Script, xml), loc), adamc@1065: str "))"] adamc@1065: val sc = setAttrs sc adamc@1065: in adamc@1065: (strcat [str ""], adamc@1065: fm) adamc@1065: end) adamc@154: adamc@1065: | "coption" => normal ("option", NONE, NONE) adamc@797: adamc@1099: | "ctextarea" => adamc@1099: (case List.find (fn ("Source", _, _) => true | _ => false) attrs of adamc@1099: NONE => adamc@1099: let adamc@1099: val (ts, fm) = tagStart "textarea" adamc@1099: in adamc@1099: ((L'.EStrcat (ts, adamc@1099: (L'.EPrim (Prim.String " />"), loc)), adamc@1099: loc), fm) adamc@1099: end adamc@1099: | SOME (_, src, _) => adamc@1099: let adamc@1099: val sc = strcat [str "tbx(exec(", adamc@1099: (L'.EJavaScript (L'.Script, src), loc), adamc@1099: str "))"] adamc@1099: val sc = setAttrs sc adamc@1099: in adamc@1099: (strcat [str ""], adamc@1099: fm) adamc@1099: end) adamc@1099: adamc@1065: | "tabl" => normal ("table", NONE, NONE) adamc@1065: | _ => normal (tag, NONE, NONE)) adamc@95: end adamc@94: adamc@141: | L.EApp ((L.ECApp ( adamc@361: (L.ECApp ((L.EFfi ("Basis", "form"), _), _), _), adamc@734: (L.CRecord (_, fields), _)), _), adamc@141: xml) => adamc@143: let adamc@143: fun findSubmit (e, _) = adamc@143: case e of adamc@143: L.EApp ( adamc@143: (L.EApp ( adamc@143: (L.ECApp ( adamc@143: (L.ECApp ( adamc@143: (L.ECApp ( adamc@143: (L.ECApp ( adamc@143: (L.EFfi ("Basis", "join"), adamc@143: _), _), _), adamc@143: _), _), adamc@143: _), _), adamc@143: _), _), adamc@143: xml1), _), adamc@143: xml2) => (case findSubmit xml1 of adamc@143: Error => Error adamc@143: | NotFound => findSubmit xml2 adamc@143: | Found e => adamc@143: case findSubmit xml2 of adamc@143: NotFound => Found e adamc@143: | _ => Error) adamc@143: | L.EApp ( adamc@143: (L.EApp ( adamc@143: (L.EApp ( adamc@730: (L.EApp ( adamc@143: (L.ECApp ( adamc@143: (L.ECApp ( adamc@143: (L.ECApp ( adamc@143: (L.ECApp ( adamc@143: (L.ECApp ( adamc@143: (L.ECApp ( adamc@143: (L.ECApp ( adamc@730: (L.ECApp ( adamc@730: (L.EFfi ("Basis", "tag"), adamc@730: _), _), _), _), _), _), _), _), _), _), _), _), _), _), _), _), _), adamc@730: _), _), adamc@143: attrs), _), adamc@143: _), _), adamc@143: xml) => adamc@143: (case #1 attrs of adamc@143: L.ERecord xes => adamc@143: (case ListUtil.search (fn ((L.CName "Action", _), e, t) => SOME (e, t) adamc@143: | _ => NONE) xes of adamc@143: NONE => findSubmit xml adamc@143: | SOME et => adamc@143: case findSubmit xml of adamc@143: NotFound => Found et adamc@143: | _ => Error) adamc@143: | _ => findSubmit xml) adamc@143: | _ => NotFound adamc@143: adamc@735: val (func, action, fm) = case findSubmit xml of adamc@735: NotFound => (0, (L'.EPrim (Prim.String ""), loc), fm) adamc@143: | Error => raise Fail "Not ready for multi-submit lforms yet" adamc@598: | Found (action, actionT) => adamc@598: let adamc@735: val func = case #1 action of adamc@735: L.EClosure (n, _) => n adamc@735: | _ => raise Fail "Monoize: Action is not a closure" adamc@598: val actionT = monoType env actionT adamc@598: val (action, fm) = monoExp (env, st, fm) action adamc@598: val (action, fm) = urlifyExp env fm (action, actionT) adamc@598: in adamc@735: (func, adamc@735: (L'.EStrcat ((L'.EPrim (Prim.String " action=\""), loc), adamc@598: (L'.EStrcat (action, adamc@598: (L'.EPrim (Prim.String "\""), loc)), loc)), loc), adamc@598: fm) adamc@598: end adamc@734: adamc@737: val hasUpload = CoreUtil.Exp.exists {kind = fn _ => false, adamc@737: con = fn _ => false, adamc@737: exp = fn e => adamc@737: case e of adamc@737: L.EFfi ("Basis", "upload") => true adamc@737: | _ => false} xml adamc@737: adamc@179: val (xml, fm) = monoExp (env, st, fm) xml adamc@735: adamc@735: val xml = adamc@735: if IS.member (!readCookie, func) then adamc@735: let adamc@735: fun inFields s = List.exists (fn ((L.CName s', _), _) => s' = s adamc@735: | _ => true) fields adamc@735: adamc@735: fun getSigName () = adamc@735: let adamc@735: fun getSigName' n = adamc@735: let adamc@735: val s = "Sig" ^ Int.toString n adamc@735: in adamc@735: if inFields s then adamc@735: getSigName' (n + 1) adamc@735: else adamc@735: s adamc@735: end adamc@735: in adamc@735: if inFields "Sig" then adamc@735: getSigName' 0 adamc@735: else adamc@735: "Sig" adamc@735: end adamc@735: adamc@735: val sigName = getSigName () adamc@735: val sigSet = (L'.EFfiApp ("Basis", "sigString", [(L'.ERecord [], loc)]), loc) adamc@735: val sigSet = (L'.EStrcat ((L'.EPrim (Prim.String (""), loc)), loc) adamc@735: in adamc@735: (L'.EStrcat (sigSet, xml), loc) adamc@735: end adamc@735: else adamc@735: xml adamc@737: adamc@737: val action = if hasUpload then adamc@737: (L'.EStrcat (action, adamc@737: (L'.EPrim (Prim.String " enctype=\"multipart/form-data\""), loc)), loc) adamc@737: else adamc@737: action adamc@737: adamc@143: in adamc@1026: ((L'.EStrcat ((L'.EStrcat ((L'.EPrim (Prim.String "
"), loc)), loc)), loc), adamc@179: fm) adamc@143: end adamc@141: adamc@756: | L.ECApp ((L.ECApp ((L.ECApp ((L.ECApp ( adamc@756: (L.EFfi ("Basis", "subform"), _), _), _), _), adamc@756: _), _), _), (L.CName nm, loc)) => adamc@756: let adamc@756: val s = (L'.TFfi ("Basis", "string"), loc) adamc@756: in adamc@756: ((L'.EAbs ("xml", s, s, adamc@756: strcat [(L'.EPrim (Prim.String ("")), loc), adamc@756: (L'.ERel 0, loc), adamc@803: (L'.EPrim (Prim.String ("")), loc)]), adamc@756: loc), adamc@756: fm) adamc@756: end adamc@756: adamc@758: | L.ECApp ((L.ECApp ((L.ECApp ((L.ECApp ( adamc@758: (L.EFfi ("Basis", "subforms"), _), _), _), _), adamc@758: _), _), _), (L.CName nm, loc)) => adamc@758: let adamc@758: val s = (L'.TFfi ("Basis", "string"), loc) adamc@758: in adamc@758: ((L'.EAbs ("xml", s, s, adamc@758: strcat [(L'.EPrim (Prim.String ("")), loc), adamc@758: (L'.ERel 0, loc), adamc@803: (L'.EPrim (Prim.String ("")), loc)]), adamc@758: loc), adamc@758: fm) adamc@758: end adamc@758: adamc@758: | L.ECApp ((L.ECApp ( adamc@758: (L.EFfi ("Basis", "entry"), _), _), _), _) => adamc@758: let adamc@758: val s = (L'.TFfi ("Basis", "string"), loc) adamc@758: in adamc@758: ((L'.EAbs ("xml", s, s, adamc@803: strcat [(L'.EPrim (Prim.String ("")), loc), adamc@758: (L'.ERel 0, loc), adamc@803: (L'.EPrim (Prim.String ("")), loc)]), adamc@758: loc), adamc@758: fm) adamc@758: end adamc@758: adamc@148: | L.EApp ((L.ECApp ( adamc@148: (L.ECApp ( adamc@148: (L.ECApp ( adamc@148: (L.ECApp ( adamc@148: (L.EFfi ("Basis", "useMore"), _), _), _), adamc@148: _), _), adamc@148: _), _), adamc@148: _), _), adamc@179: xml) => monoExp (env, st, fm) xml adamc@148: adamc@283: | L.ECApp ((L.EFfi ("Basis", "error"), _), t) => adamc@283: let adamc@283: val t = monoType env t adamc@283: in adamc@283: ((L'.EAbs ("s", (L'.TFfi ("Basis", "string"), loc), t, adamc@283: (L'.EError ((L'.ERel 0, loc), t), loc)), loc), adamc@283: fm) adamc@283: end adamc@741: | L.ECApp ((L.EFfi ("Basis", "returnBlob"), _), t) => adamc@741: let adamc@741: val t = monoType env t adamc@741: val un = (L'.TRecord [], loc) adamc@741: in adamc@741: ((L'.EAbs ("b", (L'.TFfi ("Basis", "blob"), loc), adamc@741: (L'.TFun ((L'.TFfi ("Basis", "string"), loc), (L'.TFun (un, t), loc)), loc), adamc@741: (L'.EAbs ("mt", (L'.TFfi ("Basis", "string"), loc), (L'.TFun (un, t), loc), adamc@741: (L'.EAbs ("_", un, t, adamc@741: (L'.EReturnBlob {blob = (L'.ERel 2, loc), adamc@741: mimeType = (L'.ERel 1, loc), adamc@741: t = t}, loc)), loc)), loc)), loc), adamc@741: fm) adamc@741: end adamc@1065: | L.ECApp ((L.EFfi ("Basis", "redirect"), _), t) => adamc@1065: let adamc@1065: val t = monoType env t adamc@1065: val un = (L'.TRecord [], loc) adamc@1065: in adamc@1065: ((L'.EAbs ("url", (L'.TFfi ("Basis", "string"), loc), (L'.TFun (un, t), loc), adamc@1065: (L'.EAbs ("_", un, t, adamc@1065: (L'.ERedirect ((L'.ERel 1, loc), t), loc)), loc)), loc), adamc@1065: fm) adamc@1065: end adamc@283: adamc@1104: | L.ECApp ((L.EFfi ("Basis", "serialize"), _), t) => adamc@1104: let adamc@1104: val t = monoType env t adamc@1104: val (e, fm) = urlifyExp env fm ((L'.ERel 0, loc), t) adamc@1104: in adamc@1104: ((L'.EAbs ("v", t, (L'.TFfi ("Basis", "string"), loc), e), loc), adamc@1104: fm) adamc@1104: end adamc@1104: | L.ECApp ((L.EFfi ("Basis", "deserialize"), _), t) => adamc@1104: let adamc@1104: val t = monoType env t adamc@1104: in adamc@1112: ((L'.EAbs ("v", (L'.TFfi ("Basis", "string"), loc), t, (L'.EUnurlify ((L'.ERel 0, loc), t, false), adamc@1112: loc)), loc), adamc@1104: fm) adamc@1104: end adamc@1104: adamc@1067: | L.EFfiApp ("Basis", "url", [e]) => adamc@1067: let adamc@1067: val (e, fm) = monoExp (env, st, fm) e adamc@1067: in adamc@1067: urlifyExp env fm (e, dummyTyp) adamc@1067: end adamc@1067: adamc@179: | L.EApp (e1, e2) => adamc@179: let adamc@179: val (e1, fm) = monoExp (env, st, fm) e1 adamc@179: val (e2, fm) = monoExp (env, st, fm) e2 adamc@179: in adamc@179: ((L'.EApp (e1, e2), loc), fm) adamc@179: end adamc@26: | L.EAbs (x, dom, ran, e) => adamc@179: let adamc@179: val (e, fm) = monoExp (Env.pushERel env x dom, st, fm) e adamc@179: in adamc@179: ((L'.EAbs (x, monoType env dom, monoType env ran, e), loc), fm) adamc@179: end adamc@25: | L.ECApp _ => poly () adamc@25: | L.ECAbs _ => poly () adamc@25: adamc@252: | L.EFfi mx => ((L'.EFfi mx, loc), fm) adamc@252: | L.EFfiApp (m, x, es) => adamc@252: let adamc@252: val (es, fm) = ListUtil.foldlMap (fn (e, fm) => monoExp (env, st, fm) e) fm es adamc@252: in adamc@252: ((L'.EFfiApp (m, x, es), loc), fm) adamc@252: end adamc@252: adamc@179: | L.ERecord xes => adamc@179: let adamc@179: val (xes, fm) = ListUtil.foldlMap adamc@179: (fn ((x, e, t), fm) => adamc@179: let adamc@179: val (e, fm) = monoExp (env, st, fm) e adamc@179: in adamc@179: ((monoName env x, adamc@179: e, adamc@179: monoType env t), fm) adamc@179: end) fm xes adamc@905: adamc@905: val xes = ListMergeSort.sort (fn ((x, _, _), (y, _, _)) => String.compare (x, y) = GREATER) xes adamc@179: in adamc@179: ((L'.ERecord xes, loc), fm) adamc@179: end adamc@179: | L.EField (e, x, _) => adamc@179: let adamc@179: val (e, fm) = monoExp (env, st, fm) e adamc@179: in adamc@179: ((L'.EField (e, monoName env x), loc), fm) adamc@179: end adamc@445: | L.EConcat _ => poly () adamc@149: | L.ECut _ => poly () adamc@493: | L.ECutMulti _ => poly () adamc@177: adamc@182: | L.ECase (e, pes, {disc, result}) => adamc@179: let adamc@179: val (e, fm) = monoExp (env, st, fm) e adamc@179: val (pes, fm) = ListUtil.foldlMap adamc@179: (fn ((p, e), fm) => adamc@179: let adamc@179: val (e, fm) = monoExp (env, st, fm) e adamc@179: in adamc@182: ((monoPat env p, e), fm) adamc@179: end) fm pes adamc@179: in adamc@182: ((L'.ECase (e, pes, {disc = monoType env disc, result = monoType env result}), loc), fm) adamc@179: end adamc@177: adamc@179: | L.EWrite e => adamc@179: let adamc@179: val (e, fm) = monoExp (env, st, fm) e adamc@179: in adamc@252: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TRecord [], loc), adamc@252: (L'.EWrite (liftExpInExp 0 e), loc)), loc), fm) adamc@179: end adamc@110: adamc@179: | L.EClosure (n, es) => adamc@179: let adamc@179: val (es, fm) = ListUtil.foldlMap (fn (e, fm) => adamc@179: monoExp (env, st, fm) e) adamc@1065: fm es adamc@1065: val e = (L'.EClosure (n, es), loc) adamc@179: in adamc@1067: (e, fm) adamc@179: end adamc@450: adamc@450: | L.ELet (x, t, e1, e2) => adamc@450: let adamc@450: val t' = monoType env t adamc@450: val (e1, fm) = monoExp (env, st, fm) e1 adamc@450: val (e2, fm) = monoExp (Env.pushERel env x t, st, fm) e2 adamc@450: in adamc@450: ((L'.ELet (x, t', e1, e2), loc), fm) adamc@450: end adamc@607: adamc@1020: | L.EServerCall (n, es, t) => adamc@608: let adamc@609: val t = monoType env t adamc@614: val (_, ft, _, name) = Env.lookupENamed env n adamc@608: val (es, fm) = ListUtil.foldlMap (fn (e, fm) => monoExp (env, st, fm) e) fm es adamc@614: adamc@614: fun encodeArgs (es, ft, acc, fm) = adamc@614: case (es, ft) of adamc@614: ([], _) => (rev acc, fm) adamc@614: | (e :: es, (L.TFun (dom, ran), _)) => adamc@614: let adamc@614: val (e, fm) = urlifyExp env fm (e, monoType env dom) adamc@614: in adamc@614: encodeArgs (es, ran, e adamc@614: :: (L'.EPrim (Prim.String "/"), loc) adamc@614: :: acc, fm) adamc@614: end adamc@614: | _ => raise Fail "Monoize: Not enough arguments visible in RPC function type" adamc@614: adamc@614: val (call, fm) = encodeArgs (es, ft, [], fm) adamc@614: val call = foldl (fn (e, call) => (L'.EStrcat (call, e), loc)) adamc@614: (L'.EPrim (Prim.String name), loc) call adamc@614: adamc@905: val unit = (L'.TRecord [], loc) adamc@905: adamc@736: val eff = if IS.member (!readCookie, n) then adamc@736: L'.ReadCookieWrite adamc@736: else adamc@736: L'.ReadOnly adamc@905: adamc@1020: val e = (L'.EServerCall (call, t, eff), loc) adamc@651: val e = liftExpInExp 0 e adamc@651: val e = (L'.EAbs ("_", unit, unit, e), loc) adamc@608: in adamc@651: (e, fm) adamc@608: end adamc@626: adamc@626: | L.EKAbs _ => poly () adamc@626: | L.EKApp _ => poly () adamc@25: end adamc@25: adamc@179: fun monoDecl (env, fm) (all as (d, loc)) = adamc@25: let adamc@25: fun poly () = adamc@25: (E.errorAt loc "Unsupported declaration"; adamc@25: Print.eprefaces' [("Declaration", CorePrint.p_decl env all)]; adamc@25: NONE) adamc@25: in adamc@25: case d of adamc@25: L.DCon _ => NONE adamc@808: | L.DDatatype [("list", n, [_], [("Nil", _, NONE), adamc@808: ("Cons", _, SOME (L.TRecord (L.CRecord (_, adamc@808: [((L.CName "1", _), adamc@808: (L.CRel 0, _)), adamc@808: ((L.CName "2", _), adamc@808: (L.CApp ((L.CNamed n', _), adamc@808: (L.CRel 0, _)), adamc@808: _))]), _), _))])] => adamc@757: if n = n' then adamc@757: NONE adamc@757: else adamc@757: poly () adamc@808: | L.DDatatype dts => adamc@808: let adamc@808: val env' = Env.declBinds env all adamc@808: val dts = map (fn (x, n, [], xncs) => adamc@808: (x, n, map (fn (x, n, to) => (x, n, Option.map (monoType env') to)) xncs) adamc@808: | _ => (E.errorAt loc "Polymorphic datatype needed too late"; adamc@808: Print.eprefaces' [("Declaration", CorePrint.p_decl env all)]; adamc@808: ("", 0, []))) dts adamc@808: val d = (L'.DDatatype dts, loc) adamc@808: in adamc@808: SOME (env', fm, [d]) adamc@808: end adamc@179: | L.DVal (x, n, t, e, s) => adamc@179: let adamc@179: val (e, fm) = monoExp (env, St.empty, fm) e adamc@179: in adamc@179: SOME (Env.pushENamed env x n t NONE s, adamc@179: fm, adamc@273: [(L'.DVal (x, n, monoType env t, e, s), loc)]) adamc@179: end adamc@128: | L.DValRec vis => adamc@128: let adamc@1107: val vis = map (fn (x, n, t, e, s) => adamc@1107: let adamc@1107: fun maybeTransaction (t, e) = adamc@1107: case (#1 t, #1 e) of adamc@1107: (L.CApp ((L.CFfi ("Basis", "transaction"), _), _), _) => adamc@1107: SOME (L.EAbs ("_", adamc@1107: (L.TRecord (L.CRecord ((L.KType, loc), []), loc), loc), adamc@1107: t, adamc@1107: (L.EApp (CoreEnv.liftExpInExp 0 e, adamc@1107: (L.ERecord [], loc)), loc)), loc) adamc@1107: | (L.TFun (dom, ran), L.EAbs (x, _, _, e)) => adamc@1107: (case maybeTransaction (ran, e) of adamc@1107: NONE => NONE adamc@1107: | SOME e => SOME (L.EAbs (x, dom, ran, e), loc)) adamc@1107: | _ => NONE adamc@1107: in adamc@1107: (x, n, t, adamc@1107: case maybeTransaction (t, e) of adamc@1107: NONE => e adamc@1107: | SOME e => e, adamc@1107: s) adamc@1107: end) vis adamc@1107: adamc@128: val env = foldl (fn ((x, n, t, e, s), env) => Env.pushENamed env x n t NONE s) env vis adamc@179: adamc@179: val (vis, fm) = ListUtil.foldlMap adamc@179: (fn ((x, n, t, e, s), fm) => adamc@179: let adamc@179: val (e, fm) = monoExp (env, St.empty, fm) e adamc@179: in adamc@179: ((x, n, monoType env t, e, s), fm) adamc@179: end) adamc@179: fm vis adamc@128: in adamc@128: SOME (env, adamc@179: fm, adamc@273: [(L'.DValRec vis, loc)]) adamc@128: end adamc@1104: | L.DExport (ek, n, b) => adamc@115: let adamc@120: val (_, t, _, s) = Env.lookupENamed env n adamc@120: adamc@609: fun unwind (t, args) = adamc@609: case #1 t of adamc@609: L.TFun (dom, ran) => unwind (ran, dom :: args) adamc@314: | L.CApp ((L.CFfi ("Basis", "transaction"), _), t) => adamc@609: unwind (t, (L.TRecord (L.CRecord ((L.KType, loc), []), loc), loc) :: args) adamc@609: | _ => (rev args, t) adamc@120: adamc@609: val (ts, ran) = unwind (t, []) adamc@609: val ts = map (monoType env) ts adamc@609: val ran = monoType env ran adamc@115: in adamc@1104: SOME (env, fm, [(L'.DExport (ek, s, n, ts, ran, b), loc)]) adamc@115: end adamc@707: | L.DTable (x, n, (L.CRecord (_, xts), _), s, pe, _, ce, _) => adamc@251: let adamc@251: val t = (L.CFfi ("Basis", "string"), loc) adamc@251: val t' = (L'.TFfi ("Basis", "string"), loc) adamc@311: val s = "uw_" ^ s adamc@704: val e_name = (L'.EPrim (Prim.String s), loc) adamc@273: adamc@273: val xts = map (fn (x, t) => (monoName env x, monoType env t)) xts adamc@704: adamc@707: val (pe, fm) = monoExp (env, St.empty, fm) pe adamc@707: val (ce, fm) = monoExp (env, St.empty, fm) ce adamc@251: in adamc@251: SOME (Env.pushENamed env x n t NONE s, adamc@251: fm, adamc@707: [(L'.DTable (s, xts, pe, ce), loc), adamc@704: (L'.DVal (x, n, t', e_name, s), loc)]) adamc@251: end adamc@273: | L.DTable _ => poly () adamc@754: | L.DView (x, n, s, e, (L.CRecord (_, xts), _)) => adamc@754: let adamc@754: val t = (L.CFfi ("Basis", "string"), loc) adamc@754: val t' = (L'.TFfi ("Basis", "string"), loc) adamc@754: val s = "uw_" ^ s adamc@754: val e_name = (L'.EPrim (Prim.String s), loc) adamc@754: adamc@754: val xts = map (fn (x, t) => (monoName env x, monoType env t)) xts adamc@754: adamc@754: val (e, fm) = monoExp (env, St.empty, fm) e adamc@754: val e = (L'.EFfiApp ("Basis", "viewify", [e]), loc) adamc@754: in adamc@754: SOME (Env.pushENamed env x n t NONE s, adamc@754: fm, adamc@754: [(L'.DView (s, xts, e), loc), adamc@754: (L'.DVal (x, n, t', e_name, s), loc)]) adamc@754: end adamc@754: | L.DView _ => poly () adamc@338: | L.DSequence (x, n, s) => adamc@338: let adamc@338: val t = (L.CFfi ("Basis", "string"), loc) adamc@338: val t' = (L'.TFfi ("Basis", "string"), loc) adamc@338: val s = "uw_" ^ s adamc@338: val e = (L'.EPrim (Prim.String s), loc) adamc@338: in adamc@338: SOME (Env.pushENamed env x n t NONE s, adamc@338: fm, adamc@338: [(L'.DSequence s, loc), adamc@338: (L'.DVal (x, n, t', e, s), loc)]) adamc@338: end adamc@683: | L.DDatabase _ => NONE adamc@462: | L.DCookie (x, n, t, s) => adamc@462: let adamc@462: val t = (L.CFfi ("Basis", "string"), loc) adamc@462: val t' = (L'.TFfi ("Basis", "string"), loc) adamc@462: val e = (L'.EPrim (Prim.String s), loc) adamc@462: in adamc@462: SOME (Env.pushENamed env x n t NONE s, adamc@462: fm, adamc@725: [(L'.DCookie s, loc), adamc@725: (L'.DVal (x, n, t', e, s), loc)]) adamc@462: end adamc@720: | L.DStyle (x, n, s) => adamc@718: let adamc@718: val t = (L.CFfi ("Basis", "string"), loc) adamc@718: val t' = (L'.TFfi ("Basis", "string"), loc) adamc@718: val e = (L'.EPrim (Prim.String s), loc) adamc@718: in adamc@718: SOME (Env.pushENamed env x n t NONE s, adamc@718: fm, adamc@720: [(L'.DStyle s, loc), adamc@718: (L'.DVal (x, n, t', e, s), loc)]) adamc@718: end adamc@1075: | L.DTask (e1, e2) => adamc@1073: let adamc@1075: val (e1, fm) = monoExp (env, St.empty, fm) e1 adamc@1075: val (e2, fm) = monoExp (env, St.empty, fm) e2 adamc@1073: in adamc@1073: SOME (env, adamc@1073: fm, adamc@1075: [(L'.DTask (e1, e2), loc)]) adamc@1073: end adamc@1199: | L.DPolicy e => adamc@1199: let adamc@1199: val (e, make) = adamc@1199: case #1 e of adamc@1214: L.EApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sendClient"), _), _), _), _), _), e) => adamc@1214: (e, L'.PolClient) adamc@1214: | _ => (poly (); (e, L'.PolClient)) adamc@1199: adamc@1199: val (e, fm) = monoExp (env, St.empty, fm) e adamc@1199: in adamc@1199: SOME (env, adamc@1199: fm, adamc@1199: [(L'.DPolicy (make e), loc)]) adamc@1199: end adamc@25: end adamc@25: adamc@683: datatype expungable = Client | Channel adamc@683: adamc@683: fun monoize env file = adamc@25: let adamc@735: (* Calculate which exported functions need cookie signature protection *) adamc@735: val rcook = foldl (fn ((d, _), rcook) => adamc@735: case d of adamc@1104: L.DExport (L.Action L.ReadCookieWrite, n, _) => IS.add (rcook, n) adamc@1104: | L.DExport (L.Rpc L.ReadCookieWrite, n, _) => IS.add (rcook, n) adamc@735: | _ => rcook) adamc@735: IS.empty file adamc@735: val () = readCookie := rcook adamc@735: adamc@683: val loc = E.dummySpan adamc@683: val client = (L'.TFfi ("Basis", "client"), loc) adamc@683: val unit = (L'.TRecord [], loc) adamc@687: adamc@687: fun calcClientish xts = adamc@687: foldl (fn ((x : L.con, t : L.con), st as (nullable, notNullable)) => adamc@687: case #1 x of adamc@687: L.CName x => adamc@687: (case #1 t of adamc@687: L.CFfi ("Basis", "client") => adamc@687: (nullable, (x, Client) :: notNullable) adamc@687: | L.CApp ((L.CFfi ("Basis", "option"), _), adamc@687: (L.CFfi ("Basis", "client"), _)) => adamc@687: ((x, Client) :: nullable, notNullable) adamc@687: | L.CApp ((L.CFfi ("Basis", "channel"), _), _) => adamc@687: (nullable, (x, Channel) :: notNullable) adamc@687: | L.CApp ((L.CFfi ("Basis", "option"), _), adamc@687: (L.CApp ((L.CFfi ("Basis", "channel"), _), _), _)) => adamc@687: ((x, Channel) :: nullable, notNullable) adamc@687: | _ => st) adamc@687: | _ => st) ([], []) xts adamc@687: adamc@683: fun expunger () = adamc@683: let adamc@683: val target = (L'.EFfiApp ("Basis", "sqlifyClient", [(L'.ERel 0, loc)]), loc) adamc@683: adamc@683: fun doTable (tab, xts, e) = adamc@683: case xts of adamc@683: L.CRecord (_, xts) => adamc@683: let adamc@687: val (nullable, notNullable) = calcClientish xts adamc@683: adamc@684: fun cond (x, v) = adamc@684: (L'.EStrcat ((L'.EPrim (Prim.String ("uw_" ^ x adamc@684: ^ (case v of adamc@684: Client => "" adamc@684: | Channel => " >> 32") adamc@684: ^ " = ")), loc), adamc@684: target), loc) adamc@684: adamc@684: val e = adamc@684: foldl (fn ((x, v), e) => adamc@684: (L'.ESeq ( adamc@684: (L'.EDml (L'.EStrcat ( adamc@684: (L'.EPrim (Prim.String ("UPDATE uw_" adamc@684: ^ tab adamc@684: ^ " SET uw_" adamc@684: ^ x adamc@684: ^ " = NULL WHERE ")), loc), adamc@684: cond (x, v)), loc), loc), adamc@684: e), loc)) adamc@684: e nullable adamc@684: adamc@683: val e = adamc@683: case notNullable of adamc@683: [] => e adamc@683: | eb :: ebs => adamc@684: (L'.ESeq ( adamc@684: (L'.EDml (foldl adamc@684: (fn (eb, s) => adamc@684: (L'.EStrcat (s, adamc@687: (L'.EStrcat ((L'.EPrim (Prim.String " OR "), adamc@684: loc), adamc@684: cond eb), loc)), loc)) adamc@684: (L'.EStrcat ((L'.EPrim (Prim.String ("DELETE FROM uw_" adamc@684: ^ tab adamc@684: ^ " WHERE ")), loc), adamc@684: cond eb), loc) adamc@684: ebs), loc), adamc@684: e), loc) adamc@683: in adamc@683: e adamc@683: end adamc@683: | _ => e adamc@683: adamc@683: val e = (L'.ERecord [], loc) adamc@683: in adamc@683: foldl (fn ((d, _), e) => adamc@683: case d of adamc@707: L.DTable (_, _, xts, tab, _, _, _, _) => doTable (tab, #1 xts, e) adamc@683: | _ => e) e file adamc@683: end adamc@683: adamc@687: fun initializer () = adamc@687: let adamc@687: fun doTable (tab, xts, e) = adamc@687: case xts of adamc@687: L.CRecord (_, xts) => adamc@687: let adamc@687: val (nullable, notNullable) = calcClientish xts adamc@687: adamc@687: val e = adamc@687: case nullable of adamc@687: [] => e adamc@687: | (x, _) :: ebs => adamc@687: (L'.ESeq ( adamc@687: (L'.EDml (L'.EPrim (Prim.String adamc@687: (foldl (fn ((x, _), s) => adamc@687: s ^ ", uw_" ^ x ^ " = NULL") adamc@687: ("UPDATE uw_" adamc@687: ^ tab adamc@687: ^ " SET uw_" adamc@687: ^ x adamc@687: ^ " = NULL") adamc@687: ebs)), loc), loc), adamc@687: e), loc) adamc@687: adamc@687: val e = adamc@687: case notNullable of adamc@687: [] => e adamc@687: | eb :: ebs => adamc@687: (L'.ESeq ( adamc@687: (L'.EDml (L'.EPrim (Prim.String ("DELETE FROM uw_" adamc@687: ^ tab)), loc), loc), adamc@687: e), loc) adamc@687: in adamc@687: e adamc@687: end adamc@687: | _ => e adamc@687: adamc@687: val e = (L'.ERecord [], loc) adamc@687: in adamc@687: foldl (fn ((d, _), e) => adamc@687: case d of adamc@707: L.DTable (_, _, xts, tab, _, _, _, _) => doTable (tab, #1 xts, e) adamc@687: | _ => e) e file adamc@687: end adamc@687: adamc@179: val (_, _, ds) = List.foldl (fn (d, (env, fm, ds)) => adamc@683: case #1 d of adamc@683: L.DDatabase s => adamc@683: let adamc@687: val (nExp, fm) = Fm.freshName fm adamc@687: val (nIni, fm) = Fm.freshName fm adamc@687: adamc@687: val dExp = L'.DVal ("expunger", adamc@687: nExp, adamc@687: (L'.TFun (client, unit), loc), adamc@687: (L'.EAbs ("cli", client, unit, expunger ()), loc), adamc@687: "expunger") adamc@687: val dIni = L'.DVal ("initializer", adamc@687: nIni, adamc@687: (L'.TFun (unit, unit), loc), adamc@687: (L'.EAbs ("_", unit, unit, initializer ()), loc), adamc@687: "initializer") adamc@683: in adamc@687: (env, Fm.enter fm, (L'.DDatabase {name = s, adamc@687: expunge = nExp, adamc@687: initialize = nIni}, loc) adamc@687: :: (dExp, loc) adamc@687: :: (dIni, loc) adamc@683: :: ds) adamc@683: end adamc@683: | _ => adamc@683: case monoDecl (env, fm) d of adamc@683: NONE => (env, fm, ds) adamc@683: | SOME (env, fm, ds') => adamc@683: (env, adamc@683: Fm.enter fm, adamc@683: ds' @ Fm.decls fm @ ds)) adamc@683: (env, Fm.empty (CoreUtil.File.maxName file + 1), []) file adamc@25: in adamc@25: rev ds adamc@25: end adamc@25: adamc@25: end