# HG changeset patch # User Adam Chlipala # Date 1229806008 18000 # Node ID 55fc747a67dc2dedc93b07151e919ee069071e9f # Parent 1901db85acb444cf112231b6d9646402f260f8e7 Initial support diff -r 1901db85acb4 -r 55fc747a67dc lib/basis.urs --- a/lib/basis.urs Sat Dec 20 14:19:21 2008 -0500 +++ b/lib/basis.urs Sat Dec 20 15:46:48 2008 -0500 @@ -376,6 +376,9 @@ con tabl = [Body, Table] con tr = [Body, Tr] +val dyn : ctx ::: {Unit} -> use ::: {Type} -> bind ::: {Type} -> unit + -> tag [Signal = signal (xml ctx use bind)] ctx [] use bind + val head : unit -> tag [] html head [] [] val title : unit -> tag [] head [] [] [] @@ -433,7 +436,7 @@ val select : formTag string select [] val option : unit -> tag [Value = string, Selected = bool] select [] [] [] -val submit : ctx ::: {Unit} -> use ::: {Type} +val submit : ctx ::: {Unit} -> use ::: {Type} -> fn [[Form] ~ ctx] => unit -> tag [Value = string, Action = $use -> transaction page] diff -r 1901db85acb4 -r 55fc747a67dc src/cjrize.sml --- a/src/cjrize.sml Sat Dec 20 14:19:21 2008 -0500 +++ b/src/cjrize.sml Sat Dec 20 15:46:48 2008 -0500 @@ -120,6 +120,7 @@ in ((L'.TOption t, loc), sm) end + | L.TSignal _ => raise Fail "Cjrize: TSignal remains" in cify IM.empty x end @@ -420,7 +421,8 @@ ((L'.EUnurlify (e, t), loc), sm) end - | L.EJavaScript _ => raise Fail "EJavaScript remains" + | L.EJavaScript _ => raise Fail "Cjrize: EJavaScript remains" + | L.ESignalReturn _ => raise Fail "Cjrize: ESignalReturn remains" fun cifyDecl ((d, loc), sm) = case d of diff -r 1901db85acb4 -r 55fc747a67dc src/jscomp.sml --- a/src/jscomp.sml Sat Dec 20 14:19:21 2008 -0500 +++ b/src/jscomp.sml Sat Dec 20 15:46:48 2008 -0500 @@ -69,8 +69,15 @@ | ENextval _ => 0 | EUnurlify _ => 0 | EJavaScript _ => 0 + | ESignalReturn e => varDepth e -fun jsExp inAttr outer = +fun strcat loc es = + case es of + [] => (EPrim (Prim.String ""), loc) + | [x] => x + | x :: es' => (EStrcat (x, strcat loc es'), loc) + +fun jsExp mode outer = let val len = length outer @@ -85,11 +92,7 @@ PConVar n => str (Int.toString n) | PConFfi {con, ...} => str ("\"_" ^ con ^ "\"") - fun strcat es = - case es of - [] => (EPrim (Prim.String ""), loc) - | [x] => x - | x :: es' => (EStrcat (x, strcat es'), loc) + fun isNullable (t, _) = case t of @@ -99,17 +102,19 @@ fun unsupported s = (EM.errorAt loc (s ^ " in code to be compiled to JavaScript"); (str "ERROR", st)) + + val strcat = strcat loc in case #1 e of EPrim (Prim.String s) => (str ("\"" ^ String.translate (fn #"'" => - if inAttr then + if mode = Attribute then "\\047" else "'" | #"<" => - if inAttr then + if mode = Script then "<" else "\\074" @@ -274,7 +279,14 @@ st) end - | EWrite _ => unsupported "EWrite" + | EWrite e => + let + val (e, st) = jsE inner (e, st) + in + (strcat [str "document.write(", + e, + str ")"], st) + end | ESeq (e1, e2) => let @@ -301,6 +313,15 @@ | ENextval _ => unsupported "Nextval" | EUnurlify _ => unsupported "EUnurlify" | EJavaScript _ => unsupported "Nested JavaScript" + | ESignalReturn e => + let + val (e, st) = jsE inner (e, st) + in + (strcat [(*str "sreturn(",*) + e(*, + str ")"*)], + st) + end end in jsE @@ -309,14 +330,25 @@ val decl : state -> decl -> decl * state = U.Decl.foldMapB {typ = fn x => x, exp = fn (env, e, st) => - case e of - EJavaScript (EAbs (_, t, _, e), _) => - let - val (e, st) = jsExp true (t :: env) 0 (e, st) - in - (#1 e, st) - end - | _ => (e, st), + let + fun doCode m env e = + let + val len = length env + fun str s = (EPrim (Prim.String s), #2 e) + + val locals = List.tabulate + (varDepth e, + fn i => str ("var uwr" ^ Int.toString (len + i) ^ ";")) + val (e, st) = jsExp m env 0 (e, st) + in + (#1 (strcat (#2 e) (locals @ [e])), st) + end + in + case e of + EJavaScript (m, (EAbs (_, t, _, e), _)) => doCode m (t :: env) e + | EJavaScript (m, e) => doCode m env e + | _ => (e, st) + end, decl = fn (_, e, st) => (e, st), bind = fn (env, U.Decl.RelE (_, t)) => t :: env | (env, _) => env} diff -r 1901db85acb4 -r 55fc747a67dc src/mono.sml --- a/src/mono.sml Sat Dec 20 14:19:21 2008 -0500 +++ b/src/mono.sml Sat Dec 20 15:46:48 2008 -0500 @@ -37,6 +37,7 @@ | TDatatype of int * (datatype_kind * (string * int * typ option) list) ref | TFfi of string * string | TOption of typ + | TSignal of typ withtype typ = typ' located @@ -55,6 +56,11 @@ withtype pat = pat' located +datatype javascript_mode = + Attribute + | Script + | File + datatype exp' = EPrim of Prim.t | ERel of int @@ -96,8 +102,9 @@ | EUnurlify of exp * typ - | EJavaScript of exp + | EJavaScript of javascript_mode * exp + | ESignalReturn of exp withtype exp = exp' located diff -r 1901db85acb4 -r 55fc747a67dc src/mono_print.sml --- a/src/mono_print.sml Sat Dec 20 14:19:21 2008 -0500 +++ b/src/mono_print.sml Sat Dec 20 15:46:48 2008 -0500 @@ -65,6 +65,9 @@ | TOption t => box [string "option(", p_typ env t, string ")"] + | TSignal t => box [string "signal(", + p_typ env t, + string ")"] and p_typ env = p_typ' false env @@ -275,9 +278,13 @@ | EUnurlify (e, _) => box [string "unurlify(", p_exp env e, string ")"] - | EJavaScript e => box [string "JavaScript(", - p_exp env e, - string ")"] + | EJavaScript (_, e) => box [string "JavaScript(", + p_exp env e, + string ")"] + + | ESignalReturn e => box [string "Return(", + p_exp env e, + string ")"] and p_exp env = p_exp' false env diff -r 1901db85acb4 -r 55fc747a67dc src/mono_reduce.sml --- a/src/mono_reduce.sml Sat Dec 20 14:19:21 2008 -0500 +++ b/src/mono_reduce.sml Sat Dec 20 15:46:48 2008 -0500 @@ -75,7 +75,8 @@ | ELet (_, _, e1, e2) => impure e1 orelse impure e2 | EClosure (_, es) => List.exists impure es - | EJavaScript e => impure e + | EJavaScript (_, e) => impure e + | ESignalReturn e => impure e val liftExpInExp = Monoize.liftExpInExp @@ -330,7 +331,8 @@ | EDml e => summarize d e @ [WriteDb] | ENextval e => summarize d e @ [WriteDb] | EUnurlify (e, _) => summarize d e - | EJavaScript e => summarize d e + | EJavaScript (_, e) => summarize d e + | ESignalReturn e => summarize d e fun exp env e = @@ -421,6 +423,7 @@ fun trySub () = case t of (TFfi ("Basis", "string"), _) => doSub () + | (TSignal _, _) => e | _ => case e' of (ECase _, _) => e diff -r 1901db85acb4 -r 55fc747a67dc src/mono_util.sml --- a/src/mono_util.sml Sat Dec 20 14:19:21 2008 -0500 +++ b/src/mono_util.sml Sat Dec 20 15:46:48 2008 -0500 @@ -51,6 +51,7 @@ | (TDatatype (n1, _), TDatatype (n2, _)) => Int.compare (n1, n2) | (TFfi (m1, x1), TFfi (m2, x2)) => join (String.compare (m1, m2), fn () => String.compare (x1, x2)) | (TOption t1, TOption t2) => compare (t1, t2) + | (TSignal t1, TSignal t2) => compare (t1, t2) | (TFun _, _) => LESS | (_, TFun _) => GREATER @@ -64,6 +65,9 @@ | (TFfi _, _) => LESS | (_, TFfi _) => GREATER + | (TOption _, _) => LESS + | (_, TOption _) => GREATER + and compareFields ((x1, t1), (x2, t2)) = join (String.compare (x1, x2), fn () => compare (t1, t2)) @@ -96,6 +100,10 @@ S.map2 (mft t, fn t' => (TOption t, loc)) + | TSignal t => + S.map2 (mft t, + fn t' => + (TSignal t, loc)) in mft end @@ -311,10 +319,14 @@ S.map2 (mft t, fn t' => (EUnurlify (e', t'), loc))) - | EJavaScript e => + | EJavaScript (m, e) => S.map2 (mfe ctx e, fn e' => - (EJavaScript e', loc)) + (EJavaScript (m, e'), loc)) + | ESignalReturn e => + S.map2 (mfe ctx e, + fn e' => + (ESignalReturn e', loc)) in mfe end diff -r 1901db85acb4 -r 55fc747a67dc src/monoize.sml --- a/src/monoize.sml Sat Dec 20 14:19:21 2008 -0500 +++ b/src/monoize.sml Sat Dec 20 15:46:48 2008 -0500 @@ -135,6 +135,8 @@ (L'.TFun ((L'.TRecord [], loc), mt env dtmap t), loc) | L.CApp ((L.CFfi ("Basis", "source"), _), t) => (L'.TFfi ("Basis", "int"), loc) + | L.CApp ((L.CFfi ("Basis", "signal"), _), t) => + (L'.TSignal (mt env dtmap t), loc) | L.CApp ((L.CFfi ("Basis", "http_cookie"), _), _) => (L'.TFfi ("Basis", "string"), loc) | L.CApp ((L.CFfi ("Basis", "sql_table"), _), _) => @@ -978,6 +980,16 @@ fm) end + | L.EApp ((L.ECApp ((L.ECApp ((L.EFfi ("Basis", "return"), _), _), _), t), _), + (L.EFfi ("Basis", "signal_monad"), _)) => + let + val t = monoType env t + in + ((L'.EAbs ("x", t, (L'.TSignal t, loc), + (L'.ESignalReturn (L'.ERel 0, loc), loc)), loc), + fm) + end + | L.ECApp ((L.EFfi ("Basis", "getCookie"), _), t) => let val s = (L'.TFfi ("Basis", "string"), loc) @@ -1752,7 +1764,7 @@ (L'.EStrcat ( (L'.EPrim (Prim.String s'), loc), (L'.EStrcat ( - (L'.EJavaScript e, loc), + (L'.EJavaScript (L'.Attribute, e), loc), (L'.EPrim (Prim.String "'"), loc)), loc)), loc)), loc), fm) @@ -1833,6 +1845,25 @@ case tag of "body" => normal ("body", NONE, SOME (L'.EFfiApp ("Basis", "get_script", [(L'.ERecord [], loc)]), loc)) + + | "dyn" => + (case #1 attrs of + (*L'.ERecord [("Signal", (L'.ESignalReturn e, _), _)] => (e, fm) + | L'.ERecord [("Signal", (L'.EApp ((L'.EAbs (_, _, _, (L'.ESignalReturn (L'.ERel 0, _), _)), _), + e), _), _)] => (e, fm) *) + + L'.ERecord [("Signal", e, _)] => + ((L'.EStrcat + ((L'.EPrim (Prim.String ""), loc)), loc)), loc), + fm) + | _ => raise Fail "Monoize: Bad dyn attributes") | "submit" => normal ("input type=\"submit\"", NONE, NONE) diff -r 1901db85acb4 -r 55fc747a67dc tests/sreturn.ur --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/sreturn.ur Sat Dec 20 15:46:48 2008 -0500 @@ -0,0 +1,5 @@ +fun main () : transaction page = return +

Before

+

Hi!}/>

+

After

+
diff -r 1901db85acb4 -r 55fc747a67dc tests/sreturn.urp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/sreturn.urp Sat Dec 20 15:46:48 2008 -0500 @@ -0,0 +1,3 @@ +debug + +sreturn