Mercurial > urweb
changeset 325:e457d8972ff1
Crud listing IDs
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Thu, 11 Sep 2008 17:41:52 -0400 |
parents | b91480c9a729 |
children | 950320f33232 |
files | lib/basis.urs lib/top.ur lib/top.urs src/cjr_print.sml src/compiler.sml src/elaborate.sig src/elaborate.sml src/monoize.sml src/unpoly.sml src/urweb.grm tests/crud.ur tests/crud.urs tests/crud1.ur tests/crud1.urp |
diffstat | 14 files changed, 338 insertions(+), 117 deletions(-) [+] |
line wrap: on
line diff
--- a/lib/basis.urs Thu Sep 11 13:06:51 2008 -0400 +++ b/lib/basis.urs Thu Sep 11 17:41:52 2008 -0400 @@ -250,6 +250,7 @@ con xhtml = xml [Html] con page = xhtml [] [] +con xbody = xml [Body] [] [] (*** HTML details *) @@ -304,6 +305,13 @@ -> use ::: {Type} -> unit -> tag [Action = $use -> transaction page] ([LForm] ++ ctx) ([LForm] ++ ctx) use [] +(*** Tables *) + +val tabl : unit -> tag [Border = int] [Body] [Body, Table] [] [] +val tr : unit -> tag [] [Body, Table] [Body, Tr] [] [] +val th : unit -> tag [] [Body, Tr] [Body] [] [] +val td : unit -> tag [] [Body, Tr] [Body] [] [] + (** Aborting *)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/top.ur Thu Sep 11 17:41:52 2008 -0400 @@ -0,0 +1,6 @@ +con mapTT (f :: Type -> Type) = fold (fn nm t acc => [nm] ~ acc => + [nm = f t] ++ acc) [] + +fun compose (t1 ::: Type) (t2 ::: Type) (t3 ::: Type) (f1 : t2 -> t3) (f2 : t1 -> t2) (x : t1) = f1 (f2 x) + +fun txt (t ::: Type) (ctx ::: {Unit}) (use ::: {Type}) (sh : show t) (v : t) = cdata (show sh v)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/top.urs Thu Sep 11 17:41:52 2008 -0400 @@ -0,0 +1,8 @@ +con mapTT = fn f :: Type -> Type => fold (fn nm t acc => [nm] ~ acc => + [nm = f t] ++ acc) [] + +val compose : t1 ::: Type -> t2 ::: Type -> t3 ::: Type + -> (t2 -> t3) -> (t1 -> t2) -> (t1 -> t3) + +val txt : t ::: Type -> ctx ::: {Unit} -> use ::: {Type} -> show t -> t + -> xml ctx use []
--- a/src/cjr_print.sml Thu Sep 11 13:06:51 2008 -0400 +++ b/src/cjr_print.sml Thu Sep 11 17:41:52 2008 -0400 @@ -738,6 +738,7 @@ tables val outputs = exps @ tables + val outputs = ListMergeSort.sort (fn ((s1, _), (s2, _)) => String.compare (s1, s2) = GREATER) outputs val wontLeakStrings = notLeaky env true state val wontLeakAnything = notLeaky env false state @@ -1721,7 +1722,7 @@ val q'' = String.concat ["SELECT COUNT(*) FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = '", s, - "') AND attnum >= 0"] + "') AND attname LIKE 'uw_%'"] in box [string "res = PQexec(conn, \"", string q,
--- a/src/compiler.sml Thu Sep 11 13:06:51 2008 -0400 +++ b/src/compiler.sml Thu Sep 11 17:41:52 2008 -0400 @@ -355,8 +355,10 @@ val elaborate = { func = fn file => let val basis = #func parseUrs "lib/basis.urs" + val topSgn = #func parseUrs "lib/top.urs" + val topStr = #func parseUr "lib/top.ur" in - Elaborate.elabFile basis ElabEnv.empty file + Elaborate.elabFile basis topStr topSgn ElabEnv.empty file end, print = ElabPrint.p_file ElabEnv.empty }
--- a/src/elaborate.sig Thu Sep 11 13:06:51 2008 -0400 +++ b/src/elaborate.sig Thu Sep 11 17:41:52 2008 -0400 @@ -27,6 +27,7 @@ signature ELABORATE = sig - val elabFile : Source.sgn_item list -> ElabEnv.env -> Source.file -> Elab.file + val elabFile : Source.sgn_item list -> Source.decl list -> Source.sgn_item list + -> ElabEnv.env -> Source.file -> Elab.file end
--- a/src/elaborate.sml Thu Sep 11 13:06:51 2008 -0400 +++ b/src/elaborate.sml Thu Sep 11 17:41:52 2008 -0400 @@ -2805,6 +2805,98 @@ pos end +fun wildifyStr env (str, sgn) = + case #1 (hnormSgn env sgn) of + L'.SgnConst sgis => + (case #1 str of + L.StrConst ds => + let + fun decompileCon env (c, loc) = + case c of + L'.CRel i => + let + val (s, _) = E.lookupCRel env i + in + SOME (L.CVar ([], s), loc) + end + | L'.CNamed i => + let + val (s, _, _) = E.lookupCNamed env i + in + SOME (L.CVar ([], s), loc) + end + | L'.CModProj (m1, ms, x) => + let + val (s, _) = E.lookupStrNamed env m1 + in + SOME (L.CVar (s :: ms, x), loc) + end + | L'.CName s => SOME (L.CName s, loc) + | L'.CRecord (_, xcs) => + let + fun fields xcs = + case xcs of + [] => SOME [] + | (x, t) :: xcs => + case (decompileCon env x, decompileCon env t, fields xcs) of + (SOME x, SOME t, SOME xcs) => SOME ((x, t) :: xcs) + | _ => NONE + in + Option.map (fn xcs => (L.CRecord xcs, loc)) + (fields xcs) + end + | L'.CConcat (c1, c2) => + (case (decompileCon env c1, decompileCon env c2) of + (SOME c1, SOME c2) => SOME (L.CConcat (c1, c2), loc) + | _ => NONE) + | L'.CUnit => SOME (L.CUnit, loc) + + | _ => NONE + + val (needed, constraints, _) = + foldl (fn ((sgi, loc), (needed, constraints, env')) => + let + val (needed, constraints) = + case sgi of + L'.SgiConAbs (x, _, _) => (SS.add (needed, x), constraints) + | L'.SgiConstraint cs => (needed, (env', cs, loc) :: constraints) + | _ => (needed, constraints) + in + (needed, constraints, E.sgiBinds env' (sgi, loc)) + end) + (SS.empty, [], env) sgis + + val needed = foldl (fn ((d, _), needed) => + case d of + L.DCon (x, _, _) => (SS.delete (needed, x) + handle NotFound => + needed) + | L.DClass (x, _) => (SS.delete (needed, x) + handle NotFound => needed) + | L.DOpen _ => SS.empty + | _ => needed) + needed ds + + val cds = List.mapPartial (fn (env', (c1, c2), loc) => + case (decompileCon env' c1, decompileCon env' c2) of + (SOME c1, SOME c2) => + SOME (L.DConstraint (c1, c2), loc) + | _ => NONE) constraints + in + case SS.listItems needed of + [] => (L.StrConst (ds @ cds), #2 str) + | xs => + let + val kwild = (L.KWild, #2 str) + val cwild = (L.CWild kwild, #2 str) + val ds' = map (fn x => (L.DCon (x, NONE, cwild), #2 str)) xs + in + (L.StrConst (ds @ ds' @ cds), #2 str) + end + end + | _ => str) + | _ => str + fun elabDecl (dAll as (d, loc), (env, denv, gs : constraint list)) = let (*val () = preface ("elabDecl", SourcePrint.p_decl (d, loc))*) @@ -3010,43 +3102,7 @@ end | SOME (formal, gs1) => let - val str = - case #1 (hnormSgn env formal) of - L'.SgnConst sgis => - (case #1 str of - L.StrConst ds => - let - val needed = foldl (fn ((sgi, _), needed) => - case sgi of - L'.SgiConAbs (x, _, _) => SS.add (needed, x) - | _ => needed) - SS.empty sgis - - val needed = foldl (fn ((d, _), needed) => - case d of - L.DCon (x, _, _) => (SS.delete (needed, x) - handle NotFound => - needed) - | L.DClass (x, _) => (SS.delete (needed, x) - handle NotFound => needed) - | L.DOpen _ => SS.empty - | _ => needed) - needed ds - in - case SS.listItems needed of - [] => str - | xs => - let - val kwild = (L.KWild, #2 str) - val cwild = (L.CWild kwild, #2 str) - val ds' = map (fn x => (L.DCon (x, NONE, cwild), #2 str)) xs - in - (L.StrConst (ds @ ds'), #2 str) - end - end - | _ => str) - | _ => str - + val str = wildifyStr env (str, formal) val (str', actual, gs2) = elabStr (env, denv) str in subSgn (env, denv) (selfifyAt env {str = str', sgn = actual}) formal; @@ -3125,47 +3181,52 @@ fun doOne (all as (sgi, _), env) = (case sgi of L'.SgiVal (x, n, t) => - (case hnormCon (env, denv) t of - ((L'.TFun (dom, ran), _), []) => - (case (hnormCon (env, denv) dom, hnormCon (env, denv) ran) of - (((L'.TRecord domR, _), []), - ((L'.CApp (tf, arg), _), [])) => - (case (hnormCon (env, denv) tf, hnormCon (env, denv) arg) of - (((L'.CModProj (basis, [], "transaction"), _), []), - ((L'.CApp (tf, arg3), _), [])) => - (case (basis = !basis_r, - hnormCon (env, denv) tf, hnormCon (env, denv) arg3) of - (true, - ((L'.CApp (tf, arg2), _), []), - (((L'.CRecord (_, []), _), []))) => - (case (hnormCon (env, denv) tf) of - ((L'.CApp (tf, arg1), _), []) => - (case (hnormCon (env, denv) tf, - hnormCon (env, denv) domR, - hnormCon (env, denv) arg1, - hnormCon (env, denv) arg2) of - ((tf, []), (domR, []), (arg1, []), - ((L'.CRecord (_, []), _), [])) => - let - val t = (L'.CApp (tf, arg1), loc) - val t = (L'.CApp (t, arg2), loc) - val t = (L'.CApp (t, arg3), loc) - val t = (L'.CApp ( - (L'.CModProj - (basis, [], "transaction"), loc), - t), loc) - in - (L'.SgiVal (x, n, (L'.TFun ((L'.TRecord domR, - loc), - t), - loc)), loc) - end - | _ => all) - | _ => all) - | _ => all) - | _ => all) - | _ => all) - | _ => all) + let + fun doPage (makeRes, ran) = + case hnormCon (env, denv) ran of + ((L'.CApp (tf, arg), _), []) => + (case (hnormCon (env, denv) tf, hnormCon (env, denv) arg) of + (((L'.CModProj (basis, [], "transaction"), _), []), + ((L'.CApp (tf, arg3), _), [])) => + (case (basis = !basis_r, + hnormCon (env, denv) tf, hnormCon (env, denv) arg3) of + (true, + ((L'.CApp (tf, arg2), _), []), + (((L'.CRecord (_, []), _), []))) => + (case (hnormCon (env, denv) tf) of + ((L'.CApp (tf, arg1), _), []) => + (case (hnormCon (env, denv) tf, + hnormCon (env, denv) arg1, + hnormCon (env, denv) arg2) of + ((tf, []), (arg1, []), + ((L'.CRecord (_, []), _), [])) => + let + val t = (L'.CApp (tf, arg1), loc) + val t = (L'.CApp (t, arg2), loc) + val t = (L'.CApp (t, arg3), loc) + val t = (L'.CApp ( + (L'.CModProj + (basis, [], "transaction"), loc), + t), loc) + in + (L'.SgiVal (x, n, makeRes t), loc) + end + | _ => all) + | _ => all) + | _ => all) + | _ => all) + | _ => all + in + case hnormCon (env, denv) t of + ((L'.TFun (dom, ran), _), []) => + (case hnormCon (env, denv) dom of + ((L'.TRecord domR, _), []) => + doPage (fn t => (L'.TFun ((L'.TRecord domR, + loc), + t), loc), ran) + | _ => all) + | _ => doPage (fn t => t, t) + end | _ => all, E.sgiBinds env all) in @@ -3375,6 +3436,11 @@ | L.StrApp (str1, str2) => let val (str1', sgn1, gs1) = elabStr (env, denv) str1 + val str2 = + case sgn1 of + (L'.SgnFun (_, _, dom, _), _) => + wildifyStr env (str2, dom) + | _ => str2 val (str2', sgn2, gs2) = elabStr (env, denv) str2 in case #1 (hnormSgn env sgn1) of @@ -3392,7 +3458,7 @@ (strerror, sgnerror, [])) end -fun elabFile basis env file = +fun elabFile basis topStr topSgn env file = let val (sgn, gs) = elabSgn (env, D.empty) (L.SgnConst basis, ErrorMsg.dummySpan) val () = case gs of @@ -3419,6 +3485,25 @@ val () = discoverC string "string" val () = discoverC table "sql_table" + val (topSgn, gs) = elabSgn (env', D.empty) (L.SgnConst topSgn, ErrorMsg.dummySpan) + val () = case gs of + [] => () + | _ => raise Fail "Unresolved disjointness constraints in top.urs" + val (topStr, topSgn', gs) = elabStr (env', D.empty) (L.StrConst topStr, ErrorMsg.dummySpan) + val () = case gs of + [] => () + | _ => (app (fn Disjoint (_, env, _, c1, c2) => + prefaces "Unresolved" + [("c1", p_con env c1), + ("c2", p_con env c2)] + | TypeClass _ => TextIO.print "Type class\n") gs; + raise Fail "Unresolved constraints in top.ur") + val () = subSgn (env', D.empty) topSgn' topSgn + + val (env', top_n) = E.pushStrNamed env' "Top" topSgn + + val (ds', (env', _)) = dopen (env', D.empty) {str = top_n, strs = [], sgn = topSgn} + fun elabDecl' (d, (env, gs)) = let val () = resetKunif () @@ -3461,7 +3546,10 @@ SOME e => r := SOME e | NONE => expError env (Unresolvable (loc, c))) gs; - (L'.DFfiStr ("Basis", basis_n, sgn), ErrorMsg.dummySpan) :: ds @ file + (L'.DFfiStr ("Basis", basis_n, sgn), ErrorMsg.dummySpan) + :: ds + @ (L'.DStr ("Top", top_n, topSgn, topStr), ErrorMsg.dummySpan) + :: ds' @ file end end
--- a/src/monoize.sml Thu Sep 11 13:06:51 2008 -0400 +++ b/src/monoize.sml Thu Sep 11 17:41:52 2008 -0400 @@ -1372,6 +1372,7 @@ | "loption" => normal ("option", NONE) + | "tabl" => normal ("table", NONE) | _ => normal (tag, NONE) end
--- a/src/unpoly.sml Thu Sep 11 13:06:51 2008 -0400 +++ b/src/unpoly.sml Thu Sep 11 17:41:52 2008 -0400 @@ -56,7 +56,19 @@ rep else e - | ECApp (e, _) => #1 e + | ECApp (e', _) => + let + fun isTheOne (e, _) = + case e of + ENamed xn' => xn' = xn + | ECApp (e, _) => isTheOne e + | _ => false + in + if isTheOne e' then + #1 e' + else + e + end | _ => e} type state = { @@ -110,7 +122,7 @@ let val e = foldl (fn ((_, n, n_old, _, _, _), e) => unpolyNamed (n_old, ENamed n) e) - e vis + e vis in SOME (t, e) end
--- a/src/urweb.grm Thu Sep 11 13:06:51 2008 -0400 +++ b/src/urweb.grm Thu Sep 11 17:41:52 2008 -0400 @@ -152,6 +152,11 @@ val inDml = ref false +fun tagIn bt = + case bt of + "table" => "tabl" + | _ => bt + %% %header (functor UrwebLrValsFn(structure Token : TOKEN)) @@ -187,7 +192,7 @@ %nonterm file of decl list | decls of decl list - | decl of decl + | decl of decl list | vali of string * con option * exp | valis of (string * con option * exp) list | copt of con option @@ -326,7 +331,7 @@ s (SIGleft, sgisright))]) decls : ([]) - | decl decls (decl :: decls) + | decl decls (decl @ decls) decl : CON SYMBOL cargl2 kopt EQ cexp (let val loc = s (CONleft, cexpright) @@ -334,47 +339,59 @@ val k = Option.getOpt (kopt, (KWild, loc)) val (c, k) = cargl2 (cexp, k) in - (DCon (SYMBOL, SOME k, c), loc) + [(DCon (SYMBOL, SOME k, c), loc)] end) - | LTYPE SYMBOL EQ cexp (DCon (SYMBOL, SOME (KType, s (LTYPEleft, cexpright)), cexp), - s (LTYPEleft, cexpright)) - | DATATYPE SYMBOL dargs EQ barOpt dcons(DDatatype (SYMBOL, dargs, dcons), s (DATATYPEleft, dconsright)) + | LTYPE SYMBOL EQ cexp ([(DCon (SYMBOL, SOME (KType, s (LTYPEleft, cexpright)), cexp), + s (LTYPEleft, cexpright))]) + | DATATYPE SYMBOL dargs EQ barOpt dcons([(DDatatype (SYMBOL, dargs, dcons), s (DATATYPEleft, dconsright))]) | DATATYPE SYMBOL dargs EQ DATATYPE CSYMBOL DOT path (case dargs of - [] => (DDatatypeImp (SYMBOL, CSYMBOL :: #1 path, #2 path), s (DATATYPEleft, pathright)) + [] => [(DDatatypeImp (SYMBOL, CSYMBOL :: #1 path, #2 path), s (DATATYPEleft, pathright))] | _ => raise Fail "Arguments specified for imported datatype") - | VAL vali (DVal vali, s (VALleft, valiright)) - | VAL REC valis (DValRec valis, s (VALleft, valisright)) - | FUN valis (DValRec valis, s (FUNleft, valisright)) + | VAL vali ([(DVal vali, s (VALleft, valiright))]) + | VAL REC valis ([(DValRec valis, s (VALleft, valisright))]) + | FUN valis ([(DValRec valis, s (FUNleft, valisright))]) - | SIGNATURE CSYMBOL EQ sgn (DSgn (CSYMBOL, sgn), s (SIGNATUREleft, sgnright)) - | STRUCTURE CSYMBOL EQ str (DStr (CSYMBOL, NONE, str), s (STRUCTUREleft, strright)) - | STRUCTURE CSYMBOL COLON sgn EQ str (DStr (CSYMBOL, SOME sgn, str), s (STRUCTUREleft, strright)) + | SIGNATURE CSYMBOL EQ sgn ([(DSgn (CSYMBOL, sgn), s (SIGNATUREleft, sgnright))]) + | STRUCTURE CSYMBOL EQ str ([(DStr (CSYMBOL, NONE, str), s (STRUCTUREleft, strright))]) + | STRUCTURE CSYMBOL COLON sgn EQ str ([(DStr (CSYMBOL, SOME sgn, str), s (STRUCTUREleft, strright))]) | FUNCTOR CSYMBOL LPAREN CSYMBOL COLON sgn RPAREN EQ str - (DStr (CSYMBOL1, NONE, - (StrFun (CSYMBOL2, sgn1, NONE, str), s (FUNCTORleft, strright))), - s (FUNCTORleft, strright)) + ([(DStr (CSYMBOL1, NONE, + (StrFun (CSYMBOL2, sgn1, NONE, str), s (FUNCTORleft, strright))), + s (FUNCTORleft, strright))]) | FUNCTOR CSYMBOL LPAREN CSYMBOL COLON sgn RPAREN COLON sgn EQ str - (DStr (CSYMBOL1, NONE, - (StrFun (CSYMBOL2, sgn1, SOME sgn2, str), s (FUNCTORleft, strright))), - s (FUNCTORleft, strright)) - | EXTERN STRUCTURE CSYMBOL COLON sgn (DFfiStr (CSYMBOL, sgn), s (EXTERNleft, sgnright)) + ([(DStr (CSYMBOL1, NONE, + (StrFun (CSYMBOL2, sgn1, SOME sgn2, str), s (FUNCTORleft, strright))), + s (FUNCTORleft, strright))]) + | EXTERN STRUCTURE CSYMBOL COLON sgn ([(DFfiStr (CSYMBOL, sgn), s (EXTERNleft, sgnright))]) | OPEN mpath (case mpath of [] => raise Fail "Impossible mpath parse [1]" - | m :: ms => (DOpen (m, ms), s (OPENleft, mpathright))) + | m :: ms => [(DOpen (m, ms), s (OPENleft, mpathright))]) + | OPEN mpath LPAREN str RPAREN (let + val loc = s (OPENleft, RPARENright) + + val m = case mpath of + [] => raise Fail "Impossible mpath parse [4]" + | m :: ms => + foldl (fn (m, str) => (StrProj (str, m), loc)) + (StrVar m, loc) ms + in + [(DStr ("anon", NONE, (StrApp (m, str), loc)), loc), + (DOpen ("anon", []), loc)] + end) | OPEN CONSTRAINTS mpath (case mpath of [] => raise Fail "Impossible mpath parse [3]" - | m :: ms => (DOpenConstraints (m, ms), s (OPENleft, mpathright))) - | CONSTRAINT cterm TWIDDLE cterm (DConstraint (cterm1, cterm2), s (CONSTRAINTleft, ctermright)) - | EXPORT spath (DExport spath, s (EXPORTleft, spathright)) - | TABLE SYMBOL COLON cexp (DTable (SYMBOL, entable cexp), s (TABLEleft, cexpright)) - | CLASS SYMBOL EQ cexp (DClass (SYMBOL, cexp), s (CLASSleft, cexpright)) + | m :: ms => [(DOpenConstraints (m, ms), s (OPENleft, mpathright))]) + | CONSTRAINT cterm TWIDDLE cterm ([(DConstraint (cterm1, cterm2), s (CONSTRAINTleft, ctermright))]) + | EXPORT spath ([(DExport spath, s (EXPORTleft, spathright))]) + | TABLE SYMBOL COLON cexp ([(DTable (SYMBOL, entable cexp), s (TABLEleft, cexpright))]) + | CLASS SYMBOL EQ cexp ([(DClass (SYMBOL, cexp), s (CLASSleft, cexpright))]) | CLASS SYMBOL SYMBOL EQ cexp (let val loc = s (CLASSleft, cexpright) val k = (KType, loc) val c = (CAbs (SYMBOL2, SOME k, cexp), loc) in - (DClass (SYMBOL1, c), s (CLASSleft, cexpright)) + [(DClass (SYMBOL1, c), s (CLASSleft, cexpright))] end) kopt : (NONE) @@ -853,15 +870,19 @@ | tag GT xml END_TAG (let val pos = s (tagleft, GTright) + val et = tagIn END_TAG in - if #1 tag = END_TAG then - if END_TAG = "lform" then + if #1 tag = et then + if et = "lform" then (EApp ((EVar (["Basis"], "lform"), pos), xml), pos) else (EApp (#2 tag, xml), pos) else - (ErrorMsg.errorAt pos "Begin and end tags don't match."; + (if ErrorMsg.anyErrors () then + () + else + ErrorMsg.errorAt pos "Begin and end tags don't match."; (EFold, pos)) end) | LBRACE eexp RBRACE (eexp) @@ -878,10 +899,11 @@ end) tagHead: BEGIN_TAG (let + val bt = tagIn BEGIN_TAG val pos = s (BEGIN_TAGleft, BEGIN_TAGright) in - (BEGIN_TAG, - (EVar ([], BEGIN_TAG), pos)) + (bt, + (EVar ([], bt), pos)) end) | tagHead LBRACE cexp RBRACE (#1 tagHead, (ECApp (#2 tagHead, cexp), s (tagHeadleft, RBRACEright)))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/crud.ur Thu Sep 11 17:41:52 2008 -0400 @@ -0,0 +1,40 @@ +functor Make(M : sig + con cols :: {Type} + constraint [Id] ~ cols + val tab : sql_table ([Id = int] ++ cols) + + val title : string + + val cols : $(mapTT (fn t => {Show : t -> xbody}) cols) +end) = struct + +open constraints M +val tab = M.tab + +fun list () = + rows <- query (SELECT * FROM tab AS T) + (fn fs acc => return <body> + {acc} <tr> <td>{txt _ fs.T.Id}</td> </tr> + </body>) <body></body>; + return <html><head> + <title>List</title> + + </head><body> + + <h1>List</h1> + + <table border={1}> + <tr> <th>ID</th> </tr> + {rows} + </table> + </body></html> + +fun main () : transaction page = return <html><head> + <title>{cdata M.title}</title> + </head><body> + <h1>{cdata M.title}</h1> + + <li> <a link={list ()}>List all rows</a></li> +</body></html> + +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/crud.urs Thu Sep 11 17:41:52 2008 -0400 @@ -0,0 +1,11 @@ +functor Make(M : sig + con cols :: {Type} + constraint [Id] ~ cols + val tab : sql_table ([Id = int] ++ cols) + + val title : string + + val cols : $(mapTT (fn t => {Show : t -> xbody}) cols) +end) : sig + val main : unit -> transaction page +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/crud1.ur Thu Sep 11 17:41:52 2008 -0400 @@ -0,0 +1,14 @@ +table t1 : {Id : int, A : int, B : string, C : float, D : bool} + +open Crud.Make(struct + val tab = t1 + + val title = "Crud1" + + val cols = { + A = {Show = txt _}, + B = {Show = txt _}, + C = {Show = txt _}, + D = {Show = txt _} + } +end)