diff options
-rw-r--r-- | lib/js/urweb.js | 18 | ||||
-rw-r--r-- | lib/ur/monad.ur | 35 | ||||
-rw-r--r-- | lib/ur/monad.urs | 24 | ||||
-rw-r--r-- | lib/ur/top.ur | 12 | ||||
-rw-r--r-- | lib/ur/top.urs | 6 | ||||
-rw-r--r-- | src/cjr_print.sml | 89 | ||||
-rw-r--r-- | src/cjrize.sml | 1 | ||||
-rw-r--r-- | src/compiler.sml | 9 | ||||
-rw-r--r-- | src/elab_ops.sml | 22 | ||||
-rw-r--r-- | src/jscomp.sml | 18 | ||||
-rw-r--r-- | src/mono.sml | 2 | ||||
-rw-r--r-- | src/mono_opt.sig | 2 | ||||
-rw-r--r-- | src/mono_opt.sml | 8 | ||||
-rw-r--r-- | src/mono_print.sml | 10 | ||||
-rw-r--r-- | src/mono_reduce.sml | 2 | ||||
-rw-r--r-- | src/mono_util.sml | 8 | ||||
-rw-r--r-- | src/monoize.sml | 19 |
17 files changed, 243 insertions, 42 deletions
diff --git a/lib/js/urweb.js b/lib/js/urweb.js index 57ad5454..ef2c7b49 100644 --- a/lib/js/urweb.js +++ b/lib/js/urweb.js @@ -306,7 +306,7 @@ function dyn(pnode, s) { var arr = dummy.getElementsByTagName("tbody"); firstChild = null; - if (arr.length > 0) { + if (arr.length > 0 && table != null) { var tbody = arr[0], next; firstChild = document.createElement("script"); table.insertBefore(firstChild, x); @@ -323,7 +323,7 @@ function dyn(pnode, s) { var arr = dummy.getElementsByTagName("tr"); firstChild = null; - if (arr.length > 0) { + if (arr.length > 0 && table != null) { var tbody = arr[0], next; firstChild = document.createElement("script"); table.insertBefore(firstChild, x); @@ -468,7 +468,19 @@ function uf(s) { } function uu(s) { - return unescape(s); + return unescape(s.replace(new RegExp ("\\+", "g"), " ")); +} + +function uul(getToken, getData) { + var tok = getToken(); + if (tok == "Nil") { + return null; + } else if (tok == "Cons") { + var d = getData(); + var l = uul(getToken, getData); + return {_1:d, _2:l}; + } else + throw ("Can't unmarshal list (" + tok + ")"); } diff --git a/lib/ur/monad.ur b/lib/ur/monad.ur index 73001094..356173fd 100644 --- a/lib/ur/monad.ur +++ b/lib/ur/monad.ur @@ -7,3 +7,38 @@ fun exec [m ::: Type -> Type] (_ : monad m) [ts ::: {Type}] r (fd : folder ts) = (return {}) [ts] fd r fun ignore [m ::: Type -> Type] (_ : monad m) [t] (v : m t) = x <- v; return () + +fun foldR [K] [m] (_ : monad m) [tf :: K -> Type] [tr :: {K} -> Type] + (f : nm :: Name -> t :: K -> rest :: {K} + -> [[nm] ~ rest] => + tf t -> tr rest -> m (tr ([nm = t] ++ rest))) + (i : tr []) [r :: {K}] (fl : folder r) = + Top.fold [fn r :: {K} => $(map tf r) -> m (tr r)] + (fn [nm :: Name] [t :: K] [rest :: {K}] [[nm] ~ rest] + (acc : _ -> m (tr rest)) r => + acc' <- acc (r -- nm); + f [nm] [t] [rest] ! r.nm acc') + (fn _ => return i) + [_] fl + +fun foldR2 [K] [m] (_ : monad m) [tf1 :: K -> Type] [tf2 :: K -> Type] [tr :: {K} -> Type] + (f : nm :: Name -> t :: K -> rest :: {K} + -> [[nm] ~ rest] => + tf1 t -> tf2 t -> tr rest -> m (tr ([nm = t] ++ rest))) + (i : tr []) [r :: {K}] (fl : folder r) = + Top.fold [fn r :: {K} => $(map tf1 r) -> $(map tf2 r) -> m (tr r)] + (fn [nm :: Name] [t :: K] [rest :: {K}] [[nm] ~ rest] + (acc : _ -> _ -> m (tr rest)) r1 r2 => + acc' <- acc (r1 -- nm) (r2 -- nm); + f [nm] [t] [rest] ! r1.nm r2.nm acc') + (fn _ _ => return i) + [_] fl + +fun mapR [K] [m] (_ : monad m) [tf :: K -> Type] [tr :: K -> Type] + (f : nm :: Name -> t :: K -> tf t -> m (tr t)) = + @@foldR [m] _ [tf] [fn r => $(map tr r)] + (fn [nm :: Name] [t :: K] [rest :: {K}] [[nm] ~ rest] (v : tf t) + (acc : $(map tr rest)) => + v' <- f [nm] [t] v; + return (acc ++ {nm = v'})) + {} diff --git a/lib/ur/monad.urs b/lib/ur/monad.urs index b3cb3d6f..662d780f 100644 --- a/lib/ur/monad.urs +++ b/lib/ur/monad.urs @@ -3,3 +3,27 @@ val exec : m ::: (Type -> Type) -> monad m -> ts ::: {Type} val ignore : m ::: (Type -> Type) -> monad m -> t ::: Type -> m t -> m unit + +val foldR : K --> m ::: (Type -> Type) -> monad m + -> tf :: (K -> Type) + -> tr :: ({K} -> Type) + -> (nm :: Name -> t :: K -> rest :: {K} + -> [[nm] ~ rest] => + tf t -> tr rest -> m (tr ([nm = t] ++ rest))) + -> tr [] + -> r :: {K} -> folder r -> $(map tf r) -> m (tr r) + +val foldR2 : K --> m ::: (Type -> Type) -> monad m + -> tf1 :: (K -> Type) -> tf2 :: (K -> Type) + -> tr :: ({K} -> Type) + -> (nm :: Name -> t :: K -> rest :: {K} + -> [[nm] ~ rest] => + tf1 t -> tf2 t -> tr rest -> m (tr ([nm = t] ++ rest))) + -> tr [] + -> r :: {K} -> folder r -> $(map tf1 r) -> $(map tf2 r) -> m (tr r) + +val mapR : K --> m ::: (Type -> Type) -> monad m + -> tf :: (K -> Type) + -> tr :: (K -> Type) + -> (nm :: Name -> t :: K -> tf t -> m (tr t)) + -> r :: {K} -> folder r -> $(map tf r) -> m ($(map tr r)) diff --git a/lib/ur/top.ur b/lib/ur/top.ur index 3dac7ff0..ce110b27 100644 --- a/lib/ur/top.ur +++ b/lib/ur/top.ur @@ -98,12 +98,12 @@ fun mp [K] [tf1 :: K -> Type] [tf2 :: K -> Type] (f : t ::: K -> tf1 t -> tf2 t) acc (r -- nm) ++ {nm = f r.nm}) (fn _ => {}) -fun map2 [K1] [K2] [tf1 :: K1 -> Type] [tf2 :: K2 -> Type] [tf :: K1 -> K2] - (f : t ::: K1 -> tf1 t -> tf2 (tf t)) [r :: {K1}] (fl : folder r) = - fl [fn r :: {K1} => $(map tf1 r) -> $(map tf2 (map tf r))] - (fn [nm :: Name] [t :: K1] [rest :: {K1}] [[nm] ~ rest] acc r => - acc (r -- nm) ++ {nm = f r.nm}) - (fn _ => {}) +fun map2 [K] [tf1 :: K -> Type] [tf2 :: K -> Type] [tf3 :: K -> Type] + (f : t ::: K -> tf1 t -> tf2 t -> tf3 t) [r :: {K}] (fl : folder r) = + fl [fn r :: {K} => $(map tf1 r) -> $(map tf2 r) -> $(map tf3 r)] + (fn [nm :: Name] [t :: K] [rest :: {K}] [[nm] ~ rest] acc r1 r2 => + acc (r1 -- nm) (r2 -- nm) ++ {nm = f r1.nm r2.nm}) + (fn _ _ => {}) fun foldUR [tf :: Type] [tr :: {Unit} -> Type] (f : nm :: Name -> rest :: {Unit} diff --git a/lib/ur/top.urs b/lib/ur/top.urs index 33c90651..bdf9d904 100644 --- a/lib/ur/top.urs +++ b/lib/ur/top.urs @@ -48,9 +48,9 @@ val txt : t ::: Type -> ctx ::: {Unit} -> use ::: {Type} -> show t -> t val mp : K --> tf1 :: (K -> Type) -> tf2 :: (K -> Type) -> (t ::: K -> tf1 t -> tf2 t) -> r :: {K} -> folder r -> $(map tf1 r) -> $(map tf2 r) -val map2 : K1 --> K2 --> tf1 :: (K1 -> Type) -> tf2 :: (K2 -> Type) -> tf :: (K1 -> K2) - -> (t ::: K1 -> tf1 t -> tf2 (tf t)) - -> r :: {K1} -> folder r -> $(map tf1 r) -> $(map tf2 (map tf r)) +val map2 : K --> tf1 :: (K -> Type) -> tf2 :: (K -> Type) -> tf3 :: (K -> Type) + -> (t ::: K -> tf1 t -> tf2 t -> tf3 t) + -> r :: {K} -> folder r -> $(map tf1 r) -> $(map tf2 r) -> $(map tf3 r) val foldUR : tf :: Type -> tr :: ({Unit} -> Type) -> (nm :: Name -> rest :: {Unit} diff --git a/src/cjr_print.sml b/src/cjr_print.sml index 83b49719..0fd6339d 100644 --- a/src/cjr_print.sml +++ b/src/cjr_print.sml @@ -962,9 +962,11 @@ fun unurlify env (t, loc) = unurlify' IS.empty t end +val urlify1 = ref 0 + fun urlify env t = let - fun urlify' rf level (t as (_, loc)) = + fun urlify' rf rfl level (t as (_, loc)) = case #1 t of TFfi ("Basis", "unit") => box [] | TFfi (m, t) => box [string ("uw_" ^ ident m ^ "_urlify" ^ capitalize t @@ -1007,7 +1009,7 @@ fun urlify env t = newline] else []), - urlify' rf (level + 1) t, + urlify' rf rfl (level + 1) t, string "}", newline] :: blocks, true) @@ -1079,8 +1081,9 @@ fun urlify env t = string "it0) {", newline, box [string "if (it0) {", + newline, if isUnboxable t then - urlify' rf 0 t + urlify' rf rfl 0 t else box [p_typ env t, space, @@ -1094,11 +1097,12 @@ fun urlify env t = string has_arg, string "/\");", newline, - urlify' rf 1 t, + urlify' rf rfl 1 t, string ";", newline], string "} else {", - box [string "uw_write(ctx, \"", + box [newline, + string "uw_write(ctx, \"", string no_arg, string "\");", newline], @@ -1165,7 +1169,7 @@ fun urlify env t = string x', string ";", newline, - urlify' rf 1 t, + urlify' rf rfl 1 t, newline], string "} else {", newline, @@ -1208,7 +1212,7 @@ fun urlify env t = if isUnboxable t then box [string "uw_write(ctx, \"Some/\");", newline, - urlify' rf level t] + urlify' rf rfl level t] else box [p_typ env t, space, @@ -1223,19 +1227,84 @@ fun urlify env t = newline, string "uw_write(ctx, \"Some/\");", newline, - urlify' rf (level + 1) t, + urlify' rf rfl (level + 1) t, string ";", newline], string "} else {", - box [string "uw_write(ctx, \"None\");", + box [newline, + string "uw_write(ctx, \"None\");", newline], string "}", newline] + | TList (t, i) => + if IS.member (rfl, i) then + box [string "urlifyl_", + string (Int.toString i), + string "(it", + string (Int.toString level), + string ");", + newline] + else + let + val rfl = IS.add (rfl, i) + in + box [string "({", + space, + string "void", + space, + string "urlifyl_", + string (Int.toString i), + string "(struct __uws_", + string (Int.toString i), + space, + string "*it0) {", + newline, + box [string "if (it0) {", + newline, + p_typ env t, + space, + string "it1", + space, + string "=", + space, + string "it0->__uwf_1;", + newline, + string "uw_write(ctx, \"Cons/\");", + newline, + urlify' rf rfl 1 t, + string ";", + newline, + string "uw_write(ctx, \"/\");", + newline, + string "urlifyl_", + string (Int.toString i), + string "(it0->__uwf_2);", + newline, + string "} else {", + newline, + box [string "uw_write(ctx, \"Nil\");", + newline], + string "}", + newline], + string "}", + newline, + newline, + + string "urlifyl_", + string (Int.toString i), + string "(it", + string (Int.toString level), + string ");", + newline, + string "});", + newline] + end + | _ => (ErrorMsg.errorAt loc "Unable to choose a URL encoding function"; space) in - urlify' IS.empty 0 t + urlify' IS.empty IS.empty 0 t end fun sql_type_in env (tAll as (t, loc)) = diff --git a/src/cjrize.sml b/src/cjrize.sml index 5f3ea5a8..6a79b4e6 100644 --- a/src/cjrize.sml +++ b/src/cjrize.sml @@ -112,6 +112,7 @@ fun cifyTyp x = end | L.TRecord xts => let + val xts = ListMergeSort.sort (fn ((x, _), (y, _)) => String.compare (x, y) = GREATER) xts val old_xts = xts val (xts, sm) = ListUtil.foldlMap (fn ((x, t), sm) => let diff --git a/src/compiler.sml b/src/compiler.sml index c99c0eeb..13bb77f9 100644 --- a/src/compiler.sml +++ b/src/compiler.sml @@ -805,7 +805,7 @@ val monoize = { val toMonoize = transform monoize "monoize" o toEffectize val mono_opt = { - func = MonoOpt.optimize, + func = (fn x => (MonoOpt.removeServerCalls := false; MonoOpt.optimize x)), print = MonoPrint.p_file MonoEnv.empty } @@ -841,7 +841,12 @@ val jscomp = { val toJscomp = transform jscomp "jscomp" o toMono_opt2 -val toMono_opt3 = transform mono_opt "mono_opt3" o toJscomp +val mono_opt' = { + func = (fn x => (MonoOpt.removeServerCalls := true; MonoOpt.optimize x)), + print = MonoPrint.p_file MonoEnv.empty +} + +val toMono_opt3 = transform mono_opt' "mono_opt3" o toJscomp val fuse = { func = Fuse.fuse, diff --git a/src/elab_ops.sml b/src/elab_ops.sml index a26ba17d..b5292e9b 100644 --- a/src/elab_ops.sml +++ b/src/elab_ops.sml @@ -131,6 +131,18 @@ fun subStrInSgn (m1, m2) = sgn_item = fn sgi => sgi, sgn = fn sgn => sgn} +val occurs = + U.Con.existsB {kind = fn _ => false, + con = fn (n, c) => + case c of + CRel n' => n' = n + | _ => false, + bind = fn (n, b) => + case b of + U.Con.RelC _ => n + 1 + | _ => n} + 0 + fun hnormCon env (cAll as (c, loc)) = case c of @@ -156,6 +168,16 @@ fun hnormCon env (cAll as (c, loc)) = | SOME (_, SOME c) => hnormCon env c end + (* Eta reduction *) + | CAbs (x, k, b) => + (case #1 (hnormCon (E.pushCRel env x k) b) of + CApp (f, (CRel 0, _)) => + if occurs f then + cAll + else + hnormCon env (subConInCon (0, (CUnit, loc)) f) + | _ => cAll) + | CApp (c1, c2) => (case #1 (hnormCon env c1) of CAbs (x, k, cb) => diff --git a/src/jscomp.sml b/src/jscomp.sml index 63f3d883..d42c659e 100644 --- a/src/jscomp.sml +++ b/src/jscomp.sml @@ -86,7 +86,7 @@ fun varDepth (e, _) = | ESignalReturn e => varDepth e | ESignalBind (e1, e2) => Int.max (varDepth e1, varDepth e2) | ESignalSource e => varDepth e - | EServerCall (e, ek, _, _) => Int.max (varDepth e, varDepth ek) + | EServerCall (e, ek, _, _, _) => Int.max (varDepth e, varDepth ek) | ERecv (e, ek, _) => Int.max (varDepth e, varDepth ek) | ESleep (e, ek) => Int.max (varDepth e, varDepth ek) @@ -130,7 +130,7 @@ fun closedUpto d = | ESignalReturn e => cu inner e | ESignalBind (e1, e2) => cu inner e1 andalso cu inner e2 | ESignalSource e => cu inner e - | EServerCall (e, ek, _, _) => cu inner e andalso cu inner ek + | EServerCall (e, ek, _, _, _) => cu inner e andalso cu inner ek | ERecv (e, ek, _) => cu inner e andalso cu inner ek | ESleep (e, ek) => cu inner e andalso cu inner ek in @@ -434,6 +434,13 @@ fun process file = ("(t[i++]==\"Some\"?" ^ e ^ ":null)", st) end + | TList t => + let + val (e, st) = unurlifyExp loc (t, st) + in + ("uul(function(){return t[i++];},function(){return " ^ e ^ "})", st) + end + | TDatatype (n, ref (dk, cs)) => (case IM.find (#decoders st, n) of SOME n' => ("(tmp=_n" ^ Int.toString n' ^ "(t,i),i=tmp._1,tmp._2)", st) @@ -1034,7 +1041,7 @@ fun process file = st) end - | EServerCall (e, ek, t, eff) => + | EServerCall (e, ek, t, eff, _) => let val (e, st) = jsE inner (e, st) val (ek, st) = jsE inner (ek, st) @@ -1313,12 +1320,13 @@ fun process file = ((ESignalSource e, loc), st) end - | EServerCall (e1, e2, t, ef) => + | EServerCall (e1, e2, t, ef, ue) => let val (e1, st) = exp outer (e1, st) val (e2, st) = exp outer (e2, st) + val (ue, st) = exp outer (ue, st) in - ((EServerCall (e1, e2, t, ef), loc), st) + ((EServerCall (e1, e2, t, ef, ue), loc), st) end | ERecv (e1, e2, t) => let diff --git a/src/mono.sml b/src/mono.sml index 64ed448c..2d29af48 100644 --- a/src/mono.sml +++ b/src/mono.sml @@ -114,7 +114,7 @@ datatype exp' = | ESignalBind of exp * exp | ESignalSource of exp - | EServerCall of exp * exp * typ * effect + | EServerCall of exp * exp * typ * effect * exp | ERecv of exp * exp * typ | ESleep of exp * exp diff --git a/src/mono_opt.sig b/src/mono_opt.sig index d0268087..7368f684 100644 --- a/src/mono_opt.sig +++ b/src/mono_opt.sig @@ -30,4 +30,6 @@ signature MONO_OPT = sig val optimize : Mono.file -> Mono.file val optExp : Mono.exp -> Mono.exp + val removeServerCalls : bool ref + end diff --git a/src/mono_opt.sml b/src/mono_opt.sml index bf39b311..7bfce88b 100644 --- a/src/mono_opt.sml +++ b/src/mono_opt.sml @@ -30,6 +30,8 @@ structure MonoOpt :> MONO_OPT = struct open Mono structure U = MonoUtil +val removeServerCalls = ref false + fun typ t = t fun decl d = d @@ -480,6 +482,12 @@ fun exp e = | [] => raise Fail "MonoOpt impossible nil") | NONE => e end + + | EServerCall (_, _, _, _, ue) => + if !removeServerCalls then + optExp ue + else + e | _ => e diff --git a/src/mono_print.sml b/src/mono_print.sml index 71bc734a..ed63b2a0 100644 --- a/src/mono_print.sml +++ b/src/mono_print.sml @@ -335,11 +335,11 @@ fun p_exp' par env (e, _) = p_exp env e, string ")"] - | EServerCall (n, e, _, _) => box [string "Server(", - p_exp env n, - string ")[", - p_exp env e, - string "]"] + | EServerCall (n, e, _, _, _) => box [string "Server(", + p_exp env n, + string ")[", + p_exp env e, + string "]"] | ERecv (n, e, _) => box [string "Recv(", p_exp env n, string ")[", diff --git a/src/mono_reduce.sml b/src/mono_reduce.sml index 4bbb430d..62368f9b 100644 --- a/src/mono_reduce.sml +++ b/src/mono_reduce.sml @@ -354,7 +354,7 @@ fun reduce file = | ESignalBind (e1, e2) => summarize d e1 @ summarize d e2 | ESignalSource e => summarize d e - | EServerCall (e, ek, _, _) => summarize d e @ summarize d ek @ [Unsure] + | EServerCall (e, ek, _, _, _) => summarize d e @ summarize d ek @ [Unsure] | ERecv (e, ek, _) => summarize d e @ summarize d ek @ [Unsure] | ESleep (e, ek) => summarize d e @ summarize d ek @ [Unsure] in diff --git a/src/mono_util.sml b/src/mono_util.sml index e2bed8eb..0a4bb048 100644 --- a/src/mono_util.sml +++ b/src/mono_util.sml @@ -362,14 +362,16 @@ fun mapfoldB {typ = fc, exp = fe, bind} = fn e' => (ESignalSource e', loc)) - | EServerCall (s, ek, t, eff) => + | EServerCall (s, ek, t, eff, ue) => S.bind2 (mfe ctx s, fn s' => S.bind2 (mfe ctx ek, fn ek' => - S.map2 (mft t, + S.bind2 (mft t, fn t' => - (EServerCall (s', ek', t', eff), loc)))) + S.map2 (mfe ctx ue, + fn ue' => + (EServerCall (s', ek', t', eff, ue'), loc))))) | ERecv (s, ek, t) => S.bind2 (mfe ctx s, fn s' => diff --git a/src/monoize.sml b/src/monoize.sml index d774c697..c0351756 100644 --- a/src/monoize.sml +++ b/src/monoize.sml @@ -93,7 +93,12 @@ fun monoType env = L.TFun (c1, c2) => (L'.TFun (mt env dtmap c1, mt env dtmap c2), loc) | L.TCFun _ => poly () | L.TRecord (L.CRecord ((L.KType, _), xcs), _) => - (L'.TRecord (map (fn (x, t) => (monoName env x, mt env dtmap t)) xcs), loc) + let + val xcs = map (fn (x, t) => (monoName env x, mt env dtmap t)) xcs + val xcs = ListMergeSort.sort (fn ((x, _), (y, _)) => String.compare (x, y) = GREATER) xcs + in + (L'.TRecord xcs, loc) + end | L.TRecord _ => poly () | L.CApp ((L.CFfi ("Basis", "option"), _), t) => @@ -3076,6 +3081,8 @@ fun monoExp (env, st, fm) (all as (e, loc)) = e, monoType env t), fm) end) fm xes + + val xes = ListMergeSort.sort (fn ((x, _, _), (y, _, _)) => String.compare (x, y) = GREATER) xes in ((L'.ERecord xes, loc), fm) end @@ -3154,6 +3161,12 @@ fun monoExp (env, st, fm) (all as (e, loc)) = val (ek, fm) = monoExp (env, st, fm) ek + val unRpced = foldl (fn (e1, e2) => (L'.EApp (e2, e1), loc)) (L'.ENamed n, loc) es + val unRpced = (L'.EApp (unRpced, (L'.ERecord [], loc)), loc) + val unRpced = (L'.EApp (ek, unRpced), loc) + val unRpced = (L'.EApp (unRpced, (L'.ERecord [], loc)), loc) + val unit = (L'.TRecord [], loc) + val ekf = (L'.EAbs ("f", (L'.TFun (t, (L'.TFun ((L'.TRecord [], loc), @@ -3171,9 +3184,9 @@ fun monoExp (env, st, fm) (all as (e, loc)) = L'.ReadCookieWrite else L'.ReadOnly - val e = (L'.EServerCall (call, ek, t, eff), loc) + + val e = (L'.EServerCall (call, ek, t, eff, unRpced), loc) val e = liftExpInExp 0 e - val unit = (L'.TRecord [], loc) val e = (L'.EAbs ("_", unit, unit, e), loc) in (e, fm) |