# HG changeset patch # User Adam Chlipala # Date 1240945477 14400 # Node ID 8688e01ae469abfc7cd87ed11f1a6ff3d7059510 # Parent d484df4e841a1595fb2ace7517f653baaaa1c6c2 A view query works diff -r d484df4e841a -r 8688e01ae469 src/cjr.sml --- a/src/cjr.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/cjr.sml Tue Apr 28 15:04:37 2009 -0400 @@ -107,6 +107,7 @@ | DTable of string * (string * typ) list * string * (string * string) list | DSequence of string + | DView of string * (string * typ) list * string | DDatabase of {name : string, expunge : int, initialize : int} | DPreparedStatements of (string * int) list diff -r d484df4e841a -r 8688e01ae469 src/cjr_env.sml --- a/src/cjr_env.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/cjr_env.sml Tue Apr 28 15:04:37 2009 -0400 @@ -164,6 +164,7 @@ end) env vis | DTable _ => env | DSequence _ => env + | DView _ => env | DDatabase _ => env | DPreparedStatements _ => env | DJavaScript _ => env diff -r d484df4e841a -r 8688e01ae469 src/cjr_print.sml --- a/src/cjr_print.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/cjr_print.sml Tue Apr 28 15:04:37 2009 -0400 @@ -2069,6 +2069,15 @@ string x, string " */", newline] + | DView (x, _, s) => box [string "/* SQL view ", + string x, + space, + string "AS", + space, + string s, + space, + string " */", + newline] | DDatabase {name, expunge, initialize} => box [string "static void uw_db_validate(uw_context);", newline, @@ -3089,6 +3098,17 @@ string ";", newline, newline] + | DView (s, xts, q) => + box [string "CREATE VIEW", + space, + string s, + space, + string "AS", + space, + string q, + string ";", + newline, + newline] | _ => box [] in (pp, E.declBinds env dAll) diff -r d484df4e841a -r 8688e01ae469 src/cjrize.sml --- a/src/cjrize.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/cjrize.sml Tue Apr 28 15:04:37 2009 -0400 @@ -562,6 +562,34 @@ end | L.DSequence s => (SOME (L'.DSequence s, loc), NONE, sm) + | L.DView (s, xts, e) => + let + val (xts, sm) = ListUtil.foldlMap (fn ((x, t), sm) => + let + val (t, sm) = cifyTyp (t, sm) + in + ((x, t), sm) + end) sm xts + + fun flatten e = + case #1 e of + L.ERecord [] => [] + | L.ERecord [(x, (L.EPrim (Prim.String v), _), _)] => [(x, v)] + | L.EStrcat (e1, e2) => flatten e1 @ flatten e2 + | _ => (ErrorMsg.errorAt loc "Constraint has not been fully determined"; + Print.prefaces "Undetermined constraint" + [("e", MonoPrint.p_exp MonoEnv.empty e)]; + []) + + val e = case #1 e of + L.EPrim (Prim.String s) => s + | _ => (ErrorMsg.errorAt loc "VIEW query has not been fully determined"; + Print.prefaces "Undetermined VIEW query" + [("e", MonoPrint.p_exp MonoEnv.empty e)]; + "") + in + (SOME (L'.DView (s, xts, e), loc), NONE, sm) + end | L.DDatabase s => (SOME (L'.DDatabase s, loc), NONE, sm) | L.DJavaScript s => (SOME (L'.DJavaScript s, loc), NONE, sm) | L.DCookie args => (SOME (L'.DCookie args, loc), NONE, sm) diff -r d484df4e841a -r 8688e01ae469 src/core.sml --- a/src/core.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/core.sml Tue Apr 28 15:04:37 2009 -0400 @@ -130,6 +130,7 @@ | DExport of export_kind * int | DTable of string * int * con * string * exp * con * exp * con | DSequence of string * int * string + | DView of string * int * string * exp * con | DDatabase of string | DCookie of string * int * con * string | DStyle of string * int * string diff -r d484df4e841a -r 8688e01ae469 src/core_env.sml --- a/src/core_env.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/core_env.sml Tue Apr 28 15:04:37 2009 -0400 @@ -327,6 +327,13 @@ in pushENamed env x n t NONE s end + | DView (x, n, s, _, c) => + let + val ct = (CFfi ("Basis", "sql_view"), loc) + val ct = (CApp (ct, c), loc) + in + pushENamed env x n ct NONE s + end | DDatabase _ => env | DCookie (x, n, c, s) => let diff -r d484df4e841a -r 8688e01ae469 src/core_print.sml --- a/src/core_print.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/core_print.sml Tue Apr 28 15:04:37 2009 -0400 @@ -566,6 +566,13 @@ string "as", space, string s] + | DView (x, n, s, e, _) => box [string "view", + space, + p_named x n, + space, + string "as", + space, + p_exp env e] | DDatabase s => box [string "database", space, string s] diff -r d484df4e841a -r 8688e01ae469 src/core_util.sml --- a/src/core_util.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/core_util.sml Tue Apr 28 15:04:37 2009 -0400 @@ -946,6 +946,12 @@ fn cc' => (DTable (x, n, c', s, pe', pc', ce', cc'), loc)))))) | DSequence _ => S.return2 dAll + | DView (x, n, s, e, c) => + S.bind2 (mfe ctx e, + fn e' => + S.map2 (mfc ctx c, + fn c' => + (DView (x, n, s, e', c'), loc))) | DDatabase _ => S.return2 dAll | DCookie (x, n, c, s) => S.map2 (mfc ctx c, @@ -1082,6 +1088,14 @@ in bind (ctx, NamedE (x, n, t, NONE, s)) end + | DView (x, n, s, _, c) => + let + val loc = #2 d' + val ct = (CFfi ("Basis", "sql_view"), loc) + val ct = (CApp (ct, c), loc) + in + bind (ctx, NamedE (x, n, ct, NONE, s)) + end | DDatabase _ => ctx | DCookie (x, n, c, s) => let @@ -1154,6 +1168,7 @@ | DExport _ => count | DTable (_, n, _, _, _, _, _, _) => Int.max (n, count) | DSequence (_, n, _) => Int.max (n, count) + | DView (_, n, _, _, _) => Int.max (n, count) | DDatabase _ => count | DCookie (_, n, _, _) => Int.max (n, count) | DStyle (_, n, _) => Int.max (n, count)) 0 diff -r d484df4e841a -r 8688e01ae469 src/corify.sml --- a/src/corify.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/corify.sml Tue Apr 28 15:04:37 2009 -0400 @@ -992,6 +992,13 @@ in ([(L'.DSequence (x, n, s), loc)], st) end + | L.DView (_, x, n, e, c) => + let + val (st, n) = St.bindVal st x n + val s = relify (doRestify (mods, x)) + in + ([(L'.DView (x, n, s, corifyExp st e, corifyCon st c), loc)], st) + end | L.DDatabase s => ([(L'.DDatabase s, loc)], st) @@ -1063,6 +1070,7 @@ | L.DExport _ => n | L.DTable (_, _, n', _, _, _, _, _) => Int.max (n, n') | L.DSequence (_, _, n') => Int.max (n, n') + | L.DView (_, _, n', _, _) => Int.max (n, n') | L.DDatabase _ => n | L.DCookie (_, _, n', _) => Int.max (n, n') | L.DStyle (_, _, n') => Int.max (n, n')) diff -r d484df4e841a -r 8688e01ae469 src/elab.sml --- a/src/elab.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/elab.sml Tue Apr 28 15:04:37 2009 -0400 @@ -165,6 +165,7 @@ | DExport of int * sgn * str | DTable of int * string * int * con * exp * con * exp * con | DSequence of int * string * int + | DView of int * string * int * exp * con | DClass of string * int * kind * con | DDatabase of string | DCookie of int * string * int * con diff -r d484df4e841a -r 8688e01ae469 src/elab_env.sml --- a/src/elab_env.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/elab_env.sml Tue Apr 28 15:04:37 2009 -0400 @@ -591,6 +591,22 @@ exception Bad of con * con +val hasUnif = U.Con.exists {kind = fn _ => false, + con = fn CUnif (_, _, _, ref NONE) => true + | _ => false} + +fun startsWithUnif c = + let + fun firstArg (c, acc) = + case #1 c of + CApp (f, x) => firstArg (f, SOME x) + | _ => acc + in + case firstArg (c, NONE) of + NONE => false + | SOME x => hasUnif x + end + fun resolveClass (hnorm : con -> con) (consEq : con * con -> bool) (env : env) = let fun resolve c = @@ -671,34 +687,37 @@ tryGrounds (#ground class) end in - case #1 c of - TRecord c => - (case #1 (hnorm c) of - CRecord (_, xts) => - let - fun resolver (xts, acc) = - case xts of - [] => SOME (ERecord acc, #2 c) - | (x, t) :: xts => - let - val t = hnorm t + if startsWithUnif c then + NONE + else + case #1 c of + TRecord c => + (case #1 (hnorm c) of + CRecord (_, xts) => + let + fun resolver (xts, acc) = + case xts of + [] => SOME (ERecord acc, #2 c) + | (x, t) :: xts => + let + val t = hnorm t - val t = case t of - (CApp (f, x), loc) => (CApp (hnorm f, hnorm x), loc) - | _ => t - in - case resolve t of - NONE => NONE - | SOME e => resolver (xts, (x, e, t) :: acc) - end - in - resolver (xts, []) - end - | _ => NONE) - | _ => - case class_head_in c of - SOME f => doHead f - | _ => NONE + val t = case t of + (CApp (f, x), loc) => (CApp (hnorm f, hnorm x), loc) + | _ => t + in + case resolve t of + NONE => NONE + | SOME e => resolver (xts, (x, e, t) :: acc) + end + in + resolver (xts, []) + end + | _ => NONE) + | _ => + case class_head_in c of + SOME f => doHead f + | _ => NONE end in resolve @@ -1482,6 +1501,13 @@ in pushENamedAs env x n t end + | DView (tn, x, n, _, c) => + let + val ct = (CModProj (tn, [], "sql_view"), loc) + val ct = (CApp (ct, c), loc) + in + pushENamedAs env x n ct + end | DClass (x, n, k, c) => let val k = (KArrow (k, (KType, loc)), loc) diff -r d484df4e841a -r 8688e01ae469 src/elab_print.sml --- a/src/elab_print.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/elab_print.sml Tue Apr 28 15:04:37 2009 -0400 @@ -758,6 +758,13 @@ | DSequence (_, x, n) => box [string "sequence", space, p_named x n] + | DView (_, x, n, e, _) => box [string "view", + space, + p_named x n, + space, + string "as", + space, + p_exp env e] | DClass (x, n, k, c) => box [string "class", space, p_named x n, diff -r d484df4e841a -r 8688e01ae469 src/elab_util.sml --- a/src/elab_util.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/elab_util.sml Tue Apr 28 15:04:37 2009 -0400 @@ -791,6 +791,13 @@ end | DSequence (tn, x, n) => bind (ctx, NamedE (x, (CModProj (n, [], "sql_sequence"), loc))) + | DView (tn, x, n, _, c) => + let + val ct = (CModProj (n, [], "sql_view"), loc) + val ct = (CApp (ct, c), loc) + in + bind (ctx, NamedE (x, ct)) + end | DClass (x, n, k, _) => bind (ctx, NamedC (x, n, (KArrow (k, (KType, loc)), loc))) | DDatabase _ => ctx @@ -899,6 +906,12 @@ fn cc' => (DTable (tn, x, n, c', pe', pc', ce', cc'), loc)))))) | DSequence _ => S.return2 dAll + | DView (tn, x, n, e, c) => + S.bind2 (mfe ctx e, + fn e' => + S.map2 (mfc ctx c, + fn c' => + (DView (tn, x, n, e', c'), loc))) | DClass (x, n, k, c) => S.bind2 (mfk ctx k, @@ -1051,6 +1064,7 @@ | DExport _ => 0 | DTable (n1, _, n2, _, _, _, _, _) => Int.max (n1, n2) | DSequence (n1, _, n2) => Int.max (n1, n2) + | DView (n1, _, n2, _, _) => Int.max (n1, n2) | DDatabase _ => 0 | DCookie (n1, _, n2, _) => Int.max (n1, n2) | DStyle (n1, _, n2) => Int.max (n1, n2) diff -r d484df4e841a -r 8688e01ae469 src/elaborate.sml --- a/src/elaborate.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/elaborate.sml Tue Apr 28 15:04:37 2009 -0400 @@ -803,19 +803,22 @@ handle GuessFailure => false end - val (fs1, fs2, others1, others2) = + val (fs1, fs2, others1, others2, unifs1, unifs2) = case (fs1, fs2, others1, others2, unifs1, unifs2) of ([], _, [other1], [], [], _) => if isGuessable (other1, fs2, unifs2) then - ([], [], [], []) + ([], [], [], [], [], []) else - (fs1, fs2, others1, others2) + (fs1, fs2, others1, others2, unifs1, unifs2) | (_, [], [], [other2], _, []) => if isGuessable (other2, fs1, unifs1) then - ([], [], [], []) + ([], [], [], [], [], []) else - (fs1, fs2, others1, others2) - | _ => (fs1, fs2, others1, others2) + (prefaces "Not guessable" [("other2", p_con env other2), + ("fs1", p_con env (L'.CRecord (k, fs1), loc)), + ("#unifs1", PD.string (Int.toString (length unifs1)))]; + (fs1, fs2, others1, others2, unifs1, unifs2)) + | _ => (fs1, fs2, others1, others2, unifs1, unifs2) (*val () = eprefaces "Summaries5" [("#1", p_summary env {fields = fs1, unifs = unifs1, others = others1}), ("#2", p_summary env {fields = fs2, unifs = unifs2, others = others2})]*) @@ -849,7 +852,7 @@ fun unfold (dom, ran, f, r, c) = let fun unfold (r, c) = - case #1 c of + case #1 (hnormCon env c) of L'.CRecord (_, []) => unifyCons env r (L'.CRecord (dom, []), loc) | L'.CRecord (_, [(x, v)]) => let @@ -878,8 +881,7 @@ unfold (r2, c2'); unifyCons env r (L'.CConcat (r1, r2), loc) end - | L'.CUnif (_, _, _, ref (SOME c)) => unfold (r, c) - | L'.CUnif (_, _, _, ur as ref NONE) => + | L'.CUnif (_, _, _, ur) => let val ur' = cunif (loc, (L'.KRecord dom, loc)) in @@ -1935,6 +1937,8 @@ fun tableOf () = (L'.CModProj (!basis_r, [], "sql_table"), ErrorMsg.dummySpan) fun sequenceOf () = (L'.CModProj (!basis_r, [], "sql_sequence"), ErrorMsg.dummySpan) +fun viewOf () = (L'.CModProj (!basis_r, [], "sql_view"), ErrorMsg.dummySpan) +fun queryOf () = (L'.CModProj (!basis_r, [], "sql_query"), ErrorMsg.dummySpan) fun cookieOf () = (L'.CModProj (!basis_r, [], "http_cookie"), ErrorMsg.dummySpan) fun styleOf () = (L'.CModProj (!basis_r, [], "css_class"), ErrorMsg.dummySpan) @@ -2434,6 +2438,8 @@ [(L'.SgiVal (x, n, (L'.CApp ((L'.CApp (tableOf (), c), loc), (L'.CConcat (pc, cc), loc)), loc)), loc)] | L'.DSequence (tn, x, n) => [(L'.SgiVal (x, n, sequenceOf ()), loc)] + | L'.DView (tn, x, n, _, c) => + [(L'.SgiVal (x, n, (L'.CApp (viewOf (), c), loc)), loc)] | L'.DClass (x, n, k, c) => [(L'.SgiClass (x, n, k, c), loc)] | L'.DDatabase _ => [] | L'.DCookie (tn, x, n, c) => [(L'.SgiVal (x, n, (L'.CApp (cookieOf (), c), loc)), loc)] @@ -3405,6 +3411,29 @@ in ([(L'.DSequence (!basis_r, x, n), loc)], (env, denv, gs)) end + | L.DView (x, e) => + let + val (e', t, gs') = elabExp (env, denv) e + + val k = (L'.KRecord (L'.KType, loc), loc) + val fs = cunif (loc, k) + val ts = cunif (loc, (L'.KRecord k, loc)) + val tf = (L'.CApp ((L'.CMap (k, k), loc), + (L'.CAbs ("_", k, (L'.CRecord ((L'.KType, loc), []), loc)), loc)), loc) + val ts = (L'.CApp (tf, ts), loc) + + val cv = viewOf () + val cv = (L'.CApp (cv, fs), loc) + val (env', n) = E.pushENamed env x cv + + val ct = queryOf () + val ct = (L'.CApp (ct, ts), loc) + val ct = (L'.CApp (ct, fs), loc) + in + checkCon env e' t ct; + ([(L'.DView (!basis_r, x, n, e', fs), loc)], + (env', denv, gs' @ gs)) + end | L.DClass (x, k, c) => let diff -r d484df4e841a -r 8688e01ae469 src/elisp/urweb-mode.el --- a/src/elisp/urweb-mode.el Tue Apr 28 14:02:23 2009 -0400 +++ b/src/elisp/urweb-mode.el Tue Apr 28 15:04:37 2009 -0400 @@ -137,7 +137,7 @@ "fun" "functor" "if" "include" "of" "open" "let" "in" "rec" "sequence" "sig" "signature" "cookie" "style" - "struct" "structure" "table" "then" "type" "val" "where" + "struct" "structure" "table" "view" "then" "type" "val" "where" "with" "Name" "Type" "Unit") diff -r d484df4e841a -r 8688e01ae469 src/expl.sml --- a/src/expl.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/expl.sml Tue Apr 28 15:04:37 2009 -0400 @@ -143,6 +143,7 @@ | DExport of int * sgn * str | DTable of int * string * int * con * exp * con * exp * con | DSequence of int * string * int + | DView of int * string * int * exp * con | DDatabase of string | DCookie of int * string * int * con | DStyle of int * string * int diff -r d484df4e841a -r 8688e01ae469 src/expl_env.sml --- a/src/expl_env.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/expl_env.sml Tue Apr 28 15:04:37 2009 -0400 @@ -312,6 +312,13 @@ in pushENamed env x n t end + | DView (tn, x, n, _, c) => + let + val ct = (CModProj (tn, [], "sql_view"), loc) + val ct = (CApp (ct, c), loc) + in + pushENamed env x n ct + end | DDatabase _ => env | DCookie (tn, x, n, c) => let diff -r d484df4e841a -r 8688e01ae469 src/expl_print.sml --- a/src/expl_print.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/expl_print.sml Tue Apr 28 15:04:37 2009 -0400 @@ -681,6 +681,13 @@ | DSequence (_, x, n) => box [string "sequence", space, p_named x n] + | DView (_, x, n, e, _) => box [string "view", + space, + p_named x n, + space, + string "as", + space, + p_exp env e] | DDatabase s => box [string "database", space, string s] diff -r d484df4e841a -r 8688e01ae469 src/explify.sml --- a/src/explify.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/explify.sml Tue Apr 28 15:04:37 2009 -0400 @@ -182,6 +182,8 @@ SOME (L'.DTable (nt, x, n, explifyCon c, explifyExp pe, explifyCon pc, explifyExp ce, explifyCon cc), loc) + | L.DView (nt, x, n, e, c) => + SOME (L'.DView (nt, x, n, explifyExp e, explifyCon c), loc) | L.DSequence (nt, x, n) => SOME (L'.DSequence (nt, x, n), loc) | L.DClass (x, n, k, c) => SOME (L'.DCon (x, n, (L'.KArrow (explifyKind k, (L'.KType, loc)), loc), explifyCon c), loc) diff -r d484df4e841a -r 8688e01ae469 src/mono.sml --- a/src/mono.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/mono.sml Tue Apr 28 15:04:37 2009 -0400 @@ -127,6 +127,7 @@ | DTable of string * (string * typ) list * exp * exp | DSequence of string + | DView of string * (string * typ) list * exp | DDatabase of {name : string, expunge : int, initialize : int} | DJavaScript of string diff -r d484df4e841a -r 8688e01ae469 src/mono_env.sml --- a/src/mono_env.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/mono_env.sml Tue Apr 28 15:04:37 2009 -0400 @@ -109,6 +109,7 @@ | DExport _ => env | DTable _ => env | DSequence _ => env + | DView _ => env | DDatabase _ => env | DJavaScript _ => env | DCookie _ => env diff -r d484df4e841a -r 8688e01ae469 src/mono_opt.sml --- a/src/mono_opt.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/mono_opt.sml Tue Apr 28 15:04:37 2009 -0400 @@ -422,6 +422,31 @@ EPrim (Prim.String s) end + | EFfiApp ("Basis", "viewify", [(EPrim (Prim.String s), loc)]) => + let + fun uwify (cs, acc) = + case cs of + [] => String.concat (rev acc) + | #"A" :: #"S" :: #" " :: #"_" :: cs => uwify (cs, "AS uw_" :: acc) + | #"'" :: cs => + let + fun waitItOut (cs, acc) = + case cs of + [] => raise Fail "MonoOpt: Unterminated SQL string literal" + | #"'" :: cs => uwify (cs, "'" :: acc) + | #"\\" :: #"'" :: cs => waitItOut (cs, "\\'" :: acc) + | #"\\" :: #"\\" :: cs => waitItOut (cs, "\\\\" :: acc) + | c :: cs => waitItOut (cs, str c :: acc) + in + waitItOut (cs, "'" :: acc) + end + | c :: cs => uwify (cs, str c :: acc) + + val s = uwify (String.explode s, []) + in + EPrim (Prim.String s) + end + | _ => e and optExp e = #1 (U.Exp.map {typ = typ, exp = exp} e) diff -r d484df4e841a -r 8688e01ae469 src/mono_print.sml --- a/src/mono_print.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/mono_print.sml Tue Apr 28 15:04:37 2009 -0400 @@ -438,6 +438,13 @@ | DSequence s => box [string "(* SQL sequence ", string s, string "*)"] + | DView (s, _, e) => box [string "(* SQL view ", + string s, + space, + string "as", + space, + p_exp env e, + string "*)"] | DDatabase {name, expunge, initialize} => box [string "database", space, string name, diff -r d484df4e841a -r 8688e01ae469 src/mono_shake.sml --- a/src/mono_shake.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/mono_shake.sml Tue Apr 28 15:04:37 2009 -0400 @@ -57,6 +57,7 @@ | ((DExport _, _), acc) => acc | ((DTable _, _), acc) => acc | ((DSequence _, _), acc) => acc + | ((DView _, _), acc) => acc | ((DDatabase _, _), acc) => acc | ((DJavaScript _, _), acc) => acc | ((DCookie _, _), acc) => acc @@ -116,6 +117,7 @@ | (DExport _, _) => true | (DTable _, _) => true | (DSequence _, _) => true + | (DView _, _) => true | (DDatabase _, _) => true | (DJavaScript _, _) => true | (DCookie _, _) => true diff -r d484df4e841a -r 8688e01ae469 src/mono_util.sml --- a/src/mono_util.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/mono_util.sml Tue Apr 28 15:04:37 2009 -0400 @@ -492,6 +492,10 @@ fn ce' => (DTable (s, xts, pe', ce'), loc))) | DSequence _ => S.return2 dAll + | DView (s, xts, e) => + S.map2 (mfe ctx e, + fn e' => + (DView (s, xts, e'), loc)) | DDatabase _ => S.return2 dAll | DJavaScript _ => S.return2 dAll | DCookie _ => S.return2 dAll @@ -575,6 +579,7 @@ | DExport _ => ctx | DTable _ => ctx | DSequence _ => ctx + | DView _ => ctx | DDatabase _ => ctx | DJavaScript _ => ctx | DCookie _ => ctx @@ -626,6 +631,7 @@ | DExport _ => count | DTable _ => count | DSequence _ => count + | DView _ => count | DDatabase _ => count | DJavaScript _ => count | DCookie _ => count diff -r d484df4e841a -r 8688e01ae469 src/monoize.sml --- a/src/monoize.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/monoize.sml Tue Apr 28 15:04:37 2009 -0400 @@ -2938,6 +2938,24 @@ (L'.DVal (x, n, t', e_name, s), loc)]) end | L.DTable _ => poly () + | L.DView (x, n, s, e, (L.CRecord (_, xts), _)) => + let + val t = (L.CFfi ("Basis", "string"), loc) + val t' = (L'.TFfi ("Basis", "string"), loc) + val s = "uw_" ^ s + val e_name = (L'.EPrim (Prim.String s), loc) + + val xts = map (fn (x, t) => (monoName env x, monoType env t)) xts + + val (e, fm) = monoExp (env, St.empty, fm) e + val e = (L'.EFfiApp ("Basis", "viewify", [e]), loc) + in + SOME (Env.pushENamed env x n t NONE s, + fm, + [(L'.DView (s, xts, e), loc), + (L'.DVal (x, n, t', e_name, s), loc)]) + end + | L.DView _ => poly () | L.DSequence (x, n, s) => let val t = (L.CFfi ("Basis", "string"), loc) diff -r d484df4e841a -r 8688e01ae469 src/prepare.sml --- a/src/prepare.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/prepare.sml Tue Apr 28 15:04:37 2009 -0400 @@ -266,6 +266,7 @@ | DTable _ => (d, sns) | DSequence _ => (d, sns) + | DView _ => (d, sns) | DDatabase _ => (d, sns) | DPreparedStatements _ => (d, sns) | DJavaScript _ => (d, sns) diff -r d484df4e841a -r 8688e01ae469 src/reduce.sml --- a/src/reduce.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/reduce.sml Tue Apr 28 15:04:37 2009 -0400 @@ -467,6 +467,7 @@ exp (namedC, namedE) [] ce, con namedC [] cc), loc), st) | DSequence _ => (d, st) + | DView (s, n, s', e, c) => ((DView (s, n, s', exp (namedC, namedE) [] e, con namedC [] c), loc), st) | DDatabase _ => (d, st) | DCookie (s, n, c, s') => ((DCookie (s, n, con namedC [] c, s'), loc), st) | DStyle (s, n, s') => ((DStyle (s, n, s'), loc), st) diff -r d484df4e841a -r 8688e01ae469 src/reduce_local.sml --- a/src/reduce_local.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/reduce_local.sml Tue Apr 28 15:04:37 2009 -0400 @@ -158,6 +158,7 @@ | DExport _ => d | DTable _ => d | DSequence _ => d + | DView _ => d | DDatabase _ => d | DCookie _ => d | DStyle _ => d diff -r d484df4e841a -r 8688e01ae469 src/shake.sml --- a/src/shake.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/shake.sml Tue Apr 28 15:04:37 2009 -0400 @@ -84,6 +84,8 @@ (cdef, IM.insert (edef, n, ([], c, dummye))) | ((DSequence (_, n, _), _), (cdef, edef)) => (cdef, IM.insert (edef, n, ([], dummyt, dummye))) + | ((DView (_, n, _, _, c), _), (cdef, edef)) => + (cdef, IM.insert (edef, n, ([], c, dummye))) | ((DDatabase _, _), acc) => acc | ((DCookie (_, n, c, _), _), (cdef, edef)) => (cdef, IM.insert (edef, n, ([], c, dummye))) @@ -159,8 +161,9 @@ | (DVal (_, n, _, _, _), _) => IS.member (#exp s, n) | (DValRec vis, _) => List.exists (fn (_, n, _, _, _) => IS.member (#exp s, n)) vis | (DExport _, _) => true + | (DView _, _) => true + | (DSequence _, _) => true | (DTable _, _) => true - | (DSequence _, _) => true | (DDatabase _, _) => true | (DCookie _, _) => true | (DStyle _, _) => true) file diff -r d484df4e841a -r 8688e01ae469 src/source.sml --- a/src/source.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/source.sml Tue Apr 28 15:04:37 2009 -0400 @@ -161,6 +161,7 @@ | DExport of str | DTable of string * con * exp * exp | DSequence of string + | DView of string * exp | DClass of string * kind * con | DDatabase of string | DCookie of string * con diff -r d484df4e841a -r 8688e01ae469 src/source_print.sml --- a/src/source_print.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/source_print.sml Tue Apr 28 15:04:37 2009 -0400 @@ -621,6 +621,13 @@ | DSequence x => box [string "sequence", space, string x] + | DView (x, e) => box [string "view", + space, + string x, + space, + string "=", + space, + p_exp e] | DClass (x, k, c) => box [string "class", space, string x, diff -r d484df4e841a -r 8688e01ae469 src/unnest.sml --- a/src/unnest.sml Tue Apr 28 14:02:23 2009 -0400 +++ b/src/unnest.sml Tue Apr 28 15:04:37 2009 -0400 @@ -404,6 +404,7 @@ | DExport _ => default () | DTable _ => default () | DSequence _ => default () + | DView _ => default () | DClass _ => default () | DDatabase _ => default () | DCookie _ => default () diff -r d484df4e841a -r 8688e01ae469 src/urweb.grm --- a/src/urweb.grm Tue Apr 28 14:02:23 2009 -0400 +++ b/src/urweb.grm Tue Apr 28 15:04:37 2009 -0400 @@ -195,7 +195,7 @@ | FN | PLUSPLUS | MINUSMINUS | MINUSMINUSMINUS | DOLLAR | TWIDDLE | CARET | LET | IN | STRUCTURE | SIGNATURE | STRUCT | SIG | END | FUNCTOR | WHERE | EXTERN | SQL - | INCLUDE | OPEN | CONSTRAINT | CONSTRAINTS | EXPORT | TABLE | SEQUENCE + | INCLUDE | OPEN | CONSTRAINT | CONSTRAINTS | EXPORT | TABLE | SEQUENCE | VIEW | COOKIE | STYLE | CASE | IF | THEN | ELSE @@ -438,6 +438,10 @@ | TABLE SYMBOL COLON cterm pkopt commaOpt cstopt([(DTable (SYMBOL, entable cterm, pkopt, cstopt), s (TABLEleft, cstoptright))]) | SEQUENCE SYMBOL ([(DSequence SYMBOL, s (SEQUENCEleft, SYMBOLright))]) + | VIEW SYMBOL EQ query ([(DView (SYMBOL, query), + s (VIEWleft, queryright))]) + | VIEW SYMBOL EQ LBRACE eexp RBRACE ([(DView (SYMBOL, eexp), + s (VIEWleft, RBRACEright))]) | CLASS SYMBOL EQ cexp (let val loc = s (CLASSleft, cexpright) in @@ -674,6 +678,13 @@ in (SgiVal (SYMBOL, t), loc) end) + | VIEW SYMBOL COLON cexp (let + val loc = s (VIEWleft, cexpright) + val t = (CVar (["Basis"], "sql_view"), loc) + val t = (CApp (t, cexp), loc) + in + (SgiVal (SYMBOL, t), loc) + end) | CLASS SYMBOL (let val loc = s (CLASSleft, SYMBOLright) val k = (KArrow ((KType, loc), (KType, loc)), loc) diff -r d484df4e841a -r 8688e01ae469 src/urweb.lex --- a/src/urweb.lex Tue Apr 28 14:02:23 2009 -0400 +++ b/src/urweb.lex Tue Apr 28 15:04:37 2009 -0400 @@ -317,6 +317,7 @@ "export" => (Tokens.EXPORT (pos yypos, pos yypos + size yytext)); "table" => (Tokens.TABLE (pos yypos, pos yypos + size yytext)); "sequence" => (Tokens.SEQUENCE (pos yypos, pos yypos + size yytext)); + "view" => (Tokens.VIEW (pos yypos, pos yypos + size yytext)); "class" => (Tokens.CLASS (pos yypos, pos yypos + size yytext)); "cookie" => (Tokens.COOKIE (pos yypos, pos yypos + size yytext)); "style" => (Tokens.STYLE (pos yypos, pos yypos + size yytext)); diff -r d484df4e841a -r 8688e01ae469 tests/view.ur --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/view.ur Tue Apr 28 15:04:37 2009 -0400 @@ -0,0 +1,10 @@ +table t : { A : int, B : string } + +view v = SELECT t.A AS X FROM t + +fun main () = + rows <- queryX (SELECT * FROM v) + (fn r =>
  • {[r.V.X]}
  • ); + return + {rows} + diff -r d484df4e841a -r 8688e01ae469 tests/view.urp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/view.urp Tue Apr 28 15:04:37 2009 -0400 @@ -0,0 +1,5 @@ +debug +database dbname=view +sql view.sql + +view diff -r d484df4e841a -r 8688e01ae469 tests/view.urs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/view.urs Tue Apr 28 15:04:37 2009 -0400 @@ -0,0 +1,1 @@ +val main : unit -> transaction page