adam@2008: (* Copyright (c) 2008-2014, 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 adam@1682: * 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: adam@1287: structure SK = struct adam@1287: type ord_key = string adam@1287: val compare = String.compare adam@1287: end adam@1287: adam@1287: structure SS = BinarySetFn(SK) adam@1287: structure SM = BinaryMapFn(SK) adam@1287: adam@1287: structure RM = BinaryMapFn(struct adam@1287: type ord_key = (string * L'.typ) list adam@1287: fun compare (r1, r2) = MonoUtil.Typ.compare ((L'.TRecord r1, E.dummySpan), adam@1287: (L'.TRecord r2, E.dummySpan)) adamc@984: end) adamc@984: adam@1287: val nextPvar = ref 0 adam@1287: val pvars = ref (RM.empty : (int * (string * int * L'.typ) list) RM.map) adam@1713: val pvarDefs = ref ([] : (string * int * (string * int * L'.typ option) list) list) adam@1288: val pvarOldDefs = ref ([] : (int * (string * int * L.con option) list) list) adam@1287: adam@1287: fun choosePvar () = adam@1287: let adam@1287: val n = !nextPvar adam@1287: in adam@1287: nextPvar := n + 1; adam@1287: n adam@1287: end adam@1287: adam@1288: fun pvar (r, r', loc) = adam@1288: case RM.find (!pvars, r') of adam@1287: NONE => adam@1287: let adam@1287: val n = choosePvar () adam@1288: val fs = map (fn (x, t) => (x, choosePvar (), t)) r' adam@1734: val r = ListMergeSort.sort (fn (((L.CName x, _), _), ((L.CName y, _), _)) => String.compare (x, y) = GREATER adam@1734: | _ => raise Fail "Monoize: pvar, not CName") r adam@1288: val (r, fs') = ListPair.foldr (fn ((_, t), (x, n, _), (r, fs')) => adam@1288: ((x, n, SOME t) :: r, adam@1288: SM.insert (fs', x, n))) ([], SM.empty) (r, fs) adam@1287: in adam@1288: pvars := RM.insert (!pvars, r', (n, fs)); adam@1713: pvarDefs := ("$poly" ^ Int.toString n, n, map (fn (x, n, t) => (x, n, SOME t)) fs) adam@1287: :: !pvarDefs; adam@1288: pvarOldDefs := (n, r) :: !pvarOldDefs; adam@1287: (n, fs) adam@1287: end adam@1287: | SOME v => v adam@1287: 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", adam@1841: "img", adam@1841: "base", adam@1841: "meta", adam@1841: "param", adam@1841: "area", adam@1841: "col"]) 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: adam@1287: | L.CApp ((L.CFfi ("Basis", "variant"), _), (L.CRecord ((L.KType, _), xts), _)) => adam@1287: let adam@1288: val xts' = map (fn (x, t) => (monoName env x, mt env dtmap t)) xts adam@1288: val xts' = ListMergeSort.sort (fn ((x, _), (y, _)) => String.compare (x, y) = GREATER) xts' adam@1288: val (n, cs) = pvar (xts, xts', loc) adam@1287: val cs = map (fn (x, n, t) => (x, n, SOME t)) cs adam@1287: in adam@1287: (L'.TDatatype (n, ref (ElabUtil.classifyDatatype cs, cs)), loc) adam@1287: end adam@1287: 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)), mad@1831: ("Mod", (L'.TFun (t, (L'.TFun (t, t), loc)), loc)), adam@1832: ("Pow", (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) adam@1921: | L.CFfi ("Basis", "xhead") => (L'.TFfi ("Basis", "string"), loc) adamc@1176: | L.CFfi ("Basis", "xbody") => (L'.TFfi ("Basis", "string"), loc) kkallio@1475: | L.CFfi ("Basis", "xtable") => (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) adam@1750: | L.CFfi ("Basis", "css_value") => (L'.TFfi ("Basis", "string"), loc) adam@1750: | L.CFfi ("Basis", "css_property") => (L'.TFfi ("Basis", "string"), loc) adam@1750: | L.CFfi ("Basis", "css_style") => (L'.TFfi ("Basis", "string"), loc) adam@1556: | L.CFfi ("Basis", "id") => (L'.TFfi ("Basis", "string"), loc) adam@1799: | L.CFfi ("Basis", "requestHeader") => (L'.TFfi ("Basis", "string"), loc) adam@1799: | L.CFfi ("Basis", "responseHeader") => (L'.TFfi ("Basis", "string"), loc) adam@1799: | L.CFfi ("Basis", "envVar") => (L'.TFfi ("Basis", "string"), loc) adam@2047: | L.CFfi ("Basis", "data_attr_kind") => (L'.TFfi ("Basis", "string"), loc) adam@2008: | L.CFfi ("Basis", "data_attr") => (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) adam@1394: | L.CApp ((L.CApp ((L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_query"), _), _), _), _), _), _), _), _) => adamc@252: (L'.TFfi ("Basis", "string"), loc) adam@1394: | L.CApp ((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) adam@1778: | L.CApp ((L.CApp ((L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_exp"), _), _), _), _), _), _), _), _) => adam@1778: (L'.TFfi ("Basis", "string"), loc) adam@1778: | L.CApp ((L.CApp ((L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_expw"), _), _), _), _), _), _), _), _) => adam@1778: (L'.TFfi ("Basis", "string"), loc) adam@1778: | L.CApp ((L.CFfi ("Basis", "sql_window"), _), _) => adam@1778: (L'.TRecord [], loc) adam@1778: | L.CApp ((L.CApp ((L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_window_function"), _), _), _), _), _), _), _), _) => 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) adam@1870: | L.CFfi ("Basis", "dml") => adam@1870: (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) adam@1778: | L.CApp ((L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_partition"), _), _), _), _), _), _) => adam@1778: (L'.TFfi ("Basis", "string"), loc) adam@1778: | L.CApp ((L.CApp ((L.CApp ((L.CApp ((L.CFfi ("Basis", "sql_window"), _), _), _), _), _), _), _), _) => adam@1778: (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 adam@1682: adamc@196: val dtmap' = IM.insert (dtmap, n, r) adam@1682: 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: adam@1730: type vr = string * int * L'.typ * L'.exp * string adam@1730: adamc@179: structure Fm :> sig adamc@179: type t adamc@179: adamc@179: val empty : int -> t adamc@179: adam@1730: val lookup : t -> foo_kind -> int -> (int -> t -> vr * t) -> t * int adam@1730: val lookupList : t -> foo_kind -> L'.typ -> (int -> t -> vr * 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, adam@1730: decls : vr 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: adam@1287: fun chooseNext count = adam@1287: let adam@1287: val n = !nextPvar adam@1287: in adam@1287: if count < n then adam@1287: (count, count+1) adam@1287: else adam@1287: (nextPvar := n + 1; adam@1287: (n, n+1)) adam@1287: end adam@1287: adamc@758: fun enter ({count, map, listMap, ...} : t) = {count = count, map = map, listMap = listMap, decls = []} adam@1287: fun freshName {count, map, listMap, decls} = adam@1287: let adam@1287: val (next, count) = chooseNext count adam@1287: in adam@1287: (next, {count = count , map = map, listMap = listMap, decls = decls}) adam@1287: end adam@1730: fun decls ({decls, ...} : t) = adam@1730: case decls of adam@1730: [] => [] adam@1730: | _ => [(L'.DValRec decls, ErrorMsg.dummySpan)] 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 adam@2048: ((L'.EPrim (Prim.String (Prim.Normal, 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, adam@2048: (L'.EStrcat ((L'.EPrim (Prim.String (Prim.Normal, "/")), 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 adam@2048: attrify (args, ft, (L'.EPrim (Prim.String (Prim.Normal, Settings.getUrlPrefix () ^ s)), loc), fm) adamc@120: end adamc@120: | _ => adamc@120: case t of adam@2048: L'.TFfi ("Basis", "unit") => ((L'.EPrim (Prim.String (Prim.Normal, "")), loc), fm) adam@1663: | L'.TFfi (m, x) => ((L'.EFfiApp (m, fk2s fk ^ "ify" ^ capitalize x, [(e, tAll)]), loc), fm) adamc@200: adam@2048: | L'.TRecord [] => ((L'.EPrim (Prim.String (Prim.Normal, "")), 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, adam@2048: (L'.EStrcat ((L'.EPrim (Prim.String (Prim.Normal, "/")), 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 adam@1655: val (x, xncs) = adam@1713: case ListUtil.search (fn (x, i', xncs) => adam@1655: if i' = i then adam@1655: SOME (x, xncs) adam@1655: else adam@1713: NONE) (!pvarDefs) of adam@1655: NONE => adam@1655: let adam@1655: val (x, _, xncs) = Env.lookupDatatype env i adam@1655: in adam@1655: (x, map (fn (x, n, c) => (x, n, Option.map (monoType env) c)) xncs) adam@1655: end adam@1655: | SOME v => v 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), adam@2048: (L'.EPrim (Prim.String (Prim.Normal, x)), loc)), adamc@179: fm) adamc@179: | SOME t => adamc@179: let 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), adam@2048: (L'.EStrcat ((L'.EPrim (Prim.String (Prim.Normal, 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 adam@1730: ((fk2s fk ^ "ify_" ^ x, adam@1730: n, adam@1730: (L'.TFun (dom, ran), loc), adam@1730: (L'.EAbs ("x", adam@1730: dom, adam@1730: ran, adam@1730: (L'.ECase ((L'.ERel 0, loc), adam@1730: branches, adam@1730: {disc = dom, adam@1730: result = ran}), loc)), loc), adam@1730: ""), adamc@179: fm) adam@1682: 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), adam@2048: (L'.EPrim (Prim.String (Prim.Normal, "None")), loc)), adam@1682: adamc@471: ((L'.PSome (t, (L'.PVar ("x", t), loc)), loc), adam@2048: (L'.EStrcat ((L'.EPrim (Prim.String (Prim.Normal, "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), adam@2048: (L'.EPrim (Prim.String (Prim.Normal, "Nil")), loc)), adamc@758: ((L'.PSome (rt, (L'.PVar ("a", rt), loc)), loc), adam@2048: (L'.EStrcat ((L'.EPrim (Prim.String (Prim.Normal, "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 adam@1730: ((fk2s fk ^ "ify_list", adam@1730: n, adam@1730: (L'.TFun (dom, ran), loc), adam@1730: (L'.EAbs ("x", adam@1730: dom, adam@1730: ran, adam@1730: (L'.ECase ((L'.ERel 0, loc), adam@1730: branches, adam@1730: {disc = dom, adam@1730: result = ran}), loc)), loc), adam@1730: ""), 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 adam@2048: [] => (L'.EPrim (Prim.String (Prim.Normal, "")), 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 adam@2048: [] => (L'.EPrim (Prim.String (Prim.Normal, "")), 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 adam@2048: ((L'.EPrim (Prim.String (_, "")), _), _) => e' adam@2048: | (_, (L'.EPrim (Prim.String (_, "")), _)) => e adamc@252: | _ => adamc@252: (L'.EStrcat (e, adam@2048: (L'.EStrcat ((L'.EPrim (Prim.String (Prim.Normal, ", ")), 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 adam@2048: fun str s = (L'.EPrim (Prim.String (Prim.Normal, s)), loc) adam@2048: fun strH s = (L'.EPrim (Prim.String (Prim.Html, 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)), mad@1831: ("Mod", (L'.TFun (t, (L'.TFun (t, t), loc)), loc)), adam@1832: ("Pow", (L'.TFun (t, (L'.TFun (t, t), loc)), loc))], loc) mad@1831: fun numEx (t, zero, neg, plus, minus, times, dv, md, ex) = 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)), mad@1831: ("Mod", md, (L'.TFun (t, (L'.TFun (t, t), loc)), loc)), adam@1832: ("Pow", ex, (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: adam@1287: | L.ECApp ( adam@1287: (L.ECApp ( adam@1288: (L.ECApp ((L.EFfi ("Basis", "make"), _), nmC as (L.CName nm, _)), _), adam@1287: t), _), adam@1287: (L.CRecord (_, xts), _)) => adam@1287: let adam@1288: val t' = monoType env t adam@1288: val xts' = map (fn (x, t) => (monoName env x, monoType env t)) xts adam@1288: val xts' = (nm, t') :: xts' adam@1288: val xts' = ListMergeSort.sort (fn ((x, _), (y, _)) => String.compare (x, y) = GREATER) xts' adam@1288: val (n, cs) = pvar ((nmC, t) :: xts, xts', loc) adam@1287: val cs' = map (fn (x, n, t) => (x, n, SOME t)) cs adam@1287: val cl = ElabUtil.classifyDatatype cs' adam@1287: in adam@1287: case List.find (fn (nm', _, _) => nm' = nm) cs of adam@1287: NONE => raise Fail "Monoize: Polymorphic variant tag mismatch for 'make'" adam@1288: | SOME (_, n', _) => ((L'.EAbs ("x", t', (L'.TDatatype (n, ref (cl, cs')), loc), adam@1287: (L'.ECon (cl, L'.PConVar n', SOME (L'.ERel 0, loc)), loc)), loc), adam@1287: fm) adam@1287: end adam@1287: adam@1287: | L.ECApp ( adam@1287: (L.ECApp ((L.EFfi ("Basis", "match"), _), (L.CRecord (_, xts), _)), _), adam@1287: t) => adam@1287: let adam@1287: val t = monoType env t adam@1288: val xts' = map (fn (x, t) => (monoName env x, monoType env t)) xts adam@1288: val xts' = ListMergeSort.sort (fn ((x, _), (y, _)) => String.compare (x, y) = GREATER) xts' adam@1288: val (n, cs) = pvar (xts, xts', loc) adam@1287: val cs' = map (fn (x, n, t) => (x, n, SOME t)) cs adam@1287: val cl = ElabUtil.classifyDatatype cs' adam@1288: val fs = (L'.TRecord (map (fn (x, t') => (x, (L'.TFun (t', t), loc))) xts'), loc) adam@1287: val dt = (L'.TDatatype (n, ref (cl, cs')), loc) adam@1287: in adam@1287: ((L'.EAbs ("v", adam@1287: dt, adam@1287: (L'.TFun (fs, t), loc), adam@1287: (L'.EAbs ("fs", fs, t, adam@1287: (L'.ECase ((L'.ERel 1, loc), adam@1287: map (fn (x, n', t') => adam@1287: ((L'.PCon (cl, L'.PConVar n', SOME (L'.PVar ("x", t'), loc)), loc), adam@1287: (L'.EApp ((L'.EField ((L'.ERel 1, loc), x), loc), adam@1287: (L'.ERel 0, loc)), loc))) cs, adam@1287: {disc = dt, result = t}), loc)), loc)), loc), adam@1287: fm) adam@1287: end adam@1287: 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), adam@1360: (L'.EBinop (L'.Int, "==", (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), adam@1360: (L'.EBinop (L'.NotInt, "==", (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), adam@1360: (L'.EBinop (L'.NotInt, "==", (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), adam@1360: (L'.EBinop (L'.NotInt, "!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), adam@1360: (L'.EBinop (L'.NotInt, "==", (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), adam@1663: (L'.EFfiApp ("Basis", "eq_time", [((L'.ERel 1, loc), (L'.TFfi ("Basis", "time"), loc)), adam@1663: ((L'.ERel 0, loc), (L'.TFfi ("Basis", "time"), 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 adam@1832: | L.ECApp ((L.EFfi ("Basis", "pow"), _), t) => mad@1831: let mad@1831: val t = monoType env t mad@1831: in mad@1831: ((L'.EAbs ("r", numTy t, (L'.TFun (t, (L'.TFun (t, t), loc)), loc), adam@1832: (L'.EField ((L'.ERel 0, loc), "Pow"), loc)), loc), fm) mad@1831: 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), adam@1360: (L'.EBinop (L'.Int, 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 "/", mad@1831: intBin "%", mad@1831: intBin "powl" mad@1831: ) 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), adam@1360: (L'.EBinop (L'.NotInt, 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 "*", adam@1619: floatBin "fdiv", mad@1831: floatBin "fmod", mad@1831: floatBin "powf" mad@1831: ) 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), adam@1360: (L'.EBinop (L'.Int, 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), adam@1360: (L'.EBinop (L'.NotInt, 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), adam@1371: (L'.EBinop (L'.NotInt, s, (L'.ERel 1, loc), (L'.ERel 0, loc)), loc)), loc)), loc) adamc@394: in adamc@394: ordEx ((L'.TFfi ("Basis", "bool"), loc), adam@1371: boolBin "<", adam@1371: 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), adam@1360: (L'.EBinop (L'.NotInt, s, adam@1360: (L'.EBinop (L'.NotInt, "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), adam@1360: (L'.EBinop (L'.NotInt, 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), adam@1663: (L'.EFfiApp ("Basis", s, [((L'.ERel 1, loc), (L'.TFfi ("Basis", "time"), loc)), adam@1663: ((L'.ERel 0, loc), (L'.TFfi ("Basis", "time"), loc))]), loc)), loc)), loc) adamc@437: in adamc@437: ordEx ((L'.TFfi ("Basis", "time"), loc), adam@1365: boolBin "lt_time", adam@1365: boolBin "le_time") 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 adam@1682: 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 adam@1370: | L.EFfi ("Basis", "show_queryString") => adam@1370: let adam@1370: val s = (L'.TFfi ("Basis", "string"), loc) adam@1370: in adam@1370: ((L'.EAbs ("s", s, s, (L'.ERel 0, loc)), loc), fm) adam@1370: 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 adam@1477: | L.EFfi ("Basis", "show_css_class") => adam@1477: let adam@1477: val s = (L'.TFfi ("Basis", "string"), loc) adam@1477: in adam@1477: ((L'.EAbs ("s", s, s, (L'.ERel 0, loc)), loc), fm) adam@1477: end grrwlf@1929: | L.EFfi ("Basis", "show_id") => grrwlf@1929: let grrwlf@1929: val s = (L'.TFfi ("Basis", "string"), loc) grrwlf@1929: in grrwlf@1929: ((L'.EAbs ("s", s, s, (L'.ERel 0, loc)), loc), fm) grrwlf@1929: 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 adam@1810: | L.ECApp ((L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "show_sql_query"), _), _), _), _), _), _), _), _) => adam@1810: let adam@1810: val s = (L'.TFfi ("Basis", "string"), loc) adam@1810: in adam@1810: ((L'.EAbs ("s", s, s, (L'.ERel 0, loc)), loc), fm) adam@1810: 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: adam@1544: | L.ECApp ((L.EFfi ("Basis", "transaction_return"), _), t) => adamc@252: let adamc@252: val t = monoType env t adamc@252: in adam@1544: ((L'.EAbs ("x", t, adamc@820: (L'.TFun ((L'.TRecord [], loc), t), loc), adamc@820: (L'.EAbs ("_", (L'.TRecord [], loc), t, adam@1544: (L'.ERel 1, loc)), loc)), loc), adamc@820: fm) adamc@252: end adam@1544: | L.ECApp ((L.ECApp ((L.EFfi ("Basis", "transaction_bind"), _), 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 adam@1544: ((L'.EAbs ("m1", mt1, (L'.TFun ((L'.TFun (t1, mt2), loc), (L'.TFun (un, un), loc)), loc), adam@1544: (L'.EAbs ("m2", (L'.TFun (t1, mt2), loc), (L'.TFun (un, un), loc), adam@1544: (L'.EAbs ("_", un, un, adam@1544: (L'.ELet ("r", t1, (L'.EApp ((L'.ERel 2, loc), adam@1544: (L'.ERecord [], loc)), loc), adam@1544: (L'.EApp ( adam@1544: (L'.EApp ((L'.ERel 2, loc), (L'.ERel 0, loc)), loc), adam@1544: (L'.ERecord [], loc)), adam@1544: 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: adam@1663: | L.EFfiApp ("Basis", "float", [(e, t)]) => adam@1571: let adam@1571: val (e, fm) = monoExp (env, st, fm) e adam@1571: in adam@1663: ((L'.EFfiApp ("Basis", "floatFromInt", [(e, monoType env t)]), loc), fm) adam@1571: end adam@1571: adam@1663: | 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", adam@1663: [((L'.EJavaScript (L'.Source t, (L'.ERel 1, loc)), loc), adam@1663: (L'.TSource, 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", adam@1663: [((L'.ERel 2, loc), (L'.TSource, loc)), adam@1663: ((L'.EJavaScript (L'.Source t, adam@1663: (L'.ERel 1, loc)), loc), adam@1664: (L'.TFfi ("Basis", "string"), 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", adam@1663: [((L'.ERel 1, loc), (L'.TSource, 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", adam@1663: [((L'.ERel 1, loc), (L'.TSource, loc))]), adamc@841: loc)), loc)), loc), adamc@841: fm) adamc@841: end adamc@565: adam@1663: | 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: adam@1544: | L.ECApp ((L.EFfi ("Basis", "signal_return"), _), t) => adamc@568: let adamc@568: val t = monoType env t adamc@568: in adam@1544: ((L'.EAbs ("x", t, (L'.TSignal t, loc), adam@1544: (L'.ESignalReturn (L'.ERel 0, loc), loc)), loc), adamc@568: fm) adamc@568: end adam@1544: | L.ECApp ((L.ECApp ((L.EFfi ("Basis", "signal_bind"), _), 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 adam@1544: ((L'.EAbs ("m1", mt1, (L'.TFun ((L'.TFun (t1, mt2), loc), mt2), loc), adam@1544: (L'.EAbs ("m2", (L'.TFun (t1, mt2), loc), mt2, adam@1544: (L'.ESignalBind ((L'.ERel 1, loc), (L'.ERel 0, loc)), loc)), loc)), 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, adam@1663: (L'.EUnurlify ((L'.EFfiApp ("Basis", "get_cookie", [((L'.ERel 1, loc), s)]), 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, adam@2048: (L'.EFfiApp ("Basis", "set_cookie", [(str (Settings.getUrlPrefix ()), s), adam@1663: ((L'.ERel 2, loc), s), adam@1663: (e, s), adam@1663: (fd "Expires", (L'.TOption (L'.TFfi ("Basis", "time"), loc), loc)), adam@1663: (fd "Secure", (L'.TFfi ("Basis", "bool"), loc))]) 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", adam@2048: [(str (Settings.getUrlPrefix ()), s), adam@1663: ((L'.ERel 1, loc), s)]), 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), adam@1663: (L'.EFfiApp ("Basis", "new_channel", [((L'.ERecord [], loc), (L'.TRecord [], 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", adam@1663: [((L'.ERel 2, loc), (L'.TFfi ("Basis", "channel"), loc)), adam@1663: (e, (L'.TFfi ("Basis", "string"), loc))]), adamc@668: loc)), loc)), loc)), loc), adamc@668: fm) adamc@668: end adamc@668: adamc@707: | L.ECApp ((L.EFfi ("Basis", "no_primary_key"), _), _) => adam@2048: (str "", 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), adam@2048: (str adam@2048: (String.concatWith ", " adam@2048: (map (fn (x, _) => adam@2048: Settings.mangleSql (monoNameLc env x) adam@2048: ^ (if #textKeysNeedLengths (Settings.currentDbms ()) adam@2048: andalso isBlobby t then adam@2048: "(767)" adam@2048: else adam@2048: "")) unique)))), adam@2048: 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 adam@2048: (str ("UNIQUE (" adam@2048: ^ String.concatWith ", " adam@2048: (map (fn (x, t) => Settings.mangleSql (monoNameLc env x) adam@2048: ^ (if #textKeysNeedLengths (Settings.currentDbms ()) adam@2048: andalso isBlobby t then adam@2048: "(767)" adam@2048: else adam@2048: "")) unique) adam@2048: ^ ")"), 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) adam@2048: val stringE = str "" 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), adam@2048: [((L'.PPrim (Prim.String (Prim.Normal, "")), loc), adam@2048: (L'.ERecord [("1", str (Settings.mangleSql (lowercaseFirst nm1)), adam@2048: string), adam@2048: ("2", str (Settings.mangleSql (lowercaseFirst nm2)), adam@2048: string)], loc)), adamc@712: ((L'.PWild, loc), adamc@712: (L'.ERecord [("1", (L'.EStrcat ( adam@2048: str (Settings.mangleSql (lowercaseFirst nm1) adam@2048: ^ ", "), adamc@712: (L'.EField ((L'.ERel 0, loc), "1"), loc)), adamc@712: loc), string), adamc@712: ("2", (L'.EStrcat ( adam@2048: str (Settings.mangleSql (lowercaseFirst nm2) adam@2048: ^ ", "), 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: adam@2048: | L.ECApp ((L.EFfi ("Basis", "restrict"), _), _) => (str "RESTRICT", fm) adam@2048: | L.ECApp ((L.EFfi ("Basis", "cascade"), _), _) => (str "CASCADE", fm) adam@2048: | L.ECApp ((L.EFfi ("Basis", "no_action"), _), _) => (str "NO ACTION", fm) adam@2048: | L.ECApp ((L.EFfi ("Basis", "set_null"), _), _) => (str "SET NULL", 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), adam@2048: [((L'.PPrim (Prim.String (Prim.Normal, "NO ACTION")), loc), adam@2048: str ""), adamc@709: ((L'.PWild, loc), adam@2048: strcat [str (" ON " ^ kw ^ " "), 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, adam@2048: strcat [str "FOREIGN KEY (", adamc@709: (L'.EField ((L'.ERel 2, loc), "1"), loc), adam@2048: str ") REFERENCES ", adamc@709: (L'.ERel 1, loc), adam@2048: str " (", adamc@709: (L'.EField ((L'.ERel 2, loc), "2"), loc), adam@2048: str ")", 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, adam@2048: (L'.EStrcat (str "CHECK ", adamc@714: (L'.EFfiApp ("Basis", "checkString", adam@1663: [((L'.ERel 0, loc), string)]), loc)), loc)), loc), adamc@714: fm) adamc@714: end adamc@714: adam@1663: | L.EFfiApp ("Basis", "dml", [(e, _)]) => adamc@307: let adamc@307: val (e, fm) = monoExp (env, st, fm) e adamc@307: in adam@1293: ((L'.EDml (e, L'.Error), loc), adam@1293: fm) adam@1293: end adam@1293: adam@1663: | L.EFfiApp ("Basis", "tryDml", [(e, _)]) => adam@1293: let adam@1293: val (e, fm) = monoExp (env, st, fm) e adam@1293: in adam@1293: ((L'.EDml (e, L'.None), 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: in adamc@307: ((L'.EAbs ("tab", s, (L'.TFun (rt, s), loc), adamc@307: (L'.EAbs ("fs", rt, s, adam@2048: strcat [str "INSERT INTO ", adamc@598: (L'.ERel 1, loc), adam@2048: str " (", adam@2048: strcatComma (map (fn (x, _) => str (Settings.mangleSql x)) fields), adam@2048: str ") VALUES (", adamc@598: strcatComma (map (fn (x, _) => adamc@598: (L'.EField ((L'.ERel 0, loc), adamc@598: x), loc)) fields), adam@2048: str ")"]), 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: 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 adam@2048: strcat [str "UPDATE ", adamc@886: (L'.ERel 1, loc), adam@2048: str " AS T_T SET ", adamc@886: strcatComma (map (fn (x, _) => adam@2048: strcat [str (Settings.mangleSql x adamc@886: ^ " = "), adamc@886: (L'.EField adamc@886: ((L'.ERel 2, adamc@886: loc), adamc@886: x), loc)]) adamc@886: changed), adam@2048: str " WHERE ", adamc@886: (L'.ERel 0, loc)] adamc@886: else adam@2048: strcat [str "UPDATE ", adamc@886: (L'.ERel 1, loc), adam@2048: str " SET ", adamc@886: strcatComma (map (fn (x, _) => adam@2048: strcat [str (Settings.mangleSql x adamc@886: ^ " = "), adam@1466: (L'.EFfiApp ("Basis", "unAs", adam@1663: [((L'.EField adam@1663: ((L'.ERel 2, adam@1663: loc), adam@1663: x), loc), adam@1663: s)]), loc)]) adamc@886: changed), adam@2048: str " WHERE ", adam@1663: (L'.EFfiApp ("Basis", "unAs", [((L'.ERel 0, loc), s)]), 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: 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 adam@2048: strcat [str "DELETE FROM ", adamc@874: (L'.ERel 1, loc), adam@2048: str " AS T_T WHERE ", adamc@874: (L'.ERel 0, loc)] adamc@874: else adam@2048: strcat [str "DELETE FROM ", adamc@874: (L'.ERel 1, loc), adam@2048: str " WHERE ", adam@1663: (L'.EFfiApp ("Basis", "unAs", [((L'.ERel 0, loc), s)]), 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: adam@1394: | L.ECApp ((L.ECApp ((L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sql_query"), _), _), _), _), _), _), _), _), _), _) => adamc@252: let 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", adam@2048: [((L'.PPrim (Prim.String (Prim.Normal, "")), loc), str ""), adam@2084: ((L'.PVar ("orderby", s), loc), adam@2048: strcat [str " ORDER BY ", adam@2084: (L'.ERel 0, loc)])], 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 ( adam@1394: (L.ECApp ( adam@1394: (L.EFfi ("Basis", "sql_query1"), _), adam@1394: _), _), 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: 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, adam@2048: strcat [str "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), adam@2048: str "DISTINCT "), 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), adam@2048: str "")], 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), adam@2048: str (" AS " ^ Settings.mangleSql x) adamc@598: ]) sexps adamc@598: @ map (fn (x, xts) => adamc@598: strcatComma adamc@598: (map (fn (x', _) => adam@2048: str ("T_" ^ x adam@1953: ^ "." adam@1953: ^ Settings.mangleSql x')) adamc@598: xts)) stables), adamc@1195: (L'.ECase (gf "From", adam@2048: [((L'.PPrim (Prim.String (Prim.Normal, "")), loc), adam@2048: str ""), adamc@1195: ((L'.PVar ("x", s), loc), adam@2048: strcat [str " FROM ", adamc@1195: (L'.ERel 0, loc)])], adamc@1195: {disc = s, adamc@1195: result = s}), loc), adamc@598: (L'.ECase (gf "Where", adam@2048: [((L'.PPrim (Prim.String (Prim.Normal, #trueString (Settings.currentDbms ()))), adamc@1266: loc), adam@2048: str ""), adam@2084: ((L'.PVar ("where", s), loc), adam@2084: strcat [str " WHERE ", (L'.ERel 0, loc)])], adamc@598: {disc = s, adamc@598: result = s}), loc), adam@1682: 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 adam@2048: str "" adamc@598: else adamc@598: strcat [ adam@2048: str " GROUP BY ", adamc@598: strcatComma (map (fn (x, xts) => adamc@598: strcatComma adamc@598: (map (fn (x', _) => adam@2048: str ("T_" ^ x adam@2004: ^ "." adam@1953: ^ Settings.mangleSql x')) adamc@598: xts)) grouped) adamc@598: ], adamc@259: adamc@598: (L'.ECase (gf "Having", adamc@1014: [((L'.PPrim (Prim.String adam@2048: (Prim.Normal, #trueString (Settings.currentDbms ()))), loc), adam@2048: str ""), adam@2084: ((L'.PVar ("having", s), loc), adam@2084: strcat [str " HAVING ", (L'.ERel 0, loc)])], 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 ( adam@1778: (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), adam@1663: (L'.EFfiApp ("Basis", "sqlifyInt", [((L'.ERel 0, loc), (L'.TFfi ("Basis", "int"), 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), adam@1663: (L'.EFfiApp ("Basis", "sqlifyFloat", [((L'.ERel 0, loc), (L'.TFfi ("Basis", "float"), 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), adam@1663: (L'.EFfiApp ("Basis", "sqlifyBool", [((L'.ERel 0, loc), (L'.TFfi ("Basis", "bool"), 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), adam@1663: (L'.EFfiApp ("Basis", "sqlifyString", [((L'.ERel 0, loc), (L'.TFfi ("Basis", "string"), 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), adam@1663: (L'.EFfiApp ("Basis", "sqlifyChar", [((L'.ERel 0, loc), (L'.TFfi ("Basis", "char"), 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), adam@1663: (L'.EFfiApp ("Basis", "sqlifyTime", [((L'.ERel 0, loc), (L'.TFfi ("Basis", "time"), 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), adam@1663: (L'.EFfiApp ("Basis", "sqlifyBlob", [((L'.ERel 0, loc), (L'.TFfi ("Basis", "blob"), 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), adam@1663: (L'.EFfiApp ("Basis", "sqlifyChannel", [((L'.ERel 0, loc), (L'.TFfi ("Basis", "channel"), 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), adam@1663: (L'.EFfiApp ("Basis", "sqlifyClient", [((L'.ERel 0, loc), (L'.TFfi ("Basis", "client"), 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), adam@1663: (L'.EFfiApp ("Basis", "sqlifyString", [((L'.ERel 0, loc), (L'.TFfi ("Basis", "string"), loc))]), loc)), loc), adamc@1104: fm) adam@2029: | L.EFfi ("Basis", "sql_url") => adam@2029: ((L'.EAbs ("x", (L'.TFfi ("Basis", "string"), loc), (L'.TFfi ("Basis", "string"), loc), adam@2029: (L'.EFfiApp ("Basis", "sqlifyString", [((L'.ERel 0, loc), (L'.TFfi ("Basis", "string"), loc))]), loc)), loc), adam@2029: 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), adam@2048: str "NULL"), 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 adam@1682: 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"), _), _) => adam@2048: (str "", 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), adam@2048: str (" AS T_" ^ name)]), 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: in adamc@1192: ((L'.EAbs ("q", s, s, adam@2048: strcat [str "(", adamc@1192: (L'.ERel 0, loc), adam@2048: str (") 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), adam@2048: [((L'.PRecord [("1", (L'.PPrim (Prim.String (Prim.Normal, "")), loc), s)], loc), adamc@1195: (L'.ERel 0, loc)), adam@2048: ((L'.PRecord [("2", (L'.PPrim (Prim.String (Prim.Normal, "")), loc), s)], loc), adamc@1195: (L'.ERel 1, loc)), adamc@1195: ((L'.PWild, loc), adamc@1195: strcat [(L'.ERel 1, loc), adam@2048: str ", ", 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), adam@2048: [((L'.PRecord [("1", (L'.PPrim (Prim.String (Prim.Normal, "")), loc), s)], loc), adamc@1195: (L'.ERel 1, loc)), adam@2048: ((L'.PRecord [("2", (L'.PPrim (Prim.String (Prim.Normal, "")), loc), s)], loc), adamc@1195: (L'.ERel 2, loc)), adamc@1195: ((L'.PWild, loc), adamc@1266: strcat ((if #nestedRelops adamc@1266: (Settings.currentDbms ()) then adam@2048: [str "("] adamc@1266: else adamc@1266: []) adamc@1266: @ [(L'.ERel 2, loc), adam@2048: str " JOIN ", adamc@1266: (L'.ERel 1, loc), adam@2048: str " ON ", adamc@1266: (L'.ERel 0, loc)] adamc@1266: @ (if #nestedRelops adamc@1266: (Settings.currentDbms ()) then adam@2048: [str ")"] adamc@1266: else adamc@1266: [])))], 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), adam@2048: [((L'.PRecord [("1", (L'.PPrim (Prim.String (Prim.Normal, "")), adamc@1195: loc), s)], loc), adamc@1195: (L'.ERel 1, loc)), adam@2048: ((L'.PRecord [("2", (L'.PPrim (Prim.String (Prim.Normal, "")), adamc@1195: loc), s)], loc), adamc@1195: (L'.ERel 2, loc)), adamc@1195: ((L'.PWild, loc), adamc@1266: strcat ((if #nestedRelops adamc@1266: (Settings.currentDbms ()) then adam@2048: [str "("] adamc@1266: else adamc@1266: []) adamc@1266: @ [(L'.ERel 2, loc), adam@2048: str " LEFT JOIN ", adamc@1266: (L'.ERel 1, loc), adam@2048: str " ON ", adamc@1266: (L'.ERel 0, loc)] adamc@1266: @ (if #nestedRelops adamc@1266: (Settings.currentDbms ()) then adam@2048: [str ")"] adamc@1266: else adamc@1266: [])))], 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), adam@2048: [((L'.PRecord [("1", (L'.PPrim (Prim.String (Prim.Normal, "")), adamc@1195: loc), s)], loc), adamc@1195: (L'.ERel 1, loc)), adam@2048: ((L'.PRecord [("2", (L'.PPrim (Prim.String (Prim.Normal, "")), adamc@1195: loc), s)], loc), adamc@1195: (L'.ERel 2, loc)), adamc@1195: ((L'.PWild, loc), adamc@1266: strcat ((if #nestedRelops adamc@1266: (Settings.currentDbms ()) then adam@2048: [str "("] adamc@1266: else adamc@1266: []) adamc@1266: @ [(L'.ERel 2, loc), adam@2048: str " RIGHT JOIN ", adamc@1266: (L'.ERel 1, loc), adam@2048: str " ON ", adamc@1266: (L'.ERel 0, loc)] adamc@1266: @ (if #nestedRelops adamc@1266: (Settings.currentDbms ()) then adam@2048: [str ")"] adamc@1266: else adamc@1266: [])))], 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), adam@2048: [((L'.PRecord [("1", (L'.PPrim (Prim.String (Prim.Normal, "")), adamc@1195: loc), s)], loc), adamc@1195: (L'.ERel 1, loc)), adam@2048: ((L'.PRecord [("2", (L'.PPrim (Prim.String (Prim.Normal, "")), adamc@1195: loc), s)], loc), adamc@1195: (L'.ERel 2, loc)), adamc@1195: ((L'.PWild, loc), adamc@1266: strcat ((if #nestedRelops adamc@1266: (Settings.currentDbms ()) then adam@2048: [str "("] adamc@1266: else adamc@1266: []) adamc@1266: @ [(L'.ERel 2, loc), adam@2048: str " FULL JOIN ", adamc@1266: (L'.ERel 1, loc), adam@2048: str " ON ", adamc@1266: (L'.ERel 0, loc)] adamc@1266: @ (if #nestedRelops adamc@1266: (Settings.currentDbms ()) then adam@2048: [str ")"] adamc@1266: else adamc@1266: [])))], 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"), _), _), _), _) => adam@2048: (str "", fm) adam@1682: | L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sql_order_by_random"), _), _), _), _) => adam@2048: (str (#randomFunction (Settings.currentDbms ()) ^ "()"), fm) adamc@261: | L.ECApp ( adamc@261: (L.ECApp ( adamc@261: (L.ECApp ( adam@1778: (L.ECApp ( adam@1778: (L.EFfi ("Basis", "sql_order_by_Cons"), _), adam@1778: _), _), adamc@261: _), _), adamc@261: _), _), adamc@261: _) => adamc@261: let adamc@261: val s = (L'.TFfi ("Basis", "string"), loc) adamc@261: in adam@1778: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFun (s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc)), loc), adam@1778: (L'.EAbs ("e1", s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc), adam@1778: (L'.EAbs ("d", s, (L'.TFun (s, s), loc), adam@1778: (L'.EAbs ("e2", s, s, adam@1778: (L'.ECase ((L'.ERel 0, loc), adam@2048: [((L'.PPrim (Prim.String (Prim.Normal, "")), loc), adam@1778: strcat [(L'.ERel 2, loc), adam@1778: (L'.ERel 1, loc)]), adam@1778: ((L'.PWild, loc), adam@1778: strcat [(L'.ERel 2, loc), adam@1778: (L'.ERel 1, loc), adam@2048: str ", ", adam@1778: (L'.ERel 0, loc)])], adam@1778: {disc = s, result = s}), loc)), loc)), loc)), loc)), loc), adamc@261: fm) adamc@261: end adamc@252: adamc@252: | L.EFfi ("Basis", "sql_no_limit") => adam@2048: (str "", fm) adam@1663: | L.EFfiApp ("Basis", "sql_limit", [(e, t)]) => adamc@262: let adamc@262: val (e, fm) = monoExp (env, st, fm) e adamc@262: in adamc@598: (strcat [ adam@2048: str " LIMIT ", adam@1663: (L'.EFfiApp ("Basis", "sqlifyInt", [(e, monoType env t)]), loc) adamc@262: ], adamc@262: fm) adamc@262: end adamc@262: adamc@252: | L.EFfi ("Basis", "sql_no_offset") => adam@2048: (str "", fm) adam@1663: | L.EFfiApp ("Basis", "sql_offset", [(e, t)]) => adamc@263: let adamc@263: val (e, fm) = monoExp (env, st, fm) e adamc@263: in adamc@598: (strcat [ adam@2048: str " OFFSET ", adam@1663: (L'.EFfiApp ("Basis", "sqlifyInt", [(e, monoType env t)]), loc) adamc@263: ], adamc@263: fm) adamc@263: end adamc@253: adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_eq"), _), _) => adam@2048: (str "=", fm) adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_ne"), _), _) => adam@2048: (str "<>", fm) adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_lt"), _), _) => adam@2048: (str "<", fm) adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_le"), _), _) => adam@2048: (str "<=", fm) adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_gt"), _), _) => adam@2048: (str ">", fm) adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_ge"), _), _) => adam@2048: (str ">=", fm) adamc@253: adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_plus"), _), _) => adamc@559: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc), adam@2048: str "+"), loc), fm) adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_minus"), _), _) => adamc@559: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc), adam@2048: str "-"), loc), fm) adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_times"), _), _) => adamc@559: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc), adam@2048: str "*"), loc), fm) adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_div"), _), _) => adamc@559: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc), adam@2048: str "/"), loc), fm) adamc@559: | L.EFfi ("Basis", "sql_mod") => adam@2048: (str "%", fm) adamc@559: kkallio@1607: | L.EFfi ("Basis", "sql_like") => adam@2048: (str "LIKE", fm) kkallio@1607: 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: 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), adam@2048: strcat [str "(", adamc@598: (L'.ERel 1, loc), adam@2048: str " ", adamc@598: (L'.ERel 0, loc), adam@2048: str ")"]), loc)), loc), adamc@264: fm) adamc@264: end adam@2048: | L.EFfi ("Basis", "sql_not") => (str "NOT", fm) adamc@559: | L.ECApp ((L.EFfi ("Basis", "sql_neg"), _), _) => adamc@559: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc), adam@2048: str "-"), 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 ( adam@1778: (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: 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, adam@2048: strcat [str "(", adamc@598: (L'.ERel 1, loc), adam@2048: str " ", adamc@598: (L'.ERel 2, loc), adam@2048: str " ", adamc@598: (L'.ERel 0, loc), adam@2048: str ")"]), loc)), loc)), loc), adamc@254: fm) adamc@254: end adam@2048: | L.EFfi ("Basis", "sql_and") => (str "AND", fm) adam@2048: | L.EFfi ("Basis", "sql_or") => (str "OR", 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 ( adam@1778: (L.EFfi ("Basis", "sql_field"), _), adamc@253: _), _), adamc@253: _), _), adamc@253: _), _), adamc@253: _), _), adamc@253: _), _), adamc@253: (L.CName tab, _)), _), adam@2048: (L.CName field, _)) => (str ("T_" ^ tab ^ "." ^ Settings.mangleSql (lowercaseFirst field)), fm) adamc@260: adamc@260: | L.ECApp ( adamc@260: (L.ECApp ( adamc@260: (L.ECApp ( adamc@260: (L.ECApp ( adamc@261: (L.ECApp ( adam@1778: (L.EFfi ("Basis", "sql_exp"), _), adamc@261: _), _), adamc@261: _), _), adamc@261: _), _), adamc@261: _), _), adam@2048: (L.CName nm, _)) => (str (Settings.mangleSql (lowercaseFirst nm)), fm) adamc@261: adamc@261: | L.ECApp ( adamc@261: (L.ECApp ( adamc@261: (L.ECApp ( adamc@261: (L.ECApp ( adamc@1191: (L.ECApp ( adam@1416: (L.ECApp ( adam@1416: (L.EFfi ("Basis", "sql_relop"), _), adam@1416: _), _), adamc@1191: _), _), adamc@260: _), _), adamc@260: _), _), adamc@260: _), _), adamc@260: _) => adamc@260: let adamc@260: val s = (L'.TFfi ("Basis", "string"), loc) adamc@260: in adamc@1196: (if #nestedRelops (Settings.currentDbms ()) then adam@1427: (L'.EAbs ("c", s, (L'.TFun ((L'.TFfi ("Basis", "bool"), loc), (L'.TFun (s, (L'.TFun (s, s), loc)), loc)), loc), adam@1427: (L'.EAbs ("all", (L'.TFfi ("Basis", "bool"), loc), (L'.TFun (s, (L'.TFun (s, s), loc)), loc), adam@1427: (L'.EAbs ("e1", s, (L'.TFun (s, s), loc), adam@1427: (L'.EAbs ("e2", s, s, adam@2048: strcat [str "((", adam@1427: (L'.ERel 1, loc), adam@2048: str ") ", adam@1427: (L'.ERel 3, loc), adam@1427: (L'.ECase ((L'.ERel 2, loc), adam@1427: [((L'.PCon (L'.Enum, L'.PConFfi {mod = "Basis", adam@1427: datatyp = "bool", adam@1427: con = "True", adam@1427: arg = NONE}, NONE), loc), adam@2048: str " ALL"), adam@1427: ((L'.PWild, loc), adam@2048: str "")], adam@1427: {disc = (L'.TFfi ("Basis", "bool"), loc), adam@1427: result = s}), loc), adam@2048: str " (", adam@1427: (L'.ERel 0, loc), adam@2048: str "))"]), loc)), loc)), loc)), loc) adamc@1196: else adam@1427: (L'.EAbs ("c", s, (L'.TFun ((L'.TFfi ("Basis", "bool"), loc), (L'.TFun (s, (L'.TFun (s, s), loc)), loc)), loc), adam@1427: (L'.EAbs ("all", (L'.TFfi ("Basis", "bool"), loc), (L'.TFun (s, (L'.TFun (s, s), loc)), loc), adam@1427: (L'.EAbs ("e1", s, (L'.TFun (s, s), loc), adam@1427: (L'.EAbs ("e2", s, s, adam@1427: strcat [(L'.ERel 1, loc), adam@2048: str " ", adam@1427: (L'.ERel 3, loc), adam@1427: (L'.ECase ((L'.ERel 2, loc), adam@1427: [((L'.PCon (L'.Enum, L'.PConFfi {mod = "Basis", adam@1427: datatyp = "bool", adam@1427: con = "True", adam@1427: arg = NONE}, NONE), loc), adam@2048: str " ALL"), adam@1427: ((L'.PWild, loc), adam@2048: str "")], adam@1427: {disc = (L'.TFfi ("Basis", "bool"), loc), adam@1427: result = s}), loc), adam@2048: str " ", adam@1427: (L'.ERel 0, loc)]), 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 ( adam@1394: (L.ECApp ( adam@1394: (L.EFfi ("Basis", "sql_forget_tables"), _), adam@1394: _), _), adamc@1191: _), _), adamc@1071: _), _), adamc@1071: _), _), adamc@1071: _) => adamc@1071: let adamc@1071: val s = (L'.TFfi ("Basis", "string"), loc) adamc@1071: in adamc@1071: ((L'.EAbs ("x", s, s, (L'.ERel 0, loc)), loc), adamc@1071: fm) adamc@1071: end adamc@260: adam@2048: | L.EFfi ("Basis", "sql_union") => (str "UNION", 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: (); adam@2048: (str "INTERSECT", 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: (); adam@2048: (str "EXCEPT", fm)) adamc@260: adamc@265: | L.ECApp ( adamc@265: (L.ECApp ( adamc@265: (L.ECApp ( adam@1778: (L.EFfi ("Basis", "sql_count"), _), adamc@265: _), _), adamc@265: _), _), adam@2048: _) => (str "COUNT(*)", fm) adamc@266: adamc@266: | L.ECApp ( adamc@266: (L.ECApp ( adamc@266: (L.ECApp ( adamc@266: (L.ECApp ( adamc@1187: (L.ECApp ( adam@1778: (L.EFfi ("Basis", "sql_aggregate"), _), adamc@1187: _), _), adamc@266: _), _), adamc@266: _), _), adamc@266: _), _), adamc@1168: t) => adamc@266: let adamc@266: val s = (L'.TFfi ("Basis", "string"), loc) adam@1357: adam@1357: val main = strcat [(L'.ERel 1, loc), adam@2048: str "(", adam@1357: (L'.ERel 0, loc), adam@2048: str ")"] adamc@266: in adamc@266: ((L'.EAbs ("c", s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc), adam@1778: (L'.EAbs ("e1", s, (L'.TFun (s, s), loc), main), loc)), loc), adamc@266: fm) adamc@266: end adamc@266: adamc@1187: | L.ECApp ((L.EFfi ("Basis", "sql_count_col"), _), _) => adam@2048: (str "COUNT", 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) adam@1357: | L.ECApp ((L.EFfi ("Basis", "sql_summable_option"), _), _) => adam@1357: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TRecord [], loc), adam@1357: (L'.ERecord [], loc)), loc), adam@1357: fm) adam@1777: | L.ECApp ((L.EFfi ("Basis", "sql_avg"), _), _) => adam@1777: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc), adam@2048: str "AVG"), loc), adamc@266: fm) adam@1394: | L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sql_sum"), _), _), _), _) => adam@1394: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFun ((L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc)), loc), adam@1394: (L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc), adam@2048: str "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) adam@1427: | L.ECApp ((L.EFfi ("Basis", "sql_arith_option"), _), _) => adam@1427: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TRecord [], loc), adam@1427: (L'.ERecord [], loc)), loc), adam@1427: 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) adam@1357: | L.ECApp ((L.EFfi ("Basis", "sql_maxable_option"), _), _) => adam@1357: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TRecord [], loc), adam@1357: (L'.ERecord [], loc)), loc), adam@1357: fm) adam@1394: | L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sql_max"), _), _), _), _) => adam@1394: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFun ((L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc)), loc), adam@1394: (L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc), adam@2048: str "MAX"), loc)), loc), adamc@266: fm) adam@1394: | L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sql_min"), _), _), _), _) => adam@1394: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFun ((L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc)), loc), adam@1394: (L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFfi ("Basis", "string"), loc), adam@2048: str "MIN"), loc)), loc), adamc@266: fm) adamc@266: adam@2048: | L.EFfi ("Basis", "sql_asc") => (str "", fm) adam@2048: | L.EFfi ("Basis", "sql_desc") => (str " DESC", fm) adam@1777: | L.ECApp ( adam@1777: (L.ECApp ( adam@1777: (L.ECApp ( adam@1777: (L.ECApp ( adam@1778: (L.EFfi ("Basis", "sql_nfunc"), _), adam@1778: _), _), adam@1778: _), _), adam@1778: _), _), adam@1778: _) => adam@1778: let adam@1778: val s = (L'.TFfi ("Basis", "string"), loc) adam@1778: in adam@1778: ((L'.EAbs ("s", s, s, (L'.ERel 0, loc)), loc), adam@1778: fm) adam@1778: end adam@1778: adam@1778: | L.EFfi ("Basis", "sql_window_normal") => ((L'.ERecord [], loc), fm) adam@1778: | L.EFfi ("Basis", "sql_window_fancy") => ((L'.ERecord [], loc), fm) adam@1778: | L.ECApp ( adam@1778: (L.ECApp ( adam@1778: (L.ECApp ( adam@1778: (L.ECApp ( adam@1778: (L.ECApp ( adam@1778: (L.EFfi ("Basis", "sql_window"), _), adam@1778: _), _), adam@1777: _), _), adam@1777: _), _), adam@1777: _), _), adam@1777: _) => adam@1777: let adam@1777: val s = (L'.TFfi ("Basis", "string"), loc) adam@1777: in adam@1778: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFun (s, s), loc), adam@1778: (L'.EAbs ("e", s, s, adam@1778: (L'.ERel 0, loc)), loc)), loc), adam@1777: fm) adam@1777: end adam@1777: adam@2048: | L.EFfi ("Basis", "sql_current_timestamp") => (str "CURRENT_TIMESTAMP", fm) adam@1776: adam@1776: | L.ECApp ( adam@1776: (L.ECApp ( adam@1776: (L.ECApp ( adam@1776: (L.ECApp ( adam@1776: (L.ECApp ( adam@1778: (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: 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), adam@2048: str "(", adamc@746: (L'.ERel 0, loc), adam@2048: str ")"]), loc)), loc), adamc@746: fm) adamc@746: end adamc@890: | L.EFfi ("Basis", "sql_octet_length") => adam@2048: (str (if #supportsOctetLength (Settings.currentDbms ()) then adam@2048: "octet_length" adam@2048: else adam@2048: "length"), fm) adam@1636: | L.EFfi ("Basis", "sql_lower") => adam@2048: (str "lower", fm) adam@1636: | L.EFfi ("Basis", "sql_upper") => adam@2048: (str "upper", 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 ( adam@1778: (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: in adamc@470: ((L'.EAbs ("s", s, s, adam@2048: strcat [str "(", adamc@598: (L'.ERel 0, loc), adam@2048: str " IS NULL)"]), loc), adamc@470: fm) adamc@470: end adamc@470: kkallio@1572: | (L.ECApp ( kkallio@1572: (L.ECApp ( kkallio@1572: (L.ECApp ( kkallio@1572: (L.ECApp ( adam@1602: (L.EFfi ("Basis", "sql_coalesce"), _), _), adam@1602: _), _), adam@1602: _), _), adam@1602: _), _)) => adam@1602: let adam@1602: val s = (L'.TFfi ("Basis", "string"), loc) adam@1602: in adam@1602: ((L'.EAbs ("x1", s, (L'.TFun (s, s), loc), adam@1602: (L'.EAbs ("x1", s, s, adam@2048: strcat [str "COALESCE(", adam@1602: (L'.ERel 1, loc), adam@2048: str ",", adam@1602: (L'.ERel 0, loc), adam@2048: str ")"]), loc)), loc), adam@1602: fm) adam@1602: end adam@1602: adam@1602: | (L.ECApp ( adam@1602: (L.ECApp ( adam@1602: (L.ECApp ( adam@1602: (L.ECApp ( adam@1778: (L.EFfi ("Basis", "sql_if_then_else"), _), _), kkallio@1572: _), _), kkallio@1572: _), _), kkallio@1572: _), _)) => kkallio@1572: let kkallio@1572: val s = (L'.TFfi ("Basis", "string"), loc) kkallio@1572: in adam@1573: ((L'.EAbs ("if", s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc), kkallio@1572: (L'.EAbs ("then", s, (L'.TFun (s, s), loc), adam@1573: (L'.EAbs ("else", s, s, adam@2048: strcat [str "(CASE WHEN (", kkallio@1572: (L'.ERel 2, loc), adam@2048: str ") THEN (", kkallio@1572: (L'.ERel 1, loc), adam@2048: str ") ELSE (", kkallio@1572: (L'.ERel 0, loc), adam@2048: str ") END)"]), loc)), loc)), loc), kkallio@1572: fm) kkallio@1572: end kkallio@1572: adamc@1081: | L.ECApp ( adamc@1081: (L.ECApp ( adamc@1081: (L.ECApp ( adamc@1081: (L.ECApp ( adam@1778: (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: 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 adam@1682: adamc@1191: | L.ECApp ( adamc@1191: (L.ECApp ( adamc@1191: (L.ECApp ( adamc@1191: (L.ECApp ( adamc@1191: (L.ECApp ( adam@1421: (L.ECApp ( adam@1778: (L.EFfi ("Basis", "sql_subquery"), _), adam@1421: _), _), adamc@1191: _), _), adamc@1191: _), _), adamc@1191: _), _), adamc@1191: _), _), adamc@1191: _) => adamc@1191: let adamc@1191: val s = (L'.TFfi ("Basis", "string"), loc) adamc@1191: in adam@1421: ((L'.EAbs ("_", (L'.TRecord [], loc), (L'.TFun (s, s), loc), adam@1421: (L'.EAbs ("x", s, s, adam@2048: strcat [str "(", adam@1421: (L'.ERel 0, loc), adam@2048: str ")"]), loc)), loc), adamc@1191: fm) adamc@1191: end adamc@1081: adam@1778: | L.ECApp ( adam@1778: (L.ECApp ( adam@1778: (L.ECApp ( adam@1778: (L.EFfi ("Basis", "sql_no_partition"), _), adam@1778: _), _), adam@1778: _), _), adam@2048: _) => (str "", fm) adam@1778: | L.ECApp ( adam@1778: (L.ECApp ( adam@1778: (L.ECApp ( adam@1778: (L.ECApp ( adam@1778: (L.EFfi ("Basis", "sql_partition"), _), adam@1778: _), _), adam@1778: _), _), adam@1778: _), _), adam@1778: _) => adam@1778: let adam@1778: val s = (L'.TFfi ("Basis", "string"), loc) adam@1778: in adam@2048: ((L'.EAbs ("e", s, s, strcat [str "PARTITION BY ", (L'.ERel 0, loc)]), loc), adam@1778: fm) adam@1778: end adam@1778: adam@1778: | L.ECApp ( adam@1778: (L.ECApp ( adam@1778: (L.ECApp ( adam@1778: (L.ECApp ( adam@1778: (L.EFfi ("Basis", "sql_window_function"), _), adam@1778: _), _), adam@1778: _), _), adam@1778: _), _), adam@1778: _) => adam@1778: let adam@1778: val () = if #windowFunctions (Settings.currentDbms ()) then adam@1778: () adam@1778: else adam@1778: ErrorMsg.errorAt loc "The DBMS you've selected doesn't support window functions." adam@1778: adam@1778: val s = (L'.TFfi ("Basis", "string"), loc) adam@1778: adam@1778: val main = strcat [(L'.ERel 2, loc), adam@2048: str " OVER (", adam@1778: (L'.ERel 1, loc), adam@1778: (L'.ECase ((L'.ERel 0, loc), adam@2048: [((L'.PPrim (Prim.String (Prim.Normal, "")), loc), adam@2048: str ""), adam@1778: ((L'.PWild, loc), adam@2048: strcat [str " ORDER BY ", adam@1778: (L'.ERel 0, loc)])], adam@1778: {disc = s, adam@1778: result = s}), loc), adam@2048: str ")"] adam@1778: in adam@1778: ((L'.EAbs ("w", s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc), adam@1778: (L'.EAbs ("p", s, (L'.TFun (s, s), loc), adam@1778: (L'.EAbs ("o", s, s, adam@1778: main), loc)), loc)), loc), adam@1778: fm) adam@1778: end adam@1778: adam@1778: | L.ECApp ( adam@1778: (L.ECApp ( adam@1778: (L.ECApp ( adam@1778: (L.ECApp ( adam@1778: (L.ECApp ( adam@1778: (L.EFfi ("Basis", "sql_window_aggregate"), _), adam@1778: _), _), adam@1778: _), _), adam@1778: _), _), adam@1778: _), _), adam@1778: _) => adam@1778: let adam@1778: val s = (L'.TFfi ("Basis", "string"), loc) adam@1778: adam@1778: val main = strcat [(L'.ERel 1, loc), adam@2048: str "(", adam@1778: (L'.ERel 0, loc), adam@2048: str ")"] adam@1778: in adam@1778: ((L'.EAbs ("c", s, (L'.TFun (s, (L'.TFun (s, s), loc)), loc), adam@1778: (L'.EAbs ("e1", s, s, main), loc)), loc), adam@1778: fm) adam@1778: end adam@1778: adam@1778: | L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sql_window_count"), _), _), _), _), _), _) => adam@2048: (str "COUNT(*)", fm) adam@1778: | L.ECApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "sql_rank"), _), _), _), _), _), _) => adam@2048: (str "RANK()", fm) adam@1778: adam@1663: | 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 adam@1663: | 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: adam@2048: | L.EFfi ("Basis", "null") => (str "", fm) adam@1567: adam@1663: | L.EFfiApp ("Basis", "classes", [(s1, _), (s2, _)]) => adam@1292: let adam@1292: val (s1, fm) = monoExp (env, st, fm) s1 adam@1292: val (s2, fm) = monoExp (env, st, fm) s2 adam@1292: in adam@2048: ((L'.EStrcat (s1, (L'.EStrcat (str " ", s2), loc)), loc), adam@1292: fm) adam@1292: end adam@1292: adam@2048: | L.EFfi ("Basis", "data_kind") => (str "data-", fm) adam@2048: | L.EFfi ("Basis", "aria_kind") => (str "aria-", fm) adam@2047: adam@2047: | L.EFfiApp ("Basis", "data_attr", [(sk, _), (s1, _), (s2, _)]) => adam@2008: let adam@2047: val (sk, fm) = monoExp (env, st, fm) sk adam@2008: val (s1, fm) = monoExp (env, st, fm) s1 adam@2008: val (s2, fm) = monoExp (env, st, fm) s2 adam@2008: in adam@2047: ((L'.EStrcat (sk, adam@2008: (L'.EStrcat ((L'.EFfiApp ("Basis", "blessData", [(s1, (L'.TFfi ("Basis", "string"), loc))]), loc), adam@2048: (L'.EStrcat (str "=\"", adam@2008: (L'.EStrcat ((L'.EFfiApp ("Basis", "attrifyString", [(s2, (L'.TFfi ("Basis", "string"), loc))]), loc), adam@2048: str "\""), loc)), adam@2008: loc)), loc)), loc), adam@2008: fm) adam@2008: end adam@2008: adam@2008: | L.EFfiApp ("Basis", "data_attrs", [(s1, _), (s2, _)]) => adam@2008: let adam@2008: val (s1, fm) = monoExp (env, st, fm) s1 adam@2008: val (s2, fm) = monoExp (env, st, fm) s2 adam@2008: in adam@2048: ((L'.EStrcat (s1, (L'.EStrcat (str " ", s2), loc)), loc), adam@2008: fm) adam@2008: end adam@2008: adam@1750: | L.EFfiApp ("Basis", "css_url", [(s, _)]) => adam@1750: let adam@1750: val (s, fm) = monoExp (env, st, fm) s adam@1750: in adam@2048: ((L'.EStrcat (str "url(", adam@1750: (L'.EStrcat ((L'.EFfiApp ("Basis", "css_url", [(s, (L'.TFfi ("Basis", "string"), loc))]), loc), adam@2048: str ")"), loc)), loc), adam@1750: fm) adam@1750: end adam@1750: adam@1750: | L.EFfiApp ("Basis", "property", [(s, _)]) => adam@1750: let adam@1750: val (s, fm) = monoExp (env, st, fm) s adam@1750: in adam@1750: ((L'.EStrcat ((L'.EFfiApp ("Basis", "property", [(s, (L'.TFfi ("Basis", "string"), loc))]), loc), adam@2048: str ":"), loc), adam@1750: fm) adam@1750: end adam@1750: | L.EFfiApp ("Basis", "value", [(s1, _), (s2, _)]) => adam@1750: let adam@1750: val (s1, fm) = monoExp (env, st, fm) s1 adam@1750: val (s2, fm) = monoExp (env, st, fm) s2 adam@1750: in adam@2048: ((L'.EStrcat (s1, (L'.EStrcat (str " ", s2), loc)), loc), adam@1750: fm) adam@1750: end adam@1750: adam@2048: | L.EFfi ("Basis", "noStyle") => (str "", fm) adam@1750: | L.EFfiApp ("Basis", "oneProperty", [(s1, _), (s2, _)]) => adam@1750: let adam@1750: val (s1, fm) = monoExp (env, st, fm) s1 adam@1750: val (s2, fm) = monoExp (env, st, fm) s2 adam@1750: in adam@2048: ((L'.EStrcat (s1, (L'.EStrcat (s2, str ";"), loc)), loc), adam@1750: fm) adam@1750: end adam@1750: 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 adam@1663: ((L'.EFfiApp ("Basis", "htmlifyString", [(se, (L'.TFfi ("Basis", "string"), loc))]), loc), fm) adamc@179: end adam@1358: | L.ECApp ( adam@1358: (L.ECApp ((L.EFfi ("Basis", "cdataChar"), _), _), _), adam@1358: _) => adam@1358: ((L'.EAbs ("ch", (L'.TFfi ("Basis", "char"), loc), (L'.TFfi ("Basis", "string"), loc), adam@1663: (L'.EFfiApp ("Basis", "htmlifySpecialChar", [((L'.ERel 0, loc), (L'.TFfi ("Basis", "char"), loc))]), loc)), loc), fm) 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 ( adam@1643: (L.EApp ( adam@1750: (L.EApp ( adam@1751: (L.EApp ( adam@1751: (L.ECApp ( adamc@139: (L.ECApp ( adamc@139: (L.ECApp ( adamc@139: (L.ECApp ( adamc@721: (L.ECApp ( adam@1643: (L.ECApp ( adam@1750: (L.ECApp ( adam@1751: (L.ECApp ( adam@1751: (L.EFfi ("Basis", "tag"), adam@2012: _), (L.CRecord (_, attrsGiven), _)), _), _), _), ctxOuter), _), _), _), _), _), _), _), _), _), _), _), adam@1751: class), _), adam@1751: dynClass), _), adam@1751: style), _), adam@1751: dynStyle), _), adamc@720: attrs), _), adamc@720: tag), _), adamc@95: xml) => adamc@95: let adamc@140: fun getTag' (e, _) = adamc@140: case e of adam@1833: L.EFfi (_, 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 adam@1833: L.EFfiApp (_, 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@1272: | _ => map (fn ((L.CName x, _), t) => (x, (L'.EField (attrs, x), loc), monoType env t) adamc@1272: | (c, t) => (E.errorAt loc "Non-constant field name for HTML tag attribute"; adamc@1272: Print.eprefaces' [("Name", CorePrint.p_con env c)]; adamc@1272: ("", (L'.EField (attrs, ""), loc), monoType env t))) attrsGiven 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) adam@1682: vshabanoff@1711: val (onload, onunload, attrs) = vshabanoff@1711: if tag = "body" then vshabanoff@1711: findOnload (attrs, NONE, NONE, []) vshabanoff@1711: else vshabanoff@1711: (NONE, NONE, attrs) adamc@668: adam@2026: (* Special case for