← urwebplay

add demo files from main project

b914866c47a898d1bfb51a82c2faa09b9d08ae0e · ovidiucs · Jan 3, 2016 18:49

+11275 · 360 files changed

  • demo/alert.ur +3 −0
  • demo/alert.urp +1 −0
  • demo/alert.urs +1 −0
  • demo/batch.ur +82 −0
  • demo/batch.urp +3 −0
  • demo/batch.urs +1 −0
  • demo/batchFun.ur +155 −0
  • demo/batchFun.urp +1 −0
  • demo/batchFun.urs +27 −0
  • demo/batchG.ur +9 −0
  • demo/batchG.urp +5 −0
  • demo/batchG.urs +1 −0
  • demo/broadcast.ur +29 −0
  • demo/broadcast.urs +11 −0
  • demo/buffer.ur +25 −0
  • demo/buffer.urs +5 −0
  • demo/chat.ur +92 −0
  • demo/chat.urp +6 −0
  • demo/chat.urs +1 −0
  • demo/constraints.ur +38 −0
  • demo/constraints.urp +4 −0
  • demo/constraints.urs +1 −0
  • demo/cookie.ur +44 −0
  • demo/cookie.urp +1 −0
  • demo/cookie.urs +1 −0
  • demo/cookieSec.ur +39 −0
  • demo/cookieSec.urp +4 −0
  • demo/cookieSec.urs +1 −0
  • demo/counter.ur +8 −0
  • demo/counter.urp +1 −0
  • demo/counter.urs +1 −0
  • demo/crud.ur +173 −0
  • demo/crud.urp +2 −0
  • demo/crud.urs +27 −0
  • demo/crud1.ur +13 −0
  • demo/crud1.urp +5 −0
  • demo/crud2.ur +35 −0
  • demo/crud2.urp +5 −0
  • demo/crud3.ur +27 −0
  • demo/crud3.urp +5 −0
  • demo/css.ur +11 −0
  • demo/css.urp +4 −0
  • demo/css.urs +1 −0
  • demo/demo.sql +138 −0
  • demo/demo.ur +38 −0
  • demo/demo.urp +58 −0
  • demo/demo.urs +1 −0
  • demo/form.ur +18 −0
  • demo/form.urp +1 −0
  • demo/form.urs +1 −0
  • demo/hello.ur +9 −0
  • demo/hello.urp +1 −0
  • demo/hello.urs +1 −0
  • demo/increment.ur +10 −0
  • demo/increment.urp +3 −0
  • demo/increment.urs +1 −0
  • demo/link.ur +7 −0
  • demo/link.urp +1 −0
  • demo/link.urs +1 −0
  • demo/list.ur +21 −0
  • demo/list.urs +5 −0
  • demo/listEdit.ur +54 −0
  • demo/listEdit.urp +1 −0
  • demo/listEdit.urs +1 −0
  • demo/listFun.ur +33 −0
  • demo/listFun.urs +7 −0
  • demo/listShop.ur +20 −0
  • demo/listShop.urp +3 −0
  • demo/listShop.urs +1 −0
  • demo/metaform.ur +28 −0
  • demo/metaform.urs +7 −0
  • demo/metaform1.ur +3 −0
  • demo/metaform1.urp +2 −0
  • demo/metaform1.urs +1 −0
  • demo/metaform2.ur +12 −0
  • demo/metaform2.urp +2 −0
  • demo/metaform2.urs +1 −0
  • demo/more/dbgrid.ur +430 −0
  • demo/more/dbgrid.urs +132 −0
  • demo/more/dlist.ur +303 −0
  • demo/more/dlist.urs +22 −0
  • demo/more/dragList.ur +39 −0
  • demo/more/dragList.urp +5 −0
  • demo/more/dragList.urs +1 −0
  • demo/more/grid.ur +330 −0
  • demo/more/grid.urp +8 −0
  • demo/more/grid.urs +57 −0
  • demo/more/grid0.ur +34 −0
  • demo/more/grid0.urp +7 −0
  • demo/more/grid1.ur +78 −0
  • demo/more/grid1.urp +7 −0
  • demo/more/grid1.urs +1 −0
  • demo/more/orm.ur +95 −0
  • demo/more/orm.urp +3 −0
  • demo/more/orm.urs +49 −0
  • demo/more/orm1.ur +46 −0
  • demo/more/orm1.urp +6 −0
  • demo/more/orm1.urs +1 −0
  • demo/more/out/dragList.css +18 −0
  • demo/more/out/grid.css +19 −0
  • demo/more/prose +15 −0
  • demo/more/versioned.ur +134 −0
  • demo/more/versioned.urp +4 −0
  • demo/more/versioned.urs +24 −0
  • demo/more/versioned1.ur +80 −0
  • demo/more/versioned1.urp +5 −0
  • demo/more/versioned1.urs +1 −0
  • demo/nested.ur +62 −0
  • demo/nested.urp +1 −0
  • demo/nested.urs +1 −0
  • demo/noisy.ur +43 −0
  • demo/noisy.urp +4 −0
  • demo/noisy.urs +1 −0
  • demo/out/alert.desc.html +15 −0
  • demo/out/alert.html +4 −0
  • demo/out/alert.ur.html +50 −0
  • demo/out/alert.urp.html +6 −0
  • demo/out/alert.urs.html +39 −0
  • demo/out/batch.desc.html +13 −0
  • demo/out/batch.html +4 −0
  • demo/out/batch.ur.html +145 −0
  • demo/out/batch.urp.html +8 −0
  • demo/out/batch.urs.html +39 −0
  • demo/out/batchFun.ur.html +228 −0
  • demo/out/batchFun.urp.html +6 −0
  • demo/out/batchFun.urs.html +77 −0
  • demo/out/batchG.desc.html +26 −0
  • demo/out/batchG.html +4 −0
  • demo/out/batchG.ur.html +59 −0
  • demo/out/batchG.urp.html +10 −0
  • demo/out/batchG.urs.html +39 −0
  • demo/out/broadcast.ur.html +88 −0
  • demo/out/broadcast.urs.html +61 −0
  • demo/out/buffer.ur.html +80 −0
  • demo/out/buffer.urs.html +47 −0
  • demo/out/chat.desc.html +16 −0
  • demo/out/chat.html +4 −0
  • demo/out/chat.ur.html +159 −0
  • demo/out/chat.urp.html +11 −0
  • demo/out/chat.urs.html +39 −0
  • demo/out/constraints.desc.html +20 −0
  • demo/out/constraints.html +4 −0
  • demo/out/constraints.ur.html +97 −0
  • demo/out/constraints.urp.html +9 −0
  • demo/out/constraints.urs.html +39 −0
  • demo/out/cookie.desc.html +15 −0
  • demo/out/cookie.html +4 −0
  • demo/out/cookie.ur.html +99 −0
  • demo/out/cookie.urp.html +6 −0
  • demo/out/cookie.urs.html +39 −0
  • demo/out/cookieSec.desc.html +15 −0
  • demo/out/cookieSec.html +4 −0
  • demo/out/cookieSec.ur.html +98 −0
  • demo/out/cookieSec.urp.html +9 −0
  • demo/out/cookieSec.urs.html +39 −0
  • demo/out/counter.desc.html +15 −0
  • demo/out/counter.html +4 −0
  • demo/out/counter.ur.html +54 −0
  • demo/out/counter.urp.html +6 −0
  • demo/out/counter.urs.html +39 −0
  • demo/out/crud.ur.html +250 −0
  • demo/out/crud.urp.html +7 −0
  • demo/out/crud.urs.html +77 −0
  • demo/out/crud1.desc.html +40 −0
  • demo/out/crud1.html +4 −0
  • demo/out/crud1.ur.html +63 −0
  • demo/out/crud1.urp.html +10 −0
  • demo/out/crud2.desc.html +13 −0
  • demo/out/crud2.html +4 −0
  • demo/out/crud2.ur.html +89 −0
  • demo/out/crud2.urp.html +10 −0
  • demo/out/crud3.desc.html +15 −0
  • demo/out/crud3.html +4 −0
  • demo/out/crud3.ur.html +81 −0
  • demo/out/crud3.urp.html +10 −0
  • demo/out/css.desc.html +13 −0
  • demo/out/css.html +4 −0
  • demo/out/css.ur.html +58 −0
  • demo/out/css.urp.html +9 −0
  • demo/out/css.urs.html +39 −0
  • demo/out/demos.html +42 −0
  • demo/out/form.desc.html +13 −0
  • demo/out/form.html +4 −0
  • demo/out/form.ur.html +69 −0
  • demo/out/form.urp.html +6 −0
  • demo/out/form.urs.html +39 −0
  • demo/out/hello.desc.html +19 −0
  • demo/out/hello.html +4 −0
  • demo/out/hello.ur.html +56 −0
  • demo/out/hello.urp.html +6 −0
  • demo/out/hello.urs.html +39 −0
  • demo/out/increment.desc.html +13 −0
  • demo/out/increment.html +4 −0
  • demo/out/increment.ur.html +57 −0
  • demo/out/increment.urp.html +8 −0
  • demo/out/increment.urs.html +39 −0
  • demo/out/index.html +4 −0
  • demo/out/intro.html +42 −0
  • demo/out/link.desc.html +13 −0
  • demo/out/link.html +4 −0
  • demo/out/link.ur.html +54 −0
  • demo/out/link.urp.html +6 −0
  • demo/out/link.urs.html +39 −0
  • demo/out/list.ur.html +68 −0
  • demo/out/list.urs.html +51 −0
  • demo/out/listEdit.desc.html +17 −0
  • demo/out/listEdit.html +4 −0
  • demo/out/listEdit.ur.html +113 −0
  • demo/out/listEdit.urp.html +6 −0
  • demo/out/listEdit.urs.html +39 −0
  • demo/out/listFun.ur.html +96 −0
  • demo/out/listFun.urs.html +57 −0
  • demo/out/listShop.desc.html +19 −0
  • demo/out/listShop.html +4 −0
  • demo/out/listShop.ur.html +83 −0
  • demo/out/listShop.urp.html +8 −0
  • demo/out/listShop.urs.html +39 −0
  • demo/out/metaform.ur.html +92 −0
  • demo/out/metaform.urs.html +57 −0
  • demo/out/metaform1.desc.html +16 −0
  • demo/out/metaform1.html +4 −0
  • demo/out/metaform1.ur.html +49 −0
  • demo/out/metaform1.urp.html +7 −0
  • demo/out/metaform1.urs.html +39 −0
  • demo/out/metaform2.desc.html +13 −0
  • demo/out/metaform2.html +4 −0
  • demo/out/metaform2.ur.html +71 −0
  • demo/out/metaform2.urp.html +7 −0
  • demo/out/metaform2.urs.html +39 −0
  • demo/out/nested.desc.html +13 −0
  • demo/out/nested.html +4 −0
  • demo/out/nested.ur.html +117 −0
  • demo/out/nested.urp.html +6 −0
  • demo/out/nested.urs.html +39 −0
  • demo/out/noisy.desc.html +13 −0
  • demo/out/noisy.html +4 −0
  • demo/out/noisy.ur.html +106 −0
  • demo/out/noisy.urp.html +9 −0
  • demo/out/noisy.urs.html +39 −0
  • demo/out/outer.desc.html +13 −0
  • demo/out/outer.html +4 −0
  • demo/out/outer.ur.html +94 −0
  • demo/out/outer.urp.html +9 −0
  • demo/out/outer.urs.html +39 −0
  • demo/out/react.desc.html +15 −0
  • demo/out/react.html +4 −0
  • demo/out/react.ur.html +53 −0
  • demo/out/react.urp.html +6 −0
  • demo/out/react.urs.html +39 −0
  • demo/out/rec.desc.html +13 −0
  • demo/out/rec.html +4 −0
  • demo/out/rec.ur.html +54 −0
  • demo/out/rec.urp.html +6 −0
  • demo/out/rec.urs.html +39 −0
  • demo/out/ref.desc.html +17 −0
  • demo/out/ref.html +4 −0
  • demo/out/ref.ur.html +89 −0
  • demo/out/ref.urp.html +10 −0
  • demo/out/ref.urs.html +39 −0
  • demo/out/refFun.ur.html +96 −0
  • demo/out/refFun.urs.html +60 −0
  • demo/out/roundTrip.desc.html +19 −0
  • demo/out/roundTrip.html +4 −0
  • demo/out/roundTrip.ur.html +93 −0
  • demo/out/roundTrip.urp.html +10 −0
  • demo/out/roundTrip.urs.html +39 −0
  • demo/out/sql.desc.html +21 −0
  • demo/out/sql.html +4 −0
  • demo/out/sql.ur.html +112 −0
  • demo/out/sql.urp.html +9 −0
  • demo/out/sql.urs.html +39 −0
  • demo/out/subforms.desc.html +13 −0
  • demo/out/subforms.html +4 −0
  • demo/out/subforms.ur.html +94 −0
  • demo/out/subforms.urp.html +6 −0
  • demo/out/subforms.urs.html +39 −0
  • demo/out/sum.desc.html +37 −0
  • demo/out/sum.html +4 −0
  • demo/out/sum.ur.html +61 −0
  • demo/out/sum.urp.html +6 −0
  • demo/out/sum.urs.html +39 −0
  • demo/out/tcSum.desc.html +13 −0
  • demo/out/tcSum.html +4 −0
  • demo/out/tcSum.ur.html +60 −0
  • demo/out/tcSum.urp.html +6 −0
  • demo/out/tcSum.urs.html +39 −0
  • demo/out/threads.desc.html +21 −0
  • demo/out/threads.html +4 −0
  • demo/out/threads.ur.html +68 −0
  • demo/out/threads.urp.html +7 −0
  • demo/out/threads.urs.html +39 −0
  • demo/out/tree.desc.html +23 −0
  • demo/out/tree.html +4 −0
  • demo/out/tree.ur.html +100 −0
  • demo/out/tree.urp.html +10 −0
  • demo/out/tree.urs.html +39 −0
  • demo/out/treeFun.ur.html +101 −0
  • demo/out/treeFun.urs.html +71 −0
  • demo/out/upload.desc.html +15 −0
  • demo/out/upload.html +4 −0
  • demo/out/upload.ur.html +62 −0
  • demo/out/upload.urp.html +10 −0
  • demo/out/upload.urs.html +39 −0
  • demo/out/url.desc.html +15 −0
  • demo/out/url.html +4 −0
  • demo/out/url.ur.html +64 −0
  • demo/out/url.urp.html +9 −0
  • demo/out/url.urs.html +39 −0
  • demo/out/view.desc.html +13 −0
  • demo/out/view.html +4 −0
  • demo/out/view.ur.html +84 −0
  • demo/out/view.urp.html +9 −0
  • demo/out/view.urs.html +39 −0
  • demo/outer.ur +35 −0
  • demo/outer.urp +4 −0
  • demo/outer.urs +1 −0
  • demo/prose +325 −0
  • demo/react.ur +6 −0
  • demo/react.urp +1 −0
  • demo/react.urs +1 −0
  • demo/rec.ur +7 −0
  • demo/rec.urp +1 −0
  • demo/rec.urs +1 −0
  • demo/ref.ur +30 −0
  • demo/ref.urp +5 −0
  • demo/ref.urs +1 −0
  • demo/refFun.ur +29 −0
  • demo/refFun.urs +10 −0
  • demo/roundTrip.ur +34 −0
  • demo/roundTrip.urp +5 −0
  • demo/roundTrip.urs +1 −0
  • demo/sql.ur +53 −0
  • demo/sql.urp +4 −0
  • demo/sql.urs +1 −0
  • demo/subforms.ur +43 −0
  • demo/subforms.urp +1 −0
  • demo/subforms.urs +1 −0
  • demo/sum.ur +10 −0
  • demo/sum.urp +1 −0
  • demo/sum.urs +1 −0
  • demo/tcSum.ur +9 −0
  • demo/tcSum.urp +1 −0
  • demo/tcSum.urs +1 −0
  • demo/threads.ur +17 −0
  • demo/threads.urp +2 −0
  • demo/threads.urs +1 −0
  • demo/tree.ur +37 −0
  • demo/tree.urp +5 −0
  • demo/tree.urs +1 −0
  • demo/treeFun.ur +34 −0
  • demo/treeFun.urs +21 −0
  • demo/upload.ur +11 −0
  • demo/upload.urp +5 −0
  • demo/upload.urs +1 −0
  • demo/url.ur +13 −0
  • demo/url.urp +4 −0
  • demo/url.urs +1 −0
  • demo/view.ur +25 −0
  • demo/view.urp +4 −0
  • demo/view.urs +1 −0
diff --git a/demo/alert.ur b/demo/alert.ur
new file mode 100644
index 0000000..dcd8c20
--- /dev/null
+++ b/demo/alert.ur
@@ -0,0 +1,3 @@
+fun main () = return <xml><body>
+  <button value="Click me!" onclick={fn _ => alert "You clicked me!"}/>
+</body></xml>
diff --git a/demo/alert.urp b/demo/alert.urp
new file mode 100644
index 0000000..34016b9
--- /dev/null
+++ b/demo/alert.urp
@@ -0,0 +1 @@
+alert
diff --git a/demo/alert.urs b/demo/alert.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/alert.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/batch.ur b/demo/batch.ur
new file mode 100644
index 0000000..74a5346
--- /dev/null
+++ b/demo/batch.ur
@@ -0,0 +1,82 @@
+datatype list t = Nil | Cons of t * list t
+
+table t : {Id : int, A : string}
+  PRIMARY KEY Id
+
+fun allRows () =
+    query (SELECT * FROM t)
+    (fn r acc => return (Cons ((r.T.Id, r.T.A), acc)))
+    Nil
+
+fun doBatch ls =
+    case ls of
+        Nil => return ()
+      | Cons ((id, a), ls') =>
+        dml (INSERT INTO t (Id, A) VALUES ({[id]}, {[a]}));
+        doBatch ls'
+
+fun del id =
+    dml (DELETE FROM t WHERE t.Id = {[id]})
+
+fun show withDel lss =
+    let
+        fun show' ls =
+            case ls of
+                Nil => <xml/>
+              | Cons ((id, a), ls) => <xml>
+                <tr><td>{[id]}</td> <td>{[a]}</td> {if withDel then
+                                                        <xml><td><button value="Delete" onclick={fn _ => rpc (del id)}/>
+                                                        </td></xml>
+                                                    else
+                                                        <xml/>} </tr>
+                {show' ls}
+              </xml>
+    in
+        <xml><dyn signal={ls <- signal lss; return <xml><table>
+          <tr> <th>Id</th> <th>A</th> </tr>
+          {show' ls}
+        </table></xml>}/></xml>
+    end
+
+fun main () =
+    lss <- source Nil;
+    batched <- source Nil;
+
+    id <- source "";
+    a <- source "";
+
+    let
+        fun add () =
+            id <- get id;
+            a <- get a;
+            ls <- get batched;
+
+            set batched (Cons ((readError id, a), ls))
+
+        fun exec () =
+            ls <- get batched;
+
+            rpc (doBatch ls);
+            set batched Nil
+    in
+        return <xml><body>
+          <h2>Rows</h2>
+
+          {show True lss}
+
+          <button value="Update" onclick={fn _ => ls <- rpc (allRows ()); set lss ls}/><br/>
+          <br/>
+
+          <h2>Batch new rows to add</h2>
+
+          <table>
+            <tr> <th>Id:</th> <td><ctextbox source={id}/></td> </tr>
+            <tr> <th>A:</th> <td><ctextbox source={a}/></td> </tr>
+            <tr> <th/> <td><button value="Batch it" onclick={fn _ => add ()}/></td> </tr>
+          </table>
+
+          <h2>Already batched:</h2>
+          {show False batched}
+          <button value="Execute" onclick={fn _ => exec ()}/>
+        </body></xml>
+    end
diff --git a/demo/batch.urp b/demo/batch.urp
new file mode 100644
index 0000000..00a7b25
--- /dev/null
+++ b/demo/batch.urp
@@ -0,0 +1,3 @@
+database dbname=test
+
+batch
diff --git a/demo/batch.urs b/demo/batch.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/batch.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/batchFun.ur b/demo/batchFun.ur
new file mode 100644
index 0000000..2147868
--- /dev/null
+++ b/demo/batchFun.ur
@@ -0,0 +1,155 @@
+con colMeta = fn (db :: Type, state :: Type) =>
+                 {Nam : string,
+                  Show : db -> xbody,
+                  Inject : sql_injectable db,
+
+                  NewState : transaction state,
+                  Widget : state -> xbody,
+                  ReadState : state -> transaction db}
+con colsMeta = fn cols => $(map colMeta cols)
+
+fun default [t] (sh : show t) (rd : read t) (inj : sql_injectable t)
+            name : colMeta (t, source string) =
+    {Nam = name,
+     Show = txt,
+     Inject = _,
+
+     NewState = source "",
+     Widget = fn s => <xml><ctextbox source={s}/></xml>,
+     ReadState = fn s => v <- get s; return (readError v)}
+
+val int = default
+val float = default
+val string = default
+
+functor Make(M : sig
+                 con cols :: {(Type * Type)}
+                 constraint [Id] ~ cols
+                 val fl : folder cols
+                          
+                 table tab : ([Id = int] ++ map fst cols)
+                           
+                 val title : string
+                             
+                 val cols : colsMeta cols
+             end) = struct
+
+    val t = M.tab
+
+    datatype list t = Nil | Cons of t * list t
+
+    fun allRows () =
+        query (SELECT * FROM t)
+              (fn r acc => return (Cons (r.T, acc)))
+              Nil
+
+    fun add r =
+        dml (insert t
+                    (@foldR2 [fst] [colMeta]
+                      [fn cols => $(map (fn t => sql_exp [] [] [] t.1) cols)]
+                      (fn [nm :: Name] [t ::_] [rest ::_] [[nm] ~ rest] input col acc =>
+                          acc ++ {nm = @sql_inject col.Inject input})
+                      {} M.fl (r -- #Id) M.cols
+                      ++ {Id = (SQL {[r.Id]})}))
+
+    fun doBatch ls =
+        case ls of
+            Nil => return ()
+          | Cons (r, ls') =>
+            add r;
+            doBatch ls'
+
+    fun del id =
+        dml (DELETE FROM t WHERE t.Id = {[id]})
+
+    fun show withDel lss =
+        let
+            fun show' ls =
+                case ls of
+                    Nil => <xml/>
+                  | Cons (r, ls) => <xml>
+                    <tr>
+                      <td>{[r.Id]}</td>
+                      {@mapX2 [colMeta] [fst] [_]
+                        (fn [nm :: Name] [p ::_] [rest ::_] [[nm] ~ rest] m v =>
+                            <xml><td>{m.Show v}</td></xml>)
+                        M.fl M.cols (r -- #Id)}
+                      {if withDel then
+                           <xml><td><button value="Delete" onclick={fn _ => rpc (del r.Id)}/></td></xml>
+                       else
+                           <xml/>}
+                    </tr>
+                    {show' ls}
+                  </xml>
+        in
+            <xml><dyn signal={ls <- signal lss; return <xml><table>
+              <tr>
+                <th>Id</th>
+                {@mapX [colMeta] [tr]
+                  (fn [nm :: Name] [p ::_] [rest ::_] [[nm] ~ rest] m =>
+                      <xml><th>{[m.Nam]}</th></xml>)
+                  M.fl M.cols}
+              </tr>
+              {show' ls}
+            </table></xml>}/></xml>
+        end
+
+    fun main () =
+        lss <- source Nil;
+        batched <- source Nil;
+
+        id <- source "";
+        inps <- @foldR [colMeta] [fn r => transaction ($(map snd r))]
+                 (fn [nm :: Name] [p ::_] [rest ::_] [[nm] ~ rest] m acc =>
+                     s <- m.NewState;
+                     r <- acc;
+                     return ({nm = s} ++ r))
+                 (return {})
+                 M.fl M.cols;
+        
+        let
+            fun add () =
+                id <- get id;
+                vs <- @foldR2 [colMeta] [snd] [fn r => transaction ($(map fst r))]
+                       (fn [nm :: Name] [p ::_] [rest ::_] [[nm] ~ rest] m s acc =>
+                           v <- m.ReadState s;
+                           r <- acc;
+                           return ({nm = v} ++ r))
+                       (return {})
+                       M.fl M.cols inps;
+                ls <- get batched;
+
+                set batched (Cons ({Id = readError id} ++ vs, ls))
+
+            fun exec () =
+                ls <- get batched;
+
+                rpc (doBatch ls);
+                set batched Nil
+        in
+            return <xml><body>
+              <h2>Rows</h2>
+
+              {show True lss}
+
+              <button value="Update" onclick={fn _ => ls <- rpc (allRows ()); set lss ls}/><br/>
+              <br/>
+
+              <h2>Batch new rows to add</h2>
+
+              <table>
+                <tr> <th>Id:</th> <td><ctextbox source={id}/></td> </tr>
+                {@mapX2 [colMeta] [snd] [_]
+                  (fn [nm :: Name] [p ::_] [rest ::_] [[nm] ~ rest] m s =>
+                      <xml><tr> <th>{[m.Nam]}:</th> <td>{m.Widget s}</td> </tr></xml>)
+                  M.fl M.cols inps}
+                <tr> <th/> <td><button value="Batch it" onclick={fn _ => add ()}/></td> </tr>
+              </table>
+
+              <h2>Already batched:</h2>
+              {show False batched}
+              <button value="Execute" onclick={fn _ => exec ()}/>
+            </body></xml>
+        end
+
+end
diff --git a/demo/batchFun.urp b/demo/batchFun.urp
new file mode 100644
index 0000000..a646565
--- /dev/null
+++ b/demo/batchFun.urp
@@ -0,0 +1 @@
+batchFun
diff --git a/demo/batchFun.urs b/demo/batchFun.urs
new file mode 100644
index 0000000..56e1e88
--- /dev/null
+++ b/demo/batchFun.urs
@@ -0,0 +1,27 @@
+con colMeta = fn (db :: Type, state :: Type) =>
+                 {Nam : string,
+                  Show : db -> xbody,
+                  Inject : sql_injectable db,
+
+                  NewState : transaction state,
+                  Widget : state -> xbody,
+                  ReadState : state -> transaction db}
+con colsMeta = fn cols :: {(Type * Type)} => $(map colMeta cols)
+
+val int : string -> colMeta (int, source string)
+val float : string -> colMeta (float, source string)
+val string : string -> colMeta (string, source string)
+
+functor Make(M : sig
+                 con cols :: {(Type * Type)}
+                 constraint [Id] ~ cols
+                 val fl : folder cols
+
+                 table tab : ([Id = int] ++ map fst cols)
+
+                 val title : string
+
+                 val cols : colsMeta cols
+             end) : sig
+    val main : unit -> transaction page
+end
diff --git a/demo/batchG.ur b/demo/batchG.ur
new file mode 100644
index 0000000..d0071d7
--- /dev/null
+++ b/demo/batchG.ur
@@ -0,0 +1,9 @@
+table t : {Id : int, A : string, B : float}
+  PRIMARY KEY Id
+
+open BatchFun.Make(struct
+                       val tab = t
+                       val title = "BatchG"
+                       val cols = {A = BatchFun.string "A",
+                                   B = BatchFun.float "B"}
+                   end)
diff --git a/demo/batchG.urp b/demo/batchG.urp
new file mode 100644
index 0000000..ba4ce18
--- /dev/null
+++ b/demo/batchG.urp
@@ -0,0 +1,5 @@
+database dbname=test
+sql batchG.sql
+
+batchFun
+batchG
diff --git a/demo/batchG.urs b/demo/batchG.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/batchG.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/broadcast.ur b/demo/broadcast.ur
new file mode 100644
index 0000000..0b04b13
--- /dev/null
+++ b/demo/broadcast.ur
@@ -0,0 +1,29 @@
+functor Make(M : sig type t end) = struct
+    sequence s
+    table t : {Id : int, Client : client, Channel : channel M.t}
+      PRIMARY KEY (Id, Client)
+
+    type topic = int
+
+    val inj : sql_injectable topic = _
+
+    val create = nextval s
+
+    fun subscribe id =
+        cli <- self;
+        ro <- oneOrNoRows (SELECT t.Channel FROM t WHERE t.Id = {[id]} AND t.Client = {[cli]});
+        case ro of
+            None =>
+            ch <- channel;
+            dml (INSERT INTO t (Id, Client, Channel) VALUES ({[id]}, {[cli]}, {[ch]}));
+            return ch
+          | Some r => return r.T.Channel
+
+    fun send id msg =
+        queryI (SELECT t.Channel FROM t WHERE t.Id = {[id]})
+        (fn r => Basis.send r.T.Channel msg)
+
+    fun subscribers id =
+        r <- oneRow (SELECT COUNT( * ) AS N FROM t WHERE t.Id = {[id]});
+        return r.N
+end
diff --git a/demo/broadcast.urs b/demo/broadcast.urs
new file mode 100644
index 0000000..9a4d0bb
--- /dev/null
+++ b/demo/broadcast.urs
@@ -0,0 +1,11 @@
+functor Make(M : sig type t end) : sig
+    type topic
+
+    val inj : sql_injectable topic
+
+    val create : transaction topic
+    val subscribe : topic -> transaction (channel M.t)
+    val send : topic -> M.t -> transaction unit
+
+    val subscribers : topic -> transaction int
+end
diff --git a/demo/buffer.ur b/demo/buffer.ur
new file mode 100644
index 0000000..27e2b80
--- /dev/null
+++ b/demo/buffer.ur
@@ -0,0 +1,25 @@
+datatype lines = End | Line of string * source lines
+
+type t = { Head : source lines, Tail : source (source lines) }
+
+val create =
+    head <- source End;
+    tail <- source head;
+    return {Head = head, Tail = tail}
+
+fun renderL lines =
+    case lines of
+        End => <xml/>
+      | Line (line, linesS) => <xml>{[line]}<br/><dyn signal={renderS linesS}/></xml>
+
+and renderS linesS =
+    lines <- signal linesS;
+    return (renderL lines)
+
+fun render t = renderS t.Head
+
+fun write t s =
+    oldTail <- get t.Tail;
+    newTail <- source End;
+    set oldTail (Line (s, newTail));
+    set t.Tail newTail
diff --git a/demo/buffer.urs b/demo/buffer.urs
new file mode 100644
index 0000000..58312bb
--- /dev/null
+++ b/demo/buffer.urs
@@ -0,0 +1,5 @@
+type t
+
+val create : transaction t
+val render : t -> signal xbody
+val write : t -> string -> transaction unit
diff --git a/demo/chat.ur b/demo/chat.ur
new file mode 100644
index 0000000..720130b
--- /dev/null
+++ b/demo/chat.ur
@@ -0,0 +1,92 @@
+structure Room = Broadcast.Make(struct
+                                    type t = string
+                                end)
+
+sequence s
+table t : { Id : int, Title : string, Room : Room.topic }
+  PRIMARY KEY Id
+
+fun chat id () =
+    r <- oneRow (SELECT t.Title, t.Room FROM t WHERE t.Id = {[id]});
+    ch <- Room.subscribe r.T.Room;
+
+    newLine <- source "";
+    buf <- Buffer.create;
+
+    let
+        fun onload () =
+            let
+                fun listener () =
+                    s <- recv ch;
+                    Buffer.write buf s;
+                    listener ()
+            in
+                listener ()
+            end
+
+        fun getRoom () =
+            r <- oneRow (SELECT t.Room FROM t WHERE t.Id = {[id]});
+            return r.T.Room
+
+        fun speak line =
+            room <- getRoom ();
+            Room.send room line
+
+        fun doSpeak () =
+            line <- get newLine;
+            set newLine "";
+            rpc (speak line)
+    in
+        return <xml><body onload={onload ()}>
+          <h1>{[r.T.Title]}</h1>
+
+          <button value="Send:" onclick={fn _ => doSpeak ()}/> <ctextbox source={newLine}/>
+
+          <h2>Messages</h2>
+
+          <dyn signal={Buffer.render buf}/>
+          
+        </body></xml>            
+    end
+
+fun list () =
+    queryX' (SELECT * FROM t)
+    (fn r =>
+        count <- Room.subscribers r.T.Room;
+        return <xml><tr>
+          <td>{[r.T.Id]}</td>
+          <td>{[r.T.Title]}</td>
+          <td>{[count]}</td>
+          <td><form><submit action={chat r.T.Id} value="Enter"/></form></td>
+          <td><form><submit action={delete r.T.Id} value="Delete"/></form></td>
+        </tr></xml>)
+
+and delete id () =
+    dml (DELETE FROM t WHERE Id = {[id]});
+    main ()
+
+and main () =
+    let
+        fun create r =
+            id <- nextval s;
+            room <- Room.create;
+            dml (INSERT INTO t (Id, Title, Room) VALUES ({[id]}, {[r.Title]}, {[room]}));
+            main ()
+    in
+        ls <- list ();
+        return <xml><body>
+          <h1>Current Channels</h1>
+
+          <table>
+            <tr> <th>ID</th> <th>Title</th> <th>#Subscribers</th> </tr>
+            {ls}
+          </table>
+          
+          <h1>New Channel</h1>
+          
+          <form>
+            Title: <textbox{#Title}/><br/>
+            <submit action={create}/>
+          </form>
+        </body></xml>
+    end
diff --git a/demo/chat.urp b/demo/chat.urp
new file mode 100644
index 0000000..29da66b
--- /dev/null
+++ b/demo/chat.urp
@@ -0,0 +1,6 @@
+database dbname=test
+sql chat.sql
+
+broadcast
+buffer
+chat
diff --git a/demo/chat.urs b/demo/chat.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/chat.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/constraints.ur b/demo/constraints.ur
new file mode 100644
index 0000000..bcd88bb
--- /dev/null
+++ b/demo/constraints.ur
@@ -0,0 +1,38 @@
+table t : { Id : int, Nam : string, Parent : option int }
+  PRIMARY KEY Id,
+  CONSTRAINT Nam UNIQUE Nam,
+  CONSTRAINT Id CHECK Id >= 0,
+  CONSTRAINT Parent FOREIGN KEY Parent REFERENCES t(Id)
+
+fun main () =
+    list <- queryX (SELECT * FROM t)
+            (fn r => <xml><tr>
+              <td>{[r.T.Id]}</td>
+              <td>{[r.T.Nam]}</td>
+              <td>{case r.T.Parent of
+                       None => <xml>NULL</xml>
+                     | Some id => <xml>{[id]}</xml>}</td>
+            </tr></xml>);
+    return <xml><body>
+      <table>
+        <tr> <th>Id</th> <th>Name</th> <th>Parent</th> </tr>
+        {list}
+      </table>
+
+      <form>
+        <table>
+          <tr> <th>Id:</th> <td><textbox{#Id}/></td> </tr>
+          <tr> <th>Name:</th> <td><textbox{#Nam}/></td> </tr>
+          <tr> <th>Parent:</th> <td><textbox{#Parent}/></td> </tr>
+          <tr> <th/> <td><submit action={add}/></td> </tr>
+        </table>
+      </form>
+    </body></xml>
+
+and add r =
+    dml (INSERT INTO t (Id, Nam, Parent)
+           VALUES ({[readError r.Id]}, {[r.Nam]},
+               {[case r.Parent of
+                   "" => None
+                 | s => Some (readError s)]}));
+    main ()
diff --git a/demo/constraints.urp b/demo/constraints.urp
new file mode 100644
index 0000000..d5b991b
--- /dev/null
+++ b/demo/constraints.urp
@@ -0,0 +1,4 @@
+database dbname=test
+sql constraints.sql
+
+constraints
diff --git a/demo/constraints.urs b/demo/constraints.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/constraints.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/cookie.ur b/demo/cookie.ur
new file mode 100644
index 0000000..7e01115
--- /dev/null
+++ b/demo/cookie.ur
@@ -0,0 +1,44 @@
+cookie c : {A : string, B : float, C : int}
+
+fun set r =
+    setCookie c {Value = {A = r.A, B = readError r.B, C = readError r.C},
+                 Expires = None,
+                 Secure = False};
+    return <xml>Cookie set.</xml>
+
+fun setExp r =
+    setCookie c {Value = {A = r.A, B = readError r.B, C = readError r.C},
+                 Expires = Some (readError "2012-11-6 00:00:00"),
+                 Secure = False};
+    return <xml>Cookie set robustly.</xml>
+
+fun delete () =
+    clearCookie c;
+    return <xml>Cookie cleared.</xml>
+
+fun main () =
+    ro <- getCookie c;
+    return <xml><body>
+      {case ro of
+           None => <xml>No cookie set.</xml>
+         | Some v => <xml>
+           Cookie: A = {[v.A]}, B = {[v.B]}, C = {[v.C]}<br/>
+           <form><submit value="Delete" action={delete}/></form>
+         </xml>}
+      <br/><br/>
+
+      <form>
+        A: <textbox{#A}/><br/>
+        B: <textbox{#B}/><br/>
+        C: <textbox{#C}/><br/>
+        <submit action={set}/>
+      </form><br/>
+
+      <form>
+        <b>Version that expires on November 6, 2012:</b><br/>
+        A: <textbox{#A}/><br/>
+        B: <textbox{#B}/><br/>
+        C: <textbox{#C}/><br/>
+        <submit action={setExp}/>
+      </form>
+    </body></xml>
diff --git a/demo/cookie.urp b/demo/cookie.urp
new file mode 100644
index 0000000..871bb87
--- /dev/null
+++ b/demo/cookie.urp
@@ -0,0 +1 @@
+cookie
diff --git a/demo/cookie.urs b/demo/cookie.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/cookie.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/cookieSec.ur b/demo/cookieSec.ur
new file mode 100644
index 0000000..98615c7
--- /dev/null
+++ b/demo/cookieSec.ur
@@ -0,0 +1,39 @@
+cookie username : string
+
+table lastVisit : { User : string, When : time }
+  PRIMARY KEY User
+
+fun main () =
+    userO <- getCookie username;
+
+    list <- queryX (SELECT * FROM lastVisit)
+                   (fn r => <xml><tr><td>{[r.LastVisit.User]}</td> <td>{[r.LastVisit.When]}</td></tr></xml>);
+
+    return <xml><body>
+      Cookie: {[userO]}<br/>
+
+      <table>
+        <tr><th>User</th> <th>Last Visit</th></tr>
+        {list}
+      </table>
+
+      <h2>Set cookie value</h2>
+      <form><textbox{#User}/> <submit action={set}/></form>
+
+      <h2>Record your visit</h2>
+      <form><submit action={imHere}/></form>
+    </body></xml>
+
+and set r =
+    setCookie username {Value = r.User, Expires = None, Secure = False};
+    main ()
+
+and imHere () =
+    userO <- getCookie username;
+    case userO of
+        None => return <xml>You don't have a cookie set!</xml>
+      | Some user =>
+        dml (DELETE FROM lastVisit WHERE User = {[user]});
+        dml (INSERT INTO lastVisit (User, When) VALUES ({[user]}, CURRENT_TIMESTAMP));
+        main ()
+
diff --git a/demo/cookieSec.urp b/demo/cookieSec.urp
new file mode 100644
index 0000000..7475551
--- /dev/null
+++ b/demo/cookieSec.urp
@@ -0,0 +1,4 @@
+database dbname=test
+sql cookieSec.sql
+
+cookieSec
diff --git a/demo/cookieSec.urs b/demo/cookieSec.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/cookieSec.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/counter.ur b/demo/counter.ur
new file mode 100644
index 0000000..23768ad
--- /dev/null
+++ b/demo/counter.ur
@@ -0,0 +1,8 @@
+(* Workhorse function, which [main] will call *)
+fun counter n = return <xml><body>
+  Current counter: {[n]}<br/>
+  <a link={counter (n + 1)}>Increment</a><br/>
+  <a link={counter (n - 1)}>Decrement</a>
+</body></xml>
+
+fun main () = counter 0
diff --git a/demo/counter.urp b/demo/counter.urp
new file mode 100644
index 0000000..e64bdbf
--- /dev/null
+++ b/demo/counter.urp
@@ -0,0 +1 @@
+counter
diff --git a/demo/counter.urs b/demo/counter.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/counter.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/crud.ur b/demo/crud.ur
new file mode 100644
index 0000000..4d2753e
--- /dev/null
+++ b/demo/crud.ur
@@ -0,0 +1,173 @@
+con colMeta = fn (db :: Type, widget :: Type) =>
+                 {Nam : string,
+                  Show : db -> xbody,
+                  Widget : nm :: Name -> xml form [] [nm = widget],
+                  WidgetPopulated : nm :: Name -> db -> xml form [] [nm = widget],
+                  Parse : widget -> db,
+                  Inject : sql_injectable db}
+con colsMeta = fn cols => $(map colMeta cols)
+
+fun default [t] (sh : show t) (rd : read t) (inj : sql_injectable t)
+            name : colMeta (t, string) =
+    {Nam = name,
+     Show = txt,
+     Widget = fn [nm :: Name] => <xml><textbox{nm}/></xml>,
+     WidgetPopulated = fn [nm :: Name] n =>
+                          <xml><textbox{nm} value={show n}/></xml>,
+     Parse = readError,
+     Inject = _}
+
+val int = default
+val float = default
+val string = default
+
+fun bool name = {Nam = name,
+                 Show = txt,
+                 Widget = fn [nm :: Name] => <xml><checkbox{nm}/></xml>,
+                 WidgetPopulated = fn [nm :: Name] b =>
+                                      <xml><checkbox{nm} checked={b}/></xml>,
+                 Parse = fn x => x,
+                 Inject = _}
+
+functor Make(M : sig
+                 con cols :: {(Type * Type)}
+                 constraint [Id] ~ cols
+                 val fl : folder cols
+
+                 table tab : ([Id = int] ++ map fst cols)
+
+                 val title : string
+
+                 val cols : colsMeta cols
+             end) = struct
+
+    val tab = M.tab
+
+    sequence seq
+
+    fun list () =
+        rows <- queryX (SELECT * FROM tab AS T)
+                       (fn (fs : {T : $([Id = int] ++ map fst M.cols)}) => <xml>
+                         <tr>
+                           <td>{[fs.T.Id]}</td>
+                           {@mapX2 [fst] [colMeta] [tr]
+                             (fn [nm :: Name] [t ::_] [rest ::_] [[nm] ~ rest] v col => <xml>
+                               <td>{col.Show v}</td>
+                             </xml>)
+                             M.fl (fs.T -- #Id) M.cols}
+                           <td>
+                             <a link={upd fs.T.Id}>[Update]</a>
+                             <a link={confirm fs.T.Id}>[Delete]</a>
+                           </td>
+                         </tr>
+                       </xml>);
+        return <xml>
+          <table border={1}>
+            <tr>
+              <th>ID</th>
+              {@mapX [colMeta] [tr]
+                (fn [nm :: Name] [t ::_] [rest ::_] [[nm] ~ rest] col => <xml>
+                  <th>{cdata col.Nam}</th>
+                </xml>)
+                M.fl M.cols}
+            </tr>
+            {rows}
+          </table>
+
+          <br/><hr/><br/>
+
+          <form>
+            {@foldR [colMeta] [fn cols => xml form [] (map snd cols)]
+              (fn [nm :: Name] [t ::_] [rest ::_] [[nm] ~ rest] (col : colMeta t) acc => <xml>
+                <li> {cdata col.Nam}: {col.Widget [nm]}</li>
+                {useMore acc}
+              </xml>)
+              <xml/>
+              M.fl M.cols}
+            
+            <submit action={create}/>
+          </form>
+        </xml>
+
+    and create (inputs : $(map snd M.cols)) =
+        id <- nextval seq;
+        dml (insert tab
+                    (@foldR2 [snd] [colMeta]
+                      [fn cols => $(map (fn t => sql_exp [] [] [] t.1) cols)]
+                      (fn [nm :: Name] [t ::_] [rest ::_] [[nm] ~ rest] =>
+                       fn input col acc => acc ++ {nm = @sql_inject col.Inject (col.Parse input)})
+                      {} M.fl inputs M.cols
+                     ++ {Id = (SQL {[id]})}));
+        ls <- list ();
+        return <xml><body>
+          <p>Inserted with ID {[id]}.</p>
+
+          {ls}
+        </body></xml>
+
+    and upd (id : int) =
+        let
+            fun save (inputs : $(map snd M.cols)) =
+                dml (update [map fst M.cols]
+                            (@foldR2 [snd] [colMeta]
+                              [fn cols => $(map (fn t => sql_exp [T = [Id = int] ++ map fst M.cols] [] [] t.1) cols)]
+                              (fn [nm :: Name] [t ::_] [rest ::_] [[nm] ~ rest] =>
+                               fn input col acc => acc ++ {nm =
+                                                           @sql_inject col.Inject (col.Parse input)})
+                              {} M.fl inputs M.cols)
+                            tab (WHERE T.Id = {[id]}));
+                ls <- list ();
+                return <xml><body>
+                  <p>Saved!</p>
+
+                  {ls}
+                </body></xml>
+        in
+            fso <- oneOrNoRows (SELECT tab.{{map fst M.cols}} FROM tab WHERE tab.Id = {[id]});
+            case fso : (Basis.option {Tab : $(map fst M.cols)}) of
+                None => return <xml><body>Not found!</body></xml>
+              | Some fs => return <xml><body><form>
+                {@foldR2 [fst] [colMeta] [fn cols => xml form [] (map snd cols)]
+                  (fn [nm :: Name] [t ::_] [rest ::_] [[nm] ~ rest] v (col : colMeta t)
+                                   (acc : xml form [] (map snd rest)) =>
+                      <xml>
+                        <li> {cdata col.Nam}: {col.WidgetPopulated [nm] v}</li>
+                        {useMore acc}
+                      </xml>)
+                  <xml/>
+                  M.fl fs.Tab M.cols}
+
+                <submit action={save}/>
+              </form></body></xml>
+        end
+
+    and confirm (id : int) =
+        let
+            fun delete () =
+                dml (DELETE FROM tab WHERE Id = {[id]});
+                ls <- list ();
+                return <xml><body>
+                  <p>The deed is done.</p>
+                  
+                  {ls}
+                </body></xml>
+        in
+            return <xml><body>
+              <p>Are you sure you want to delete ID #{[id]}?</p>
+              
+              <form><submit action={delete} value="I was born sure!"/></form>
+            </body></xml>
+        end
+
+    and main () =
+        ls <- list ();
+        return <xml><head>
+          <title>{cdata M.title}</title>
+        </head><body>
+
+          <h1>{cdata M.title}</h1>
+
+          {ls}
+        </body></xml>
+
+end
diff --git a/demo/crud.urp b/demo/crud.urp
new file mode 100644
index 0000000..223bc7a
--- /dev/null
+++ b/demo/crud.urp
@@ -0,0 +1,2 @@
+
+crud
diff --git a/demo/crud.urs b/demo/crud.urs
new file mode 100644
index 0000000..3690d31
--- /dev/null
+++ b/demo/crud.urs
@@ -0,0 +1,27 @@
+con colMeta = fn (db :: Type, widget :: Type) =>
+                 {Nam : string,
+                  Show : db -> xbody,
+                  Widget : nm :: Name -> xml form [] [nm = widget],
+                  WidgetPopulated : nm :: Name -> db -> xml form [] [nm = widget],
+                  Parse : widget -> db,
+                  Inject : sql_injectable db}
+con colsMeta = fn cols :: {(Type * Type)} => $(map colMeta cols)
+
+val int : string -> colMeta (int, string)
+val float : string -> colMeta (float, string)
+val string : string -> colMeta (string, string)
+val bool : string -> colMeta (bool, bool)
+
+functor Make(M : sig
+                 con cols :: {(Type * Type)}
+                 constraint [Id] ~ cols
+                 val fl : folder cols
+
+                 table tab : ([Id = int] ++ map fst cols)
+
+                 val title : string
+
+                 val cols : colsMeta cols
+             end) : sig
+    val main : unit -> transaction page
+end
diff --git a/demo/crud1.ur b/demo/crud1.ur
new file mode 100644
index 0000000..796c063
--- /dev/null
+++ b/demo/crud1.ur
@@ -0,0 +1,13 @@
+table t1 : {Id : int, A : int, B : string, C : float, D : bool}
+  PRIMARY KEY Id
+
+open Crud.Make(struct
+                   val tab = t1
+                             
+                   val title = "Crud1"
+                               
+                   val cols = {A = Crud.int "A",
+                               B = Crud.string "B",
+                               C = Crud.float "C",
+                               D = Crud.bool "D"}
+               end)
diff --git a/demo/crud1.urp b/demo/crud1.urp
new file mode 100644
index 0000000..bfc2d14
--- /dev/null
+++ b/demo/crud1.urp
@@ -0,0 +1,5 @@
+database dbname=test
+sql crud1.sql
+
+crud
+crud1
diff --git a/demo/crud2.ur b/demo/crud2.ur
new file mode 100644
index 0000000..a89b37b
--- /dev/null
+++ b/demo/crud2.ur
@@ -0,0 +1,35 @@
+table t : {Id : int, Nam : string, Ready : bool}
+  PRIMARY KEY Id
+
+open Crud.Make(struct
+                   val tab = t
+                             
+                   val title = "Are you ready?"
+
+                   val cols = {Nam = Crud.string "Name",
+                               Ready = {Nam = "Ready",
+                                        Show = (fn b => if b then
+                                                            <xml>Ready!</xml>
+                                                        else
+                                                            <xml>Not ready</xml>),
+                                        Widget = (fn [nm :: Name] => <xml>
+                                          <select{nm}>
+                                            <option>Ready</option>
+                                            <option>Not ready</option>
+                                          </select>
+                                        </xml>),
+                                        WidgetPopulated = (fn [nm :: Name] b => <xml>
+                                          <select{nm}>
+                                            <option selected={b}>Ready</option>
+                                            <option selected={not b}>Not ready</option>
+                                          </select>
+                                        </xml>),
+                                        Parse = (fn s =>
+                                                    case s of
+                                                        "Ready" => True
+                                                      | "Not ready" => False
+                                                      | _ => error <xml>Invalid ready/not ready</xml>),
+                                        Inject = _
+                                       }
+                              }
+               end)
diff --git a/demo/crud2.urp b/demo/crud2.urp
new file mode 100644
index 0000000..d552e1a
--- /dev/null
+++ b/demo/crud2.urp
@@ -0,0 +1,5 @@
+database dbname=test
+sql crud2.sql
+
+crud
+crud2
diff --git a/demo/crud3.ur b/demo/crud3.ur
new file mode 100644
index 0000000..5be035d
--- /dev/null
+++ b/demo/crud3.ur
@@ -0,0 +1,27 @@
+table t : {Id : int, Text : string}
+  PRIMARY KEY Id
+
+open Crud.Make(struct
+                   val tab = t
+                             
+                   val title = "Crud3"
+
+                   val cols = {Text = {Nam = "Text",
+                                       Show = txt,
+                                       Widget = (fn [nm :: Name] => <xml>
+                                         <subform{nm}>
+                                           <textbox{#A}/>
+                                           <textbox{#B}/>
+                                         </subform>
+                                       </xml>),
+                                       WidgetPopulated = (fn [nm :: Name] s => <xml>
+                                         <subform{nm}>
+                                           <textbox{#A} value={s}/>
+                                           <textbox{#B}/>
+                                         </subform>
+                                       </xml>),
+                                       Parse = (fn p : {A : string, B : string} => p.A ^ p.B),
+                                       Inject = _
+                                      }
+                              }
+               end)
diff --git a/demo/crud3.urp b/demo/crud3.urp
new file mode 100644
index 0000000..cc3be2f
--- /dev/null
+++ b/demo/crud3.urp
@@ -0,0 +1,5 @@
+database dbname=test
+sql crud3.sql
+
+crud
+crud3
diff --git a/demo/css.ur b/demo/css.ur
new file mode 100644
index 0000000..0c1d8f7
--- /dev/null
+++ b/demo/css.ur
@@ -0,0 +1,11 @@
+style quote
+
+fun main () = return <xml>
+  <head>
+    <link rel="stylesheet" type="text/css" href="http://adam.chlipala.net/style.css"/>
+  </head>
+
+  <body>
+    <div class={quote}>Here's a quote.</div>
+  </body>
+</xml>
diff --git a/demo/css.urp b/demo/css.urp
new file mode 100644
index 0000000..150808d
--- /dev/null
+++ b/demo/css.urp
@@ -0,0 +1,4 @@
+allow url http://adam.chlipala.net/style.css
+rewrite style Css/quote quote
+
+css
diff --git a/demo/css.urs b/demo/css.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/css.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/demo.sql b/demo/demo.sql
new file mode 100644
index 0000000..2e72378
--- /dev/null
+++ b/demo/demo.sql
@@ -0,0 +1,138 @@
+CREATE TABLE uw_Sql_t(uw_a int8 NOT NULL, uw_b float8 NOT NULL, 
+                       uw_c text NOT NULL, uw_d bool NOT NULL,
+ PRIMARY KEY (uw_a)
+  
+ );
+ 
+ CREATE SEQUENCE uw_Ref_IR_s;
+  
+  CREATE TABLE uw_Ref_IR_t(uw_id int8 NOT NULL, uw_data int8 NOT NULL,
+   PRIMARY KEY (uw_id)
+    
+   );
+   
+   CREATE SEQUENCE uw_Ref_SR_s;
+    
+    CREATE TABLE uw_Ref_SR_t(uw_id int8 NOT NULL, uw_data text NOT NULL,
+     PRIMARY KEY (uw_id)
+      
+     );
+     
+     CREATE SEQUENCE uw_Tree_s;
+      
+      CREATE TABLE uw_Tree_t(uw_id int8 NOT NULL, uw_parent int8, 
+                              uw_nam text NOT NULL,
+       PRIMARY KEY (uw_id),
+        CONSTRAINT uw_Tree_t_F
+         FOREIGN KEY (uw_parent) REFERENCES uw_Tree_t (uw_id) ON DELETE CASCADE
+       );
+       
+       CREATE TABLE uw_Constraints_t(uw_id int8 NOT NULL, uw_nam text NOT NULL, 
+                                      uw_parent int8,
+        PRIMARY KEY (uw_id),
+         CONSTRAINT uw_Constraints_t_Nam UNIQUE (uw_nam),
+                                                         
+          CONSTRAINT uw_Constraints_t_Id CHECK (uw_id >= 0::int8),
+                                                                  
+          CONSTRAINT uw_Constraints_t_Parent
+           FOREIGN KEY (uw_parent) REFERENCES uw_Constraints_t (uw_id)
+        );
+        
+        CREATE TABLE uw_Outer_t(uw_id int8 NOT NULL, uw_b text NOT NULL,
+         PRIMARY KEY (uw_id)
+          
+         );
+         
+         CREATE TABLE uw_Outer_u(uw_id int8 NOT NULL, uw_link int8 NOT NULL, 
+                                  uw_c text NOT NULL, uw_d float8,
+          PRIMARY KEY (uw_id),
+           CONSTRAINT uw_Outer_u_Link
+            FOREIGN KEY (uw_link) REFERENCES uw_Outer_t (uw_id)
+          );
+          
+          CREATE TABLE uw_View_t(uw_a int8 NOT NULL
+           );
+           
+           CREATE VIEW uw_View_v AS
+            SELECT T_T.uw_a AS uw_A FROM uw_View_t AS T_T WHERE (T_T.uw_a > 7::int8);
+            
+            CREATE TABLE uw_CookieSec_lastVisit(uw_user text NOT NULL, 
+                                                 uw_when timestamp NOT NULL,
+             PRIMARY KEY (uw_user)
+              
+             );
+             
+             CREATE TABLE uw_Crud1_t1(uw_id int8 NOT NULL, uw_a int8 NOT NULL, 
+                                       uw_b text NOT NULL, 
+                                       uw_c float8 NOT NULL, uw_d bool NOT NULL,
+              PRIMARY KEY (uw_id)
+               
+              );
+              
+              CREATE SEQUENCE uw_Crud1_seq;
+               
+               CREATE TABLE uw_Crud2_t(uw_id int8 NOT NULL, 
+                                        uw_nam text NOT NULL, 
+                                        uw_ready bool NOT NULL,
+                PRIMARY KEY (uw_id)
+                 
+                );
+                
+                CREATE SEQUENCE uw_Crud2_seq;
+                 
+                 CREATE TABLE uw_Crud3_t(uw_id int8 NOT NULL, 
+                                          uw_text text NOT NULL,
+                  PRIMARY KEY (uw_id)
+                   
+                  );
+                  
+                  CREATE SEQUENCE uw_Crud3_seq;
+                   
+                   CREATE SEQUENCE uw_Increment_seq;
+                    
+                    CREATE TABLE uw_Noisy_t(uw_id int8 NOT NULL, 
+                                             uw_a text NOT NULL,
+                     PRIMARY KEY (uw_id)
+                      
+                     );
+                     
+                     CREATE TABLE uw_Batch_t(uw_id int8 NOT NULL, 
+                                              uw_a text NOT NULL,
+                      PRIMARY KEY (uw_id)
+                       
+                      );
+                      
+                      CREATE TABLE uw_BatchG_t(uw_id int8 NOT NULL, 
+                                                uw_a text NOT NULL, 
+                                                uw_b float8 NOT NULL,
+                       PRIMARY KEY (uw_id)
+                        
+                       );
+                       
+                       CREATE TABLE uw_RoundTrip_channels(uw_client
+                                                           int4 NOT NULL, 
+                                                           uw_channel
+                                                            int8 NOT NULL,
+                        PRIMARY KEY (uw_client)
+                         
+                        );
+                        
+                        CREATE SEQUENCE uw_Chat_Room_s;
+                         
+                         CREATE TABLE uw_Chat_Room_t(uw_id int8 NOT NULL, 
+                                                      uw_client int4 NOT NULL, 
+                                                      uw_channel int8 NOT NULL,
+                          PRIMARY KEY (uw_client, uw_id)
+                           
+                          );
+                          
+                          CREATE SEQUENCE uw_Chat_s;
+                           
+                           CREATE TABLE uw_Chat_t(uw_id int8 NOT NULL, 
+                                                   uw_title text NOT NULL, 
+                                                   uw_room int8 NOT NULL,
+                            PRIMARY KEY (uw_id)
+                             
+                            );
+                            
+                            
\ No newline at end of file
diff --git a/demo/demo.ur b/demo/demo.ur
new file mode 100644
index 0000000..2929e99
--- /dev/null
+++ b/demo/demo.ur
@@ -0,0 +1,38 @@
+fun main () = return <xml><body>
+  <li> <a link={Hello.main ()}>Hello</a></li>
+  <li> <a link={Link.main ()}>Link</a></li>
+  <li> <a link={Rec.main ()}>Rec</a></li>
+  <li> <a link={Counter.main ()}>Counter</a></li>
+  <li> <a link={Form.main ()}>Form</a></li>
+  <li> <a link={Nested.main ()}>Nested</a></li>
+  <li> <a link={Cookie.main ()}>Cookie</a></li>
+  <li> <a link={Url.main ()}>Url</a></li>
+  <li> <a link={Css.main ()}>Css</a></li>
+  <li> <a link={Upload.main ()}>Upload</a></li>
+  <li> <a link={Subforms.main ()}>Subforms</a></li>
+  <li> <a link={ListShop.main ()}>ListShop</a></li>
+  <li> <a link={Sql.main ()}>Sql</a></li>
+  <li> <a link={Ref.main ()}>Ref</a></li>
+  <li> <a link={Tree.main ()}>Tree</a></li>
+  <li> <a link={Constraints.main ()}>Constraints</a></li>
+  <li> <a link={Outer.main ()}>Outer</a></li>
+  <li> <a link={View.main ()}>View</a></li>
+  <li> <a link={CookieSec.main ()}>CookieSec</a></li>
+  <li> <a link={Sum.main ()}>Sum</a></li>
+  <li> <a link={TcSum.main ()}>TcSum</a></li>
+  <li> <a link={Metaform1.main ()}>Metaform1</a></li>
+  <li> <a link={Metaform2.main ()}>Metaform2</a></li>
+  <li> <a link={Crud1.main ()}>Crud1</a></li>
+  <li> <a link={Crud2.main ()}>Crud2</a></li>
+  <li> <a link={Crud3.main ()}>Crud3</a></li>
+  <li> <a link={Alert.main ()}>Alert</a></li>
+  <li> <a link={React.main ()}>React</a></li>
+  <li> <a link={ListEdit.main ()}>ListEdit</a></li>
+  <li> <a link={Increment.main ()}>Increment</a></li>
+  <li> <a link={Noisy.main ()}>Noisy</a></li>
+  <li> <a link={Batch.main ()}>Batch</a></li>
+  <li> <a link={BatchG.main ()}>BatchG</a></li>
+  <li> <a link={Threads.main ()}>Threads</a></li>
+  <li> <a link={RoundTrip.main ()}>RoundTrip</a></li>
+  <li> <a link={Chat.main ()}>Chat</a></li>
+</body></xml>
diff --git a/demo/demo.urp b/demo/demo.urp
new file mode 100644
index 0000000..eb78d6a
--- /dev/null
+++ b/demo/demo.urp
@@ -0,0 +1,58 @@
+database dbname=test
+sql demo.sql
+prefix /Demo
+rewrite style Css/quote quote
+deny url http://en.wikipedia.org/wiki/PHP
+allow url http://en.wikipedia.org/wiki/*
+allow url http://adam.chlipala.net/style.css
+allow mime text/plain
+allow mime image/png
+allow mime image/gif
+
+/home/mig/git/urweb-20151220/demo/hello
+/home/mig/git/urweb-20151220/demo/link
+/home/mig/git/urweb-20151220/demo/rec
+/home/mig/git/urweb-20151220/demo/counter
+/home/mig/git/urweb-20151220/demo/form
+/home/mig/git/urweb-20151220/demo/nested
+/home/mig/git/urweb-20151220/demo/cookie
+/home/mig/git/urweb-20151220/demo/url
+/home/mig/git/urweb-20151220/demo/css
+/home/mig/git/urweb-20151220/demo/upload
+/home/mig/git/urweb-20151220/demo/subforms
+/home/mig/git/urweb-20151220/demo/list
+/home/mig/git/urweb-20151220/demo/listFun
+/home/mig/git/urweb-20151220/demo/listShop
+/home/mig/git/urweb-20151220/demo/sql
+/home/mig/git/urweb-20151220/demo/refFun
+/home/mig/git/urweb-20151220/demo/ref
+/home/mig/git/urweb-20151220/demo/treeFun
+/home/mig/git/urweb-20151220/demo/tree
+/home/mig/git/urweb-20151220/demo/constraints
+/home/mig/git/urweb-20151220/demo/outer
+/home/mig/git/urweb-20151220/demo/view
+/home/mig/git/urweb-20151220/demo/cookieSec
+/home/mig/git/urweb-20151220/demo/sum
+/home/mig/git/urweb-20151220/demo/tcSum
+/home/mig/git/urweb-20151220/demo/metaform
+/home/mig/git/urweb-20151220/demo/metaform1
+/home/mig/git/urweb-20151220/demo/metaform2
+/home/mig/git/urweb-20151220/demo/crud
+/home/mig/git/urweb-20151220/demo/crud1
+/home/mig/git/urweb-20151220/demo/crud2
+/home/mig/git/urweb-20151220/demo/crud3
+/home/mig/git/urweb-20151220/demo/alert
+/home/mig/git/urweb-20151220/demo/react
+/home/mig/git/urweb-20151220/demo/listEdit
+/home/mig/git/urweb-20151220/demo/increment
+/home/mig/git/urweb-20151220/demo/noisy
+/home/mig/git/urweb-20151220/demo/batch
+/home/mig/git/urweb-20151220/demo/batchFun
+/home/mig/git/urweb-20151220/demo/batchG
+/home/mig/git/urweb-20151220/demo/buffer
+/home/mig/git/urweb-20151220/demo/threads
+/home/mig/git/urweb-20151220/demo/roundTrip
+/home/mig/git/urweb-20151220/demo/broadcast
+/home/mig/git/urweb-20151220/demo/chat
+
+demo
diff --git a/demo/demo.urs b/demo/demo.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/demo.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/form.ur b/demo/form.ur
new file mode 100644
index 0000000..ec466db
--- /dev/null
+++ b/demo/form.ur
@@ -0,0 +1,18 @@
+fun handler r = return <xml><body>
+  <table>
+    <tr> <th>A:</th> <td>{[r.A]}</td> </tr>
+    <tr> <th>B:</th> <td>{[r.B]}</td> </tr>
+    <tr> <th>C:</th> <td>{[r.C]}</td> </tr>
+  </table>
+</body></xml>
+
+fun main () = return <xml><body>
+  <form>
+    <table>
+      <tr> <th>A:</th> <td><textbox{#A}/></td> </tr>
+      <tr> <th>B:</th> <td><textbox{#B}/></td> </tr>
+      <tr> <th>C:</th> <td><checkbox{#C}/></td> </tr>
+      <tr> <th/> <td><submit action={handler}/></td> </tr>
+    </table>
+  </form>
+</body></xml>
diff --git a/demo/form.urp b/demo/form.urp
new file mode 100644
index 0000000..335f1dd
--- /dev/null
+++ b/demo/form.urp
@@ -0,0 +1 @@
+form
diff --git a/demo/form.urs b/demo/form.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/form.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/hello.ur b/demo/hello.ur
new file mode 100644
index 0000000..9313460
--- /dev/null
+++ b/demo/hello.ur
@@ -0,0 +1,9 @@
+fun main () = return <xml>
+  <head>
+    <title>Hello world!</title>
+  </head>
+
+  <body>
+    <h1>Hello world!</h1>
+  </body>
+</xml>
diff --git a/demo/hello.urp b/demo/hello.urp
new file mode 100644
index 0000000..ce01362
--- /dev/null
+++ b/demo/hello.urp
@@ -0,0 +1 @@
+hello
diff --git a/demo/hello.urs b/demo/hello.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/hello.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/increment.ur b/demo/increment.ur
new file mode 100644
index 0000000..4ac2b2d
--- /dev/null
+++ b/demo/increment.ur
@@ -0,0 +1,10 @@
+sequence seq
+
+fun increment () = nextval seq
+
+fun main () =
+    src <- source 0;
+    return <xml><body>
+      <dyn signal={n <- signal src; return <xml>{[n]}</xml>}/>
+      <button value="Update" onclick={fn _ => n <- rpc (increment ()); set src n}/>
+    </body></xml>
diff --git a/demo/increment.urp b/demo/increment.urp
new file mode 100644
index 0000000..3a5c107
--- /dev/null
+++ b/demo/increment.urp
@@ -0,0 +1,3 @@
+database dbname=test
+
+increment
diff --git a/demo/increment.urs b/demo/increment.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/increment.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/link.ur b/demo/link.ur
new file mode 100644
index 0000000..f9e3396
--- /dev/null
+++ b/demo/link.ur
@@ -0,0 +1,7 @@
+fun target () = return <xml><body>
+  Welcome!
+</body></xml>
+
+fun main () = return <xml><body>
+  <a link={target ()}>Go there</a>
+</body></xml>
diff --git a/demo/link.urp b/demo/link.urp
new file mode 100644
index 0000000..2b2328d
--- /dev/null
+++ b/demo/link.urp
@@ -0,0 +1 @@
+link
diff --git a/demo/link.urs b/demo/link.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/link.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/list.ur b/demo/list.ur
new file mode 100644
index 0000000..961708e
--- /dev/null
+++ b/demo/list.ur
@@ -0,0 +1,21 @@
+datatype list t = Nil | Cons of t * list t
+
+fun length [t] (ls : list t) =
+    let
+        fun length' (ls : list t) (acc : int) =
+            case ls of
+                Nil => acc
+              | Cons (_, ls') => length' ls' (acc + 1)
+    in
+        length' ls 0
+    end
+
+fun rev [t] (ls : list t) = 
+    let
+        fun rev' (ls : list t) (acc : list t) =
+            case ls of
+                Nil => acc
+              | Cons (x, ls') => rev' ls' (Cons (x, acc))
+    in
+        rev' ls Nil
+    end
diff --git a/demo/list.urs b/demo/list.urs
new file mode 100644
index 0000000..e09f511
--- /dev/null
+++ b/demo/list.urs
@@ -0,0 +1,5 @@
+datatype list t = Nil | Cons of t * list t
+
+val length : t ::: Type -> list t -> int
+
+val rev : t ::: Type -> list t -> list t
diff --git a/demo/listEdit.ur b/demo/listEdit.ur
new file mode 100644
index 0000000..5b45d9a
--- /dev/null
+++ b/demo/listEdit.ur
@@ -0,0 +1,54 @@
+datatype rlist = Nil | Cons of {Data : source string,
+                                NewData : source string,
+                                Tail : source rlist}
+
+fun showString ss =
+    s <- signal ss;
+    return <xml>{[s]}</xml>
+
+fun show rls =
+    v <- signal rls;
+    show' v
+
+and show' rl =
+    case rl of
+        Nil => return <xml/>
+      | Cons {Data = ss, NewData = ss', Tail = rls} => return <xml>
+        <dyn signal={showString ss}/>
+        <button value="Change to:" onclick={fn _ => s <- get ss'; set ss s}/>
+        <ctextbox source={ss'}/><br/>
+        <dyn signal={show rls}/>
+      </xml>
+
+fun main () =
+    head <- source Nil;
+    tailP <- source head;
+    data <- source "";
+
+    let
+        fun add () =
+            data <- get data;
+            data <- source data;
+            ndata <- source "";
+            tail <- get tailP;
+            tail' <- source Nil;
+
+            let
+                val cons = Cons {Data = data, NewData = ndata, Tail = tail'}
+            in
+                set tail cons;
+                set tailP tail';
+
+                head' <- get head;
+                case head' of
+                    Nil => set head cons
+                  | _ => return ()
+            end
+    in
+        return <xml><body>
+          <ctextbox source={data}/> <button value="Add" onclick={fn _ => add ()}/><br/>
+          <br/>
+
+          <dyn signal={show head}/>
+        </body></xml>
+    end
diff --git a/demo/listEdit.urp b/demo/listEdit.urp
new file mode 100644
index 0000000..87bd245
--- /dev/null
+++ b/demo/listEdit.urp
@@ -0,0 +1 @@
+listEdit
diff --git a/demo/listEdit.urs b/demo/listEdit.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/listEdit.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/listFun.ur b/demo/listFun.ur
new file mode 100644
index 0000000..d679c2f
--- /dev/null
+++ b/demo/listFun.ur
@@ -0,0 +1,33 @@
+open List
+
+functor Make(M : sig
+                 type t
+                 val toString : t -> string
+                 val fromString : string -> option t
+             end) = struct
+    fun toXml (ls : list M.t) =
+        case ls of
+            Nil => <xml>[]</xml>
+          | Cons (x, ls') => <xml>{[M.toString x]} :: {toXml ls'}</xml>
+      
+    fun console (ls : list M.t) =
+        let
+            fun cons (r : {X : string}) =
+                case M.fromString r.X of
+                    None => return <xml><body>Invalid string!</body></xml>
+                  | Some v => console (Cons (v, ls))
+        in
+            return <xml><body>
+              Current list: {toXml ls}<br/>
+              Reversed list: {toXml (rev ls)}<br/>
+              Length: {[length ls]}<br/>
+              <br/>
+
+              <form>
+                Add element: <textbox{#X}/> <submit action={cons}/>
+              </form>
+            </body></xml>
+        end
+
+    fun main () = console Nil
+end
diff --git a/demo/listFun.urs b/demo/listFun.urs
new file mode 100644
index 0000000..909bbcf
--- /dev/null
+++ b/demo/listFun.urs
@@ -0,0 +1,7 @@
+functor Make(M : sig
+                 type t
+                 val toString : t -> string
+                 val fromString : string -> option t
+             end) : sig
+    val main : unit -> transaction page
+end
diff --git a/demo/listShop.ur b/demo/listShop.ur
new file mode 100644
index 0000000..be35d50
--- /dev/null
+++ b/demo/listShop.ur
@@ -0,0 +1,20 @@
+structure I = struct
+    type t = int
+    val toString = show
+    val fromString = read
+end
+
+structure S = struct
+    type t = string
+    val toString = show
+    val fromString = read
+end
+
+structure IL = ListFun.Make(I)
+structure SL = ListFun.Make(S)
+
+fun main () = return <xml><body>
+  Pick your poison:<br/>
+  <li> <a link={IL.main ()}>Integers</a></li>
+  <li> <a link={SL.main ()}>Strings</a></li>
+</body></xml>
diff --git a/demo/listShop.urp b/demo/listShop.urp
new file mode 100644
index 0000000..9b4b318
--- /dev/null
+++ b/demo/listShop.urp
@@ -0,0 +1,3 @@
+list
+listFun
+listShop
diff --git a/demo/listShop.urs b/demo/listShop.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/listShop.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/metaform.ur b/demo/metaform.ur
new file mode 100644
index 0000000..c6a6e54
--- /dev/null
+++ b/demo/metaform.ur
@@ -0,0 +1,28 @@
+functor Make (M : sig
+                  con fs :: {Unit}
+                  val fl : folder fs
+                  val names : $(mapU string fs)
+              end) = struct
+
+    fun handler values = return <xml><body>
+      {@mapUX2 [string] [string] [body]
+        (fn [nm :: Name] [rest ::_] [[nm] ~ rest] name value => <xml>
+          <li> {[name]} = {[value]}</li>
+        </xml>)
+        M.fl M.names values}
+    </body></xml>
+
+    fun main () = return <xml><body>
+      <form>
+        {@foldUR [string] [fn cols => xml form [] (mapU string cols)]
+          (fn [nm :: Name] [rest ::_] [[nm] ~ rest] name acc => <xml>
+            <li> {[name]}: <textbox{nm}/></li>
+            {useMore acc}
+          </xml>)
+          <xml/>
+          M.fl M.names}
+        <submit action={handler}/>
+      </form>
+    </body></xml>
+
+end
diff --git a/demo/metaform.urs b/demo/metaform.urs
new file mode 100644
index 0000000..0544e56
--- /dev/null
+++ b/demo/metaform.urs
@@ -0,0 +1,7 @@
+functor Make (M : sig
+                  con fs :: {Unit}
+                  val fl : folder fs
+                  val names : $(mapU string fs)
+              end) : sig
+    val main : unit -> transaction page
+end
diff --git a/demo/metaform1.ur b/demo/metaform1.ur
new file mode 100644
index 0000000..c6a4664
--- /dev/null
+++ b/demo/metaform1.ur
@@ -0,0 +1,3 @@
+open Metaform.Make(struct
+                       val names = {A = "Tic", B = "Tac", C = "Toe"}
+                   end)
diff --git a/demo/metaform1.urp b/demo/metaform1.urp
new file mode 100644
index 0000000..c5558e2
--- /dev/null
+++ b/demo/metaform1.urp
@@ -0,0 +1,2 @@
+metaform
+metaform1
diff --git a/demo/metaform1.urs b/demo/metaform1.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/metaform1.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/metaform2.ur b/demo/metaform2.ur
new file mode 100644
index 0000000..430a42f
--- /dev/null
+++ b/demo/metaform2.ur
@@ -0,0 +1,12 @@
+structure MM = Metaform.Make(struct
+                                 val names = {X = "x", Y = "y"}
+                             end)
+
+fun diversion () = return <xml><body>
+  Welcome to the diversion.
+</body></xml>
+
+fun main () = return <xml><body>
+  <li> <a link={diversion ()}>See something shiny!</a></li>
+  <li> <a link={MM.main ()}>Fill out a form!</a></li>
+</body></xml>
diff --git a/demo/metaform2.urp b/demo/metaform2.urp
new file mode 100644
index 0000000..623a84d
--- /dev/null
+++ b/demo/metaform2.urp
@@ -0,0 +1,2 @@
+metaform
+metaform2
diff --git a/demo/metaform2.urs b/demo/metaform2.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/metaform2.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/more/dbgrid.ur b/demo/more/dbgrid.ur
new file mode 100644
index 0000000..fc59353
--- /dev/null
+++ b/demo/more/dbgrid.ur
@@ -0,0 +1,430 @@
+con rawMeta = fn t :: Type =>
+                 {New : transaction t,
+                  Inj : sql_injectable t}
+
+con colMeta' = fn (row :: {Type}) (input :: Type) (filter :: Type) =>
+                  {Header : string,
+                   Project : $row -> transaction input,
+                   Update : $row -> input -> transaction ($row),
+                   Display : input -> xbody,
+                   Edit : input -> xbody,
+                   Validate : input -> signal bool,
+                   CreateFilter : transaction filter,
+                   DisplayFilter : filter -> xbody,
+                   Filter : filter -> $row -> signal bool,
+                   Sort : option ($row -> $row -> bool)}
+
+con colMeta = fn (row :: {Type}) (global_input_filter :: (Type * Type * Type)) =>
+                 {Initialize : transaction global_input_filter.1,
+                  Handlers : global_input_filter.1 -> colMeta' row global_input_filter.2 global_input_filter.3}
+
+con aggregateMeta = fn (row :: {Type}) (acc :: Type) =>
+                       {Initial : acc,
+                        Step : $row -> acc -> acc,
+                        Display : acc -> xbody}
+
+structure Direct = struct
+    con metaBase = fn actual_input_filter :: (Type * Type * Type) =>
+                  {Display : actual_input_filter.2 -> xbody,
+                   Edit : actual_input_filter.2 -> xbody,
+                   Initialize : actual_input_filter.1 -> transaction actual_input_filter.2,
+                   Parse : actual_input_filter.2 -> signal (option actual_input_filter.1),
+                   CreateFilter : transaction actual_input_filter.3,
+                   DisplayFilter : actual_input_filter.3 -> xbody,
+                   Filter : actual_input_filter.3 -> actual_input_filter.1 -> signal bool,
+                   Sort : actual_input_filter.1 -> actual_input_filter.1 -> bool}
+
+    datatype metaBoth actual input filter =
+             NonNull of metaBase (actual, input, filter) * metaBase (option actual, input, filter)
+           | Nullable of metaBase (actual, input, filter)
+
+    con meta = fn global_actual_input_filter =>
+                  {Initialize : transaction global_actual_input_filter.1,
+                   Handlers : global_actual_input_filter.1
+                              -> metaBoth global_actual_input_filter.2 global_actual_input_filter.3
+                                          global_actual_input_filter.4}
+
+    con editableState (ts :: (Type * Type * Type * Type)) = (ts.1, ts.3, ts.4)
+    fun editable [ts] [rest] [nm :: Name] [[nm] ~ rest] name (m : meta ts) : colMeta ([nm = ts.2] ++ rest)
+                                                                                     (editableState ts) =
+       let
+           fun doMr (mr : metaBase (ts.2, ts.3, ts.4)) : colMeta' ([nm = ts.2] ++ rest) ts.3 ts.4 =
+               {Header = name,
+                Project = fn r => mr.Initialize r.nm,
+                Update = fn r s =>
+                            vo <- current (mr.Parse s);
+                            return (case vo of
+                                        None => r
+                                      | Some v => r -- nm ++ {nm = v}),
+                Display = mr.Display,
+                Edit = mr.Edit,
+                Validate = fn s => vo <- mr.Parse s; return (Option.isSome vo),
+                CreateFilter = mr.CreateFilter,
+                DisplayFilter = mr.DisplayFilter,
+                Filter = fn i r => mr.Filter i r.nm,
+                Sort = Some (fn r1 r2 => mr.Sort r1.nm r2.nm)} 
+       in
+           {Initialize = m.Initialize,
+            Handlers = fn data => case m.Handlers data of
+                                      NonNull (mr, _) => doMr mr
+                                    | Nullable mr => doMr mr}
+       end
+        
+    con readOnlyState (ts :: (Type * Type * Type * Type)) = (ts.1, ts.3, ts.4)
+    fun readOnly [ts] [rest] [nm :: Name] [[nm] ~ rest] name (m : meta ts) : colMeta ([nm = ts.2] ++ rest)
+                                                                                     (readOnlyState ts) =
+       let
+           fun doMr mr = {Header = name,
+                          Project = fn r => mr.Initialize r.nm,
+                          Update = fn r _ => return r,
+                          Display = mr.Display,
+                          Edit = mr.Display,
+                          Validate = fn _ => return True,
+                          CreateFilter = mr.CreateFilter,
+                          DisplayFilter = mr.DisplayFilter,
+                          Filter = fn i r => mr.Filter i r.nm,
+                          Sort = Some (fn r1 r2 => mr.Sort r1.nm r2.nm)}
+       in
+           {Initialize = m.Initialize,
+            Handlers = fn data => case m.Handlers data of
+                                      NonNull (mr, _) => doMr mr
+                                    | Nullable mr => doMr mr}
+       end
+
+    con metaBasic = fn actual_input_filter :: (Type * Type * Type) =>
+                       {Display : actual_input_filter.2 -> xbody,
+                        Edit : source actual_input_filter.2 -> xbody,
+                        Initialize : actual_input_filter.1 -> actual_input_filter.2,
+                        InitializeNull : actual_input_filter.2,
+                        IsNull : actual_input_filter.2 -> bool,
+                        Parse : actual_input_filter.2 -> option actual_input_filter.1,
+                        CreateFilter : actual_input_filter.3,
+                        DisplayFilter : source actual_input_filter.3 -> xbody,
+                        Filter : actual_input_filter.3 -> actual_input_filter.1 -> bool,
+                        FilterIsNull : actual_input_filter.3 -> bool,
+                        Sort : actual_input_filter.1 -> actual_input_filter.1 -> bool}
+
+    con basicState = source
+    con basicFilter = source
+    fun basic [ts ::: (Type * Type * Type)] (m : metaBasic ts) : meta (unit, ts.1, basicState ts.2, basicFilter ts.3) =
+        {Initialize = return (),
+         Handlers = fn () => NonNull (
+                             {Display = fn s => <xml><dyn signal={v <- signal s; return (m.Display v)}/></xml>,
+                              Edit = m.Edit,
+                              Initialize = fn v => source (m.Initialize v),
+                              Parse = fn s => v <- signal s; return (m.Parse v),
+                              CreateFilter = source m.CreateFilter,
+                              DisplayFilter = m.DisplayFilter,
+                              Filter = fn f v => f <- signal f;
+                                          return (if m.FilterIsNull f then
+                                                      True
+                                                  else
+                                                      m.Filter f v),
+                              Sort = m.Sort},
+                             {Display = fn s => <xml><dyn signal={v <- signal s; return (m.Display v)}/></xml>,
+                              Edit = m.Edit,
+                              Initialize = fn v => source (case v of
+                                                       None => m.InitializeNull
+                                                     | Some v => m.Initialize v),
+                              Parse = fn s => v <- signal s;
+                                         return (if m.IsNull v then
+                                                     Some None
+                                                 else
+                                                     case m.Parse v of
+                                                         None => None
+                                                       | Some v' => Some (Some v')),
+                              CreateFilter = source m.CreateFilter,
+                              DisplayFilter = m.DisplayFilter,
+                              Filter = fn f v => f <- signal f;
+                                          return (if m.FilterIsNull f then
+                                                      True
+                                                  else
+                                                      case v of
+                                                          None => False
+                                                        | Some v => m.Filter f v),
+                              Sort = fn x y =>
+                                        case (x, y) of
+                                            (None, _) => True
+                                          | (Some x', Some y') => m.Sort x' y'
+                                          | _ => False})}
+
+    fun nullable [global] [actual] [input] [filter] (m : meta (global, actual, input, filter)) =
+        {Initialize = m.Initialize,
+         Handlers = fn d => case m.Handlers d of
+                                Nullable _ => error <xml>Don't stack calls to Direct.nullable!</xml>
+                              | NonNull (_, ho) => Nullable ho}
+
+    type intGlobal = unit
+    type intInput = basicState string
+    type intFilter = basicFilter string
+    val int : meta (intGlobal, int, intInput, intFilter) =
+        basic {Display = fn s => <xml>{[s]}</xml>,
+               Edit = fn s => <xml><ctextbox size={5} source={s}/></xml>,
+               Initialize = fn n => show n,
+               InitializeNull = "",
+               IsNull = eq "",
+               Parse = fn v => read v,
+               CreateFilter = "",
+               DisplayFilter = fn s => <xml><ctextbox size={5} source={s}/></xml> : xbody,
+               Filter = fn s n =>
+                           case read s of
+                               None => True
+                             | Some n' => n' = n,
+               FilterIsNull = eq "",
+               Sort = le}
+
+    type stringGlobal = unit
+    type stringInput = basicState string
+    type stringFilter = basicFilter string
+    val string : meta (stringGlobal, string, stringInput, stringFilter) =
+        basic {Display = fn s => <xml>{[s]}</xml>,
+               Edit = fn s => <xml><ctextbox source={s}/></xml>,
+               Initialize = fn s => s,
+               InitializeNull = "",
+               IsNull = eq "",
+               Parse = fn s => Some s,
+               CreateFilter = "",
+               DisplayFilter = fn s => <xml><ctextbox source={s}/></xml> : xbody,
+               Filter = fn s n =>
+                           case read s of
+                               None => True
+                             | Some n' => n' = n,
+               FilterIsNull = eq "",
+               Sort = le}
+
+    type boolGlobal = unit
+    type boolInput = basicState bool
+    type boolFilter = basicFilter string
+    val bool : meta (boolGlobal, bool, boolInput, boolFilter) =
+        basic {Display = fn b => <xml>{[b]}</xml>,
+               Edit = fn s => <xml><ccheckbox source={s}/></xml>,
+               Initialize = fn b => b,
+               InitializeNull = False,
+               IsNull = fn _ => False,
+               Parse = fn b => Some b,
+               CreateFilter = "",
+               DisplayFilter = fn s => <xml><cselect source={s}>
+                 <coption/>
+                 <coption value="0">False</coption>
+                 <coption value="1">True</coption>
+               </cselect></xml> : xbody,
+               Filter = fn s b =>
+                           case s of
+                               "0" => b = False
+                             | "1" => b = True
+                             | _ => True,
+               FilterIsNull = eq "",
+               Sort = le}
+
+    functor Foreign (M : sig
+                         con row :: {Type}
+                         con t :: Type
+                         val show_t : show t
+                         val read_t : read t
+                         val eq_t : eq t
+                         val ord_t : ord t
+                         val inj_t : sql_injectable t
+                         con nm :: Name
+                         constraint [nm] ~ row
+                         table tab : ([nm = t] ++ row)
+                         val render : $([nm = t] ++ row) -> string
+                     end) = struct
+        open M
+
+        type global = list (t * string)
+        type input = source string * option (t * $row)
+        type filter = source string
+
+        val getChoices = List.mapQuery (SELECT * FROM tab AS T)
+                                       (fn r => (r.T.nm, render r.T))
+
+        fun getChoice k =
+            r <- oneRow (SELECT T.{{row}} FROM tab AS T WHERE T.{nm} = {[k]});
+            return r.T
+
+        val meta : meta (global, M.t, input, filter) =
+            {Initialize = getChoices,
+             Handlers = fn choices =>
+                           NonNull (
+                           {Display = fn (_, kr) => case kr of
+                                                          None => error <xml>Unexpected Foreign null</xml>
+                                                        | Some (k, r) => <xml>{[render ({nm = k} ++ r)]}</xml>,
+                            Edit = fn (s, kr) => 
+                                      <xml><cselect source={s}>
+                                        {List.mapX (fn (k', rend) =>
+                                                       <xml><coption value={show k'} selected={case kr of
+                                                                                                   None => False
+                                                                                                 | Some (k, _) =>
+                                                                                                   k' = k}>{[rend]}</coption>
+                                                       </xml>)
+                                                   choices}
+                                      </cselect></xml>,
+                            Initialize = fn k => s <- source (show k);
+                                            r <- rpc (getChoice k);
+                                            return (s, Some (k, r)),
+                            Parse = fn (s, _) => k <- signal s; return (read k : option t),
+                            CreateFilter = source "",
+                            DisplayFilter = fn s => 
+                                               <xml><cselect source={s}>
+                                                 <coption/>
+                                                 {List.mapX (fn (k, rend) =>
+                                                                <xml><coption value={show k}>{[rend]}</coption></xml>)
+                                                            choices}
+                                               </cselect></xml> : xbody,
+                            Filter = fn s k => s <- signal s;
+                                        return (case read s : option t of
+                                                    None => True
+                                                  | Some k' => k' = k),
+                            Sort = le},
+                           {Display = fn (_, kr) => case kr of
+                                                          None => <xml>NULL</xml>
+                                                        | Some (k, r) => <xml>{[render ({nm = k} ++ r)]}</xml>,
+                            Edit = fn (s, kr) => 
+                                      <xml><cselect source={s}>
+                                        <coption value="" selected={case kr of
+                                                                        None => True
+                                                                      | _ => False}>NULL</coption>
+                                        {List.mapX (fn (k', rend) =>
+                                                       <xml><coption value={show k'} selected={case kr of
+                                                                                                   None => False
+                                                                                                 | Some (k, _) =>
+                                                                                                   k' = k}>{[rend]}</coption>
+                                                       </xml>)
+                                                   choices}
+                                      </cselect></xml>,
+                            Initialize = fn k => case k of
+                                                     None =>
+                                                     s <- source "";
+                                                     return (s, None)
+                                                   | Some k =>
+                                                     s <- source (show k);
+                                                     r <- rpc (getChoice k);
+                                                     return (s, Some (k, r)),
+                            Parse = fn (s, _) => ks <- signal s;
+                                       return (case ks of
+                                                   "" => Some None
+                                                 | _ => case read ks : option t of
+                                                            None => None
+                                                          | Some k => Some (Some k)),
+                            CreateFilter = source "",
+                            DisplayFilter = fn s => 
+                                               <xml><cselect source={s}>
+                                                 <coption/>
+                                                 <coption value="0">NULL</coption>
+                                                 {List.mapX (fn (k, rend) =>
+                                                                <xml><coption value={"1" ^ show k}>{[rend]}</coption>
+                                                                </xml>)
+                                                            choices}
+                                               </cselect></xml> : xbody,
+                            Filter = fn s ko => s <- signal s;
+                                        return (case s of
+                                                    "" => True
+                                                  | "0" => ko = None
+                                                  | _ =>
+                                                    case read (String.substring s {Start = 1,
+                                                                                   Len = String.length s - 1})
+                                                         : option t of
+                                                        None => True
+                                                      | Some k => ko = Some k),
+                            Sort = le})}
+    end
+end
+
+con computedState = (unit, xbody, unit)
+fun computed [row] [t] (_ : show t) name (f : $row -> t) : colMeta row computedState =
+    {Initialize = return (),
+     Handlers = fn () => {Header = name,
+                          Project = fn r => return <xml>{[f r]}</xml>,
+                          Update = fn r _ => return r,
+                          Display = fn x => x,
+                          Edit = fn _ => <xml>...</xml>,
+                          Validate = fn _ => return True,
+                          CreateFilter = return (),
+                          DisplayFilter = fn _ => <xml/>,
+                          Filter = fn _ _ => return True,
+                          Sort = None}}
+fun computedHtml [row] name (f : $row -> xbody) : colMeta row computedState =
+    {Initialize = return (),
+     Handlers = fn () => {Header = name,
+                          Project = fn r => return (f r),
+                          Update = fn r _ => return r,
+                          Display = fn x => x,
+                          Edit = fn _ => <xml>...</xml>,
+                          Validate = fn _ => return True,
+                          CreateFilter = return (),
+                          DisplayFilter = fn _ => <xml/>,
+                          Filter = fn _ _ => return True,
+                          Sort = None}}
+
+functor Make(M : sig
+                 con key :: {Type}
+                 con row :: {Type}
+                 constraint key ~ row
+                 table tab : (key ++ row)
+
+                 val raw : $(map rawMeta (key ++ row))
+
+                 con cols :: {(Type * Type * Type)}
+                 val cols : $(map (colMeta (key ++ row)) cols)
+
+                 val keyFolder : folder key
+                 val rowFolder : folder row
+                 val colsFolder : folder cols
+
+                 con aggregates :: {Type}
+                 val aggregates : $(map (aggregateMeta (key ++ row)) aggregates)
+                 val aggFolder : folder aggregates
+
+                 val pageLength : option int
+             end) = struct
+    open Grid.Make(struct
+                       fun keyOf r = r --- M.row
+
+                       val list = query (SELECT * FROM {{M.tab}} AS T) (fn r rs => return (r.T :: rs)) []
+
+                       val wholeRow = @Folder.concat ! M.keyFolder M.rowFolder
+
+                       fun ensql [env] (r : $(M.key ++ M.row)) =
+                           @map2 [rawMeta] [ident] [sql_exp env [] []]
+                            (fn [t] meta v => @sql_inject meta.Inj v)
+                            wholeRow M.raw r
+
+                       val new =
+                           row <- @Monad.mapR _ [rawMeta] [ident]
+                                   (fn [nm :: Name] [t :: Type] meta => meta.New)
+                                   wholeRow M.raw;
+                           dml (insert M.tab (ensql row));
+                           return row
+
+                       fun selector (r : $M.key) : sql_exp [T = M.key ++ M.row] [] [] bool =
+                         @foldR2 [rawMeta] [ident]
+                          [fn key => rest :: {Type} -> [rest ~ key] => sql_exp [T = key ++ rest] [] [] bool]
+                          (fn [nm :: Name] [t :: Type] [key :: {Type}] [[nm] ~ key]
+                                           (meta : rawMeta t) (v : t)
+                                           (exp : rest :: {Type} -> [rest ~ key] => sql_exp [T = key ++ rest] [] [] bool)
+                                           [rest :: {Type}] [rest ~ [nm = t] ++ key] =>
+                              (WHERE T.{nm} = {@sql_inject meta.Inj v} AND {exp [[nm = t] ++ rest]}))
+                          (fn [rest :: {Type}] [rest ~ []] => (WHERE TRUE))
+                          M.keyFolder (M.raw --- map rawMeta M.row) r
+                          [_] !
+
+                       fun save key row =
+                           dml (update [M.key ++ M.row]
+                                       (ensql row)
+                                       M.tab
+                                       (selector key))
+
+                       fun delete key =
+                           dml (Basis.delete M.tab (selector key))
+
+                       val cols = M.cols
+
+                       val folder = M.colsFolder
+
+                       val aggregates = M.aggregates
+
+                       val aggFolder = M.aggFolder
+
+                       val pageLength = M.pageLength
+                   end)
+end
diff --git a/demo/more/dbgrid.urs b/demo/more/dbgrid.urs
new file mode 100644
index 0000000..7dfd3db
--- /dev/null
+++ b/demo/more/dbgrid.urs
@@ -0,0 +1,132 @@
+con rawMeta = fn t :: Type =>
+                 {New : transaction t,
+                  Inj : sql_injectable t}
+
+con colMeta' = fn (row :: {Type}) (input :: Type) (filter :: Type) =>
+                  {Header : string,
+                   Project : $row -> transaction input,
+                   Update : $row -> input -> transaction ($row),
+                   Display : input -> xbody,
+                   Edit : input -> xbody,
+                   Validate : input -> signal bool,
+                   CreateFilter : transaction filter,
+                   DisplayFilter : filter -> xbody,
+                   Filter : filter -> $row -> signal bool,
+                   Sort : option ($row -> $row -> bool)}
+
+con colMeta = fn (row :: {Type}) (global_input_filter :: (Type * Type * Type)) =>
+                 {Initialize : transaction global_input_filter.1,
+                  Handlers : global_input_filter.1 -> colMeta' row global_input_filter.2 global_input_filter.3}
+
+con aggregateMeta = fn (row :: {Type}) (acc :: Type) =>
+                       {Initial : acc,
+                        Step : $row -> acc -> acc,
+                        Display : acc -> xbody}
+
+structure Direct : sig
+    con metaBase = fn actual_input_filter :: (Type * Type * Type) =>
+                  {Display : actual_input_filter.2 -> xbody,
+                   Edit : actual_input_filter.2 -> xbody,
+                   Initialize : actual_input_filter.1 -> transaction actual_input_filter.2,
+                   Parse : actual_input_filter.2 -> signal (option actual_input_filter.1),
+                   CreateFilter : transaction actual_input_filter.3,
+                   DisplayFilter : actual_input_filter.3 -> xbody,
+                   Filter : actual_input_filter.3 -> actual_input_filter.1 -> signal bool,
+                   Sort : actual_input_filter.1 -> actual_input_filter.1 -> bool}
+
+    datatype metaBoth actual input filter =
+             NonNull of metaBase (actual, input, filter) * metaBase (option actual, input, filter)
+           | Nullable of metaBase (actual, input, filter)
+
+    con meta = fn global_actual_input_filter :: (Type * Type * Type * Type) =>
+                  {Initialize : transaction global_actual_input_filter.1,
+                   Handlers : global_actual_input_filter.1
+                              -> metaBoth global_actual_input_filter.2 global_actual_input_filter.3
+                                          global_actual_input_filter.4}
+
+    con editableState :: (Type * Type * Type * Type) -> (Type * Type * Type)
+    val editable : ts ::: (Type * Type * Type * Type) -> rest ::: {Type}
+                   -> nm :: Name -> [[nm] ~ rest] => string -> meta ts
+                                                     -> colMeta ([nm = ts.2] ++ rest)
+                                                                (editableState ts)
+
+    con readOnlyState :: (Type * Type * Type * Type) -> (Type * Type * Type)
+    val readOnly : ts ::: (Type * Type * Type * Type) -> rest ::: {Type}
+                   -> nm :: Name -> [[nm] ~ rest] => string -> meta ts
+                                                     -> colMeta ([nm = ts.2] ++ rest)
+                                                                (readOnlyState ts)
+
+    val nullable : global ::: Type -> actual ::: Type -> input ::: Type -> filter ::: Type
+                   -> meta (global, actual, input, filter)
+                   -> meta (global, option actual, input, filter)
+
+    type intGlobal
+    type intInput
+    type intFilter
+    val int : meta (intGlobal, int, intInput, intFilter)
+
+    type stringGlobal
+    type stringInput
+    type stringFilter
+    val string : meta (stringGlobal, string, stringInput, stringFilter)
+
+    type boolGlobal
+    type boolInput
+    type boolFilter
+    val bool : meta (boolGlobal, bool, boolInput, boolFilter)
+
+    functor Foreign (M : sig
+                         con row :: {Type}
+                         con t :: Type
+                         val show_t : show t
+                         val read_t : read t
+                         val eq_t : eq t
+                         val ord_t : ord t
+                         val inj_t : sql_injectable t
+                         con nm :: Name
+                         constraint [nm] ~ row
+                         table tab : ([nm = t] ++ row)
+                         val render : $([nm = t] ++ row) -> string
+                     end) : sig
+        type global
+        type input
+        type filter
+        val meta : meta (global, M.t, input, filter)
+    end
+end
+
+con computedState :: (Type * Type * Type)
+val computed : row ::: {Type} -> t ::: Type -> show t
+               -> string -> ($row -> t) -> colMeta row computedState
+val computedHtml : row ::: {Type} -> string -> ($row -> xbody) -> colMeta row computedState
+
+functor Make(M : sig
+                 con key :: {Type}
+                 con row :: {Type}
+                 constraint key ~ row
+                 table tab : (key ++ row)
+
+                 val raw : $(map rawMeta (key ++ row))
+
+                 con cols :: {(Type * Type * Type)}
+                 val cols : $(map (colMeta (key ++ row)) cols)
+
+                 val keyFolder : folder key
+                 val rowFolder : folder row
+                 val colsFolder : folder cols
+
+                 con aggregates :: {Type}
+                 val aggregates : $(map (aggregateMeta (key ++ row)) aggregates)
+                 val aggFolder : folder aggregates
+
+                 val pageLength : option int
+             end) : sig
+    type grid
+
+    val grid : transaction grid
+    val sync : grid -> transaction unit
+    val render : grid -> xbody
+
+    val showSelection : grid -> source bool
+    val selection : grid -> signal (list ($(M.key ++ M.row)))
+end
diff --git a/demo/more/dlist.ur b/demo/more/dlist.ur
new file mode 100644
index 0000000..a5af8d2
--- /dev/null
+++ b/demo/more/dlist.ur
@@ -0,0 +1,303 @@
+datatype dlist'' t =
+         Nil
+       | Cons of t * source (dlist'' t)
+
+datatype dlist' t =
+         Empty
+       | Nonempty of { Head : dlist'' t, Tail : source (source (dlist'' t)) }
+
+con dlist t = source (dlist' t)
+
+type position = transaction unit
+
+fun headPos [t] (dl : dlist t) =
+    dl' <- get dl;
+    case dl' of
+        Nonempty { Head = Cons (_, tl), Tail = tl' } =>
+        cur <- get tl;
+        set dl (case cur of
+                    Nil => Empty
+                  | _ => Nonempty {Head = cur, Tail = tl'})
+      | _ => return ()
+
+fun tailPos [t] (cur : source (dlist'' t)) new tail =
+    new' <- get new;
+    set cur new';
+
+    case new' of
+        Nil => set tail cur
+      | _ => return ()
+
+val create [t] = source Empty
+
+fun clear [t] (s : dlist t) = set s Empty
+
+fun append [t] dl v =
+    dl' <- get dl;
+    case dl' of
+        Empty =>
+        tl <- source Nil;
+        tl' <- source tl;
+        set dl (Nonempty {Head = Cons (v, tl), Tail = tl'});
+        return (headPos dl)
+                
+      | Nonempty {Tail = tl, ...} =>
+        cur <- get tl;
+        new <- source Nil;
+        set cur (Cons (v, new));
+        set tl new;
+        return (tailPos cur new tl)
+
+fun replace [t] dl ls =
+    case ls of
+        [] => set dl Empty
+      | x :: ls =>
+        tl <- source Nil;
+        let
+            fun build ls acc =
+                case ls of
+                    [] => return acc
+                  | x :: ls =>
+                    this <- source (Cons (x, acc));
+                    build ls this
+        in
+            hd <- build (List.rev ls) tl;
+            tlS <- source tl;
+            set dl (Nonempty {Head = Cons (x, hd), Tail = tlS})
+        end
+
+fun renderDyn [ctx] [ctx ~ [Dyn]] [t] (f : t -> position -> xml (ctx ++ [Dyn]) [] []) filter pos len dl = <xml>
+  <dyn signal={dl' <- signal dl;
+               case dl' of
+                   Empty => return <xml/>
+                 | Nonempty {Head = hd, Tail = tlTop} => 
+                   let
+                       fun render' prev dl'' len =
+                           case len of
+                               Some 0 => <xml/>
+                             | _ =>
+                               case dl'' of
+                                   Nil => <xml/>
+                                 | Cons (v, tl) =>
+                                   let
+                                       val pos = case prev of
+                                                     None => headPos dl
+                                                   | Some prev => tailPos prev tl tlTop
+                                   in
+                                       <xml>
+                                         <dyn signal={b <- filter v;
+                                                      return <xml>
+                                                        {if b then
+                                                             f v pos
+                                                         else
+                                                             <xml/>}
+                                                        <dyn signal={tl' <- signal tl;
+                                                                     return (render' (Some tl) tl'
+                                                                                     (if b then
+                                                                                          Option.mp (fn n => n - 1) len
+                                                                                      else
+                                                                                          len))}/>
+                                                      </xml>}/>
+                                       </xml>
+                                   end
+
+                       fun skip pos hd =
+                           case pos of
+                               0 => return hd
+                             | _ =>
+                               case hd of
+                                   Nil => return hd
+                                 | Cons (_, tl) =>
+                                   tl' <- signal tl;
+                                   skip (pos-1) tl'
+                   in
+                       case pos of
+                           None => return (render' None hd len)
+                         | Some pos =>
+                           hd <- skip pos hd;
+                           return (render' None hd len)
+                   end}/>
+</xml>
+
+fun renderFlat [ctx] [ctx ~ [Dyn]] [t] (f : t -> position -> xml (ctx ++ [Dyn]) [] [])
+    : option int -> list (t * position) -> xml (ctx ++ [Dyn]) [] [] =
+    let
+        fun renderFlat' len ls =
+            case len of
+                Some 0 => <xml/>
+              | _ =>
+                case ls of
+                    [] => <xml/>
+                  | p :: ls =>
+                    let
+                        val len =
+                            case len of
+                                None => None
+                              | Some n => Some (n - 1)
+                    in
+                        <xml>{f p.1 p.2}{renderFlat' len ls}</xml>
+                    end
+    in
+        renderFlat'
+    end
+
+val split [t] =
+    let
+        fun split' acc (ls : list t) =
+            case ls of
+                [] => acc
+              | x1 :: [] => (x1 :: acc.1, acc.2)
+              | x1 :: x2 :: ls => split' (x1 :: acc.1, x2 :: acc.2) ls
+    in
+        split' ([], [])
+    end
+
+fun merge [t] (cmp : t -> t -> signal bool) =
+    let
+        fun merge' acc (ls1 : list t) (ls2 : list t) =
+            case (ls1, ls2) of
+                ([], _) => return (List.revAppend acc ls2)
+              | (_, []) => return (List.revAppend acc ls1)
+              | (x1 :: ls1', x2 :: ls2') =>
+                b <- cmp x1 x2;
+                if b then
+                    merge' (x1 :: acc) ls1' ls2
+                else
+                    merge' (x2 :: acc) ls1 ls2'
+    in
+        merge' []
+    end
+
+fun sort [t] (cmp : t -> t -> signal bool) =
+    let
+        fun sort' (ls : list t) =
+            case ls of
+                [] => return ls
+              | _ :: [] => return ls
+              | _ =>
+                let
+                    val (ls1, ls2) = split ls
+                in
+                    ls1' <- sort' ls1;
+                    ls2' <- sort' ls2;
+                    merge cmp ls1' ls2'
+                end
+    in
+        sort'
+    end
+
+fun render [ctx] [ctx ~ [Dyn]] [t] f (r : {Filter : t -> signal bool,
+                                           Sort : signal (option (t -> t -> signal bool)),
+                                           StartPosition : signal (option int),
+                                           MaxLength : signal (option int)}) dl = <xml>
+    <dyn signal={len <- r.MaxLength;
+                 cmp <- r.Sort;
+                 pos <- r.StartPosition;
+
+                 case cmp of
+                     None => return (renderDyn f r.Filter pos len dl)
+                   | Some cmp =>
+                     dl' <- signal dl;
+                     elems <- (case dl' of
+                                   Empty => return []
+                                 | Nonempty {Head = hd, Tail = tlTop} =>
+                                   let
+                                       fun listOut prev dl'' acc =
+                                           case dl'' of
+                                               Nil => return acc
+                                             | Cons (v, tl) =>
+                                               let
+                                                   val pos = case prev of
+                                                                 None => headPos dl
+                                                               | Some prev => tailPos prev tl tlTop
+                                               in
+                                                   b <- r.Filter v;
+                                                   tl' <- signal tl;
+                                                   listOut (Some tl) tl' (if b then
+                                                                              (v, pos) :: acc
+                                                                          else
+                                                                              acc)
+                                               end
+                                   in
+                                       listOut None hd []
+                                   end);
+                     elems <- sort (fn v1 v2 => cmp v1.1 v2.1) elems;
+                     let
+                         fun skip n ls =
+                             case (n, ls) of
+                                 (0, _) => ls
+                               | (n, _ :: ls) => skip (n-1) ls
+                               | (_, []) => []
+
+                         val elems =
+                             case pos of
+                                 None => elems
+                               | Some pos => skip pos elems
+                     in
+                         return (renderFlat f len elems)
+                     end}/>
+</xml>
+
+fun delete pos = pos
+
+fun elements' [t] (dl'' : dlist'' t) : signal (list t) =
+    case dl'' of
+        Nil => return []
+      | Cons (x, dl'') =>
+        dl'' <- signal dl'';
+        tl <- elements' dl'';
+        return (x :: tl)
+
+fun elements [t] (dl : dlist t) : signal (list t) =
+    dl' <- signal dl;
+    case dl' of
+        Empty => return []
+      | Nonempty {Head = hd, ...} => elements' hd
+
+fun size' [t] (dl'' : dlist'' t) : signal int =
+    case dl'' of
+        Nil => return 0
+      | Cons (x, dl'') =>
+        dl'' <- signal dl'';
+        n <- size' dl'';
+        return (n + 1)
+
+fun size [t] (dl : dlist t) : signal int =
+    dl' <- signal dl;
+    case dl' of
+        Empty => return 0
+      | Nonempty {Head = hd, ...} => size' hd
+
+fun numPassing' [t] (f : t -> signal bool) (dl'' : dlist'' t) : signal int =
+    case dl'' of
+        Nil => return 0
+      | Cons (x, dl'') =>
+        b <- f x;
+        dl'' <- signal dl'';
+        n <- numPassing' f dl'';
+        return (if b then n + 1 else n)
+
+fun numPassing [t] (f : t -> signal bool) (dl : dlist t) : signal int =
+    dl' <- signal dl;
+    case dl' of
+        Empty => return 0
+      | Nonempty {Head = hd, ...} => numPassing' f hd
+
+fun foldl [t] [acc] (f : t -> acc -> signal acc) =
+    let
+        fun foldl'' (i : acc) (dl : dlist'' t) : signal acc =
+            case dl of
+                Nil => return i
+              | Cons (v, dl') =>
+                dl' <- signal dl';
+                i' <- f v i;
+                foldl'' i' dl'
+
+        fun foldl' (i : acc) (dl : dlist t) : signal acc =
+            dl <- signal dl;
+            case dl of
+                Empty => return i
+              | Nonempty {Head = dl, ...} => foldl'' i dl
+    in
+        foldl'
+    end
diff --git a/demo/more/dlist.urs b/demo/more/dlist.urs
new file mode 100644
index 0000000..115c72b
--- /dev/null
+++ b/demo/more/dlist.urs
@@ -0,0 +1,22 @@
+con dlist :: Type -> Type
+type position
+
+val create : t ::: Type -> transaction (dlist t)
+val clear : t ::: Type -> dlist t -> transaction unit
+val append : t ::: Type -> dlist t -> t -> transaction position
+val replace : t ::: Type -> dlist t -> list t -> transaction unit
+
+val delete : position -> transaction unit
+val elements : t ::: Type -> dlist t -> signal (list t)
+val size : t ::: Type -> dlist t -> signal int
+val numPassing : t ::: Type -> (t -> signal bool) -> dlist t -> signal int
+val foldl : t ::: Type -> acc ::: Type -> (t -> acc -> signal acc) -> acc -> dlist t -> signal acc
+
+val render : ctx ::: {Unit} -> [ctx ~ [Dyn]] => t ::: Type
+             -> (t -> position -> xml (ctx ++ [Dyn]) [] [])
+             -> {StartPosition : signal (option int),
+                 MaxLength : signal (option int),
+                 Filter : t -> signal bool,
+                 Sort : signal (option (t -> t -> signal bool)) (* <= *)}
+             -> dlist t
+             -> xml (ctx ++ [Dyn]) [] []
diff --git a/demo/more/dragList.ur b/demo/more/dragList.ur
new file mode 100644
index 0000000..df4fc4f
--- /dev/null
+++ b/demo/more/dragList.ur
@@ -0,0 +1,39 @@
+fun draggableList title items =
+    itemSources <- List.mapM source items;
+    draggingItem <- source None;
+    return <xml>
+      <h2>Great {[title]}</h2>
+      <ul>
+        {List.mapX (fn itemSource => <xml>
+          <li onmousedown={fn _ => set draggingItem (Some itemSource)}
+              onmouseup={fn _ => set draggingItem None}
+              onmouseover={fn _ => di <- get draggingItem;
+                              case di of
+                                  None => return ()
+                                | Some di => original <- get di;
+                                  movedOver <- get itemSource;
+                                  set di movedOver;
+                                  set itemSource original;
+                                  set draggingItem (Some itemSource)}>
+              <dyn signal={Monad.mp cdata (signal itemSource)}/>
+         </li></xml>) itemSources}
+      </ul>
+    </xml>
+
+fun main () =
+    bears <- draggableList "Bears" ("Pooh" :: "Paddington" :: "Rupert" :: "Edward" :: []);
+    beers <- draggableList "Beers" ("Budvar" :: "Delirium Tremens" :: "Deuchars" :: []);
+    boars <- draggableList "Boars" ("Sus scrofa scrofa"
+                                        :: "Sus scrofa ussuricus"
+                                        :: "Sus scrofa cristatus"
+                                        :: "Sus scrofa taiwanus" :: []);
+    return <xml>
+      <head>
+        <link rel="stylesheet" type="text/css" href="../../dragList.css"/>
+      </head>
+      <body>
+        {bears}
+        {beers}
+        {boars}
+      </body>
+    </xml>
diff --git a/demo/more/dragList.urp b/demo/more/dragList.urp
new file mode 100644
index 0000000..42ec5c4
--- /dev/null
+++ b/demo/more/dragList.urp
@@ -0,0 +1,5 @@
+allow url ../../dragList.css
+
+$/list
+$/monad
+dragList
diff --git a/demo/more/dragList.urs b/demo/more/dragList.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/more/dragList.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/more/grid.ur b/demo/more/grid.ur
new file mode 100644
index 0000000..041115e
--- /dev/null
+++ b/demo/more/grid.ur
@@ -0,0 +1,330 @@
+con colMeta' = fn (row :: Type) (input :: Type) (filter :: Type) =>
+                  {Header : string,
+                   Project : row -> transaction input,
+                   Update : row -> input -> transaction row,
+                   Display : input -> xbody,
+                   Edit : input -> xbody,
+                   Validate : input -> signal bool,
+                   CreateFilter : transaction filter,
+                   DisplayFilter : filter -> xbody,
+                   Filter : filter -> row -> signal bool,
+                   Sort : option (row -> row -> bool)}
+
+con colMeta = fn (row :: Type) (global :: Type, input :: Type, filter :: Type) =>
+                 {Initialize : transaction global,
+                  Handlers : global -> colMeta' row input filter}                  
+
+con aggregateMeta = fn (row :: Type) (acc :: Type) =>
+                       {Initial : acc,
+                        Step : row -> acc -> acc,
+                        Display : acc -> xbody}
+
+functor Make(M : sig
+                 type row
+                 type key
+                 val keyOf : row -> key
+
+                 val list : transaction (list row)
+                 val new : transaction row
+                 val save : key -> row -> transaction unit
+                 val delete : key -> transaction unit
+
+                 con cols :: {(Type * Type * Type)}
+                 val cols : $(map (colMeta row) cols)
+
+                 val folder : folder cols
+
+                 con aggregates :: {Type}
+                 val aggregates : $(map (aggregateMeta row) aggregates)
+                 val aggFolder : folder aggregates
+
+                 val pageLength : option int
+             end) = struct
+    style tab
+    style row
+    style header
+    style data
+    style agg
+
+    fun make (row : M.row) [input] [filter] (m : colMeta' M.row input filter) : transaction input = m.Project row
+
+    fun makeAll cols row = @@Monad.exec [transaction] _ [map snd3 M.cols]
+                             (@map2 [fst3] [colMeta M.row] [fn p => transaction (snd3 p)]
+                               (fn [p] data meta => make row (meta.Handlers data))
+                               M.folder cols M.cols)
+                             (@@Folder.mp [_] [_] M.folder)
+
+    type listT = {Row : source M.row,
+                  Cols : source ($(map snd3 M.cols)),
+                  Updating : source bool,
+                  Selected : source bool}
+
+    type grid = {Cols : $(map fst3 M.cols),
+                 Rows : Dlist.dlist listT,
+                 Selection : source bool,
+                 Filters : $(map thd3 M.cols),
+                 Sort : source (option (M.row -> M.row -> bool)),
+                 Position : source int}
+
+    fun newRow cols row =
+        rowS <- source row;
+        cols <- makeAll cols row;
+        colsS <- source cols;
+        ud <- source False;
+        sd <- source False;
+        return {Row = rowS,
+                Cols = colsS,
+                Updating = ud,
+                Selected = sd}
+
+    fun addRow cols rows row =
+        r <- newRow cols row;
+        Monad.ignore (Dlist.append rows r)
+
+    val grid =
+        cols <- @Monad.mapR _ [colMeta M.row] [fst3]
+                 (fn [nm :: Name] [p :: (Type * Type * Type)] meta => meta.Initialize)
+                 M.folder M.cols;
+
+        filters <- @Monad.mapR2 _ [colMeta M.row] [fst3] [thd3]
+                    (fn [nm :: Name] [p :: (Type * Type * Type)] meta state =>
+                        (meta.Handlers state).CreateFilter)
+                    M.folder M.cols cols;
+
+        rows <- Dlist.create;
+        sel <- source False;
+        sort <- source None;
+        pos <- source 0;
+
+        return {Cols = cols,
+                Rows = rows,
+                Selection = sel,
+                Filters = filters,
+                Sort = sort,
+                Position = pos}
+
+    fun sync {Cols = cols, Rows = rows, ...} =
+        Dlist.clear rows;
+        init <- rpc M.list;
+        rs <- List.mapM (newRow cols) init;
+        Dlist.replace rows rs
+
+    fun myFilter grid all =
+        row <- signal all.Row;
+        @foldR3 [colMeta M.row] [fst3] [thd3] [fn _ => M.row -> signal bool]
+         (fn [nm :: Name] [p :: (Type * Type * Type)]
+                          [rest :: {(Type * Type * Type)}] [[nm] ~ rest]
+                          meta state filter combinedFilter row =>
+             previous <- combinedFilter row;
+             this <- (meta.Handlers state).Filter filter row;
+             return (previous && this))
+         (fn _ => return True)
+         M.folder M.cols grid.Cols grid.Filters row
+
+    fun render (grid : grid) = <xml>
+      <table class={tab}>
+        <tr class={row}>
+          <th/> <th/> <th><button value="No sort" onclick={fn _ => set grid.Sort None}/></th>
+          {@mapX2 [fst3] [colMeta M.row] [tr]
+            (fn [nm :: Name] [p :: (Type * Type * Type)] [rest :: {(Type * Type * Type)}] [[nm] ~ rest]
+                             data (meta : colMeta M.row p) =>
+                <xml><th class={header}>
+                  {case (meta.Handlers data).Sort of
+                       None => txt (meta.Handlers data).Header
+                     | sort => <xml><button value={(meta.Handlers data).Header}
+                                            onclick={fn _ => set grid.Sort sort}/></xml>}
+                </th></xml>)
+            M.folder grid.Cols M.cols}
+        </tr>
+
+        {Dlist.render (fn {Row = rowS, Cols = colsS, Updating = ud, Selected = sd} pos =>
+                          let
+                              val delete =
+                                  Dlist.delete pos;
+                                  row <- get rowS;
+                                  rpc (M.delete (M.keyOf row))
+
+                              val update = set ud True
+
+                              val cancel =
+                                  set ud False;
+                                  row <- get rowS;
+                                  cols <- makeAll grid.Cols row;
+                                  set colsS cols
+                                  
+                              val save =
+                                  cols <- get colsS;
+                                  errors <- @Monad.foldR3 _ [fst3] [colMeta M.row] [snd3] [fn _ => option string]
+                                             (fn [nm :: Name] [p :: (Type * Type * Type)] [rest :: {(Type * Type * Type)}]
+                                                              [[nm] ~ rest] data meta v errors =>
+                                                 b <- current ((meta.Handlers data).Validate v);
+                                                 return (if b then
+                                                             errors
+                                                         else
+                                                             case errors of
+                                                                 None => Some ((meta.Handlers data).Header)
+                                                               | Some s => Some ((meta.Handlers data).Header
+                                                                                 ^ ", " ^ s)))
+                                             None M.folder grid.Cols M.cols cols;
+
+                                  case errors of
+                                      Some s => alert ("Can't save because the following columns have invalid values:\n"
+                                                       ^ s)
+                                    | None =>
+                                      set ud False;
+                                      row <- get rowS;
+                                      row' <- @Monad.foldR3 _ [fst3] [colMeta M.row] [snd3] [fn _ => M.row]
+                                               (fn [nm :: Name] [t :: (Type * Type * Type)]
+                                                                [rest :: {(Type * Type * Type)}]
+                                                                [[nm] ~ rest] data meta v row' =>
+                                                   (meta.Handlers data).Update row' v)
+                                               row M.folder grid.Cols M.cols cols;
+                                      rpc (M.save (M.keyOf row) row');
+                                      set rowS row';
+
+                                      cols <- makeAll grid.Cols row';
+                                      set colsS cols
+                          in
+                              <xml><tr class={row}>
+                                <td>
+                                  <dyn signal={b <- signal grid.Selection;
+                                               return (if b then
+                                                           <xml><ccheckbox source={sd}/></xml>
+                                                       else
+                                                           <xml/>)}/>
+                                </td>
+
+                                <td>
+                                  <dyn signal={b <- signal ud;
+                                               return (if b then
+                                                           <xml><button value="Save" onclick={fn _ => save}/></xml>
+                                                       else
+                                                           <xml><button value="Update" onclick={fn _ => update}/></xml>)}/>
+                                </td>
+
+                                <td><dyn signal={b <- signal ud;
+                                                 return (if b then
+                                                             <xml><button value="Cancel" onclick={fn _ => cancel}/></xml>
+                                                         else
+                                                             <xml><button value="Delete" onclick={fn _ => delete}/></xml>)}/>
+                                </td>
+
+                                <dyn signal={cols <- signal colsS;
+                                             return (@mapX3 [fst3] [colMeta M.row] [snd3] [_]
+                                                      (fn [nm :: Name] [t :: (Type * Type * Type)]
+                                                                       [rest :: {(Type * Type * Type)}]
+                                                                       [[nm] ~ rest] dat meta v =>
+                                                          <xml><td class={data}>
+                                                            <dyn signal={b <- signal ud;
+                                                                         return (if b then
+                                                                                     (meta.Handlers dat).Edit v
+                                                                                 else
+                                                                                     (meta.Handlers dat).Display
+                                                                                                         v)}/>
+                                                            <dyn signal={b <- signal ud;
+                                                                         if b then
+                                                                             valid <-
+                                                                             (meta.Handlers dat).Validate v;
+                                                                             return (if valid then
+                                                                                         <xml/>
+                                                                                     else
+                                                                                         <xml>!</xml>)
+                                                                         else
+                                                                             return <xml/>}/>
+                                                          </td></xml>)
+                                                      M.folder grid.Cols M.cols cols)}/>
+                                </tr></xml>
+                          end)
+                      {StartPosition = case M.pageLength of
+                                           None => return None
+                                         | Some len =>
+                                           avail <- Dlist.numPassing (myFilter grid) grid.Rows;
+                                           pos <- signal grid.Position;
+                                           return (Some (if pos >= avail then
+                                                             0
+                                                         else
+                                                             pos)),
+                       MaxLength = return M.pageLength,
+                       Filter = myFilter grid,
+                       Sort = f <- signal grid.Sort;
+                              return (Option.mp (fn f r1 r2 => r1 <- signal r1.Row;
+                                                    r2 <- signal r2.Row;
+                                                    return (f r1 r2)) f)}
+                      grid.Rows}
+
+            <dyn signal={rows <- Dlist.foldl (fn row : listT =>
+                                                 @Monad.mapR2 _ [aggregateMeta M.row] [ident] [ident]
+                                                  (fn [nm :: Name] [t :: Type] meta acc =>
+                                                      Monad.mp (fn v => meta.Step v acc)
+                                                               (signal row.Row))
+                                                  M.aggFolder M.aggregates)
+                                 (@mp [aggregateMeta M.row] [ident]
+                                  (fn [t] meta => meta.Initial)
+                                  M.aggFolder M.aggregates) grid.Rows;
+                         return <xml><tr>
+                           <th colspan={3}>Aggregates</th>
+                           {@mapX2 [aggregateMeta M.row] [ident] [_]
+                             (fn [nm :: Name] [t :: Type] [rest :: {Type}] [[nm] ~ rest] meta acc =>
+                                 <xml><td class={agg}>{meta.Display acc}</td></xml>)
+                             M.aggFolder M.aggregates rows}
+                         </tr></xml>}/>
+
+              <tr><th colspan={3}>Filters</th>
+                {@mapX3 [colMeta M.row] [fst3] [thd3] [_]
+                  (fn [nm :: Name] [p :: (Type * Type * Type)] [rest :: {(Type * Type * Type)}] [[nm] ~ rest]
+                                   meta state filter => <xml><td>{(meta.Handlers state).DisplayFilter filter}</td></xml>)
+                  M.folder M.cols grid.Cols grid.Filters}
+              </tr>
+          </table>
+
+          {case M.pageLength of
+               None => <xml/>
+             | Some plen => <xml>
+               <dyn signal={avail <- Dlist.numPassing (myFilter grid) grid.Rows;
+                            return (if avail <= plen then
+                                        <xml/>
+                                    else
+                                        let
+                                            val numPages = avail / plen
+                                            val numPages = if numPages * plen < avail then
+                                                               numPages + 1
+                                                           else
+                                                               numPages
+
+                                            fun pages n =
+                                                if n * plen >= avail then
+                                                    <xml/>
+                                                else
+                                                    <xml>
+                                                      <dyn signal={pos <- signal grid.Position;
+                                                                   return (if n * plen = pos then
+                                                                               <xml><b>{[n + 1]}</b></xml>
+                                                                           else
+                                                                               <xml>
+                                                                                 <button value={show (n + 1)}
+                                                                                         onclick={fn _ => set grid.Position
+                                                                                                              (n * plen)
+                                                                                                 }/></xml>)}/>
+                                                      {if (n + 1) * plen >= avail then <xml/> else <xml>|</xml>}
+                                                      {pages (n + 1)}
+                                                    </xml>
+                                        in
+                                            <xml><p><b>Pages:</b> {pages 0}</p></xml>
+                                        end)}/>
+               </xml>}
+          
+          <button value="New row" onclick={fn _ => row <- rpc M.new;
+                                              addRow grid.Cols grid.Rows row}/>
+          <button value="Refresh" onclick={fn _ => sync grid}/>
+    </xml>
+
+    fun showSelection grid = grid.Selection
+
+    fun selection grid = Dlist.foldl (fn {Row = rowS, Selected = sd, ...} ls =>
+                                         sd <- signal sd;
+                                         if sd then
+                                             row <- signal rowS;
+                                             return (row :: ls)
+                                         else
+                                             return ls) [] grid.Rows
+end
diff --git a/demo/more/grid.urp b/demo/more/grid.urp
new file mode 100644
index 0000000..a67abdb
--- /dev/null
+++ b/demo/more/grid.urp
@@ -0,0 +1,8 @@
+
+$/option
+$/monad
+$/list
+$/string
+dlist
+grid
+dbgrid
diff --git a/demo/more/grid.urs b/demo/more/grid.urs
new file mode 100644
index 0000000..32f6af1
--- /dev/null
+++ b/demo/more/grid.urs
@@ -0,0 +1,57 @@
+con colMeta' = fn (row :: Type) (input :: Type) (filter :: Type) =>
+                  {Header : string,
+                   Project : row -> transaction input,
+                   Update : row -> input -> transaction row,
+                   Display : input -> xbody,
+                   Edit : input -> xbody,
+                   Validate : input -> signal bool,
+                   CreateFilter : transaction filter,
+                   DisplayFilter : filter -> xbody,
+                   Filter : filter -> row -> signal bool,
+                   Sort : option (row -> row -> bool)}
+                  
+con colMeta = fn (row :: Type) (global :: Type, input :: Type, filter :: Type) =>
+                 {Initialize : transaction global,
+                  Handlers : global -> colMeta' row input filter}
+
+con aggregateMeta = fn (row :: Type) (acc :: Type) =>
+                       {Initial : acc,
+                        Step : row -> acc -> acc,
+                        Display : acc -> xbody}
+
+functor Make(M : sig
+                 type row
+                 type key
+                 val keyOf : row -> key
+
+                 val list : transaction (list row)
+                 val new : transaction row
+                 val save : key -> row -> transaction unit
+                 val delete : key -> transaction unit
+
+                 con cols :: {(Type * Type * Type)}
+                 val cols : $(map (colMeta row) cols)
+
+                 val folder : folder cols
+
+                 con aggregates :: {Type}
+                 val aggregates : $(map (aggregateMeta row) aggregates)
+                 val aggFolder : folder aggregates
+
+                 val pageLength : option int
+             end) : sig
+    type grid
+
+    val grid : transaction grid
+    val sync : grid -> transaction unit
+    val render : grid -> xbody
+
+    val showSelection : grid -> source bool
+    val selection : grid -> signal (list M.row)
+
+    style tab
+    style row
+    style header
+    style data
+    style agg
+end
diff --git a/demo/more/grid0.ur b/demo/more/grid0.ur
new file mode 100644
index 0000000..410554c
--- /dev/null
+++ b/demo/more/grid0.ur
@@ -0,0 +1,34 @@
+open Dbgrid
+
+sequence s
+table t : {Id : int, A : int}
+  PRIMARY KEY Id
+
+open Make(struct
+              val tab = t
+              con key = [Id = _]
+
+              val raw = {Id = {New = nextval s,
+                               Inj = _},
+                         A = {New = return 0,
+                              Inj = _}}
+
+              val cols = {Id = Direct.readOnly [#Id] "Id" Direct.int,
+                          A = Direct.editable [#A] "A" Direct.int}
+
+              val aggregates = {}
+
+              val pageLength = None
+          end)
+
+fun main () =
+    grid <- grid;
+    set (showSelection grid) True;
+    return <xml>
+      <head>
+        <link rel="stylesheet" type="text/css" href="../../grid.css"/>
+      </head>
+      <body onload={sync grid}>
+        {render grid}
+      </body>
+    </xml>
diff --git a/demo/more/grid0.urp b/demo/more/grid0.urp
new file mode 100644
index 0000000..2cb16ec
--- /dev/null
+++ b/demo/more/grid0.urp
@@ -0,0 +1,7 @@
+debug
+database dbname=test
+library grid
+sql grid0.sql
+allow url ../../grid.css
+
+grid0
diff --git a/demo/more/grid1.ur b/demo/more/grid1.ur
new file mode 100644
index 0000000..66fe2f2
--- /dev/null
+++ b/demo/more/grid1.ur
@@ -0,0 +1,78 @@
+open Dbgrid
+
+table t1 : {Id : int, A : string}
+  PRIMARY KEY Id
+
+sequence s
+table t : {Id : int, A : int, B : string, C : bool, D : int, E : option int, F : option int}
+  PRIMARY KEY Id,
+  CONSTRAINT Foreign FOREIGN KEY (D) REFERENCES t1(Id) ON DELETE CASCADE
+
+fun page (n, s) = return <xml>A = {[n]}, B = {[s]}</xml>
+
+open Make(struct
+              structure F = Direct.Foreign(struct
+                                               con nm = #Id
+                                               val tab = t1
+                                               fun render r = r.A
+                                           end)
+
+              val tab = t
+              con key = [Id = _]
+
+              val raw = {Id = {New = nextval s,
+                               Inj = _},
+                         A = {New = return 0,
+                              Inj = _},
+                         B = {New = return "",
+                              Inj = _},
+                         C = {New = return False,
+                              Inj = _},
+                         D = {New = return 0,
+                              Inj = _},
+                         E = {New = return None,
+                              Inj = _},
+                         F = {New = return None,
+                              Inj = _}}
+
+              val cols = {Id = Direct.readOnly [#Id] "Id" Direct.int,
+                          A = Direct.editable [#A] "A" Direct.int,
+                          B = Direct.editable [#B] "B" Direct.string,
+                          C = Direct.editable [#C] "C" Direct.bool,
+                          D = Direct.editable [#D] "D" F.meta,
+                          E = Direct.editable [#E] "E" (Direct.nullable Direct.int),
+                          F = Direct.editable [#F] "F" (Direct.nullable F.meta),
+                          DA = computed "2A" (fn r => 2 * r.A),
+                          Link = computedHtml "Link" (fn r => <xml><a link={page (r.A, r.B)}>Go</a></xml>)}
+
+              val aggregates = {Dummy1 = {Initial = (),
+                                          Step = fn _ _ => (),
+                                          Display = fn _ => <xml/>},
+                                Sum = {Initial = 0,
+                                       Step = fn r n => r.A + n,
+                                       Display = txt},
+                                Dummy2 = {Initial = (),
+                                          Step = fn _ _ => (),
+                                          Display = fn _ => <xml/>},
+                                And = {Initial = True,
+                                       Step = fn r b => r.C && b,
+                                       Display = txt}}
+
+              val pageLength = Some 10
+          end)
+
+fun main () =
+    grid <- grid;
+    set (showSelection grid) True;
+    return <xml>
+      <head>
+        <link rel="stylesheet" type="text/css" href="../../grid.css"/>
+      </head>
+      <body onload={sync grid}>
+        {render grid}
+        <hr/>
+        <ccheckbox source={showSelection grid}/> Show selection<br/>
+        Selection: <dyn signal={ls <- selection grid;
+                                return (List.mapX (fn r => <xml>{[r.Id]}; </xml>) ls)}/>
+      </body>
+    </xml>
diff --git a/demo/more/grid1.urp b/demo/more/grid1.urp
new file mode 100644
index 0000000..a4f3337
--- /dev/null
+++ b/demo/more/grid1.urp
@@ -0,0 +1,7 @@
+debug
+database dbname=test
+library grid
+sql grid.sql
+allow url ../../grid.css
+
+grid1
diff --git a/demo/more/grid1.urs b/demo/more/grid1.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/more/grid1.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/more/orm.ur b/demo/more/orm.ur
new file mode 100644
index 0000000..468281f
--- /dev/null
+++ b/demo/more/orm.ur
@@ -0,0 +1,95 @@
+con link = fn col_parent :: (Type * Type) => col_parent.1 -> transaction (option col_parent.2)
+fun noParent [t ::: Type] (_ : t) : transaction (option unit) = return None
+
+con meta = fn (col :: Type, parent :: Type) => {
+	      Link : link (col, parent),
+	      Inj : sql_injectable col
+	      }
+
+fun local [t :: Type] (inj : sql_injectable t) : meta (t, unit) =
+    {Link = noParent,
+     Inj = inj}
+
+functor Table(M : sig
+                  con cols :: {(Type * Type)}
+                  val cols : $(map meta cols)
+                  constraint [Id] ~ cols
+                  val folder : folder cols
+              end) = struct
+    type id = int
+    con fs' = map fst M.cols
+    con fs = [Id = id] ++ fs'
+    type row' = $fs'
+    type row = $fs
+
+    fun resultsOut q = query q (fn r ls => return (r.T :: ls)) []
+    fun resultOut q = ro <- oneOrNoRows q; return (Option.mp (fn r => r .T) ro)
+
+    sequence s
+    table t : fs
+
+    val inj = _
+    val id = {Link = fn id => resultOut (SELECT * FROM t WHERE t.Id = {[id]}),
+              Inj = inj}
+
+    fun ensql [avail ::_] (r : row') : $(map (sql_exp avail [] []) fs') =
+        @map2 [meta] [fst] [fn ts :: (Type * Type) => sql_exp avail [] [] ts.1]
+         (fn [ts] meta v => @sql_inject meta.Inj v)
+         M.folder M.cols r
+
+    fun create (r : row') =
+        id <- nextval s;
+        dml (insert t ({Id = sql_inject id} ++ ensql [[]] r));
+        return ({Id = id} ++ r)
+
+    fun delete r = dml (DELETE FROM t WHERE t.Id = {[r.Id]})
+
+    fun save r = dml (update [fs'] (ensql [[T = [Id = int] ++ map fst M.cols]] (r -- #Id)) t (WHERE T.Id = {[r.Id]}))
+
+    fun lookup id =
+        ro <- oneOrNoRows (SELECT * FROM t WHERE t.Id = {[id]});
+        return (Option.mp (fn r => r.T) ro)
+
+
+    val list = resultsOut (SELECT * FROM t)
+
+    con col = fn t => {Exp : sql_exp [T = fs] [] [] t,
+                       Inj : sql_injectable t}
+    val idCol = {Exp = sql_field [#T] [#Id], Inj = _}
+    con meta' = fn (fs :: {Type}) (col :: Type, parent :: Type) =>
+                   {Col : {Exp : sql_exp [T = fs] [] [] col,
+                           Inj : sql_injectable col},
+                    Parent : $fs -> transaction (option parent)}
+    val cols = @foldR [meta] [fn before => after :: {(Type * Type)} -> [before ~ after] =>
+                                 $(map (meta' (map fst (before ++ after))) before)]
+                (fn [nm :: Name] [ts :: (Type * Type)] [before :: {(Type * Type)}]
+                                 [[nm] ~ before] (meta : meta ts)
+                                 (acc : after :: {(Type * Type)} -> [before ~ after] =>
+                                  $(map (meta' (map fst (before ++ after))) before))
+                                 [after :: {(Type * Type)}] [[nm = ts] ++ before ~ after] =>
+                    {nm = {Col = {Exp = sql_field [#T] [nm],
+                                  Inj = meta.Inj},
+                           Parent = fn r => meta.Link r.nm}}
+                        ++ acc [[nm = ts] ++ after])
+                (fn [after :: {(Type * Type)}] [[] ~ after] => {})
+                M.folder M.cols
+                [[Id = (id, row)]] !
+
+    type filter = sql_exp [T = fs] [] [] bool
+    fun find (f : filter) = resultOut (SELECT * FROM t WHERE {f})
+    fun search (f : filter) = resultsOut (SELECT * FROM t WHERE {f})
+
+    fun bin (b : t ::: Type -> sql_binary t t bool) [t] (c : col t) (v : t) =
+        sql_binary b c.Exp (@sql_inject c.Inj v)
+    val eq = @@bin @@sql_eq
+    val ne = @@bin @@sql_ne
+    val lt = @@bin @@sql_lt
+    val le = @@bin @@sql_le
+    val gt = @@bin @@sql_gt
+    val ge = @@bin @@sql_ge
+
+    fun bb (b : sql_binary bool bool bool) (f1 : filter) (f2 : filter) =
+        sql_binary b f1 f2
+    val _and = bb sql_and
+    val or = bb sql_or
+end
diff --git a/demo/more/orm.urp b/demo/more/orm.urp
new file mode 100644
index 0000000..01a50b5
--- /dev/null
+++ b/demo/more/orm.urp
@@ -0,0 +1,3 @@
+
+$/option
+orm
diff --git a/demo/more/orm.urs b/demo/more/orm.urs
new file mode 100644
index 0000000..63f4ffc
--- /dev/null
+++ b/demo/more/orm.urs
@@ -0,0 +1,49 @@
+con link :: (Type * Type) -> Type
+val noParent : t ::: Type -> link (t, unit)
+
+con meta = fn (col :: Type, parent :: Type) => {
+	      Link : link (col, parent),
+	      Inj : sql_injectable col
+	      }
+
+val local : t :: Type -> sql_injectable t -> meta (t, unit)
+
+functor Table(M : sig
+		  con cols :: {(Type * Type)}
+		  val cols : $(map meta cols)
+		  constraint [Id] ~ cols
+		  val folder : folder cols
+	      end) : sig
+    type id
+    type row' = $(map fst M.cols)
+    type row = $([Id = id] ++ map fst M.cols)
+
+    val inj : sql_injectable id
+    val id : meta (id, row)
+
+    val create : row' -> transaction row
+    val delete : row -> transaction unit
+    val save : row -> transaction unit
+    val lookup : id -> transaction (option row)
+    val list : transaction (list row)
+
+    con col :: Type -> Type
+    val idCol : col id
+    val cols : $(map (fn (colm :: Type, parent :: Type) =>
+                         {Col : col colm,
+                          Parent : row -> transaction (option parent)}) M.cols)
+
+    type filter
+    val find : filter -> transaction (option row)
+    val search : filter -> transaction (list row)
+
+    val eq : t ::: Type -> col t -> t -> filter
+    val ne : t ::: Type -> col t -> t -> filter
+    val lt : t ::: Type -> col t -> t -> filter
+    val le : t ::: Type -> col t -> t -> filter
+    val gt : t ::: Type -> col t -> t -> filter
+    val ge : t ::: Type -> col t -> t -> filter
+
+    val _and : filter -> filter -> filter
+    val or : filter -> filter -> filter
+end
diff --git a/demo/more/orm1.ur b/demo/more/orm1.ur
new file mode 100644
index 0000000..989741d
--- /dev/null
+++ b/demo/more/orm1.ur
@@ -0,0 +1,46 @@
+open Orm
+
+structure T = Table(struct
+                        val cols = {A = local [int],
+                                    B = local [string]}
+                    end)
+
+structure S = Table(struct
+                        val cols = {C = T.id,
+                                    D = local [float]}
+                    end)
+
+fun action () =
+    r1 <- T.create {A = 3, B = "Hi"};
+    T.save (r1 -- #B ++ {B = "Bye"});
+    r2 <- T.create {A = 4, B = "Why"};
+    r3 <- T.create {A = 66, B = "Hi"};
+
+    s <- S.create {C = r1.Id, D = 45.67};
+
+    ls <- T.list;
+    ls' <- T.search (T.eq T.cols.B.Col "Hi");
+
+    lsS <- S.list;
+    lsS <- List.mapM (fn r => p <- S.cols.C.Parent r; return (r, p)) lsS;
+
+    T.delete r1;
+    T.delete r2;
+    T.delete r3;
+
+    S.delete s;
+
+    return <xml><body>
+      {List.mapX (fn r => <xml><li> {[r.A]}: {[r.B]}</li></xml>) ls}
+      <br/>
+      {List.mapX (fn r => <xml><li> {[r.A]}: {[r.B]}</li></xml>) ls'}
+      <br/>
+      {List.mapX (fn (s, ro) => <xml><li> {[s.D]}: {case ro of
+                                                        None => <xml>No parent</xml>
+                                                      | Some r => <xml>{[r.B]}</xml>}
+      </li></xml>) lsS}
+    </body></xml>
+
+fun main () = return <xml><body>
+  <form><submit action={action}/></form>
+</body></xml>
diff --git a/demo/more/orm1.urp b/demo/more/orm1.urp
new file mode 100644
index 0000000..450f57a
--- /dev/null
+++ b/demo/more/orm1.urp
@@ -0,0 +1,6 @@
+library orm
+database dbname=test
+sql test.sql
+
+$/list
+orm1
diff --git a/demo/more/orm1.urs b/demo/more/orm1.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/more/orm1.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/more/out/dragList.css b/demo/more/out/dragList.css
new file mode 100644
index 0000000..bcd892d
--- /dev/null
+++ b/demo/more/out/dragList.css
@@ -0,0 +1,18 @@
+ul {
+  width: 200px; 
+  list-style-image: url(http://script.aculo.us/images/bullet.gif);
+}
+
+li {
+  color: #7E9E50;
+  font: 20px Georgia;
+  background-color: #ECF3E1; 
+  border: 1px solid #C5DEA1;
+  cursor: move;
+  margin: 0px;
+}
+
+h2 {
+  font: 42px/30px Georgia, serif;
+  color: #7E9E50;
+}
diff --git a/demo/more/out/grid.css b/demo/more/out/grid.css
new file mode 100644
index 0000000..3563123
--- /dev/null
+++ b/demo/more/out/grid.css
@@ -0,0 +1,19 @@
+.Grid1_tab {
+        border-style: solid
+}
+
+.Grid1_header {
+        border-style: solid
+}
+
+.Grid1_row {
+        border-style: solid
+}
+
+.Grid1_data {
+        border-style: solid
+}
+
+.Grid1_agg {
+        border-style: solid
+}
\ No newline at end of file
diff --git a/demo/more/prose b/demo/more/prose
new file mode 100644
index 0000000..9c267ca
--- /dev/null
+++ b/demo/more/prose
@@ -0,0 +1,15 @@
+<p>These are some extra demo applications written in <a href="http://www.impredicative.com/ur/">Ur/Web</a>.  See <a href="http://www.impredicative.com/ur/demo/">the main demo</a> for a more tutorial-like progression through language and library features.</p>
+
+dragList.urp
+
+<p>This is an Ur/Web version of the "draggable lists" <a href="http://groups.inf.ed.ac.uk/links/examples/">demo program from Links</a>.</p>
+
+grid1.urp
+
+orm1.urp
+
+<p>Many varieties of "object-relational mapping" (ORM) can be implemented as libraries in Ur/Web, as this demo shows.</p>
+
+versioned1.urp
+
+<p>We can also build a data store abstraction that makes it possible to view old versions of records.</p>
diff --git a/demo/more/versioned.ur b/demo/more/versioned.ur
new file mode 100644
index 0000000..d08ebcb
--- /dev/null
+++ b/demo/more/versioned.ur
@@ -0,0 +1,134 @@
+functor Make(M : sig
+                 con key :: {Type}
+                 con data :: {Type}
+                 constraint key ~ data
+                 constraint [When, Version] ~ (key ++ data)
+
+                 val key : $(map sql_injectable key)
+                 val data : $(map (fn t => {Inj : sql_injectable_prim t,
+                                            Eq : eq t}) data)
+
+                 val keyFolder : folder key
+                 val dataFolder : folder data
+             end) = struct
+    type version = int
+    con all = [When = time, Version = version] ++ M.key ++ map option M.data
+    sequence s
+    table t : all
+
+    val keys = List.mapQuery (SELECT DISTINCT t.{{M.key}} FROM t) (fn r => r.T)
+    fun keysAt vr = List.mapQuery (SELECT DISTINCT t.{{M.key}} FROM t
+                                   WHERE t.Version <= {[vr]}) (fn r => r.T)
+
+    con dmeta = fn t => {Inj : sql_injectable_prim t,
+                         Eq : eq t}
+
+    fun keyRecd (r : $(M.key ++ M.data)) =
+        @map2 [sql_injectable] [ident] [sql_exp [] [] []]
+         (fn [t] => @sql_inject)
+         M.keyFolder M.key (r --- M.data)
+
+    fun insert r =
+        vr <- nextval s;
+        dml (Basis.insert t
+                          ({Version = (SQL {[vr]}), When = (SQL CURRENT_TIMESTAMP)}
+                               ++ keyRecd r
+                               ++ @map2 [dmeta] [ident]
+                               [fn t => sql_exp [] [] [] (option t)]
+                               (fn [t] x v => @sql_inject (@sql_option_prim x.Inj)
+                                               (Some v))
+                               M.dataFolder M.data (r --- M.key)))
+
+    fun keyExp (r : $M.key) : sql_exp [T = all] [] [] bool =
+        @foldR2 [sql_injectable] [ident] [fn before => after :: {Type} -> [before ~ after]
+                                          => sql_exp [T = before ++ after] [] [] bool]
+         (fn [nm :: Name] [t :: Type] [before :: {Type}] [[nm] ~ before]
+                          (inj : sql_injectable t) (v : t)
+                          (e : after :: {Type} -> [before ~ after]
+                           => sql_exp [T = before ++ after] [] [] bool)
+                          [after :: {Type}] [[nm = t] ++ before ~ after] =>
+             (SQL t.{nm} = {[v]} AND {e [[nm = t] ++ after]}))
+         (fn [after :: {Type}] [[] ~ after] => (SQL TRUE))
+         M.keyFolder M.key r
+         [_] !
+
+    datatype bound =
+             NoBound
+           | Lt of int
+           | Le of int
+
+    fun seek vro k =
+        let
+            fun current' vro r =
+                let
+                    val complete = @foldR [option] [fn ts => option $ts]
+                                    (fn [nm :: Name] [v :: Type] [r :: {Type}] [[nm] ~ r]
+                                                     v r =>
+                                        case (v, r) of
+                                            (Some v, Some r) => Some ({nm = v} ++ r)
+                                          | _ => None)
+                                    (Some {}) M.dataFolder r
+                in
+                    case complete of
+                        Some r => return (Some r)
+                      | None =>
+                        let
+                            val filter = case vro of
+                                             NoBound => (WHERE TRUE)
+                                           | Lt vr => (WHERE t.Version < {[vr]})
+                                           | Le vr => (WHERE t.Version <= {[vr]})
+                        in
+                            ro <- oneOrNoRows (SELECT t.Version, t.{{map option M.data}}
+                                               FROM t
+                                               WHERE {filter}
+                                                 AND {keyExp k}
+                                               ORDER BY t.When DESC
+                                               LIMIT 1);
+                            case ro of
+                                None => return None
+                              | Some r' =>
+                                let
+                                    val r = @map2 [option] [option] [option]
+                                             (fn [t ::: Type] old new =>
+                                                 case old of
+                                                     None => new
+                                                   | Some _ => old)
+                                             M.dataFolder r (r'.T -- #Version)
+                                in
+                                    current' (Lt r'.T.Version) r
+                                end
+                        end
+                end
+        in
+            current' vro (@map0 [option] (fn [t :: Type] => None : option t) M.dataFolder)
+        end
+
+    val current = seek NoBound
+    fun archive vr = seek (Le vr)
+
+    fun update r =
+        cur <- current (r --- M.data);
+        case cur of
+            None => error <xml>Tried to update nonexistent key</xml>
+          | Some cur =>
+            vr <- nextval s;
+            let
+                val r' = @map3 [dmeta] [ident] [ident] [fn t => sql_exp [] [] [] (option t)]
+                          (fn [t] (meta : dmeta t) old new =>
+                              @sql_inject (@sql_option_prim meta.Inj)
+                               (if @@eq [_] meta.Eq old new then
+                                    None
+                                else
+                                    Some new))
+                          M.dataFolder M.data cur (r --- M.key)
+                val r' = {Version = (SQL {[vr]}), When = (SQL CURRENT_TIMESTAMP)}
+                             ++ keyRecd r
+                             ++ r'
+            in
+                dml (Basis.insert t r')
+            end
+
+    val updateTimes = List.mapQuery (SELECT t.Version, t.When
+                                     FROM t
+                                     ORDER BY t.When) (fn r => (r.T.Version, r.T.When))
+end
diff --git a/demo/more/versioned.urp b/demo/more/versioned.urp
new file mode 100644
index 0000000..a75d6c6
--- /dev/null
+++ b/demo/more/versioned.urp
@@ -0,0 +1,4 @@
+
+$/option
+$/list
+versioned
diff --git a/demo/more/versioned.urs b/demo/more/versioned.urs
new file mode 100644
index 0000000..47f2e52
--- /dev/null
+++ b/demo/more/versioned.urs
@@ -0,0 +1,24 @@
+functor Make(M : sig
+                 con key :: {Type}
+                 con data :: {Type}
+                 constraint key ~ data
+                 constraint [When, Version] ~ (key ++ data)
+
+                 val key : $(map sql_injectable key)
+                 val data : $(map (fn t => {Inj : sql_injectable_prim t,
+                                            Eq : eq t}) data)
+
+                 val keyFolder : folder key
+                 val dataFolder : folder data
+             end) : sig
+    val insert : $(M.key ++ M.data) -> transaction unit
+    val update : $(M.key ++ M.data) -> transaction unit
+
+    val keys : transaction (list $M.key)
+    val current : $M.key -> transaction (option $M.data)
+
+    type version
+    val keysAt : version -> transaction (list $M.key)
+    val archive : version -> $M.key -> transaction (option $M.data)
+    val updateTimes : transaction (list (version * time))
+end
diff --git a/demo/more/versioned1.ur b/demo/more/versioned1.ur
new file mode 100644
index 0000000..b5b23fb
--- /dev/null
+++ b/demo/more/versioned1.ur
@@ -0,0 +1,80 @@
+open Versioned.Make(struct
+                        con key = [Id = int]
+                        con data = [Nam = string, ShoeSize = int]
+
+                        val key = {Id = _}
+                        val data = {Nam = {Inj = _,
+                                           Eq = _},
+                                    ShoeSize = {Inj = _,
+                                                Eq = _}}
+                    end)
+
+fun retro vr =
+    ks <- keysAt vr;
+    ks <- List.mapM (fn r => fso <- archive vr r; return (r.Id, fso)) ks;
+
+    return <xml><body>
+      {List.mapX (fn (k, r) => <xml><li>
+        {[k]}: {case r of
+                    None => <xml>Whoa!</xml>
+                  | Some r => <xml>{[r.Nam]}, {[r.ShoeSize]}</xml>}
+      </li></xml>) ks}
+    </body></xml>
+
+fun expandKey k =
+    name <- source "";
+    shoeSize <- source "";
+    return {Key = k, Nam = name, ShoeSize = shoeSize}
+
+fun main () =
+    ks0 <- keys;
+    ks0 <- List.mapM (fn r => expandKey r.Id) ks0;
+    ks <- source ks0;
+
+    id <- source "";
+    name <- source "";
+    shoeSize <- source "";
+
+    times <- updateTimes;
+
+    return <xml><body>
+      <dyn signal={ks <- signal ks;
+                   return (List.mapX (fn kr => <xml><div>
+                     {[kr.Key]}:
+                     <ctextbox source={kr.Nam}/>
+                     <ctextbox size={5} source={kr.ShoeSize}/>
+                     <button value="Latest" onclick={fn _ => ro <- rpc (current {Id = kr.Key});
+                                                        case ro of
+                                                            None => alert "Can't get it!"
+                                                          | Some r =>
+                                                            set kr.Nam r.Nam;
+                                                            set kr.ShoeSize (show r.ShoeSize)}/>
+                     <button value="Update" onclick={fn _ => name <- get kr.Nam;
+                                                        shoeSize <- get kr.ShoeSize;
+                                                        rpc (update {Id = kr.Key,
+                                                                     Nam = name,
+                                                                     ShoeSize = readError shoeSize})
+                                                    }/>
+                   </div></xml>) ks)}/>
+
+      <h2>Add one:</h2>
+
+      <table>
+        <tr><th>Id:</th> <td><ctextbox size={5} source={id}/></td></tr>
+        <tr><th>Name:</th> <td><ctextbox source={name}/></td></tr>
+        <tr><th>Shoe size:</th> <td><ctextbox size={5} source={shoeSize}/></td></tr>
+        <tr><th><button value="Add" onclick={fn _ => id <- get id;
+                                                name <- get name;
+                                                shoeSize <- get shoeSize;
+                                                rpc (insert {Id = readError id, Nam = name,
+                                                             ShoeSize = readError shoeSize});
+
+                                                cur <- get ks;
+                                                kr <- expandKey (readError id);
+                                                set ks (kr :: cur)}/></th></tr>
+      </table>
+
+      <h2>Archive</h2>
+
+      {List.mapX (fn (vr, tm) => <xml><li><a link={retro vr}>{[tm]}</a></li></xml>) times}
+    </body></xml>
diff --git a/demo/more/versioned1.urp b/demo/more/versioned1.urp
new file mode 100644
index 0000000..748a081
--- /dev/null
+++ b/demo/more/versioned1.urp
@@ -0,0 +1,5 @@
+library versioned
+database dbname=test
+sql versioned1.sql
+
+versioned1
diff --git a/demo/more/versioned1.urs b/demo/more/versioned1.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/more/versioned1.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/nested.ur b/demo/nested.ur
new file mode 100644
index 0000000..31c9e1e
--- /dev/null
+++ b/demo/nested.ur
@@ -0,0 +1,62 @@
+fun pageA () = return <xml>
+  <head>
+    <title>A</title>
+  </head>
+  <body>
+    <form>
+      <table>
+        <tr>
+          <td>Forename:</td>
+          <td><textbox{#Forename}/></td>
+        </tr>
+        <tr>
+          <td>Enter a Surname?</td>
+          <td><checkbox{#EnterSurname}/></td>
+        </tr>
+      </table>
+      <submit action={fromA} />
+    </form>
+  </body>
+</xml>
+
+and fromA r =
+    let
+        val forename = r.Forename
+
+        fun pageB () = return <xml>
+          <head>
+            <title>B</title>
+          </head>
+          <body>
+            <form>
+              Surname:
+              <textbox{#Surname}/>
+              <submit action={pageC'} />
+            </form>
+            <a link={pageA ()}>Previous</a>
+          </body>
+        </xml>
+
+        and pageC' r = pageC (Some r.Surname)
+
+        and pageC surname = return <xml>
+          <head>
+            <title>C</title>
+          </head>
+          <body>
+            <p>Hello {[forename]}{case surname of
+                                      None => <xml/>
+                                    | Some s => <xml> {[s]}</xml>}</p>
+            {case surname of
+                 None => <xml><a link={pageA ()}>Previous</a></xml>
+               | Some _ => <xml><a link={pageB ()}>Previous</a></xml>}
+          </body>
+        </xml>
+    in
+        if r.EnterSurname then
+            pageB ()
+        else
+            pageC None
+    end
+
+val main = pageA
diff --git a/demo/nested.urp b/demo/nested.urp
new file mode 100644
index 0000000..79c5395
--- /dev/null
+++ b/demo/nested.urp
@@ -0,0 +1 @@
+nested
diff --git a/demo/nested.urs b/demo/nested.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/nested.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/noisy.ur b/demo/noisy.ur
new file mode 100644
index 0000000..caf5240
--- /dev/null
+++ b/demo/noisy.ur
@@ -0,0 +1,43 @@
+datatype list t = Nil | Cons of t * list t
+
+table t : { Id : int, A : string }
+  PRIMARY KEY Id
+
+fun add id s =
+    dml (INSERT INTO t (Id, A) VALUES ({[id]}, {[s]}))
+
+fun del id =
+    dml (DELETE FROM t WHERE t.Id = {[id]})
+
+fun lookup id =
+    ro <- oneOrNoRows (SELECT t.A FROM t WHERE t.Id = {[id]});
+    case ro of
+        None => return None
+      | Some r => return (Some r.T.A)
+
+fun check ls =
+    case ls of
+        Nil => return ()
+      | Cons (id, ls') =>
+        ao <- rpc (lookup id);
+        alert (case ao of
+                   None => "Nada"
+                 | Some a => a);
+        check ls'
+
+fun main () =
+    idAdd <- source "";
+    aAdd <- source "";
+
+    idDel <- source "";
+
+    return <xml><body>
+      <button value="Check values of 1, 2, and 3" onclick={fn _ => check (Cons (1, Cons (2, Cons (3, Nil))))}/><br/>
+      <br/>
+      <button value="Add" onclick={fn _ => id <- get idAdd; a <- get aAdd; rpc (add (readError id) a)}/>
+      <ctextbox source={idAdd}/>
+      <ctextbox source={aAdd}/><br/>
+      <br/>
+      <button value="Delete" onclick={fn _ => id <- get idDel; rpc (del (readError id))}/>
+      <ctextbox source={idDel}/>
+    </body></xml>
diff --git a/demo/noisy.urp b/demo/noisy.urp
new file mode 100644
index 0000000..ea08bf7
--- /dev/null
+++ b/demo/noisy.urp
@@ -0,0 +1,4 @@
+database dbname=test
+sql noisy.sql
+
+noisy
diff --git a/demo/noisy.urs b/demo/noisy.urs
new file mode 100644
index 0000000..6ac44e0
--- /dev/null
+++ b/demo/noisy.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/demo/out/alert.desc.html b/demo/out/alert.desc.html
new file mode 100644
index 0000000..9e29051
--- /dev/null
+++ b/demo/out/alert.desc.html
@@ -0,0 +1,15 @@
+<html><head>
+<title>Alert</title>
+</head><body>
+
+<h1>Alert</h1>
+
+<center>[ <a target="showcase" href="/Demo/Alert/main">Application</a> | <a target="showcase" href="alert.urp.html"><tt>alert.urp</tt></a> | <a target="showcase" href="alert.urs.html"><tt>alert.urs</tt></a> | <a target="showcase" href="alert.ur.html"><tt>alert.ur</tt></a> ]</center>
+
+
+<p>Ur/Web makes it easy to write code whose execution should be distributed between the web server and client web browsers.  Server-side code is compiled to efficient native code, and client-side code is compiled to JavaScript.  Ur/Web programmers don't need to worry about these details, because the language and standard library provide a uniform ML-like interface for the whole process.</p>
+
+<p>Here's an example of a button that, when clicked, opens an alert dialog on the client.</p>
+
+
+</body></html>
diff --git a/demo/out/alert.html b/demo/out/alert.html
new file mode 100644
index 0000000..be32694
--- /dev/null
+++ b/demo/out/alert.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/Alert/main" name="showcase">
+<frame src="alert.desc.html">
+</frameset>
diff --git a/demo/out/alert.ur.html b/demo/out/alert.ur.html
new file mode 100644
index 0000000..b20dcf4
--- /dev/null
+++ b/demo/out/alert.ur.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>alert.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">fun</span> <span class="function-name">main</span> () = return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+  </span><span class="tag">&lt;button</span> value=<span class="string">"Click me!"</span> onclick={alert <span class="string">"You clicked me!"</span>}<span class="tag">/&gt;</span><span class="string">
+</span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/alert.urp.html b/demo/out/alert.urp.html
new file mode 100644
index 0000000..3edadfe
--- /dev/null
+++ b/demo/out/alert.urp.html
@@ -0,0 +1,6 @@
+<html><body>
+
+<pre>alert
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/alert.urs.html b/demo/out/alert.urs.html
new file mode 100644
index 0000000..83638d4
--- /dev/null
+++ b/demo/out/alert.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>alert.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+</pre>
+  </body>
+</html>
diff --git a/demo/out/batch.desc.html b/demo/out/batch.desc.html
new file mode 100644
index 0000000..04fe730
--- /dev/null
+++ b/demo/out/batch.desc.html
@@ -0,0 +1,13 @@
+<html><head>
+<title>Batch</title>
+</head><body>
+
+<h1>Batch</h1>
+
+<center>[ <a target="showcase" href="/Demo/Batch/main">Application</a> | <a target="showcase" href="batch.urp.html"><tt>batch.urp</tt></a> | <a target="showcase" href="batch.urs.html"><tt>batch.urs</tt></a> | <a target="showcase" href="batch.ur.html"><tt>batch.ur</tt></a> ]</center>
+
+
+<p>This example shows more of what is possible with mixed client/server code.  The application is an editor for a simple database table, where additions of new rows can be batched in the client, before a button is clicked to trigger a mass addition.</p>
+
+
+</body></html>
diff --git a/demo/out/batch.html b/demo/out/batch.html
new file mode 100644
index 0000000..a39824a
--- /dev/null
+++ b/demo/out/batch.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/Batch/main" name="showcase">
+<frame src="batch.desc.html">
+</frameset>
diff --git a/demo/out/batch.ur.html b/demo/out/batch.ur.html
new file mode 100644
index 0000000..cff8107
--- /dev/null
+++ b/demo/out/batch.ur.html
@@ -0,0 +1,145 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>batch.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .sql {
+        /* font-lock-sql-face */
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+      .type-def {
+        /* font-lock-type-def-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">datatype</span> <span class="type-def">list</span> t = <span class="cvariable">Nil</span> | <span class="cvariable">Cons</span> <span class="keyword">of</span> t * list t
+
+<span class="keyword">table</span> <span class="variable-name">t</span> : {<span class="cvariable">Id</span> : int, <span class="cvariable">A</span> : string}
+  <span class="sql">PRIMARY</span> <span class="sql">KEY</span> <span class="cvariable">Id</span>
+
+<span class="keyword">fun</span> <span class="function-name">allRows</span> () =
+    query (<span class="sql">SELECT</span> * <span class="sql">FROM</span> t)
+    (<span class="keyword">fn</span> r acc =&gt; return (<span class="cvariable">Cons</span> ((r.<span class="cvariable">T</span>.<span class="cvariable">Id</span>, r.<span class="cvariable">T</span>.<span class="cvariable">A</span>), acc)))
+    <span class="cvariable">Nil</span>
+
+<span class="keyword">fun</span> <span class="function-name">doBatch</span> ls =
+    <span class="keyword">case</span> ls <span class="keyword">of</span>
+        <span class="cvariable">Nil</span> =&gt; return ()
+      | <span class="cvariable">Cons</span> ((id, a), ls') =&gt;
+        dml (<span class="sql">INSERT</span> <span class="sql">INTO</span> t (<span class="cvariable">Id</span>, <span class="cvariable">A</span>) <span class="sql">VALUES</span> ({[id]}, {[a]}));
+        doBatch ls'
+
+<span class="keyword">fun</span> <span class="function-name">del</span> id =
+    dml (<span class="sql">DELETE</span> <span class="sql">FROM</span> t <span class="sql">WHERE</span> t.<span class="cvariable">Id</span> = {[id]})
+
+<span class="keyword">fun</span> <span class="function-name">show</span> withDel lss =
+    <span class="keyword">let</span>
+        <span class="keyword">fun</span> <span class="function-name">show'</span> ls =
+            <span class="keyword">case</span> ls <span class="keyword">of</span>
+                <span class="cvariable">Nil</span> =&gt; <span class="tag">&lt;xml/&gt;</span>
+              | <span class="cvariable">Cons</span> ((id, a), ls) =&gt; <span class="tag">&lt;xml&gt;</span><span class="string">
+                </span><span class="tag">&lt;tr&gt;&lt;td&gt;</span>{[id]}<span class="tag">&lt;/td&gt;</span><span class="string"> </span><span class="tag">&lt;td&gt;</span>{[a]}<span class="tag">&lt;/td&gt;</span><span class="string"> </span>{<span class="keyword">if</span> withDel <span class="keyword">then</span>
+                                                        <span class="tag">&lt;xml&gt;&lt;td&gt;&lt;button</span> value=<span class="string">"Delete"</span> onclick={rpc (del id)}<span class="tag">/&gt;</span><span class="string">
+                                                        </span><span class="tag">&lt;/td&gt;&lt;/xml&gt;</span>
+                                                    <span class="keyword">else</span>
+                                                        <span class="tag">&lt;xml/&gt;</span>}<span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+                </span>{show' ls}<span class="string">
+              </span><span class="tag">&lt;/xml&gt;</span>
+    <span class="keyword">in</span>
+        <span class="tag">&lt;xml&gt;</span>&lt;dyn signal={ls &lt;- signal lss; return <span class="tag">&lt;xml&gt;&lt;table&gt;</span><span class="string">
+          </span><span class="tag">&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">Id</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">A</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+          </span>{show' ls}<span class="string">
+        </span><span class="tag">&lt;/table&gt;&lt;/xml&gt;</span>}/&gt;<span class="tag">&lt;/xml&gt;</span>
+    <span class="keyword">end</span>
+
+<span class="keyword">fun</span> <span class="function-name">main</span> () =
+    lss &lt;- source <span class="cvariable">Nil</span>;
+    batched &lt;- source <span class="cvariable">Nil</span>;
+
+    id &lt;- source <span class="string">""</span>;
+    a &lt;- source <span class="string">""</span>;
+
+    <span class="keyword">let</span>
+        <span class="keyword">fun</span> <span class="function-name">add</span> () =
+            id &lt;- get id;
+            a &lt;- get a;
+            ls &lt;- get batched;
+
+            set batched (<span class="cvariable">Cons</span> ((readError id, a), ls))
+
+        <span class="keyword">fun</span> <span class="function-name">exec</span> () =
+            ls &lt;- get batched;
+
+            rpc (doBatch ls);
+            set batched <span class="cvariable">Nil</span>
+    <span class="keyword">in</span>
+        return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+          </span><span class="tag">&lt;h2&gt;</span><span class="string">Rows</span><span class="tag">&lt;/h2&gt;</span><span class="string">
+
+          </span>{show <span class="cvariable">True</span> lss}<span class="string">
+
+          </span><span class="tag">&lt;button</span> value=<span class="string">"Update"</span> onclick={ls &lt;- rpc (allRows ()); set lss ls}<span class="tag">/&gt;&lt;br/&gt;</span><span class="string">
+          </span><span class="tag">&lt;br/&gt;</span><span class="string">
+
+          </span><span class="tag">&lt;h2&gt;</span><span class="string">Batch new rows to add</span><span class="tag">&lt;/h2&gt;</span><span class="string">
+
+          </span><span class="tag">&lt;table&gt;</span><span class="string">
+            </span><span class="tag">&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">Id:</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;td&gt;&lt;ctextbox</span> source={id}<span class="tag">/&gt;&lt;/td&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+            </span><span class="tag">&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">A:</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;td&gt;&lt;ctextbox</span> source={a}<span class="tag">/&gt;&lt;/td&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+            </span><span class="tag">&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th/&gt;</span><span class="string"> </span><span class="tag">&lt;td&gt;&lt;button</span> value=<span class="string">"Batch it"</span> onclick={add ()}<span class="tag">/&gt;&lt;/td&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+          </span><span class="tag">&lt;/table&gt;</span><span class="string">
+
+          </span><span class="tag">&lt;h2&gt;</span><span class="string">Already batched:</span><span class="tag">&lt;/h2&gt;</span><span class="string">
+          </span>{show <span class="cvariable">False</span> batched}<span class="string">
+          </span><span class="tag">&lt;button</span> value=<span class="string">"Execute"</span> onclick={exec ()}<span class="tag">/&gt;</span><span class="string">
+        </span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+    <span class="keyword">end</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/batch.urp.html b/demo/out/batch.urp.html
new file mode 100644
index 0000000..3a265f0
--- /dev/null
+++ b/demo/out/batch.urp.html
@@ -0,0 +1,8 @@
+<html><body>
+
+<pre>database dbname=test
+
+batch
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/batch.urs.html b/demo/out/batch.urs.html
new file mode 100644
index 0000000..fee2cbf
--- /dev/null
+++ b/demo/out/batch.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>batch.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+</pre>
+  </body>
+</html>
diff --git a/demo/out/batchFun.ur.html b/demo/out/batchFun.ur.html
new file mode 100644
index 0000000..8c1b080
--- /dev/null
+++ b/demo/out/batchFun.ur.html
@@ -0,0 +1,228 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>batchFun.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .module-def {
+        /* font-lock-module-def-face */
+        font-weight: bold;
+      }
+      .sql {
+        /* font-lock-sql-face */
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+      .type-def {
+        /* font-lock-type-def-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">con</span> <span class="type-def">colMeta</span> = <span class="keyword">fn</span> (db :: <span class="keyword">Type</span>, state :: <span class="keyword">Type</span>) =&gt;
+                 {<span class="cvariable">Nam</span> : string,
+                  <span class="cvariable">Show</span> : db -&gt; xbody,
+                  <span class="cvariable">Inject</span> : sql_injectable db,
+
+                  <span class="cvariable">NewState</span> : transaction state,
+                  <span class="cvariable">Widget</span> : state -&gt; xbody,
+                  <span class="cvariable">ReadState</span> : state -&gt; transaction db}
+<span class="keyword">con</span> <span class="type-def">colsMeta</span> = <span class="keyword">fn</span> cols :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)} =&gt; $(<span class="keyword">map</span> colMeta cols)
+
+<span class="keyword">fun</span> <span class="function-name">default</span> [t] (sh : show t) (rd : read t) (inj : sql_injectable t)
+            name : colMeta (t, source string) =
+    {<span class="cvariable">Nam</span> = name,
+     <span class="cvariable">Show</span> = txt,
+     <span class="cvariable">Inject</span> = _,
+
+     <span class="cvariable">NewState</span> = source <span class="string">""</span>,
+     <span class="cvariable">Widget</span> = <span class="keyword">fn</span> s =&gt; <span class="tag">&lt;xml&gt;&lt;ctextbox</span> source={s}<span class="tag">/&gt;&lt;/xml&gt;</span>,
+     <span class="cvariable">ReadState</span> = <span class="keyword">fn</span> s =&gt; v &lt;- get s; return (readError v)}
+
+<span class="keyword">val</span> <span class="variable-name">int</span> = default
+<span class="keyword">val</span> <span class="variable-name">float</span> = default
+<span class="keyword">val</span> <span class="variable-name">string</span> = default
+
+<span class="keyword">functor</span> <span class="module-def">Make</span>(<span class="cvariable">M</span> : <span class="keyword">sig</span>
+                 <span class="keyword">con</span> <span class="type-def">cols</span> :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)}
+                 <span class="keyword">constraint</span> [<span class="cvariable">Id</span>] ~ cols
+                 <span class="keyword">val</span> <span class="variable-name">fl</span> : folder cols
+                          
+                 <span class="keyword">table</span> <span class="variable-name">tab</span> : ([<span class="cvariable">Id</span> = int] ++ <span class="keyword">map</span> fst cols)
+                           
+                 <span class="keyword">val</span> <span class="variable-name">title</span> : string
+                             
+                 <span class="keyword">val</span> <span class="variable-name">cols</span> : colsMeta cols
+             <span class="keyword">end</span>) = <span class="keyword">struct</span>
+
+    <span class="keyword">val</span> <span class="variable-name">t</span> = <span class="cvariable">M</span>.tab
+
+    <span class="keyword">datatype</span> <span class="type-def">list</span> t = <span class="cvariable">Nil</span> | <span class="cvariable">Cons</span> <span class="keyword">of</span> t * list t
+
+    <span class="keyword">fun</span> <span class="function-name">allRows</span> () =
+        query (<span class="sql">SELECT</span> * <span class="sql">FROM</span> t)
+              (<span class="keyword">fn</span> r acc =&gt; return (<span class="cvariable">Cons</span> (r.<span class="cvariable">T</span>, acc)))
+              <span class="cvariable">Nil</span>
+
+    <span class="keyword">fun</span> <span class="function-name">add</span> r =
+        dml (insert t
+                    (@foldR2 [fst] [colMeta]
+                      [<span class="keyword">fn</span> cols =&gt; $(<span class="keyword">map</span> (<span class="keyword">fn</span> t :: (<span class="keyword">Type</span> * <span class="keyword">Type</span>) =&gt;
+                                            sql_exp [] [] [] t.1) cols)]
+                      (<span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] [t :: (<span class="keyword">Type</span> * <span class="keyword">Type</span>)] [rest :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)}]
+                                       [[nm] ~ rest] input col acc =&gt;
+                          acc ++ {nm = @sql_inject col.<span class="cvariable">Inject</span> input})
+                      {} <span class="cvariable">M</span>.fl (r -- #<span class="cvariable">Id</span>) <span class="cvariable">M</span>.cols
+                      ++ {<span class="cvariable">Id</span> = (<span class="sql">SQL</span> {[r.<span class="cvariable">Id</span>]})}))
+
+    <span class="keyword">fun</span> <span class="function-name">doBatch</span> ls =
+        <span class="keyword">case</span> ls <span class="keyword">of</span>
+            <span class="cvariable">Nil</span> =&gt; return ()
+          | <span class="cvariable">Cons</span> (r, ls') =&gt;
+            add r;
+            doBatch ls'
+
+    <span class="keyword">fun</span> <span class="function-name">del</span> id =
+        dml (<span class="sql">DELETE</span> <span class="sql">FROM</span> t <span class="sql">WHERE</span> t.<span class="cvariable">Id</span> = {[id]})
+
+    <span class="keyword">fun</span> <span class="function-name">show</span> withDel lss =
+        <span class="keyword">let</span>
+            <span class="keyword">fun</span> <span class="function-name">show'</span> ls =
+                <span class="keyword">case</span> ls <span class="keyword">of</span>
+                    <span class="cvariable">Nil</span> =&gt; <span class="tag">&lt;xml/&gt;</span>
+                  | <span class="cvariable">Cons</span> (r, ls) =&gt; <span class="tag">&lt;xml&gt;</span><span class="string">
+                    </span><span class="tag">&lt;tr&gt;</span><span class="string">
+                      </span><span class="tag">&lt;td&gt;</span>{[r.<span class="cvariable">Id</span>]}<span class="tag">&lt;/td&gt;</span><span class="string">
+                      </span>{@foldRX2 [colMeta] [fst] [_]
+                        (<span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] [p :: (<span class="keyword">Type</span> * <span class="keyword">Type</span>)] [rest :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)}]
+                                         [[nm] ~ rest] m v =&gt;
+                            <span class="tag">&lt;xml&gt;&lt;td&gt;</span>{m.<span class="cvariable">Show</span> v}<span class="tag">&lt;/td&gt;&lt;/xml&gt;</span>)
+                        <span class="cvariable">M</span>.fl <span class="cvariable">M</span>.cols (r -- #<span class="cvariable">Id</span>)}<span class="string">
+                      </span>{<span class="keyword">if</span> withDel <span class="keyword">then</span>
+                           <span class="tag">&lt;xml&gt;&lt;td&gt;&lt;button</span> value=<span class="string">"Delete"</span> onclick={rpc (del r.<span class="cvariable">Id</span>)}<span class="tag">/&gt;&lt;/td&gt;&lt;/xml&gt;</span>
+                       <span class="keyword">else</span>
+                           <span class="tag">&lt;xml/&gt;</span>}<span class="string">
+                    </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+                    </span>{show' ls}<span class="string">
+                  </span><span class="tag">&lt;/xml&gt;</span>
+        <span class="keyword">in</span>
+            <span class="tag">&lt;xml&gt;</span>&lt;dyn signal={ls &lt;- signal lss; return <span class="tag">&lt;xml&gt;&lt;table&gt;</span><span class="string">
+              </span><span class="tag">&lt;tr&gt;</span><span class="string">
+                </span><span class="tag">&lt;th&gt;</span><span class="string">Id</span><span class="tag">&lt;/th&gt;</span><span class="string">
+                </span>{@foldRX [colMeta] [_]
+                  (<span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] [p :: (<span class="keyword">Type</span> * <span class="keyword">Type</span>)] [rest :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)}]
+                                   [[nm] ~ rest] m =&gt;
+                      <span class="tag">&lt;xml&gt;&lt;th&gt;</span>{[m.<span class="cvariable">Nam</span>]}<span class="tag">&lt;/th&gt;&lt;/xml&gt;</span>)
+                  <span class="cvariable">M</span>.fl <span class="cvariable">M</span>.cols}<span class="string">
+              </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+              </span>{show' ls}<span class="string">
+            </span><span class="tag">&lt;/table&gt;&lt;/xml&gt;</span>}/&gt;<span class="tag">&lt;/xml&gt;</span>
+        <span class="keyword">end</span>
+
+    <span class="keyword">fun</span> <span class="function-name">main</span> () =
+        lss &lt;- source <span class="cvariable">Nil</span>;
+        batched &lt;- source <span class="cvariable">Nil</span>;
+
+        id &lt;- source <span class="string">""</span>;
+        inps &lt;- @foldR [colMeta] [<span class="keyword">fn</span> r =&gt; transaction ($(<span class="keyword">map</span> snd r))]
+                 (<span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] [p :: (<span class="keyword">Type</span> * <span class="keyword">Type</span>)] [rest :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)}] [[nm] ~ rest] m acc =&gt;
+                     s &lt;- m.<span class="cvariable">NewState</span>;
+                     r &lt;- acc;
+                     return ({nm = s} ++ r))
+                 (return {})
+                 <span class="cvariable">M</span>.fl <span class="cvariable">M</span>.cols;
+        
+        <span class="keyword">let</span>
+            <span class="keyword">fun</span> <span class="function-name">add</span> () =
+                id &lt;- get id;
+                vs &lt;- @foldR2 [colMeta] [snd] [<span class="keyword">fn</span> r =&gt; transaction ($(<span class="keyword">map</span> fst r))]
+                       (<span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] [p :: (<span class="keyword">Type</span> * <span class="keyword">Type</span>)] [rest :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)}]
+                                        [[nm] ~ rest] m s acc =&gt;
+                           v &lt;- m.<span class="cvariable">ReadState</span> s;
+                           r &lt;- acc;
+                           return ({nm = v} ++ r))
+                       (return {})
+                       <span class="cvariable">M</span>.fl <span class="cvariable">M</span>.cols inps;
+                ls &lt;- get batched;
+
+                set batched (<span class="cvariable">Cons</span> ({<span class="cvariable">Id</span> = readError id} ++ vs, ls))
+
+            <span class="keyword">fun</span> <span class="function-name">exec</span> () =
+                ls &lt;- get batched;
+
+                rpc (doBatch ls);
+                set batched <span class="cvariable">Nil</span>
+        <span class="keyword">in</span>
+            return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+              </span><span class="tag">&lt;h2&gt;</span><span class="string">Rows</span><span class="tag">&lt;/h2&gt;</span><span class="string">
+
+              </span>{show <span class="cvariable">True</span> lss}<span class="string">
+
+              </span><span class="tag">&lt;button</span> value=<span class="string">"Update"</span> onclick={ls &lt;- rpc (allRows ()); set lss ls}<span class="tag">/&gt;&lt;br/&gt;</span><span class="string">
+              </span><span class="tag">&lt;br/&gt;</span><span class="string">
+
+              </span><span class="tag">&lt;h2&gt;</span><span class="string">Batch new rows to add</span><span class="tag">&lt;/h2&gt;</span><span class="string">
+
+              </span><span class="tag">&lt;table&gt;</span><span class="string">
+                </span><span class="tag">&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">Id:</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;td&gt;&lt;ctextbox</span> source={id}<span class="tag">/&gt;&lt;/td&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+                </span>{@foldRX2 [colMeta] [snd] [_]
+                  (<span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] [p :: (<span class="keyword">Type</span> * <span class="keyword">Type</span>)] [rest :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)}]
+                                   [[nm] ~ rest] m s =&gt;
+                      <span class="tag">&lt;xml&gt;&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span>{[m.<span class="cvariable">Nam</span>]}<span class="string">:</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;td&gt;</span>{m.<span class="cvariable">Widget</span> s}<span class="tag">&lt;/td&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;&lt;/xml&gt;</span>)
+                  <span class="cvariable">M</span>.fl <span class="cvariable">M</span>.cols inps}<span class="string">
+                </span><span class="tag">&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th/&gt;</span><span class="string"> </span><span class="tag">&lt;td&gt;&lt;button</span> value=<span class="string">"Batch it"</span> onclick={add ()}<span class="tag">/&gt;&lt;/td&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+              </span><span class="tag">&lt;/table&gt;</span><span class="string">
+
+              </span><span class="tag">&lt;h2&gt;</span><span class="string">Already batched:</span><span class="tag">&lt;/h2&gt;</span><span class="string">
+              </span>{show <span class="cvariable">False</span> batched}<span class="string">
+              </span><span class="tag">&lt;button</span> value=<span class="string">"Execute"</span> onclick={exec ()}<span class="tag">/&gt;</span><span class="string">
+            </span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+        <span class="keyword">end</span>
+
+<span class="keyword">end</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/batchFun.urp.html b/demo/out/batchFun.urp.html
new file mode 100644
index 0000000..19f4011
--- /dev/null
+++ b/demo/out/batchFun.urp.html
@@ -0,0 +1,6 @@
+<html><body>
+
+<pre>batchFun
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/batchFun.urs.html b/demo/out/batchFun.urs.html
new file mode 100644
index 0000000..6f8717d
--- /dev/null
+++ b/demo/out/batchFun.urs.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>batchFun.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .module-def {
+        /* font-lock-module-def-face */
+        font-weight: bold;
+      }
+      .type-def {
+        /* font-lock-type-def-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">con</span> <span class="type-def">colMeta</span> = <span class="keyword">fn</span> (db :: <span class="keyword">Type</span>, state :: <span class="keyword">Type</span>) =&gt;
+                 {<span class="cvariable">Nam</span> : string,
+                  <span class="cvariable">Show</span> : db -&gt; xbody,
+                  <span class="cvariable">Inject</span> : sql_injectable db,
+
+                  <span class="cvariable">NewState</span> : transaction state,
+                  <span class="cvariable">Widget</span> : state -&gt; xbody,
+                  <span class="cvariable">ReadState</span> : state -&gt; transaction db}
+<span class="keyword">con</span> <span class="type-def">colsMeta</span> = <span class="keyword">fn</span> cols :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)} =&gt; $(<span class="keyword">map</span> colMeta cols)
+
+<span class="keyword">val</span> <span class="variable-name">int</span> : string -&gt; colMeta (int, source string)
+<span class="keyword">val</span> <span class="variable-name">float</span> : string -&gt; colMeta (float, source string)
+<span class="keyword">val</span> <span class="variable-name">string</span> : string -&gt; colMeta (string, source string)
+
+<span class="keyword">functor</span> <span class="module-def">Make</span>(<span class="cvariable">M</span> : <span class="keyword">sig</span>
+                 <span class="keyword">con</span> <span class="type-def">cols</span> :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)}
+                 <span class="keyword">constraint</span> [<span class="cvariable">Id</span>] ~ cols
+                 <span class="keyword">val</span> <span class="variable-name">fl</span> : folder cols
+
+                 <span class="keyword">table</span> <span class="variable-name">tab</span> : ([<span class="cvariable">Id</span> = int] ++ <span class="keyword">map</span> fst cols)
+
+                 <span class="keyword">val</span> <span class="variable-name">title</span> : string
+
+                 <span class="keyword">val</span> <span class="variable-name">cols</span> : colsMeta cols
+             <span class="keyword">end</span>) : <span class="keyword">sig</span>
+    <span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+<span class="keyword">end</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/batchG.desc.html b/demo/out/batchG.desc.html
new file mode 100644
index 0000000..a971c16
--- /dev/null
+++ b/demo/out/batchG.desc.html
@@ -0,0 +1,26 @@
+<html><head>
+<title>BatchG</title>
+</head><body>
+
+<h1>BatchG</h1>
+
+<center>[ <a target="showcase" href="/Demo/BatchG/main">Application</a> | <a target="showcase" href="batchG.urp.html"><tt>batchG.urp</tt></a> | <a target="showcase" href="batchFun.urs.html"><tt>batchFun.urs</tt></a> | <a target="showcase" href="batchFun.ur.html"><tt>batchFun.ur</tt></a> | <a target="showcase" href="batchG.urs.html"><tt>batchG.urs</tt></a> | <a target="showcase" href="batchG.ur.html"><tt>batchG.ur</tt></a> ]</center>
+
+
+<p>We can redo the last example with a generic component, like we did in the <tt>Crud</tt> examples.  The module <tt>BatchFun</tt> is analogous to the <tt>Crud</tt> module.  It contains a functor that builds a batching editor, when given a suitable description of a table.</p>
+
+<p>The signature of the functor is the same as for <tt>Crud</tt>.  We change the definition of <tt>colMeta</tt> to reflect the different kinds of column metadata that we need.  Each column is still described by a pair of types, and the first element of each pair still gives the SQL type for a column.  Now, however, the second type in a pair gives a type of <i>local state</i> to be used in a reactive widget for inputing that column.</p>
+
+<p>The first three fields of a <tt>colMeta</tt> record are the same as for <tt>Crud</tt>.  The rest of the fields are:</p>
+<ol>
+        <li><tt>NewState</tt>, which allocates some new widget local state</li>
+        <li><tt>Widget</tt>, which produces a reactive widget from some state</li>
+        <li><tt>ReadState</tt>, which reads the current value of some state to determine which SQL value it encodes</li>
+</ol>
+
+<p><tt>BatchFun.Make</tt> handles the plumbing of allocating the local state, using it to create widgets, and reading the state values when the user clicks "Batch it."</p>
+
+<p><tt>batchG.ur</tt> contains an example instantiation, which is just as easy to write as in the <tt>Crud1</tt> example.</p>
+
+
+</body></html>
diff --git a/demo/out/batchG.html b/demo/out/batchG.html
new file mode 100644
index 0000000..485aece
--- /dev/null
+++ b/demo/out/batchG.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/BatchG/main" name="showcase">
+<frame src="batchG.desc.html">
+</frameset>
diff --git a/demo/out/batchG.ur.html b/demo/out/batchG.ur.html
new file mode 100644
index 0000000..c37f474
--- /dev/null
+++ b/demo/out/batchG.ur.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>batchG.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .sql {
+        /* font-lock-sql-face */
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">table</span> <span class="variable-name">t</span> : {<span class="cvariable">Id</span> : int, <span class="cvariable">A</span> : string, <span class="cvariable">B</span> : float}
+  <span class="sql">PRIMARY</span> <span class="sql">KEY</span> <span class="cvariable">Id</span>
+
+<span class="keyword">open</span> <span class="cvariable">BatchFun</span>.<span class="cvariable">Make</span>(<span class="keyword">struct</span>
+                       <span class="keyword">val</span> <span class="variable-name">tab</span> = t
+                       <span class="keyword">val</span> <span class="variable-name">title</span> = <span class="string">"BatchG"</span>
+                       <span class="keyword">val</span> <span class="variable-name">cols</span> = {<span class="cvariable">A</span> = <span class="cvariable">BatchFun</span>.string <span class="string">"A"</span>,
+                                   <span class="cvariable">B</span> = <span class="cvariable">BatchFun</span>.float <span class="string">"B"</span>}
+                   <span class="keyword">end</span>)
+</pre>
+  </body>
+</html>
diff --git a/demo/out/batchG.urp.html b/demo/out/batchG.urp.html
new file mode 100644
index 0000000..4fed9e6
--- /dev/null
+++ b/demo/out/batchG.urp.html
@@ -0,0 +1,10 @@
+<html><body>
+
+<pre>database dbname=test
+sql batchG.sql
+
+batchFun
+batchG
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/batchG.urs.html b/demo/out/batchG.urs.html
new file mode 100644
index 0000000..11d5529
--- /dev/null
+++ b/demo/out/batchG.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>batchG.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+</pre>
+  </body>
+</html>
diff --git a/demo/out/broadcast.ur.html b/demo/out/broadcast.ur.html
new file mode 100644
index 0000000..3e50072
--- /dev/null
+++ b/demo/out/broadcast.ur.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>broadcast.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .module-def {
+        /* font-lock-module-def-face */
+        font-weight: bold;
+      }
+      .sql {
+        /* font-lock-sql-face */
+        font-weight: bold;
+      }
+      .type-def {
+        /* font-lock-type-def-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">functor</span> <span class="module-def">Make</span>(<span class="cvariable">M</span> : <span class="keyword">sig</span> <span class="keyword">type</span> <span class="type-def">t</span> <span class="keyword">end</span>) = <span class="keyword">struct</span>
+    <span class="keyword">sequence</span> s
+    <span class="keyword">table</span> <span class="variable-name">t</span> : {<span class="cvariable">Id</span> : int, <span class="cvariable">Client</span> : client, <span class="cvariable">Channel</span> : channel <span class="cvariable">M</span>.t}
+      <span class="sql">PRIMARY</span> <span class="sql">KEY</span> (<span class="cvariable">Id</span>, <span class="cvariable">Client</span>)
+
+    <span class="keyword">type</span> <span class="type-def">topic</span> = int
+
+    <span class="keyword">val</span> <span class="variable-name">inj</span> : sql_injectable topic = _
+
+    <span class="keyword">val</span> <span class="variable-name">create</span> = nextval s
+
+    <span class="keyword">fun</span> <span class="function-name">subscribe</span> id =
+        cli &lt;- self;
+        ro &lt;- oneOrNoRows (<span class="sql">SELECT</span> t.<span class="cvariable">Channel</span> <span class="sql">FROM</span> t <span class="sql">WHERE</span> t.<span class="cvariable">Id</span> = {[id]} <span class="sql">AND</span> t.<span class="cvariable">Client</span> = {[cli]});
+        <span class="keyword">case</span> ro <span class="keyword">of</span>
+            <span class="cvariable">None</span> =&gt;
+            ch &lt;- channel;
+            dml (<span class="sql">INSERT</span> <span class="sql">INTO</span> t (<span class="cvariable">Id</span>, <span class="cvariable">Client</span>, <span class="cvariable">Channel</span>) <span class="sql">VALUES</span> ({[id]}, {[cli]}, {[ch]}));
+            return ch
+          | <span class="cvariable">Some</span> r =&gt; return r.<span class="cvariable">T</span>.<span class="cvariable">Channel</span>
+
+    <span class="keyword">fun</span> <span class="function-name">send</span> id msg =
+        queryI (<span class="sql">SELECT</span> t.<span class="cvariable">Channel</span> <span class="sql">FROM</span> t <span class="sql">WHERE</span> t.<span class="cvariable">Id</span> = {[id]})
+        (<span class="keyword">fn</span> r =&gt; <span class="cvariable">Basis</span>.send r.<span class="cvariable">T</span>.<span class="cvariable">Channel</span> msg)
+
+    <span class="keyword">fun</span> <span class="function-name">subscribers</span> id =
+        r &lt;- oneRow (<span class="sql">SELECT</span> <span class="sql">COUNT</span>( * ) <span class="sql">AS</span> <span class="cvariable">N</span> <span class="sql">FROM</span> t <span class="sql">WHERE</span> t.<span class="cvariable">Id</span> = {[id]});
+        return r.<span class="cvariable">N</span>
+<span class="keyword">end</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/broadcast.urs.html b/demo/out/broadcast.urs.html
new file mode 100644
index 0000000..74fcd32
--- /dev/null
+++ b/demo/out/broadcast.urs.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>broadcast.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .module-def {
+        /* font-lock-module-def-face */
+        font-weight: bold;
+      }
+      .type-def {
+        /* font-lock-type-def-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">functor</span> <span class="module-def">Make</span>(<span class="cvariable">M</span> : <span class="keyword">sig</span> <span class="keyword">type</span> <span class="type-def">t</span> <span class="keyword">end</span>) : <span class="keyword">sig</span>
+    <span class="keyword">type</span> <span class="type-def">topic</span>
+
+    <span class="keyword">val</span> <span class="variable-name">inj</span> : sql_injectable topic
+
+    <span class="keyword">val</span> <span class="variable-name">create</span> : transaction topic
+    <span class="keyword">val</span> <span class="variable-name">subscribe</span> : topic -&gt; transaction (channel <span class="cvariable">M</span>.t)
+    <span class="keyword">val</span> <span class="variable-name">send</span> : topic -&gt; <span class="cvariable">M</span>.t -&gt; transaction unit
+
+    <span class="keyword">val</span> <span class="variable-name">subscribers</span> : topic -&gt; transaction int
+<span class="keyword">end</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/buffer.ur.html b/demo/out/buffer.ur.html
new file mode 100644
index 0000000..4c01204
--- /dev/null
+++ b/demo/out/buffer.ur.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>buffer.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+      .type-def {
+        /* font-lock-type-def-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">datatype</span> <span class="type-def">lines</span> = <span class="cvariable">End</span> | <span class="cvariable">Line</span> <span class="keyword">of</span> string * source lines
+
+<span class="keyword">type</span> <span class="type-def">t</span> = { <span class="cvariable">Head</span> : source lines, <span class="cvariable">Tail</span> : source (source lines) }
+
+<span class="keyword">val</span> <span class="variable-name">create</span> =
+    head &lt;- source <span class="cvariable">End</span>;
+    tail &lt;- source head;
+    return {<span class="cvariable">Head</span> = head, <span class="cvariable">Tail</span> = tail}
+
+<span class="keyword">fun</span> <span class="function-name">renderL</span> lines =
+    <span class="keyword">case</span> lines <span class="keyword">of</span>
+        <span class="cvariable">End</span> =&gt; <span class="tag">&lt;xml/&gt;</span>
+      | <span class="cvariable">Line</span> (line, linesS) =&gt; <span class="tag">&lt;xml&gt;</span>{[line]}<span class="tag">&lt;br/&gt;&lt;dyn</span> signal={renderS linesS}<span class="tag">/&gt;&lt;/xml&gt;</span>
+
+<span class="keyword">and</span> <span class="function-name">renderS</span> linesS =
+    lines &lt;- signal linesS;
+    return (renderL lines)
+
+<span class="keyword">fun</span> <span class="function-name">render</span> t = renderS t.<span class="cvariable">Head</span>
+
+<span class="keyword">fun</span> <span class="function-name">write</span> t s =
+    oldTail &lt;- get t.<span class="cvariable">Tail</span>;
+    newTail &lt;- source <span class="cvariable">End</span>;
+    set oldTail (<span class="cvariable">Line</span> (s, newTail));
+    set t.<span class="cvariable">Tail</span> newTail
+</pre>
+  </body>
+</html>
diff --git a/demo/out/buffer.urs.html b/demo/out/buffer.urs.html
new file mode 100644
index 0000000..035ab57
--- /dev/null
+++ b/demo/out/buffer.urs.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>buffer.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .type-def {
+        /* font-lock-type-def-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">type</span> <span class="type-def">t</span>
+
+<span class="keyword">val</span> <span class="variable-name">create</span> : transaction t
+<span class="keyword">val</span> <span class="variable-name">render</span> : t -&gt; signal xbody
+<span class="keyword">val</span> <span class="variable-name">write</span> : t -&gt; string -&gt; transaction unit
+</pre>
+  </body>
+</html>
diff --git a/demo/out/chat.desc.html b/demo/out/chat.desc.html
new file mode 100644
index 0000000..48ba5dc
--- /dev/null
+++ b/demo/out/chat.desc.html
@@ -0,0 +1,16 @@
+<html><head>
+<title>Chat</title>
+</head><body>
+
+<h1>Chat</h1>
+
+<center>[ <a target="showcase" href="/Demo/Chat/main">Application</a> | <a target="showcase" href="chat.urp.html"><tt>chat.urp</tt></a> | <a target="showcase" href="broadcast.urs.html"><tt>broadcast.urs</tt></a> | <a target="showcase" href="broadcast.ur.html"><tt>broadcast.ur</tt></a> | <a target="showcase" href="buffer.urs.html"><tt>buffer.urs</tt></a> | <a target="showcase" href="buffer.ur.html"><tt>buffer.ur</tt></a> | <a target="showcase" href="chat.urs.html"><tt>chat.urs</tt></a> | <a target="showcase" href="chat.ur.html"><tt>chat.ur</tt></a> ]</center>
+
+
+<p>This example provides a simple anonymous online chatting system, with multiple named channels.</p>
+
+<p>First, we build another useful component.  Recall that each channel has an owning client, who has the exclusive ability to read messages sent to it.  On top of that functionality, we can build a kind of broadcast channel that accepts multiple subscribers.  The <tt>Broadcast</tt> module contains a functor with such an implementation.  We instantiate the functor with the type of data we want to send over the channel.  The functor output gives us an abstract type of "topics," which are subscribable IDs.  When a client subscribes to a topic, it is handed a channel that it can use to read new messages on that topic.  We also have an operation to count the number of subscribers to a topic.  This number shouldn't be treated as too precise, since some clients that have surfed away from the application may still be considered subscribed until a timeout period elapses.</p>
+
+<p>The main <tt>Chat</tt> application includes some standard management of a table of named channels.  All of the interesting client-server work is done with the <tt>recv</tt> function and with the functions provided by <tt>Broadcast</tt>.</p>
+
+</body></html>
diff --git a/demo/out/chat.html b/demo/out/chat.html
new file mode 100644
index 0000000..0b72870
--- /dev/null
+++ b/demo/out/chat.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/Chat/main" name="showcase">
+<frame src="chat.desc.html">
+</frameset>
diff --git a/demo/out/chat.ur.html b/demo/out/chat.ur.html
new file mode 100644
index 0000000..f2e32b5
--- /dev/null
+++ b/demo/out/chat.ur.html
@@ -0,0 +1,159 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>chat.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .module-def {
+        /* font-lock-module-def-face */
+        font-weight: bold;
+      }
+      .sql {
+        /* font-lock-sql-face */
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+      .type-def {
+        /* font-lock-type-def-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">structure</span> <span class="module-def">Room</span> = <span class="cvariable">Broadcast</span>.<span class="cvariable">Make</span>(<span class="keyword">struct</span>
+                                    <span class="keyword">type</span> <span class="type-def">t</span> = string
+                                <span class="keyword">end</span>)
+
+<span class="keyword">sequence</span> s
+<span class="keyword">table</span> <span class="variable-name">t</span> : { <span class="cvariable">Id</span> : int, <span class="cvariable">Title</span> : string, <span class="cvariable">Room</span> : <span class="cvariable">Room</span>.topic }
+  <span class="sql">PRIMARY</span> <span class="sql">KEY</span> <span class="cvariable">Id</span>
+
+<span class="keyword">fun</span> <span class="function-name">chat</span> id () =
+    r &lt;- oneRow (<span class="sql">SELECT</span> t.<span class="cvariable">Title</span>, t.<span class="cvariable">Room</span> <span class="sql">FROM</span> t <span class="sql">WHERE</span> t.<span class="cvariable">Id</span> = {[id]});
+    ch &lt;- <span class="cvariable">Room</span>.subscribe r.<span class="cvariable">T</span>.<span class="cvariable">Room</span>;
+
+    newLine &lt;- source <span class="string">""</span>;
+    buf &lt;- <span class="cvariable">Buffer</span>.create;
+
+    <span class="keyword">let</span>
+        <span class="keyword">fun</span> <span class="function-name">onload</span> () =
+            <span class="keyword">let</span>
+                <span class="keyword">fun</span> <span class="function-name">listener</span> () =
+                    s &lt;- recv ch;
+                    <span class="cvariable">Buffer</span>.write buf s;
+                    listener ()
+            <span class="keyword">in</span>
+                listener ()
+            <span class="keyword">end</span>
+
+        <span class="keyword">fun</span> <span class="function-name">getRoom</span> () =
+            r &lt;- oneRow (<span class="sql">SELECT</span> t.<span class="cvariable">Room</span> <span class="sql">FROM</span> t <span class="sql">WHERE</span> t.<span class="cvariable">Id</span> = {[id]});
+            return r.<span class="cvariable">T</span>.<span class="cvariable">Room</span>
+
+        <span class="keyword">fun</span> <span class="function-name">speak</span> line =
+            room &lt;- getRoom ();
+            <span class="cvariable">Room</span>.send room line
+
+        <span class="keyword">fun</span> <span class="function-name">doSpeak</span> () =
+            line &lt;- get newLine;
+            set newLine <span class="string">""</span>;
+            rpc (speak line)
+    <span class="keyword">in</span>
+        return <span class="tag">&lt;xml&gt;&lt;body</span> onload={onload ()}<span class="tag">&gt;</span><span class="string">
+          </span><span class="tag">&lt;h1&gt;</span>{[r.<span class="cvariable">T</span>.<span class="cvariable">Title</span>]}<span class="tag">&lt;/h1&gt;</span><span class="string">
+
+          </span><span class="tag">&lt;button</span> value=<span class="string">"Send:"</span> onclick={doSpeak ()}<span class="tag">/&gt;</span><span class="string"> </span><span class="tag">&lt;ctextbox</span> source={newLine}<span class="tag">/&gt;</span><span class="string">
+
+          </span><span class="tag">&lt;h2&gt;</span><span class="string">Messages</span><span class="tag">&lt;/h2&gt;</span><span class="string">
+
+          </span><span class="tag">&lt;dyn</span> signal={<span class="cvariable">Buffer</span>.render buf}<span class="tag">/&gt;</span><span class="string">
+          
+        </span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>            
+    <span class="keyword">end</span>
+
+<span class="keyword">fun</span> <span class="function-name">list</span> () =
+    queryX' (<span class="sql">SELECT</span> * <span class="sql">FROM</span> t)
+    (<span class="keyword">fn</span> r =&gt;
+        count &lt;- <span class="cvariable">Room</span>.subscribers r.<span class="cvariable">T</span>.<span class="cvariable">Room</span>;
+        return <span class="tag">&lt;xml&gt;&lt;tr&gt;</span><span class="string">
+          </span><span class="tag">&lt;td&gt;</span>{[r.<span class="cvariable">T</span>.<span class="cvariable">Id</span>]}<span class="tag">&lt;/td&gt;</span><span class="string">
+          </span><span class="tag">&lt;td&gt;</span>{[r.<span class="cvariable">T</span>.<span class="cvariable">Title</span>]}<span class="tag">&lt;/td&gt;</span><span class="string">
+          </span><span class="tag">&lt;td&gt;</span>{[count]}<span class="tag">&lt;/td&gt;</span><span class="string">
+          </span><span class="tag">&lt;td&gt;&lt;form&gt;&lt;submit</span> action={chat r.<span class="cvariable">T</span>.<span class="cvariable">Id</span>} value=<span class="string">"Enter"</span><span class="tag">/&gt;&lt;/form&gt;&lt;/td&gt;</span><span class="string">
+          </span><span class="tag">&lt;td&gt;&lt;form&gt;&lt;submit</span> action={delete r.<span class="cvariable">T</span>.<span class="cvariable">Id</span>} value=<span class="string">"Delete"</span><span class="tag">/&gt;&lt;/form&gt;&lt;/td&gt;</span><span class="string">
+        </span><span class="tag">&lt;/tr&gt;&lt;/xml&gt;</span>)
+
+<span class="keyword">and</span> <span class="function-name">delete</span> id () =
+    dml (<span class="sql">DELETE</span> <span class="sql">FROM</span> t <span class="sql">WHERE</span> <span class="cvariable">Id</span> = {[id]});
+    main ()
+
+<span class="keyword">and</span> <span class="function-name">main</span> () =
+    <span class="keyword">let</span>
+        <span class="keyword">fun</span> <span class="function-name">create</span> r =
+            id &lt;- nextval s;
+            room &lt;- <span class="cvariable">Room</span>.create;
+            dml (<span class="sql">INSERT</span> <span class="sql">INTO</span> t (<span class="cvariable">Id</span>, <span class="cvariable">Title</span>, <span class="cvariable">Room</span>) <span class="sql">VALUES</span> ({[id]}, {[r.<span class="cvariable">Title</span>]}, {[room]}));
+            main ()
+    <span class="keyword">in</span>
+        ls &lt;- list ();
+        return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+          </span><span class="tag">&lt;h1&gt;</span><span class="string">Current Channels</span><span class="tag">&lt;/h1&gt;</span><span class="string">
+
+          </span><span class="tag">&lt;table&gt;</span><span class="string">
+            </span><span class="tag">&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">ID</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">Title</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">#Subscribers</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+            </span>{ls}<span class="string">
+          </span><span class="tag">&lt;/table&gt;</span><span class="string">
+          
+          </span><span class="tag">&lt;h1&gt;</span><span class="string">New Channel</span><span class="tag">&lt;/h1&gt;</span><span class="string">
+          
+          </span><span class="tag">&lt;form&gt;</span><span class="string">
+            Title: </span><span class="tag">&lt;textbox</span>{#<span class="cvariable">Title</span>}<span class="tag">/&gt;&lt;br/&gt;</span><span class="string">
+            </span><span class="tag">&lt;submit</span> action={create}<span class="tag">/&gt;</span><span class="string">
+          </span><span class="tag">&lt;/form&gt;</span><span class="string">
+        </span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+    <span class="keyword">end</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/chat.urp.html b/demo/out/chat.urp.html
new file mode 100644
index 0000000..5a955ea
--- /dev/null
+++ b/demo/out/chat.urp.html
@@ -0,0 +1,11 @@
+<html><body>
+
+<pre>database dbname=test
+sql chat.sql
+
+broadcast
+buffer
+chat
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/chat.urs.html b/demo/out/chat.urs.html
new file mode 100644
index 0000000..ee0c466
--- /dev/null
+++ b/demo/out/chat.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>chat.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+</pre>
+  </body>
+</html>
diff --git a/demo/out/constraints.desc.html b/demo/out/constraints.desc.html
new file mode 100644
index 0000000..dfc38c0
--- /dev/null
+++ b/demo/out/constraints.desc.html
@@ -0,0 +1,20 @@
+<html><head>
+<title>Constraints</title>
+</head><body>
+
+<h1>Constraints</h1>
+
+<center>[ <a target="showcase" href="/Demo/Constraints/main">Application</a> | <a target="showcase" href="constraints.urp.html"><tt>constraints.urp</tt></a> | <a target="showcase" href="constraints.urs.html"><tt>constraints.urs</tt></a> | <a target="showcase" href="constraints.ur.html"><tt>constraints.ur</tt></a> ]</center>
+
+
+<p>Ur/Web supports attaching SQL table constraints to table definitions.  We've sprinkled a few such constraints throughout our examples so far, without mentioning them.  This example shows a table with all four of the supported kinds of constraints.  An application would generally try to avoid inserting data that violates constraints, but, in this example, we let you insert arbitrary data, so that you can see each of the constraints failing.</p>
+
+<ol>
+        <li>The <tt>PRIMARY KEY</tt> constraint establishes the field of the table that we expect to use as a key in looking up specific rows.  It is an error for two rows to share the same primary key.</li>
+        <li>The <tt>UNIQUE</tt> constraint is like <tt>PRIMARY KEY</tt>, with the difference being that a table may have many <tt>UNIQUE</tt> constraints but no more than one primary key.</li>
+        <li>The <tt>CHECK</tt> constraint declares a boolean assertion that must hold for every row of the table.</li>
+        <li>The <tt>FOREIGN KEY</tt> constraint declares that a row of the table references a particular column of another table, or of the same table, as we see in this example.  It's a static type error to reference a foreign key column that has no <tt>PRIMARY KEY</tt> or <tt>UNIQUE</tt> constraint.</li>
+</ol>
+
+
+</body></html>
diff --git a/demo/out/constraints.html b/demo/out/constraints.html
new file mode 100644
index 0000000..2b77b53
--- /dev/null
+++ b/demo/out/constraints.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/Constraints/main" name="showcase">
+<frame src="constraints.desc.html">
+</frameset>
diff --git a/demo/out/constraints.ur.html b/demo/out/constraints.ur.html
new file mode 100644
index 0000000..425d278
--- /dev/null
+++ b/demo/out/constraints.ur.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>constraints.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .sql {
+        /* font-lock-sql-face */
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">table</span> <span class="variable-name">t</span> : { <span class="cvariable">Id</span> : int, <span class="cvariable">Nam</span> : string, <span class="cvariable">Parent</span> : option int }
+  <span class="sql">PRIMARY</span> <span class="sql">KEY</span> <span class="cvariable">Id</span>,
+  <span class="sql">CONSTRAINT</span> <span class="cvariable">Nam</span> <span class="sql">UNIQUE</span> <span class="cvariable">Nam</span>,
+  <span class="sql">CONSTRAINT</span> <span class="cvariable">Id</span> <span class="sql">CHECK</span> <span class="cvariable">Id</span> &gt;= 0,
+  <span class="sql">CONSTRAINT</span> <span class="cvariable">Parent</span> <span class="sql">FOREIGN</span> <span class="sql">KEY</span> <span class="cvariable">Parent</span> <span class="sql">REFERENCES</span> t(<span class="cvariable">Id</span>)
+
+<span class="keyword">fun</span> <span class="function-name">main</span> () =
+    list &lt;- queryX (<span class="sql">SELECT</span> * <span class="sql">FROM</span> t)
+            (<span class="keyword">fn</span> r =&gt; <span class="tag">&lt;xml&gt;&lt;tr&gt;</span><span class="string">
+              </span><span class="tag">&lt;td&gt;</span>{[r.<span class="cvariable">T</span>.<span class="cvariable">Id</span>]}<span class="tag">&lt;/td&gt;</span><span class="string">
+              </span><span class="tag">&lt;td&gt;</span>{[r.<span class="cvariable">T</span>.<span class="cvariable">Nam</span>]}<span class="tag">&lt;/td&gt;</span><span class="string">
+              </span><span class="tag">&lt;td&gt;</span>{<span class="keyword">case</span> r.<span class="cvariable">T</span>.<span class="cvariable">Parent</span> <span class="keyword">of</span>
+                       <span class="cvariable">None</span> =&gt; <span class="tag">&lt;xml&gt;</span><span class="string">NULL</span><span class="tag">&lt;/xml&gt;</span>
+                     | <span class="cvariable">Some</span> id =&gt; <span class="tag">&lt;xml&gt;</span>{[id]}<span class="tag">&lt;/xml&gt;</span>}<span class="tag">&lt;/td&gt;</span><span class="string">
+            </span><span class="tag">&lt;/tr&gt;&lt;/xml&gt;</span>);
+    return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+      </span><span class="tag">&lt;table&gt;</span><span class="string">
+        </span><span class="tag">&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">Id</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">Name</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">Parent</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+        </span>{list}<span class="string">
+      </span><span class="tag">&lt;/table&gt;</span><span class="string">
+
+      </span><span class="tag">&lt;form&gt;</span><span class="string">
+        </span><span class="tag">&lt;table&gt;</span><span class="string">
+          </span><span class="tag">&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">Id:</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;td&gt;&lt;textbox</span>{#<span class="cvariable">Id</span>}<span class="tag">/&gt;&lt;/td&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+          </span><span class="tag">&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">Name:</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;td&gt;&lt;textbox</span>{#<span class="cvariable">Nam</span>}<span class="tag">/&gt;&lt;/td&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+          </span><span class="tag">&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">Parent:</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;td&gt;&lt;textbox</span>{#<span class="cvariable">Parent</span>}<span class="tag">/&gt;&lt;/td&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+          </span><span class="tag">&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th/&gt;</span><span class="string"> </span><span class="tag">&lt;td&gt;&lt;submit</span> action={add}<span class="tag">/&gt;&lt;/td&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+        </span><span class="tag">&lt;/table&gt;</span><span class="string">
+      </span><span class="tag">&lt;/form&gt;</span><span class="string">
+    </span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+
+<span class="keyword">and</span> <span class="function-name">add</span> r =
+    dml (<span class="sql">INSERT</span> <span class="sql">INTO</span> t (<span class="cvariable">Id</span>, <span class="cvariable">Nam</span>, <span class="cvariable">Parent</span>)
+           <span class="sql">VALUES</span> ({[readError r.<span class="cvariable">Id</span>]}, {[r.<span class="cvariable">Nam</span>]},
+               {[<span class="keyword">case</span> r.<span class="cvariable">Parent</span> <span class="keyword">of</span>
+                   <span class="string">""</span> =&gt; <span class="cvariable">None</span>
+                 | s =&gt; <span class="cvariable">Some</span> (readError s)]}));
+    main ()
+</pre>
+  </body>
+</html>
diff --git a/demo/out/constraints.urp.html b/demo/out/constraints.urp.html
new file mode 100644
index 0000000..17dc815
--- /dev/null
+++ b/demo/out/constraints.urp.html
@@ -0,0 +1,9 @@
+<html><body>
+
+<pre>database dbname=test
+sql constraints.sql
+
+constraints
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/constraints.urs.html b/demo/out/constraints.urs.html
new file mode 100644
index 0000000..cb1860b
--- /dev/null
+++ b/demo/out/constraints.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>constraints.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+</pre>
+  </body>
+</html>
diff --git a/demo/out/cookie.desc.html b/demo/out/cookie.desc.html
new file mode 100644
index 0000000..304811f
--- /dev/null
+++ b/demo/out/cookie.desc.html
@@ -0,0 +1,15 @@
+<html><head>
+<title>Cookie</title>
+</head><body>
+
+<h1>Cookie</h1>
+
+<center>[ <a target="showcase" href="/Demo/Cookie/main">Application</a> | <a target="showcase" href="cookie.urp.html"><tt>cookie.urp</tt></a> | <a target="showcase" href="cookie.urs.html"><tt>cookie.urs</tt></a> | <a target="showcase" href="cookie.ur.html"><tt>cookie.ur</tt></a> ]</center>
+
+
+<p>Often, it is useful to associate persistent data with particular web clients.  Ur/Web includes an easy facility for using type-safe cookies.  This example shows how to use a form to set a named cookie.</p>
+
+<p>After setting the cookie, try browsing back to this demo from the main index.  The data you entered should still be there.</p>
+
+
+</body></html>
diff --git a/demo/out/cookie.html b/demo/out/cookie.html
new file mode 100644
index 0000000..85b3f3f
--- /dev/null
+++ b/demo/out/cookie.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/Cookie/main" name="showcase">
+<frame src="cookie.desc.html">
+</frameset>
diff --git a/demo/out/cookie.ur.html b/demo/out/cookie.ur.html
new file mode 100644
index 0000000..0fd1af6
--- /dev/null
+++ b/demo/out/cookie.ur.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>cookie.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">cookie</span> <span class="variable-name">c</span> : {<span class="cvariable">A</span> : string, <span class="cvariable">B</span> : float, <span class="cvariable">C</span> : int}
+
+<span class="keyword">fun</span> <span class="function-name">set</span> r =
+    setCookie c {<span class="cvariable">Value</span> = {<span class="cvariable">A</span> = r.<span class="cvariable">A</span>, <span class="cvariable">B</span> = readError r.<span class="cvariable">B</span>, <span class="cvariable">C</span> = readError r.<span class="cvariable">C</span>},
+                 <span class="cvariable">Expires</span> = <span class="cvariable">None</span>,
+                 <span class="cvariable">Secure</span> = <span class="cvariable">False</span>};
+    return <span class="tag">&lt;xml&gt;</span><span class="string">Cookie set.</span><span class="tag">&lt;/xml&gt;</span>
+
+<span class="keyword">fun</span> <span class="function-name">setExp</span> r =
+    setCookie c {<span class="cvariable">Value</span> = {<span class="cvariable">A</span> = r.<span class="cvariable">A</span>, <span class="cvariable">B</span> = readError r.<span class="cvariable">B</span>, <span class="cvariable">C</span> = readError r.<span class="cvariable">C</span>},
+                 <span class="cvariable">Expires</span> = <span class="cvariable">Some</span> (readError <span class="string">"2012-11-6 00:00:00"</span>),
+                 <span class="cvariable">Secure</span> = <span class="cvariable">False</span>};
+    return <span class="tag">&lt;xml&gt;</span><span class="string">Cookie set robustly.</span><span class="tag">&lt;/xml&gt;</span>
+
+<span class="keyword">fun</span> <span class="function-name">delete</span> () =
+    clearCookie c;
+    return <span class="tag">&lt;xml&gt;</span><span class="string">Cookie cleared.</span><span class="tag">&lt;/xml&gt;</span>
+
+<span class="keyword">fun</span> <span class="function-name">main</span> () =
+    ro &lt;- getCookie c;
+    return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+      </span>{<span class="keyword">case</span> ro <span class="keyword">of</span>
+           <span class="cvariable">None</span> =&gt; <span class="tag">&lt;xml&gt;</span><span class="string">No cookie set.</span><span class="tag">&lt;/xml&gt;</span>
+         | <span class="cvariable">Some</span> v =&gt; <span class="tag">&lt;xml&gt;</span><span class="string">
+           Cookie: A = </span>{[v.<span class="cvariable">A</span>]}<span class="string">, B = </span>{[v.<span class="cvariable">B</span>]}<span class="string">, C = </span>{[v.<span class="cvariable">C</span>]}<span class="tag">&lt;br/&gt;</span><span class="string">
+           </span><span class="tag">&lt;form&gt;&lt;submit</span> value=<span class="string">"Delete"</span> action={delete}<span class="tag">/&gt;&lt;/form&gt;</span><span class="string">
+         </span><span class="tag">&lt;/xml&gt;</span>}<span class="string">
+      </span><span class="tag">&lt;br/&gt;&lt;br/&gt;</span><span class="string">
+
+      </span><span class="tag">&lt;form&gt;</span><span class="string">
+        A: </span><span class="tag">&lt;textbox</span>{#<span class="cvariable">A</span>}<span class="tag">/&gt;&lt;br/&gt;</span><span class="string">
+        B: </span><span class="tag">&lt;textbox</span>{#<span class="cvariable">B</span>}<span class="tag">/&gt;&lt;br/&gt;</span><span class="string">
+        C: </span><span class="tag">&lt;textbox</span>{#<span class="cvariable">C</span>}<span class="tag">/&gt;&lt;br/&gt;</span><span class="string">
+        </span><span class="tag">&lt;submit</span> action={set}<span class="tag">/&gt;</span><span class="string">
+      </span><span class="tag">&lt;/form&gt;&lt;br/&gt;</span><span class="string">
+
+      </span><span class="tag">&lt;form&gt;</span><span class="string">
+        </span><span class="tag">&lt;b&gt;</span><span class="string">Version that expires on November 6, 2012:</span><span class="tag">&lt;/b&gt;&lt;br/&gt;</span><span class="string">
+        A: </span><span class="tag">&lt;textbox</span>{#<span class="cvariable">A</span>}<span class="tag">/&gt;&lt;br/&gt;</span><span class="string">
+        B: </span><span class="tag">&lt;textbox</span>{#<span class="cvariable">B</span>}<span class="tag">/&gt;&lt;br/&gt;</span><span class="string">
+        C: </span><span class="tag">&lt;textbox</span>{#<span class="cvariable">C</span>}<span class="tag">/&gt;&lt;br/&gt;</span><span class="string">
+        </span><span class="tag">&lt;submit</span> action={setExp}<span class="tag">/&gt;</span><span class="string">
+      </span><span class="tag">&lt;/form&gt;</span><span class="string">
+    </span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/cookie.urp.html b/demo/out/cookie.urp.html
new file mode 100644
index 0000000..793bc23
--- /dev/null
+++ b/demo/out/cookie.urp.html
@@ -0,0 +1,6 @@
+<html><body>
+
+<pre>cookie
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/cookie.urs.html b/demo/out/cookie.urs.html
new file mode 100644
index 0000000..4e361b6
--- /dev/null
+++ b/demo/out/cookie.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>cookie.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+</pre>
+  </body>
+</html>
diff --git a/demo/out/cookieSec.desc.html b/demo/out/cookieSec.desc.html
new file mode 100644
index 0000000..4cf2476
--- /dev/null
+++ b/demo/out/cookieSec.desc.html
@@ -0,0 +1,15 @@
+<html><head>
+<title>CookieSec</title>
+</head><body>
+
+<h1>CookieSec</h1>
+
+<center>[ <a target="showcase" href="/Demo/CookieSec/main">Application</a> | <a target="showcase" href="cookieSec.urp.html"><tt>cookieSec.urp</tt></a> | <a target="showcase" href="cookieSec.urs.html"><tt>cookieSec.urs</tt></a> | <a target="showcase" href="cookieSec.ur.html"><tt>cookieSec.ur</tt></a> ]</center>
+
+
+<p>Ur/Web guarantees that compiled applications are immune to certain kinds of <a href="http://www.owasp.org/index.php/Top_10_2007-A5">cross site request forgery</a>.  For instance, a "phisher" might send many e-mails linking to a form that he has set up to look like your web site.  The form is connected to your web site, where it might, say, transfer money from your bank account to the phisher's account.  The phisher doesn't know your username, but, if that username is stored in a cookie, it will be sent automatically by your browser.  Ur/Web automatically signs cookie values cryptographically, with the signature included as a POST parameter and not part of a cookie, to prevent such attacks.</p>
+
+<p>This demo shows a simple mock-up of a situation where such an attack is often possible with traditional web frameworks.  You can set an arbitrary username for yourself in a cookie, and you can modify the database in a way that depends on the current cookie value.  Try getting the latter action to succeed without first setting your desired username in the cookie.  This should be roughly as impossible as cracking the particular cryptographic hash function that is used.</p>
+
+
+</body></html>
diff --git a/demo/out/cookieSec.html b/demo/out/cookieSec.html
new file mode 100644
index 0000000..a99eac7
--- /dev/null
+++ b/demo/out/cookieSec.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/CookieSec/main" name="showcase">
+<frame src="cookieSec.desc.html">
+</frameset>
diff --git a/demo/out/cookieSec.ur.html b/demo/out/cookieSec.ur.html
new file mode 100644
index 0000000..de5ce6b
--- /dev/null
+++ b/demo/out/cookieSec.ur.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>cookieSec.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .sql {
+        /* font-lock-sql-face */
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">cookie</span> <span class="variable-name">username</span> : string
+
+<span class="keyword">table</span> <span class="variable-name">lastVisit</span> : { <span class="cvariable">User</span> : string, <span class="cvariable">When</span> : time }
+  <span class="sql">PRIMARY</span> <span class="sql">KEY</span> <span class="cvariable">User</span>
+
+<span class="keyword">fun</span> <span class="function-name">main</span> () =
+    userO &lt;- getCookie username;
+
+    list &lt;- queryX (<span class="sql">SELECT</span> * <span class="sql">FROM</span> lastVisit)
+                   (<span class="keyword">fn</span> r =&gt; <span class="tag">&lt;xml&gt;&lt;tr&gt;&lt;td&gt;</span>{[r.<span class="cvariable">LastVisit</span>.<span class="cvariable">User</span>]}<span class="tag">&lt;/td&gt;</span><span class="string"> </span><span class="tag">&lt;td&gt;</span>{[r.<span class="cvariable">LastVisit</span>.<span class="cvariable">When</span>]}<span class="tag">&lt;/td&gt;&lt;/tr&gt;&lt;/xml&gt;</span>);
+
+    return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+      Cookie: </span>{[userO]}<span class="tag">&lt;br/&gt;</span><span class="string">
+
+      </span><span class="tag">&lt;table&gt;</span><span class="string">
+        </span><span class="tag">&lt;tr&gt;&lt;th&gt;</span><span class="string">User</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">Last Visit</span><span class="tag">&lt;/th&gt;&lt;/tr&gt;</span><span class="string">
+        </span>{list}<span class="string">
+      </span><span class="tag">&lt;/table&gt;</span><span class="string">
+
+      </span><span class="tag">&lt;h2&gt;</span><span class="string">Set cookie value</span><span class="tag">&lt;/h2&gt;</span><span class="string">
+      </span><span class="tag">&lt;form&gt;&lt;textbox</span>{#<span class="cvariable">User</span>}<span class="tag">/&gt;</span><span class="string"> </span><span class="tag">&lt;submit</span> action={set}<span class="tag">/&gt;&lt;/form&gt;</span><span class="string">
+
+      </span><span class="tag">&lt;h2&gt;</span><span class="string">Record your visit</span><span class="tag">&lt;/h2&gt;</span><span class="string">
+      </span><span class="tag">&lt;form&gt;&lt;submit</span> action={imHere}<span class="tag">/&gt;&lt;/form&gt;</span><span class="string">
+    </span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+
+<span class="keyword">and</span> <span class="function-name">set</span> r =
+    setCookie username {<span class="cvariable">Value</span> = r.<span class="cvariable">User</span>, <span class="cvariable">Expires</span> = <span class="cvariable">None</span>, <span class="cvariable">Secure</span> = <span class="cvariable">False</span>};
+    main ()
+
+<span class="keyword">and</span> <span class="function-name">imHere</span> () =
+    userO &lt;- getCookie username;
+    <span class="keyword">case</span> userO <span class="keyword">of</span>
+        <span class="cvariable">None</span> =&gt; return <span class="tag">&lt;xml&gt;</span><span class="string">You don't have a cookie set!</span><span class="tag">&lt;/xml&gt;</span>
+      | <span class="cvariable">Some</span> user =&gt;
+        dml (<span class="sql">DELETE</span> <span class="sql">FROM</span> lastVisit <span class="sql">WHERE</span> <span class="cvariable">User</span> = {[user]});
+        dml (<span class="sql">INSERT</span> <span class="sql">INTO</span> lastVisit (<span class="cvariable">User</span>, <span class="cvariable">When</span>) <span class="sql">VALUES</span> ({[user]}, <span class="cvariable">CURRENT_TIMESTAMP</span>));
+        main ()
+
+</pre>
+  </body>
+</html>
diff --git a/demo/out/cookieSec.urp.html b/demo/out/cookieSec.urp.html
new file mode 100644
index 0000000..e2826b2
--- /dev/null
+++ b/demo/out/cookieSec.urp.html
@@ -0,0 +1,9 @@
+<html><body>
+
+<pre>database dbname=test
+sql cookieSec.sql
+
+cookieSec
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/cookieSec.urs.html b/demo/out/cookieSec.urs.html
new file mode 100644
index 0000000..70a4222
--- /dev/null
+++ b/demo/out/cookieSec.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>cookieSec.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+</pre>
+  </body>
+</html>
diff --git a/demo/out/counter.desc.html b/demo/out/counter.desc.html
new file mode 100644
index 0000000..0954f99
--- /dev/null
+++ b/demo/out/counter.desc.html
@@ -0,0 +1,15 @@
+<html><head>
+<title>Counter</title>
+</head><body>
+
+<h1>Counter</h1>
+
+<center>[ <a target="showcase" href="/Demo/Counter/main">Application</a> | <a target="showcase" href="counter.urp.html"><tt>counter.urp</tt></a> | <a target="showcase" href="counter.urs.html"><tt>counter.urs</tt></a> | <a target="showcase" href="counter.ur.html"><tt>counter.ur</tt></a> ]</center>
+
+
+<p>It is also easy to pass state around via functions, in the style commonly associated with "continuation-based" web servers.  As is usual for such systems, all state is stored on the client side.  In this case, it is encoded in URLs.</p>
+
+<p>In the implementation of <tt>Counter.counter</tt>, we see the notation <tt>{[...]}</tt>, which uses type classes to inject values of different types (<tt>int</tt> in this case) into XML.  It's probably worth stating explicitly that XML fragments <i>are not strings</i>, so that the type-checker will enforce that our final piece of XML is valid.</p>
+
+
+</body></html>
diff --git a/demo/out/counter.html b/demo/out/counter.html
new file mode 100644
index 0000000..9613f38
--- /dev/null
+++ b/demo/out/counter.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/Counter/main" name="showcase">
+<frame src="counter.desc.html">
+</frameset>
diff --git a/demo/out/counter.ur.html b/demo/out/counter.ur.html
new file mode 100644
index 0000000..9ec9e8c
--- /dev/null
+++ b/demo/out/counter.ur.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>counter.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">fun</span> <span class="function-name">counter</span> n = return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+  Current counter: </span>{[n]}<span class="tag">&lt;br/&gt;</span><span class="string">
+  </span><span class="tag">&lt;a</span> link={counter (n + 1)}<span class="tag">&gt;</span><span class="string">Increment</span><span class="tag">&lt;/a&gt;&lt;br/&gt;</span><span class="string">
+  </span><span class="tag">&lt;a</span> link={counter (n - 1)}<span class="tag">&gt;</span><span class="string">Decrement</span><span class="tag">&lt;/a&gt;</span><span class="string">
+</span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+
+<span class="keyword">fun</span> <span class="function-name">main</span> () = counter 0
+</pre>
+  </body>
+</html>
diff --git a/demo/out/counter.urp.html b/demo/out/counter.urp.html
new file mode 100644
index 0000000..3656dcd
--- /dev/null
+++ b/demo/out/counter.urp.html
@@ -0,0 +1,6 @@
+<html><body>
+
+<pre>counter
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/counter.urs.html b/demo/out/counter.urs.html
new file mode 100644
index 0000000..6496868
--- /dev/null
+++ b/demo/out/counter.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>counter.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+</pre>
+  </body>
+</html>
diff --git a/demo/out/crud.ur.html b/demo/out/crud.ur.html
new file mode 100644
index 0000000..4718d53
--- /dev/null
+++ b/demo/out/crud.ur.html
@@ -0,0 +1,250 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>crud.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .module-def {
+        /* font-lock-module-def-face */
+        font-weight: bold;
+      }
+      .sql {
+        /* font-lock-sql-face */
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+      .type-def {
+        /* font-lock-type-def-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">con</span> <span class="type-def">colMeta</span> = <span class="keyword">fn</span> (db :: <span class="keyword">Type</span>, widget :: <span class="keyword">Type</span>) =&gt;
+                 {<span class="cvariable">Nam</span> : string,
+                  <span class="cvariable">Show</span> : db -&gt; xbody,
+                  <span class="cvariable">Widget</span> : nm :: <span class="keyword">Name</span> -&gt; xml form [] [nm = widget],
+                  <span class="cvariable">WidgetPopulated</span> : nm :: <span class="keyword">Name</span> -&gt; db -&gt; xml form [] [nm = widget],
+                  <span class="cvariable">Parse</span> : widget -&gt; db,
+                  <span class="cvariable">Inject</span> : sql_injectable db}
+<span class="keyword">con</span> <span class="type-def">colsMeta</span> = <span class="keyword">fn</span> cols :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)} =&gt; $(<span class="keyword">map</span> colMeta cols)
+
+<span class="keyword">fun</span> <span class="function-name">default</span> [t] (sh : show t) (rd : read t) (inj : sql_injectable t)
+            name : colMeta (t, string) =
+    {<span class="cvariable">Nam</span> = name,
+     <span class="cvariable">Show</span> = txt,
+     <span class="cvariable">Widget</span> = <span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] =&gt; <span class="tag">&lt;xml&gt;&lt;textbox</span>{nm}<span class="tag">/&gt;&lt;/xml&gt;</span>,
+     <span class="cvariable">WidgetPopulated</span> = <span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] n =&gt;
+                          <span class="tag">&lt;xml&gt;&lt;textbox</span>{nm} value={show n}<span class="tag">/&gt;&lt;/xml&gt;</span>,
+     <span class="cvariable">Parse</span> = readError,
+     <span class="cvariable">Inject</span> = _}
+
+<span class="keyword">val</span> <span class="variable-name">int</span> = default
+<span class="keyword">val</span> <span class="variable-name">float</span> = default
+<span class="keyword">val</span> <span class="variable-name">string</span> = default
+
+<span class="keyword">fun</span> <span class="function-name">bool</span> name = {<span class="cvariable">Nam</span> = name,
+                 <span class="cvariable">Show</span> = txt,
+                 <span class="cvariable">Widget</span> = <span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] =&gt; <span class="tag">&lt;xml&gt;&lt;checkbox</span>{nm}<span class="tag">/&gt;&lt;/xml&gt;</span>,
+                 <span class="cvariable">WidgetPopulated</span> = <span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] b =&gt;
+                                      <span class="tag">&lt;xml&gt;&lt;checkbox</span>{nm} checked={b}<span class="tag">/&gt;&lt;/xml&gt;</span>,
+                 <span class="cvariable">Parse</span> = <span class="keyword">fn</span> x =&gt; x,
+                 <span class="cvariable">Inject</span> = _}
+
+<span class="keyword">functor</span> <span class="module-def">Make</span>(<span class="cvariable">M</span> : <span class="keyword">sig</span>
+                 <span class="keyword">con</span> <span class="type-def">cols</span> :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)}
+                 <span class="keyword">constraint</span> [<span class="cvariable">Id</span>] ~ cols
+                 <span class="keyword">val</span> <span class="variable-name">fl</span> : folder cols
+
+                 <span class="keyword">table</span> <span class="variable-name">tab</span> : ([<span class="cvariable">Id</span> = int] ++ <span class="keyword">map</span> fst cols)
+
+                 <span class="keyword">val</span> <span class="variable-name">title</span> : string
+
+                 <span class="keyword">val</span> <span class="variable-name">cols</span> : colsMeta cols
+             <span class="keyword">end</span>) = <span class="keyword">struct</span>
+
+    <span class="keyword">val</span> <span class="variable-name">tab</span> = <span class="cvariable">M</span>.tab
+
+    <span class="keyword">sequence</span> seq
+
+    <span class="keyword">fun</span> <span class="function-name">list</span> () =
+        rows &lt;- queryX (<span class="sql">SELECT</span> * <span class="sql">FROM</span> tab <span class="sql">AS</span> <span class="cvariable">T</span>)
+                       (<span class="keyword">fn</span> (fs : {<span class="cvariable">T</span> : $([<span class="cvariable">Id</span> = int] ++ <span class="keyword">map</span> fst <span class="cvariable">M</span>.cols)}) =&gt; <span class="tag">&lt;xml&gt;</span><span class="string">
+                         </span><span class="tag">&lt;tr&gt;</span><span class="string">
+                           </span><span class="tag">&lt;td&gt;</span>{[fs.<span class="cvariable">T</span>.<span class="cvariable">Id</span>]}<span class="tag">&lt;/td&gt;</span><span class="string">
+                           </span>{@foldRX2 [fst] [colMeta] [tr]
+                             (<span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] [t :: (<span class="keyword">Type</span> * <span class="keyword">Type</span>)] [rest :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)}]
+                                              [[nm] ~ rest] v col =&gt; <span class="tag">&lt;xml&gt;</span><span class="string">
+                                                </span><span class="tag">&lt;td&gt;</span>{col.<span class="cvariable">Show</span> v}<span class="tag">&lt;/td&gt;</span><span class="string">
+                                              </span><span class="tag">&lt;/xml&gt;</span>)
+                             <span class="cvariable">M</span>.fl (fs.<span class="cvariable">T</span> -- #<span class="cvariable">Id</span>) <span class="cvariable">M</span>.cols}<span class="string">
+                           </span><span class="tag">&lt;td&gt;</span><span class="string">
+                             </span><span class="tag">&lt;a</span> link={upd fs.<span class="cvariable">T</span>.<span class="cvariable">Id</span>}<span class="tag">&gt;</span><span class="string">[Update]</span><span class="tag">&lt;/a&gt;</span><span class="string">
+                             </span><span class="tag">&lt;a</span> link={confirm fs.<span class="cvariable">T</span>.<span class="cvariable">Id</span>}<span class="tag">&gt;</span><span class="string">[Delete]</span><span class="tag">&lt;/a&gt;</span><span class="string">
+                           </span><span class="tag">&lt;/td&gt;</span><span class="string">
+                         </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+                       </span><span class="tag">&lt;/xml&gt;</span>);
+        return <span class="tag">&lt;xml&gt;</span><span class="string">
+          </span><span class="tag">&lt;table</span> border={1}<span class="tag">&gt;</span><span class="string">
+            </span><span class="tag">&lt;tr&gt;</span><span class="string">
+              </span><span class="tag">&lt;th&gt;</span><span class="string">ID</span><span class="tag">&lt;/th&gt;</span><span class="string">
+              </span>{@foldRX [colMeta] [tr]
+                (<span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] [t :: (<span class="keyword">Type</span> * <span class="keyword">Type</span>)] [rest :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)}]
+                                 [[nm] ~ rest] col =&gt; <span class="tag">&lt;xml&gt;</span><span class="string">
+                                   </span><span class="tag">&lt;th&gt;</span>{cdata col.<span class="cvariable">Nam</span>}<span class="tag">&lt;/th&gt;</span><span class="string">
+                                 </span><span class="tag">&lt;/xml&gt;</span>)
+                <span class="cvariable">M</span>.fl <span class="cvariable">M</span>.cols}<span class="string">
+            </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+            </span>{rows}<span class="string">
+          </span><span class="tag">&lt;/table&gt;</span><span class="string">
+
+          </span><span class="tag">&lt;br/&gt;&lt;hr/&gt;&lt;br/&gt;</span><span class="string">
+
+          </span><span class="tag">&lt;form&gt;</span><span class="string">
+            </span>{@foldR [colMeta] [<span class="keyword">fn</span> cols :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)} =&gt; xml form [] (<span class="keyword">map</span> snd cols)]
+              (<span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] [t :: (<span class="keyword">Type</span> * <span class="keyword">Type</span>)] [rest :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)}]
+                               [[nm] ~ rest] (col : colMeta t) (acc : xml form [] (<span class="keyword">map</span> snd rest)) =&gt; <span class="tag">&lt;xml&gt;</span><span class="string">
+                                 </span><span class="tag">&lt;li&gt;</span><span class="string"> </span>{cdata col.<span class="cvariable">Nam</span>}<span class="string">: </span>{col.<span class="cvariable">Widget</span> [nm]}<span class="tag">&lt;/li&gt;</span><span class="string">
+                                 </span>{useMore acc}<span class="string">
+                               </span><span class="tag">&lt;/xml&gt;</span>)
+              <span class="tag">&lt;xml/&gt;</span>
+              <span class="cvariable">M</span>.fl <span class="cvariable">M</span>.cols}<span class="string">
+            
+            </span><span class="tag">&lt;submit</span> action={create}<span class="tag">/&gt;</span><span class="string">
+          </span><span class="tag">&lt;/form&gt;</span><span class="string">
+        </span><span class="tag">&lt;/xml&gt;</span>
+
+    <span class="keyword">and</span> <span class="function-name">create</span> (inputs : $(<span class="keyword">map</span> snd <span class="cvariable">M</span>.cols)) =
+        id &lt;- nextval seq;
+        dml (insert tab
+                    (@foldR2 [snd] [colMeta]
+                      [<span class="keyword">fn</span> cols =&gt; $(<span class="keyword">map</span> (<span class="keyword">fn</span> t :: (<span class="keyword">Type</span> * <span class="keyword">Type</span>) =&gt;
+                                            sql_exp [] [] [] t.1) cols)]
+                      (<span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] [t :: (<span class="keyword">Type</span> * <span class="keyword">Type</span>)] [rest :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)}]
+                                       [[nm] ~ rest] =&gt;
+                       <span class="keyword">fn</span> input col acc =&gt; acc ++ {nm = @sql_inject col.<span class="cvariable">Inject</span> (col.<span class="cvariable">Parse</span> input)})
+                      {} <span class="cvariable">M</span>.fl inputs <span class="cvariable">M</span>.cols
+                     ++ {<span class="cvariable">Id</span> = (<span class="sql">SQL</span> {[id]})}));
+        ls &lt;- list ();
+        return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+          </span><span class="tag">&lt;p&gt;</span><span class="string">Inserted with ID </span>{[id]}<span class="string">.</span><span class="tag">&lt;/p&gt;</span><span class="string">
+
+          </span>{ls}<span class="string">
+        </span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+
+    <span class="keyword">and</span> <span class="function-name">upd</span> (id : int) =
+        <span class="keyword">let</span>
+            <span class="keyword">fun</span> <span class="function-name">save</span> (inputs : $(<span class="keyword">map</span> snd <span class="cvariable">M</span>.cols)) =
+                dml (update [<span class="keyword">map</span> fst <span class="cvariable">M</span>.cols]
+                            (@foldR2 [snd] [colMeta]
+                              [<span class="keyword">fn</span> cols =&gt; $(<span class="keyword">map</span> (<span class="keyword">fn</span> t :: (<span class="keyword">Type</span> * <span class="keyword">Type</span>) =&gt;
+                                                    sql_exp [<span class="cvariable">T</span> = [<span class="cvariable">Id</span> = int]
+                                                                     ++ <span class="keyword">map</span> fst <span class="cvariable">M</span>.cols]
+                                                            [] [] t.1) cols)]
+                              (<span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] [t :: (<span class="keyword">Type</span> * <span class="keyword">Type</span>)] [rest :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)}]
+                                               [[nm] ~ rest] =&gt;
+                               <span class="keyword">fn</span> input col acc =&gt; acc ++ {nm =
+                                                           @sql_inject col.<span class="cvariable">Inject</span> (col.<span class="cvariable">Parse</span> input)})
+                              {} <span class="cvariable">M</span>.fl inputs <span class="cvariable">M</span>.cols)
+                            tab (<span class="sql">WHERE</span> <span class="cvariable">T</span>.<span class="cvariable">Id</span> = {[id]}));
+                ls &lt;- list ();
+                return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+                  </span><span class="tag">&lt;p&gt;</span><span class="string">Saved!</span><span class="tag">&lt;/p&gt;</span><span class="string">
+
+                  </span>{ls}<span class="string">
+                </span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+        <span class="keyword">in</span>
+            fso &lt;- oneOrNoRows (<span class="sql">SELECT</span> tab.{{<span class="keyword">map</span> fst <span class="cvariable">M</span>.cols}} <span class="sql">FROM</span> tab <span class="sql">WHERE</span> tab.<span class="cvariable">Id</span> = {[id]});
+            <span class="keyword">case</span> fso : (<span class="cvariable">Basis</span>.option {<span class="cvariable">Tab</span> : $(<span class="keyword">map</span> fst <span class="cvariable">M</span>.cols)}) <span class="keyword">of</span>
+                <span class="cvariable">None</span> =&gt; return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">Not found!</span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+              | <span class="cvariable">Some</span> fs =&gt; return <span class="tag">&lt;xml&gt;&lt;body&gt;&lt;form&gt;</span><span class="string">
+                </span>{@foldR2 [fst] [colMeta] [<span class="keyword">fn</span> cols :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)} =&gt; xml form [] (<span class="keyword">map</span> snd cols)]
+                  (<span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] [t :: (<span class="keyword">Type</span> * <span class="keyword">Type</span>)] [rest :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)}]
+                                   [[nm] ~ rest] (v : t.1) (col : colMeta t)
+                                   (acc : xml form [] (<span class="keyword">map</span> snd rest)) =&gt;
+                      <span class="tag">&lt;xml&gt;</span><span class="string">
+                        </span><span class="tag">&lt;li&gt;</span><span class="string"> </span>{cdata col.<span class="cvariable">Nam</span>}<span class="string">: </span>{col.<span class="cvariable">WidgetPopulated</span> [nm] v}<span class="tag">&lt;/li&gt;</span><span class="string">
+                        </span>{useMore acc}<span class="string">
+                      </span><span class="tag">&lt;/xml&gt;</span>)
+                  <span class="tag">&lt;xml/&gt;</span>
+                  <span class="cvariable">M</span>.fl fs.<span class="cvariable">Tab</span> <span class="cvariable">M</span>.cols}<span class="string">
+
+                </span><span class="tag">&lt;submit</span> action={save}<span class="tag">/&gt;</span><span class="string">
+              </span><span class="tag">&lt;/form&gt;&lt;/body&gt;&lt;/xml&gt;</span>
+        <span class="keyword">end</span>
+
+    <span class="keyword">and</span> <span class="function-name">confirm</span> (id : int) =
+        <span class="keyword">let</span>
+            <span class="keyword">fun</span> <span class="function-name">delete</span> () =
+                dml (<span class="sql">DELETE</span> <span class="sql">FROM</span> tab <span class="sql">WHERE</span> <span class="cvariable">Id</span> = {[id]});
+                ls &lt;- list ();
+                return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+                  </span><span class="tag">&lt;p&gt;</span><span class="string">The deed is done.</span><span class="tag">&lt;/p&gt;</span><span class="string">
+                  
+                  </span>{ls}<span class="string">
+                </span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+        <span class="keyword">in</span>
+            return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+              </span><span class="tag">&lt;p&gt;</span><span class="string">Are you sure you want to delete ID #</span>{[id]}<span class="string">?</span><span class="tag">&lt;/p&gt;</span><span class="string">
+              
+              </span><span class="tag">&lt;form&gt;&lt;submit</span> action={delete} value=<span class="string">"I was born sure!"</span><span class="tag">/&gt;&lt;/form&gt;</span><span class="string">
+            </span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+        <span class="keyword">end</span>    
+
+    <span class="keyword">and</span> <span class="function-name">main</span> () =
+        ls &lt;- list ();
+        return <span class="tag">&lt;xml&gt;&lt;head&gt;</span><span class="string">
+          </span><span class="tag">&lt;title&gt;</span>{cdata <span class="cvariable">M</span>.title}<span class="tag">&lt;/title&gt;</span><span class="string">
+        </span><span class="tag">&lt;/head&gt;&lt;body&gt;</span><span class="string">
+
+          </span><span class="tag">&lt;h1&gt;</span>{cdata <span class="cvariable">M</span>.title}<span class="tag">&lt;/h1&gt;</span><span class="string">
+
+          </span>{ls}<span class="string">
+        </span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+
+<span class="keyword">end</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/crud.urp.html b/demo/out/crud.urp.html
new file mode 100644
index 0000000..a1b94c0
--- /dev/null
+++ b/demo/out/crud.urp.html
@@ -0,0 +1,7 @@
+<html><body>
+
+<pre>
+crud
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/crud.urs.html b/demo/out/crud.urs.html
new file mode 100644
index 0000000..2a3c860
--- /dev/null
+++ b/demo/out/crud.urs.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>crud.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .module-def {
+        /* font-lock-module-def-face */
+        font-weight: bold;
+      }
+      .type-def {
+        /* font-lock-type-def-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">con</span> <span class="type-def">colMeta</span> = <span class="keyword">fn</span> (db :: <span class="keyword">Type</span>, widget :: <span class="keyword">Type</span>) =&gt;
+                 {<span class="cvariable">Nam</span> : string,
+                  <span class="cvariable">Show</span> : db -&gt; xbody,
+                  <span class="cvariable">Widget</span> : nm :: <span class="keyword">Name</span> -&gt; xml form [] [nm = widget],
+                  <span class="cvariable">WidgetPopulated</span> : nm :: <span class="keyword">Name</span> -&gt; db -&gt; xml form [] [nm = widget],
+                  <span class="cvariable">Parse</span> : widget -&gt; db,
+                  <span class="cvariable">Inject</span> : sql_injectable db}
+<span class="keyword">con</span> <span class="type-def">colsMeta</span> = <span class="keyword">fn</span> cols :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)} =&gt; $(<span class="keyword">map</span> colMeta cols)
+
+<span class="keyword">val</span> <span class="variable-name">int</span> : string -&gt; colMeta (int, string)
+<span class="keyword">val</span> <span class="variable-name">float</span> : string -&gt; colMeta (float, string)
+<span class="keyword">val</span> <span class="variable-name">string</span> : string -&gt; colMeta (string, string)
+<span class="keyword">val</span> <span class="variable-name">bool</span> : string -&gt; colMeta (bool, bool)
+
+<span class="keyword">functor</span> <span class="module-def">Make</span>(<span class="cvariable">M</span> : <span class="keyword">sig</span>
+                 <span class="keyword">con</span> <span class="type-def">cols</span> :: {(<span class="keyword">Type</span> * <span class="keyword">Type</span>)}
+                 <span class="keyword">constraint</span> [<span class="cvariable">Id</span>] ~ cols
+                 <span class="keyword">val</span> <span class="variable-name">fl</span> : folder cols
+
+                 <span class="keyword">table</span> <span class="variable-name">tab</span> : ([<span class="cvariable">Id</span> = int] ++ <span class="keyword">map</span> fst cols)
+
+                 <span class="keyword">val</span> <span class="variable-name">title</span> : string
+
+                 <span class="keyword">val</span> <span class="variable-name">cols</span> : colsMeta cols
+             <span class="keyword">end</span>) : <span class="keyword">sig</span>
+    <span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+<span class="keyword">end</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/crud1.desc.html b/demo/out/crud1.desc.html
new file mode 100644
index 0000000..286750b
--- /dev/null
+++ b/demo/out/crud1.desc.html
@@ -0,0 +1,40 @@
+<html><head>
+<title>Crud1</title>
+</head><body>
+
+<h1>Crud1</h1>
+
+<center>[ <a target="showcase" href="/Demo/Crud1/main">Application</a> | <a target="showcase" href="crud1.urp.html"><tt>crud1.urp</tt></a> | <a target="showcase" href="crud.urs.html"><tt>crud.urs</tt></a> | <a target="showcase" href="crud.ur.html"><tt>crud.ur</tt></a> | <a target="showcase" href="crud1.ur.html"><tt>crud1.ur</tt></a> ]</center>
+
+
+<p>This example pulls together much of what we have seen so far.  It involves a generic "admin interface" builder.  That is, we have the <tt>Crud.Make</tt> functor, which takes in a description of a table and outputs a sub-application for viewing and editing that table.</p>
+
+<p>The signature of <tt>Crud.Make</tt> is based around a type function <tt>colMeta</tt>, which describes which supporting values we need for each column.  This function is declared with the keyword <tt>con</tt>, which stands for "constructor," the general class of "compile-time things" that includes types.  An argument to <tt>colMeta</tt> has kind <tt>(Type * Type)</tt>, which means that it must be a type-level tuple.  The first type is how the column is represented in SQL, and the second is how we represent it in HTML forms.  In order, the components of the resulting record give:
+
+<ol>
+<li>A display name</li>
+<li>A way of pretty-printing values of the column</li>
+<li>A way of generating an HTML form widget to input this column</li>
+<li>A way of generating an HTML form widget with an initial value specified</li>
+<li>A way of parsing values of the column from strings</li>
+<li>A type class witness, showing that the SQL representation can really be included in SQL</li>
+</ol></p>
+
+<p>The function <tt>colsMeta</tt> lifts <tt>colMeta</tt> over type-level records of type pairs.  The <tt>Crud</tt> module also defines reasonable default <tt>colMeta</tt> values for some primitive types.</p>
+
+<p>The functor signature tells us (in order) that an input must contain:
+
+<ol>
+<li>A type pair record <tt>cols</tt></li>
+<li>A proof that <tt>cols</tt> does not contain a field named <tt>Id</tt></li>
+<li>A SQL table <tt>tab</tt> with an <tt>Id</tt> field of type <tt>int</tt> and other fields whose names and types are read off of <tt>cols</tt></li>
+<li>A display title for the admin interface</li>
+<li>A record of meta-data for the columns</li>
+</ol></p>
+
+<p>Looking at <tt>crud1.ur</tt>, we see that a use of the functor is almost trivial.  Only the value components of the argument structure must be provided.  The column row type is inferred, and the disjointness constraint is proved automatically.</p>
+
+<p>We won't go into detail on the implementation of <tt>Crud.Make</tt>.  The types of the functions used there can be found in the signatures of the built-in <tt>Basis</tt> module and the <tt>Top</tt> module from the standard library.  The signature of the first and the signature and implementation of the second can be found in the <tt>lib/ur</tt> directory of the Ur/Web distribution.</p>
+
+
+</body></html>
diff --git a/demo/out/crud1.html b/demo/out/crud1.html
new file mode 100644
index 0000000..1afdb29
--- /dev/null
+++ b/demo/out/crud1.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/Crud1/main" name="showcase">
+<frame src="crud1.desc.html">
+</frameset>
diff --git a/demo/out/crud1.ur.html b/demo/out/crud1.ur.html
new file mode 100644
index 0000000..c5bd927
--- /dev/null
+++ b/demo/out/crud1.ur.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>crud1.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .sql {
+        /* font-lock-sql-face */
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">table</span> <span class="variable-name">t1</span> : {<span class="cvariable">Id</span> : int, <span class="cvariable">A</span> : int, <span class="cvariable">B</span> : string, <span class="cvariable">C</span> : float, <span class="cvariable">D</span> : bool}
+  <span class="sql">PRIMARY</span> <span class="sql">KEY</span> <span class="cvariable">Id</span>
+
+<span class="keyword">open</span> <span class="cvariable">Crud</span>.<span class="cvariable">Make</span>(<span class="keyword">struct</span>
+                   <span class="keyword">val</span> <span class="variable-name">tab</span> = t1
+                             
+                   <span class="keyword">val</span> <span class="variable-name">title</span> = <span class="string">"Crud1"</span>
+                               
+                   <span class="keyword">val</span> <span class="variable-name">cols</span> = {<span class="cvariable">A</span> = <span class="cvariable">Crud</span>.int <span class="string">"A"</span>,
+                               <span class="cvariable">B</span> = <span class="cvariable">Crud</span>.string <span class="string">"B"</span>,
+                               <span class="cvariable">C</span> = <span class="cvariable">Crud</span>.float <span class="string">"C"</span>,
+                               <span class="cvariable">D</span> = <span class="cvariable">Crud</span>.bool <span class="string">"D"</span>}
+               <span class="keyword">end</span>)
+</pre>
+  </body>
+</html>
diff --git a/demo/out/crud1.urp.html b/demo/out/crud1.urp.html
new file mode 100644
index 0000000..68ab7ce
--- /dev/null
+++ b/demo/out/crud1.urp.html
@@ -0,0 +1,10 @@
+<html><body>
+
+<pre>database dbname=test
+sql crud1.sql
+
+crud
+crud1
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/crud2.desc.html b/demo/out/crud2.desc.html
new file mode 100644
index 0000000..b90143c
--- /dev/null
+++ b/demo/out/crud2.desc.html
@@ -0,0 +1,13 @@
+<html><head>
+<title>Crud2</title>
+</head><body>
+
+<h1>Crud2</h1>
+
+<center>[ <a target="showcase" href="/Demo/Crud2/main">Application</a> | <a target="showcase" href="crud2.urp.html"><tt>crud2.urp</tt></a> | <a target="showcase" href="crud.urs.html"><tt>crud.urs</tt></a> | <a target="showcase" href="crud.ur.html"><tt>crud.ur</tt></a> | <a target="showcase" href="crud2.ur.html"><tt>crud2.ur</tt></a> ]</center>
+
+
+<p>This example shows another application of <tt>Crud.Make</tt>.  We mix one standard column with one customized column.  We write an underscore for the <tt>Inject</tt> field of meta-data, since the type class facility can infer that witness.</p>
+
+
+</body></html>
diff --git a/demo/out/crud2.html b/demo/out/crud2.html
new file mode 100644
index 0000000..209e4ba
--- /dev/null
+++ b/demo/out/crud2.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/Crud2/main" name="showcase">
+<frame src="crud2.desc.html">
+</frameset>
diff --git a/demo/out/crud2.ur.html b/demo/out/crud2.ur.html
new file mode 100644
index 0000000..0bbf76c
--- /dev/null
+++ b/demo/out/crud2.ur.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>crud2.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .sql {
+        /* font-lock-sql-face */
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">table</span> <span class="variable-name">t</span> : {<span class="cvariable">Id</span> : int, <span class="cvariable">Nam</span> : string, <span class="cvariable">Ready</span> : bool}
+  <span class="sql">PRIMARY</span> <span class="sql">KEY</span> <span class="cvariable">Id</span>
+
+<span class="keyword">open</span> <span class="cvariable">Crud</span>.<span class="cvariable">Make</span>(<span class="keyword">struct</span>
+                   <span class="keyword">val</span> <span class="variable-name">tab</span> = t
+                             
+                   <span class="keyword">val</span> <span class="variable-name">title</span> = <span class="string">"Are you ready?"</span>
+
+                   <span class="keyword">val</span> <span class="variable-name">cols</span> = {<span class="cvariable">Nam</span> = <span class="cvariable">Crud</span>.string <span class="string">"Name"</span>,
+                               <span class="cvariable">Ready</span> = {<span class="cvariable">Nam</span> = <span class="string">"Ready"</span>,
+                                        <span class="cvariable">Show</span> = (<span class="keyword">fn</span> b =&gt; <span class="keyword">if</span> b <span class="keyword">then</span>
+                                                            <span class="tag">&lt;xml&gt;</span><span class="string">Ready!</span><span class="tag">&lt;/xml&gt;</span>
+                                                        <span class="keyword">else</span>
+                                                            <span class="tag">&lt;xml&gt;</span><span class="string">Not ready</span><span class="tag">&lt;/xml&gt;</span>),
+                                        <span class="cvariable">Widget</span> = (<span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] =&gt; <span class="tag">&lt;xml&gt;</span><span class="string">
+                                          </span><span class="tag">&lt;select</span>{nm}<span class="tag">&gt;</span><span class="string">
+                                            </span><span class="tag">&lt;option&gt;</span><span class="string">Ready</span><span class="tag">&lt;/option&gt;</span><span class="string">
+                                            </span><span class="tag">&lt;option&gt;</span><span class="string">Not ready</span><span class="tag">&lt;/option&gt;</span><span class="string">
+                                          </span><span class="tag">&lt;/select&gt;</span><span class="string">
+                                        </span><span class="tag">&lt;/xml&gt;</span>),
+                                        <span class="cvariable">WidgetPopulated</span> = (<span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] b =&gt; <span class="tag">&lt;xml&gt;</span><span class="string">
+                                          </span><span class="tag">&lt;select</span>{nm}<span class="tag">&gt;</span><span class="string">
+                                            </span><span class="tag">&lt;option</span> selected={b}<span class="tag">&gt;</span><span class="string">Ready</span><span class="tag">&lt;/option&gt;</span><span class="string">
+                                            </span><span class="tag">&lt;option</span> selected={not b}<span class="tag">&gt;</span><span class="string">Not ready</span><span class="tag">&lt;/option&gt;</span><span class="string">
+                                          </span><span class="tag">&lt;/select&gt;</span><span class="string">
+                                        </span><span class="tag">&lt;/xml&gt;</span>),
+                                        <span class="cvariable">Parse</span> = (<span class="keyword">fn</span> s =&gt;
+                                                    <span class="keyword">case</span> s <span class="keyword">of</span>
+                                                        <span class="string">"Ready"</span> =&gt; <span class="cvariable">True</span>
+                                                      | <span class="string">"Not ready"</span> =&gt; <span class="cvariable">False</span>
+                                                      | _ =&gt; error <span class="tag">&lt;xml&gt;</span><span class="string">Invalid ready/not ready</span><span class="tag">&lt;/xml&gt;</span>),
+                                        <span class="cvariable">Inject</span> = _
+                                       }
+                              }
+               <span class="keyword">end</span>)
+</pre>
+  </body>
+</html>
diff --git a/demo/out/crud2.urp.html b/demo/out/crud2.urp.html
new file mode 100644
index 0000000..1f0b1c9
--- /dev/null
+++ b/demo/out/crud2.urp.html
@@ -0,0 +1,10 @@
+<html><body>
+
+<pre>database dbname=test
+sql crud2.sql
+
+crud
+crud2
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/crud3.desc.html b/demo/out/crud3.desc.html
new file mode 100644
index 0000000..a1ae0a1
--- /dev/null
+++ b/demo/out/crud3.desc.html
@@ -0,0 +1,15 @@
+<html><head>
+<title>Crud3</title>
+</head><body>
+
+<h1>Crud3</h1>
+
+<center>[ <a target="showcase" href="/Demo/Crud3/main">Application</a> | <a target="showcase" href="crud3.urp.html"><tt>crud3.urp</tt></a> | <a target="showcase" href="crud.urs.html"><tt>crud.urs</tt></a> | <a target="showcase" href="crud.ur.html"><tt>crud.ur</tt></a> | <a target="showcase" href="crud3.ur.html"><tt>crud3.ur</tt></a> ]</center>
+
+
+<p>One thing that is unclear from the previous examples is how to provide more complex, multi-input widgets for taking input meant for particular fields.  The signature of <tt>Crud.Make</tt> forces every widget to define exactly one input.  The <tt>&lt;subform&gt;</tt> tag, the simpler cousin of the <tt>&lt;subforms&gt;</tt> tag that we saw earlier, provides a fix for this problem.  Via <tt>&lt;subform&gt;</tt>, an arbitrary form can be turned into a single record-valued input.</p>
+
+<p>We use that possibility here to define a silly widget for a <tt>string</tt> column, which concatenates the values entered into two different textboxes.</p>
+
+
+</body></html>
diff --git a/demo/out/crud3.html b/demo/out/crud3.html
new file mode 100644
index 0000000..56e7804
--- /dev/null
+++ b/demo/out/crud3.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/Crud3/main" name="showcase">
+<frame src="crud3.desc.html">
+</frameset>
diff --git a/demo/out/crud3.ur.html b/demo/out/crud3.ur.html
new file mode 100644
index 0000000..860d198
--- /dev/null
+++ b/demo/out/crud3.ur.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>crud3.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .sql {
+        /* font-lock-sql-face */
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">table</span> <span class="variable-name">t</span> : {<span class="cvariable">Id</span> : int, <span class="cvariable">Text</span> : string}
+  <span class="sql">PRIMARY</span> <span class="sql">KEY</span> <span class="cvariable">Id</span>
+
+<span class="keyword">open</span> <span class="cvariable">Crud</span>.<span class="cvariable">Make</span>(<span class="keyword">struct</span>
+                   <span class="keyword">val</span> <span class="variable-name">tab</span> = t
+                             
+                   <span class="keyword">val</span> <span class="variable-name">title</span> = <span class="string">"Crud3"</span>
+
+                   <span class="keyword">val</span> <span class="variable-name">cols</span> = {<span class="cvariable">Text</span> = {<span class="cvariable">Nam</span> = <span class="string">"Text"</span>,
+                                       <span class="cvariable">Show</span> = txt,
+                                       <span class="cvariable">Widget</span> = (<span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] =&gt; <span class="tag">&lt;xml&gt;</span><span class="string">
+                                         </span><span class="tag">&lt;subform</span>{nm}<span class="tag">&gt;</span><span class="string">
+                                           </span><span class="tag">&lt;textbox</span>{#<span class="cvariable">A</span>}<span class="tag">/&gt;</span><span class="string">
+                                           </span><span class="tag">&lt;textbox</span>{#<span class="cvariable">B</span>}<span class="tag">/&gt;</span><span class="string">
+                                         </span><span class="tag">&lt;/subform&gt;</span><span class="string">
+                                       </span><span class="tag">&lt;/xml&gt;</span>),
+                                       <span class="cvariable">WidgetPopulated</span> = (<span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] s =&gt; <span class="tag">&lt;xml&gt;</span><span class="string">
+                                         </span><span class="tag">&lt;subform</span>{nm}<span class="tag">&gt;</span><span class="string">
+                                           </span><span class="tag">&lt;textbox</span>{#<span class="cvariable">A</span>} value={s}<span class="tag">/&gt;</span><span class="string">
+                                           </span><span class="tag">&lt;textbox</span>{#<span class="cvariable">B</span>}<span class="tag">/&gt;</span><span class="string">
+                                         </span><span class="tag">&lt;/subform&gt;</span><span class="string">
+                                       </span><span class="tag">&lt;/xml&gt;</span>),
+                                       <span class="cvariable">Parse</span> = (<span class="keyword">fn</span> p =&gt; p.<span class="cvariable">A</span> ^ p.<span class="cvariable">B</span>),
+                                       <span class="cvariable">Inject</span> = _
+                                      }
+                              }
+               <span class="keyword">end</span>)
+</pre>
+  </body>
+</html>
diff --git a/demo/out/crud3.urp.html b/demo/out/crud3.urp.html
new file mode 100644
index 0000000..05f4691
--- /dev/null
+++ b/demo/out/crud3.urp.html
@@ -0,0 +1,10 @@
+<html><body>
+
+<pre>database dbname=test
+sql crud3.sql
+
+crud
+crud3
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/css.desc.html b/demo/out/css.desc.html
new file mode 100644
index 0000000..9977e85
--- /dev/null
+++ b/demo/out/css.desc.html
@@ -0,0 +1,13 @@
+<html><head>
+<title>Css</title>
+</head><body>
+
+<h1>Css</h1>
+
+<center>[ <a target="showcase" href="/Demo/Css/main">Application</a> | <a target="showcase" href="css.urp.html"><tt>css.urp</tt></a> | <a target="showcase" href="css.urs.html"><tt>css.urs</tt></a> | <a target="showcase" href="css.ur.html"><tt>css.ur</tt></a> ]</center>
+
+
+<p>Ur/Web supports a structured approach to Cascading Style Sheets, where each style is a first-class value within a module.  This demo shows the importing of an external style sheet with one style.  By default, like other Ur/Web entities, the name of the style would be <tt>Css_quote</tt>.  We use the <tt>rewrite</tt> directive in the <tt>.urp</tt> file to specify an alternate name for a particular canonical module path.  The external style sheet contains a definition of a style with the alternate name that we give.</p>
+
+
+</body></html>
diff --git a/demo/out/css.html b/demo/out/css.html
new file mode 100644
index 0000000..b1742cb
--- /dev/null
+++ b/demo/out/css.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/Css/main" name="showcase">
+<frame src="css.desc.html">
+</frameset>
diff --git a/demo/out/css.ur.html b/demo/out/css.ur.html
new file mode 100644
index 0000000..17888d2
--- /dev/null
+++ b/demo/out/css.ur.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>css.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">style</span> quote
+
+<span class="keyword">fun</span> <span class="function-name">main</span> () = return <span class="tag">&lt;xml&gt;</span><span class="string">
+  </span><span class="tag">&lt;head&gt;</span><span class="string">
+    </span><span class="tag">&lt;link</span> rel=<span class="string">"stylesheet"</span> <span class="keyword">type</span>=<span class="string">"text/css"</span> href=<span class="string">"http://adam.chlipala.net/style.css"</span><span class="tag">/&gt;</span><span class="string">
+  </span><span class="tag">&lt;/head&gt;</span><span class="string">
+
+  </span><span class="tag">&lt;body&gt;</span><span class="string">
+    </span><span class="tag">&lt;div</span> <span class="keyword">class</span>={quote}<span class="tag">&gt;</span><span class="string">Here's a quote.</span><span class="tag">&lt;/div&gt;</span><span class="string">
+  </span><span class="tag">&lt;/body&gt;</span><span class="string">
+</span><span class="tag">&lt;/xml&gt;</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/css.urp.html b/demo/out/css.urp.html
new file mode 100644
index 0000000..28071d9
--- /dev/null
+++ b/demo/out/css.urp.html
@@ -0,0 +1,9 @@
+<html><body>
+
+<pre>allow url http://adam.chlipala.net/style.css
+rewrite style Css/quote quote
+
+css
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/css.urs.html b/demo/out/css.urs.html
new file mode 100644
index 0000000..8387604
--- /dev/null
+++ b/demo/out/css.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>css.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+</pre>
+  </body>
+</html>
diff --git a/demo/out/demos.html b/demo/out/demos.html
new file mode 100644
index 0000000..84e07f3
--- /dev/null
+++ b/demo/out/demos.html
@@ -0,0 +1,42 @@
+<html><body>
+
+<li> <a target="staging" href="intro.html">Intro</a></li>
+
+<li> <a target="staging" href="hello.html">Hello</a></li>
+<li> <a target="staging" href="link.html">Link</a></li>
+<li> <a target="staging" href="rec.html">Rec</a></li>
+<li> <a target="staging" href="counter.html">Counter</a></li>
+<li> <a target="staging" href="form.html">Form</a></li>
+<li> <a target="staging" href="nested.html">Nested</a></li>
+<li> <a target="staging" href="cookie.html">Cookie</a></li>
+<li> <a target="staging" href="url.html">Url</a></li>
+<li> <a target="staging" href="css.html">Css</a></li>
+<li> <a target="staging" href="upload.html">Upload</a></li>
+<li> <a target="staging" href="subforms.html">Subforms</a></li>
+<li> <a target="staging" href="listShop.html">ListShop</a></li>
+<li> <a target="staging" href="sql.html">Sql</a></li>
+<li> <a target="staging" href="ref.html">Ref</a></li>
+<li> <a target="staging" href="tree.html">Tree</a></li>
+<li> <a target="staging" href="constraints.html">Constraints</a></li>
+<li> <a target="staging" href="outer.html">Outer</a></li>
+<li> <a target="staging" href="view.html">View</a></li>
+<li> <a target="staging" href="cookieSec.html">CookieSec</a></li>
+<li> <a target="staging" href="sum.html">Sum</a></li>
+<li> <a target="staging" href="tcSum.html">TcSum</a></li>
+<li> <a target="staging" href="metaform1.html">Metaform1</a></li>
+<li> <a target="staging" href="metaform2.html">Metaform2</a></li>
+<li> <a target="staging" href="crud1.html">Crud1</a></li>
+<li> <a target="staging" href="crud2.html">Crud2</a></li>
+<li> <a target="staging" href="crud3.html">Crud3</a></li>
+<li> <a target="staging" href="alert.html">Alert</a></li>
+<li> <a target="staging" href="react.html">React</a></li>
+<li> <a target="staging" href="listEdit.html">ListEdit</a></li>
+<li> <a target="staging" href="increment.html">Increment</a></li>
+<li> <a target="staging" href="noisy.html">Noisy</a></li>
+<li> <a target="staging" href="batch.html">Batch</a></li>
+<li> <a target="staging" href="batchG.html">BatchG</a></li>
+<li> <a target="staging" href="threads.html">Threads</a></li>
+<li> <a target="staging" href="roundTrip.html">RoundTrip</a></li>
+<li> <a target="staging" href="chat.html">Chat</a></li>
+
+</body></html>
diff --git a/demo/out/form.desc.html b/demo/out/form.desc.html
new file mode 100644
index 0000000..3489a30
--- /dev/null
+++ b/demo/out/form.desc.html
@@ -0,0 +1,13 @@
+<html><head>
+<title>Form</title>
+</head><body>
+
+<h1>Form</h1>
+
+<center>[ <a target="showcase" href="/Demo/Form/main">Application</a> | <a target="showcase" href="form.urp.html"><tt>form.urp</tt></a> | <a target="showcase" href="form.urs.html"><tt>form.urs</tt></a> | <a target="showcase" href="form.ur.html"><tt>form.ur</tt></a> ]</center>
+
+
+<p>Here we see a basic form.  The type system tracks which form inputs we include, and it enforces that the form handler function expects a record containing exactly those fields, with exactly the proper types.</p>
+
+
+</body></html>
diff --git a/demo/out/form.html b/demo/out/form.html
new file mode 100644
index 0000000..811cbb7
--- /dev/null
+++ b/demo/out/form.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/Form/main" name="showcase">
+<frame src="form.desc.html">
+</frameset>
diff --git a/demo/out/form.ur.html b/demo/out/form.ur.html
new file mode 100644
index 0000000..00e4031
--- /dev/null
+++ b/demo/out/form.ur.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>form.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">fun</span> <span class="function-name">handler</span> r = return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+  </span><span class="tag">&lt;table&gt;</span><span class="string">
+    </span><span class="tag">&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">A:</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;td&gt;</span>{[r.<span class="cvariable">A</span>]}<span class="tag">&lt;/td&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+    </span><span class="tag">&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">B:</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;td&gt;</span>{[r.<span class="cvariable">B</span>]}<span class="tag">&lt;/td&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+    </span><span class="tag">&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">C:</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;td&gt;</span>{[r.<span class="cvariable">C</span>]}<span class="tag">&lt;/td&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+  </span><span class="tag">&lt;/table&gt;</span><span class="string">
+</span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+
+<span class="keyword">fun</span> <span class="function-name">main</span> () = return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+  </span><span class="tag">&lt;form&gt;</span><span class="string">
+    </span><span class="tag">&lt;table&gt;</span><span class="string">
+      </span><span class="tag">&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">A:</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;td&gt;&lt;textbox</span>{#<span class="cvariable">A</span>}<span class="tag">/&gt;&lt;/td&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+      </span><span class="tag">&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">B:</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;td&gt;&lt;textbox</span>{#<span class="cvariable">B</span>}<span class="tag">/&gt;&lt;/td&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+      </span><span class="tag">&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th&gt;</span><span class="string">C:</span><span class="tag">&lt;/th&gt;</span><span class="string"> </span><span class="tag">&lt;td&gt;&lt;checkbox</span>{#<span class="cvariable">C</span>}<span class="tag">/&gt;&lt;/td&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+      </span><span class="tag">&lt;tr&gt;</span><span class="string"> </span><span class="tag">&lt;th/&gt;</span><span class="string"> </span><span class="tag">&lt;td&gt;&lt;submit</span> action={handler}<span class="tag">/&gt;&lt;/td&gt;</span><span class="string"> </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+    </span><span class="tag">&lt;/table&gt;</span><span class="string">
+  </span><span class="tag">&lt;/form&gt;</span><span class="string">
+</span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/form.urp.html b/demo/out/form.urp.html
new file mode 100644
index 0000000..bb852c6
--- /dev/null
+++ b/demo/out/form.urp.html
@@ -0,0 +1,6 @@
+<html><body>
+
+<pre>form
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/form.urs.html b/demo/out/form.urs.html
new file mode 100644
index 0000000..d00f842
--- /dev/null
+++ b/demo/out/form.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>form.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+</pre>
+  </body>
+</html>
diff --git a/demo/out/hello.desc.html b/demo/out/hello.desc.html
new file mode 100644
index 0000000..86a0be1
--- /dev/null
+++ b/demo/out/hello.desc.html
@@ -0,0 +1,19 @@
+<html><head>
+<title>Hello</title>
+</head><body>
+
+<h1>Hello</h1>
+
+<center>[ <a target="showcase" href="/Demo/Hello/main">Application</a> | <a target="showcase" href="hello.urp.html"><tt>hello.urp</tt></a> | <a target="showcase" href="hello.urs.html"><tt>hello.urs</tt></a> | <a target="showcase" href="hello.ur.html"><tt>hello.ur</tt></a> ]</center>
+
+
+<p>We must, of course, begin with "Hello World."</p>
+
+<p>The project file justs list one filename prefix, <tt>hello</tt>.  This causes both <tt>hello.urs</tt> and <tt>hello.ur</tt> to be pulled into the project.  <tt>.urs</tt> files are like <a href="http://caml.inria.fr/ocaml/">OCaml</a> <tt>.mli</tt> files, and <tt>.ur</tt> files are like OCaml <tt>.ml</tt> files.  That is, <tt>.urs</tt> files provide interfaces, and <tt>.ur</tt> files provide implementations.  <tt>.urs</tt> files may be omitted for <tt>.ur</tt> files, in which case most permissive interfaces are inferred.</p>
+
+<p>Ur/Web features a module system very similar to those found in SML and OCaml.  Like in OCaml, interface files are treated as module system signatures, and they are ascribed to structures built from implementation files.  <tt>hello.urs</tt> tells us that we only export a function named <tt>main</tt>, taking no arguments and running a transaction that results in an HTML page.  <tt>transaction</tt> is a monad in the spirit of the Haskell IO monad, with the intent that every operation performable in <tt>transaction</tt> can be undone.  By design, Ur/Web does not provide a less constrained way of running side-effecting actions.  This particular example application will employ no side effects, but the compiler requires that all pages be generated by transactions.</p>
+
+<p>Looking at <tt>hello.ur</tt>, we see an SML-looking function definition that returns a fragment of XML, written with special syntax.  This fragment is returned to browsers that request the URI <tt>/Demo/Hello/main</tt>.  That is, we take the demo-wide prefix <tt>/Demo</tt> and add a suffix that indicates we want to call the <tt>main</tt> function in the <tt>Hello</tt> module.  This path convention generalizes to arbitrary levels of nested module definitions and functor applications (which we will see later).</p>
+
+
+</body></html>
diff --git a/demo/out/hello.html b/demo/out/hello.html
new file mode 100644
index 0000000..c070656
--- /dev/null
+++ b/demo/out/hello.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/Hello/main" name="showcase">
+<frame src="hello.desc.html">
+</frameset>
diff --git a/demo/out/hello.ur.html b/demo/out/hello.ur.html
new file mode 100644
index 0000000..3f796f7
--- /dev/null
+++ b/demo/out/hello.ur.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>hello.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">fun</span> <span class="function-name">main</span> () = return <span class="tag">&lt;xml&gt;</span><span class="string">
+  </span><span class="tag">&lt;head&gt;</span><span class="string">
+    </span><span class="tag">&lt;title&gt;</span><span class="string">Hello world!</span><span class="tag">&lt;/title&gt;</span><span class="string">
+  </span><span class="tag">&lt;/head&gt;</span><span class="string">
+
+  </span><span class="tag">&lt;body&gt;</span><span class="string">
+    </span><span class="tag">&lt;h1&gt;</span><span class="string">Hello world!</span><span class="tag">&lt;/h1&gt;</span><span class="string">
+  </span><span class="tag">&lt;/body&gt;</span><span class="string">
+</span><span class="tag">&lt;/xml&gt;</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/hello.urp.html b/demo/out/hello.urp.html
new file mode 100644
index 0000000..f35f998
--- /dev/null
+++ b/demo/out/hello.urp.html
@@ -0,0 +1,6 @@
+<html><body>
+
+<pre>hello
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/hello.urs.html b/demo/out/hello.urs.html
new file mode 100644
index 0000000..374a9ff
--- /dev/null
+++ b/demo/out/hello.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>hello.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+</pre>
+  </body>
+</html>
diff --git a/demo/out/increment.desc.html b/demo/out/increment.desc.html
new file mode 100644
index 0000000..625a685
--- /dev/null
+++ b/demo/out/increment.desc.html
@@ -0,0 +1,13 @@
+<html><head>
+<title>Increment</title>
+</head><body>
+
+<h1>Increment</h1>
+
+<center>[ <a target="showcase" href="/Demo/Increment/main">Application</a> | <a target="showcase" href="increment.urp.html"><tt>increment.urp</tt></a> | <a target="showcase" href="increment.urs.html"><tt>increment.urs</tt></a> | <a target="showcase" href="increment.ur.html"><tt>increment.ur</tt></a> ]</center>
+
+
+<p>Here's an example where client-side code needs to run more code on the server.  We maintain a (server-side) SQL sequence.  When the user clicks a button, an AJAX request increments the remote sequence and gets the new value.</p>
+
+
+</body></html>
diff --git a/demo/out/increment.html b/demo/out/increment.html
new file mode 100644
index 0000000..f12ae07
--- /dev/null
+++ b/demo/out/increment.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/Increment/main" name="showcase">
+<frame src="increment.desc.html">
+</frameset>
diff --git a/demo/out/increment.ur.html b/demo/out/increment.ur.html
new file mode 100644
index 0000000..31e9442
--- /dev/null
+++ b/demo/out/increment.ur.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>increment.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">sequence</span> seq
+
+<span class="keyword">fun</span> <span class="function-name">increment</span> () = nextval seq
+
+<span class="keyword">fun</span> <span class="function-name">main</span> () =
+    src &lt;- source 0;
+    return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+      </span>&lt;dyn signal={n &lt;- signal src; return <span class="tag">&lt;xml&gt;</span>{[n]}<span class="tag">&lt;/xml&gt;</span>}/&gt;<span class="string">
+      </span><span class="tag">&lt;button</span> value=<span class="string">"Update"</span> onclick={n &lt;- rpc (increment ()); set src n}<span class="tag">/&gt;</span><span class="string">
+    </span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/increment.urp.html b/demo/out/increment.urp.html
new file mode 100644
index 0000000..6878de5
--- /dev/null
+++ b/demo/out/increment.urp.html
@@ -0,0 +1,8 @@
+<html><body>
+
+<pre>database dbname=test
+
+increment
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/increment.urs.html b/demo/out/increment.urs.html
new file mode 100644
index 0000000..f3251af
--- /dev/null
+++ b/demo/out/increment.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>increment.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+</pre>
+  </body>
+</html>
diff --git a/demo/out/index.html b/demo/out/index.html
new file mode 100644
index 0000000..4b124b1
--- /dev/null
+++ b/demo/out/index.html
@@ -0,0 +1,4 @@
+<frameset cols="15%,85%">
+<frame src="demos.html">
+<frame src="intro.html" name="staging">
+</frameset>
diff --git a/demo/out/intro.html b/demo/out/intro.html
new file mode 100644
index 0000000..c3d34e3
--- /dev/null
+++ b/demo/out/intro.html
@@ -0,0 +1,42 @@
+<html><head>
+<title>Ur/Web Demo</title>
+</head><body>
+
+<p><b>Ur/Web</b> is a domain-specific language for programming web applications backed by SQL databases.  It is (strongly) statically-typed (like ML and Haskell) and purely functional (like Haskell).  <b>Ur</b> is the base language, and the web-specific features of Ur/Web (mostly) come only in the form of special rules for parsing and optimization.  The Ur core looks a lot like <a href="http://sml.sourceforge.net/">Standard ML</a>, with a few <a href="http://www.haskell.org/">Haskell</a>-isms added, and kinder, gentler versions added of many features from dependently-typed languages like the logic behind <a href="http://coq.inria.fr/">Coq</a>.  The type system is much more expressive than in ML and Haskell, such that well-typed web applications cannot "go wrong," not just in handling single HTTP requests, but across their entire lifetimes of interacting with HTTP clients.  Beyond that, Ur is unusual in using ideas from dependent typing to enable very effective metaprogramming, or programming with explicit analysis of type structure.  Many common web application components can be built by Ur/Web functions that operate on types, where it seems impossible to achieve similar code re-use in more established statically-typed languages.</p>
+
+<p>This demo is built automatically from Ur/Web sources and supporting files.  If you unpack the Ur/Web source distribution, then the following steps will (if you're lucky) build you a local version of this demo.  If you're not lucky, you can consult the beginning of <a href="http://www.impredicative.com/ur/manual.pdf">the manual</a> for more detailed instructions.
+
+<blockquote><pre>./configure
+make
+sudo make install
+urweb -noEmacs -demo /Demo demo</pre></blockquote></p>
+
+<p>The <tt>-demo /Demo</tt> flag says that we want to build a demo application that expects its URIs to begin with <tt>/Demo</tt>.  The final argument <tt>demo</tt> gives the path to a directory housing demo files.  One of the files in that directory is <tt>prose</tt>, a file describing the different demo pieces with HTML.  Some lines of <tt>prose</tt> have the form <tt><i>foo</i>.urp</tt>, naming particular project files (with the extension <tt>.urp</tt>) in that directory.</p>
+
+<p>These project files can also be built separately.  For example, you could run
+
+<blockquote><pre>urweb demo/hello</pre></blockquote>
+
+to build the "Hello World" demo application.  Whether building the pieces separately or all at once with the <tt>-demo</tt> flag, a standalone web server executable is generated.  The <tt>-demo</tt> command line will generate <tt>demo/demo.exe</tt>, and the other command line will generate <tt>demo/hello.exe</tt>.  Either can be run with no arguments to start a single-threaded server accepting requests on port 8080.  Pass the flag <tt>-h</tt> to see which options are available.</p>
+
+<p>The <tt>-demo</tt> version also generates some HTML in a subdirectory <tt>out</tt> of the demo directory.  It is easy to set Apache up to serve these HTML files, and to proxy out to the Ur/Web web server for dynamic page requests.  This configuration works for me, where <tt>DIR</tt> is the location of an Ur/Web source distribution.
+
+<blockquote><pre>Alias /demo/ "DIR/demo/out/"
+
+ProxyPass /Demo/ http://localhost:8080/Demo/
+ProxyPassReverse /Demo/ http://localhost:8080/Demo/</pre></blockquote></p>
+
+<p>Building the demo also generates a <tt>demo.sql</tt> file, giving the SQL commands to run to define all of the tables and sequences that the applications expect to see.  The file <tt>demo.urp</tt> contains a <tt>database</tt> line with the PostgreSQL database that the demo web server will try to connect to.</p>
+
+<p>The easiest way to get a demo running locally is probably with this alternate command sequence:
+
+<blockquote><pre>urweb -dbms sqlite -db /path/to/database/file -demo /Demo demo
+sqlite3 /path/to/database/file &lt;demo/demo.sql
+demo/demo.exe</pre></blockquote></p>
+
+<p>Then you can skip the static content and connect directly to the demo server at <tt>http://localhost:8080/Demo/Demo/main</tt>, which contains links to the individual demos.  If you're running the server created just for <tt>hello</tt>, then the URL will be <tt>http://localhost:8080/Hello/main</tt>.</p>
+
+<p>The rest of the demo focuses on the individual applications.  Follow the links in the lefthand frame to visit the applications, commentary, and syntax-highlighted source code.  (An Emacs mode is behind the syntax highlighting.)  I recommend visiting the applications in the order listed, since that is the order in which new concepts are introduced.</p>
+
+
+</body></html>
diff --git a/demo/out/link.desc.html b/demo/out/link.desc.html
new file mode 100644
index 0000000..9266638
--- /dev/null
+++ b/demo/out/link.desc.html
@@ -0,0 +1,13 @@
+<html><head>
+<title>Link</title>
+</head><body>
+
+<h1>Link</h1>
+
+<center>[ <a target="showcase" href="/Demo/Link/main">Application</a> | <a target="showcase" href="link.urp.html"><tt>link.urp</tt></a> | <a target="showcase" href="link.urs.html"><tt>link.urs</tt></a> | <a target="showcase" href="link.ur.html"><tt>link.ur</tt></a> ]</center>
+
+
+<p>In <tt>link.ur</tt>, we see how easy it is to link to another page.  The Ur/Web compiler guarantees that all links are valid.  We just write some Ur/Web code inside an "antiquote" in our XML, denoting a transaction that will produce the new page if the link is clicked.</p>
+
+
+</body></html>
diff --git a/demo/out/link.html b/demo/out/link.html
new file mode 100644
index 0000000..cc8d92d
--- /dev/null
+++ b/demo/out/link.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/Link/main" name="showcase">
+<frame src="link.desc.html">
+</frameset>
diff --git a/demo/out/link.ur.html b/demo/out/link.ur.html
new file mode 100644
index 0000000..b817a1c
--- /dev/null
+++ b/demo/out/link.ur.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>link.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">fun</span> <span class="function-name">target</span> () = return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+  Welcome!
+</span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+
+<span class="keyword">fun</span> <span class="function-name">main</span> () = return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+  </span><span class="tag">&lt;a</span> link={target ()}<span class="tag">&gt;</span><span class="string">Go there</span><span class="tag">&lt;/a&gt;</span><span class="string">
+</span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/link.urp.html b/demo/out/link.urp.html
new file mode 100644
index 0000000..ca16ebb
--- /dev/null
+++ b/demo/out/link.urp.html
@@ -0,0 +1,6 @@
+<html><body>
+
+<pre>link
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/link.urs.html b/demo/out/link.urs.html
new file mode 100644
index 0000000..a51d67b
--- /dev/null
+++ b/demo/out/link.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>link.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+</pre>
+  </body>
+</html>
diff --git a/demo/out/list.ur.html b/demo/out/list.ur.html
new file mode 100644
index 0000000..255204f
--- /dev/null
+++ b/demo/out/list.ur.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>list.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .type-def {
+        /* font-lock-type-def-face */
+        font-weight: bold;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">datatype</span> <span class="type-def">list</span> t = <span class="cvariable">Nil</span> | <span class="cvariable">Cons</span> <span class="keyword">of</span> t * list t
+
+<span class="keyword">fun</span> <span class="function-name">length</span> [t] (ls : list t) =
+    <span class="keyword">let</span>
+        <span class="keyword">fun</span> <span class="function-name">length'</span> (ls : list t) (acc : int) =
+            <span class="keyword">case</span> ls <span class="keyword">of</span>
+                <span class="cvariable">Nil</span> =&gt; acc
+              | <span class="cvariable">Cons</span> (_, ls') =&gt; length' ls' (acc + 1)
+    <span class="keyword">in</span>
+        length' ls 0
+    <span class="keyword">end</span>
+
+<span class="keyword">fun</span> <span class="function-name">rev</span> [t] (ls : list t) = 
+    <span class="keyword">let</span>
+        <span class="keyword">fun</span> <span class="function-name">rev'</span> (ls : list t) (acc : list t) =
+            <span class="keyword">case</span> ls <span class="keyword">of</span>
+                <span class="cvariable">Nil</span> =&gt; acc
+              | <span class="cvariable">Cons</span> (x, ls') =&gt; rev' ls' (<span class="cvariable">Cons</span> (x, acc))
+    <span class="keyword">in</span>
+        rev' ls <span class="cvariable">Nil</span>
+    <span class="keyword">end</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/list.urs.html b/demo/out/list.urs.html
new file mode 100644
index 0000000..4281372
--- /dev/null
+++ b/demo/out/list.urs.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>list.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .type-def {
+        /* font-lock-type-def-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">datatype</span> <span class="type-def">list</span> t = <span class="cvariable">Nil</span> | <span class="cvariable">Cons</span> <span class="keyword">of</span> t * list t
+
+<span class="keyword">val</span> <span class="variable-name">length</span> : t ::: <span class="keyword">Type</span> -&gt; list t -&gt; int
+
+<span class="keyword">val</span> <span class="variable-name">rev</span> : t ::: <span class="keyword">Type</span> -&gt; list t -&gt; list t
+</pre>
+  </body>
+</html>
diff --git a/demo/out/listEdit.desc.html b/demo/out/listEdit.desc.html
new file mode 100644
index 0000000..375c136
--- /dev/null
+++ b/demo/out/listEdit.desc.html
@@ -0,0 +1,17 @@
+<html><head>
+<title>ListEdit</title>
+</head><body>
+
+<h1>ListEdit</h1>
+
+<center>[ <a target="showcase" href="/Demo/ListEdit/main">Application</a> | <a target="showcase" href="listEdit.urp.html"><tt>listEdit.urp</tt></a> | <a target="showcase" href="listEdit.urs.html"><tt>listEdit.urs</tt></a> | <a target="showcase" href="listEdit.ur.html"><tt>listEdit.ur</tt></a> ]</center>
+
+
+<p>This is a more involved functional-reactive example, involving recursive data structures that contain sources.  We build a list editor similar to the one from the <tt>ListShop</tt> example, but with all editing happening on the client side.</p>
+
+<p>The central data structure is the <tt>rlist</tt>, a list whose individual elements are sources, enabling fine-grained mutation.  Every rlist is either nil or is a cons cell made up of a source for a string data element, another source to serve as a scratchpad for GUI-based edits to the data element, and a final source that stores the remainder of the list.</p>
+
+<p>The main program provides operations to append to a list and to edit the data stored at any cell of the list.  Append is implemented by maintaining a source <tt>head</tt>, which points to the first list element; and a source <tt>tailP</tt>, which points to a <tt>source rlist</tt> where we should place the next appended node.</p>
+
+
+</body></html>
diff --git a/demo/out/listEdit.html b/demo/out/listEdit.html
new file mode 100644
index 0000000..a0fb053
--- /dev/null
+++ b/demo/out/listEdit.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/ListEdit/main" name="showcase">
+<frame src="listEdit.desc.html">
+</frameset>
diff --git a/demo/out/listEdit.ur.html b/demo/out/listEdit.ur.html
new file mode 100644
index 0000000..139f997
--- /dev/null
+++ b/demo/out/listEdit.ur.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>listEdit.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+      .type-def {
+        /* font-lock-type-def-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">datatype</span> <span class="type-def">rlist</span> = <span class="cvariable">Nil</span> | <span class="cvariable">Cons</span> <span class="keyword">of</span> {<span class="cvariable">Data</span> : source string,
+                                <span class="cvariable">NewData</span> : source string,
+                                <span class="cvariable">Tail</span> : source rlist}
+
+<span class="keyword">fun</span> <span class="function-name">showString</span> ss =
+    s &lt;- signal ss;
+    return <span class="tag">&lt;xml&gt;</span>{[s]}<span class="tag">&lt;/xml&gt;</span>
+
+<span class="keyword">fun</span> <span class="function-name">show</span> rls =
+    v &lt;- signal rls;
+    show' v
+
+<span class="keyword">and</span> <span class="function-name">show'</span> rl =
+    <span class="keyword">case</span> rl <span class="keyword">of</span>
+        <span class="cvariable">Nil</span> =&gt; return <span class="tag">&lt;xml/&gt;</span>
+      | <span class="cvariable">Cons</span> {<span class="cvariable">Data</span> = ss, <span class="cvariable">NewData</span> = ss', <span class="cvariable">Tail</span> = rls} =&gt; return <span class="tag">&lt;xml&gt;</span><span class="string">
+        </span><span class="tag">&lt;dyn</span> signal={showString ss}<span class="tag">/&gt;</span><span class="string">
+        </span><span class="tag">&lt;button</span> value=<span class="string">"Change to:"</span> onclick={s &lt;- get ss'; set ss s}<span class="tag">/&gt;</span><span class="string">
+        </span><span class="tag">&lt;ctextbox</span> source={ss'}<span class="tag">/&gt;&lt;br/&gt;</span><span class="string">
+        </span><span class="tag">&lt;dyn</span> signal={show rls}<span class="tag">/&gt;</span><span class="string">
+      </span><span class="tag">&lt;/xml&gt;</span>
+
+<span class="keyword">fun</span> <span class="function-name">main</span> () =
+    head &lt;- source <span class="cvariable">Nil</span>;
+    tailP &lt;- source head;
+    data &lt;- source <span class="string">""</span>;
+
+    <span class="keyword">let</span>
+        <span class="keyword">fun</span> <span class="function-name">add</span> () =
+            data &lt;- get data;
+            data &lt;- source data;
+            ndata &lt;- source <span class="string">""</span>;
+            tail &lt;- get tailP;
+            tail' &lt;- source <span class="cvariable">Nil</span>;
+
+            <span class="keyword">let</span>
+                <span class="keyword">val</span> <span class="variable-name">cons</span> = <span class="cvariable">Cons</span> {<span class="cvariable">Data</span> = data, <span class="cvariable">NewData</span> = ndata, <span class="cvariable">Tail</span> = tail'}
+            <span class="keyword">in</span>
+                set tail cons;
+                set tailP tail';
+
+                head' &lt;- get head;
+                <span class="keyword">case</span> head' <span class="keyword">of</span>
+                    <span class="cvariable">Nil</span> =&gt; set head cons
+                  | _ =&gt; return ()
+            <span class="keyword">end</span>
+    <span class="keyword">in</span>
+        return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+          </span><span class="tag">&lt;ctextbox</span> source={data}<span class="tag">/&gt;</span><span class="string"> </span><span class="tag">&lt;button</span> value=<span class="string">"Add"</span> onclick={add ()}<span class="tag">/&gt;&lt;br/&gt;</span><span class="string">
+          </span><span class="tag">&lt;br/&gt;</span><span class="string">
+
+          </span><span class="tag">&lt;dyn</span> signal={show head}<span class="tag">/&gt;</span><span class="string">
+        </span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+    <span class="keyword">end</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/listEdit.urp.html b/demo/out/listEdit.urp.html
new file mode 100644
index 0000000..d94475f
--- /dev/null
+++ b/demo/out/listEdit.urp.html
@@ -0,0 +1,6 @@
+<html><body>
+
+<pre>listEdit
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/listEdit.urs.html b/demo/out/listEdit.urs.html
new file mode 100644
index 0000000..55960b2
--- /dev/null
+++ b/demo/out/listEdit.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>listEdit.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+</pre>
+  </body>
+</html>
diff --git a/demo/out/listFun.ur.html b/demo/out/listFun.ur.html
new file mode 100644
index 0000000..9af2ef8
--- /dev/null
+++ b/demo/out/listFun.ur.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>listFun.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .module-def {
+        /* font-lock-module-def-face */
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+      .type-def {
+        /* font-lock-type-def-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">open</span> <span class="cvariable">List</span>
+
+<span class="keyword">functor</span> <span class="module-def">Make</span>(<span class="cvariable">M</span> : <span class="keyword">sig</span>
+                 <span class="keyword">type</span> <span class="type-def">t</span>
+                 <span class="keyword">val</span> <span class="variable-name">toString</span> : t -&gt; string
+                 <span class="keyword">val</span> <span class="variable-name">fromString</span> : string -&gt; option t
+             <span class="keyword">end</span>) = <span class="keyword">struct</span>
+    <span class="keyword">fun</span> <span class="function-name">toXml</span> (ls : list <span class="cvariable">M</span>.t) =
+        <span class="keyword">case</span> ls <span class="keyword">of</span>
+            <span class="cvariable">Nil</span> =&gt; <span class="tag">&lt;xml&gt;</span><span class="string">[]</span><span class="tag">&lt;/xml&gt;</span>
+          | <span class="cvariable">Cons</span> (x, ls') =&gt; <span class="tag">&lt;xml&gt;</span>{[<span class="cvariable">M</span>.toString x]}<span class="string"> :: </span>{toXml ls'}<span class="tag">&lt;/xml&gt;</span>
+      
+    <span class="keyword">fun</span> <span class="function-name">console</span> (ls : list <span class="cvariable">M</span>.t) =
+        <span class="keyword">let</span>
+            <span class="keyword">fun</span> <span class="function-name">cons</span> (r : {<span class="cvariable">X</span> : string}) =
+                <span class="keyword">case</span> <span class="cvariable">M</span>.fromString r.<span class="cvariable">X</span> <span class="keyword">of</span>
+                    <span class="cvariable">None</span> =&gt; return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">Invalid string!</span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+                  | <span class="cvariable">Some</span> v =&gt; console (<span class="cvariable">Cons</span> (v, ls))
+        <span class="keyword">in</span>
+            return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+              Current list: </span>{toXml ls}<span class="tag">&lt;br/&gt;</span><span class="string">
+              Reversed list: </span>{toXml (rev ls)}<span class="tag">&lt;br/&gt;</span><span class="string">
+              Length: </span>{[length ls]}<span class="tag">&lt;br/&gt;</span><span class="string">
+              </span><span class="tag">&lt;br/&gt;</span><span class="string">
+
+              </span><span class="tag">&lt;form&gt;</span><span class="string">
+                Add element: </span><span class="tag">&lt;textbox</span>{#<span class="cvariable">X</span>}<span class="tag">/&gt;</span><span class="string"> </span><span class="tag">&lt;submit</span> action={cons}<span class="tag">/&gt;</span><span class="string">
+              </span><span class="tag">&lt;/form&gt;</span><span class="string">
+            </span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+        <span class="keyword">end</span>
+
+    <span class="keyword">fun</span> <span class="function-name">main</span> () = console <span class="cvariable">Nil</span>
+<span class="keyword">end</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/listFun.urs.html b/demo/out/listFun.urs.html
new file mode 100644
index 0000000..1fc063d
--- /dev/null
+++ b/demo/out/listFun.urs.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>listFun.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .module-def {
+        /* font-lock-module-def-face */
+        font-weight: bold;
+      }
+      .type-def {
+        /* font-lock-type-def-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">functor</span> <span class="module-def">Make</span>(<span class="cvariable">M</span> : <span class="keyword">sig</span>
+                 <span class="keyword">type</span> <span class="type-def">t</span>
+                 <span class="keyword">val</span> <span class="variable-name">toString</span> : t -&gt; string
+                 <span class="keyword">val</span> <span class="variable-name">fromString</span> : string -&gt; option t
+             <span class="keyword">end</span>) : <span class="keyword">sig</span>
+    <span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+<span class="keyword">end</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/listShop.desc.html b/demo/out/listShop.desc.html
new file mode 100644
index 0000000..50a9d07
--- /dev/null
+++ b/demo/out/listShop.desc.html
@@ -0,0 +1,19 @@
+<html><head>
+<title>ListShop</title>
+</head><body>
+
+<h1>ListShop</h1>
+
+<center>[ <a target="showcase" href="/Demo/ListShop/main">Application</a> | <a target="showcase" href="listShop.urp.html"><tt>listShop.urp</tt></a> | <a target="showcase" href="list.urs.html"><tt>list.urs</tt></a> | <a target="showcase" href="list.ur.html"><tt>list.ur</tt></a> | <a target="showcase" href="listFun.urs.html"><tt>listFun.urs</tt></a> | <a target="showcase" href="listFun.ur.html"><tt>listFun.ur</tt></a> | <a target="showcase" href="listShop.urs.html"><tt>listShop.urs</tt></a> | <a target="showcase" href="listShop.ur.html"><tt>listShop.ur</tt></a> ]</center>
+
+
+<p>This example shows off algebraic datatypes, parametric polymorphism, and functors.</p>
+
+<p>The <tt>List</tt> module defines a list datatype, much in the style of SML, but with type parameters written more in Haskell style.  The types of <tt>List.length</tt> and <tt>List.rev</tt> indicate that they are polymorphic.  Types like <tt>t ::: Type -> ...</tt> indicate polymorphism, with the triple colon denoting that the value of this type parameter should be <i>inferred</i> at uses.  A double colon would mean that the type argument must be provided explicitly at uses.  In contrast to ML and Haskell, all polymorphism must be <i>declared</i> explicitly in Ur, while instantiations may be inferred at uses.</p>
+
+<p>The <tt>ListFun</tt> module defines a functor for building list editing sub-applications.  An argument to the functor <tt>Make</tt> must give the type to be stored in the lists, along with marshaling and unmarshaling functions.  In return, the functor returns an entry point function.</p>
+
+<p>The <tt>ListShop</tt> modules ties everything together by instantiating <tt>ListFun.Make</tt> with structures for integers and strings.  <tt>show</tt> and <tt>read</tt> can be used for marshaling and unmarshaling in both cases because they are type-class-generic.</p>
+
+
+</body></html>
diff --git a/demo/out/listShop.html b/demo/out/listShop.html
new file mode 100644
index 0000000..869d18c
--- /dev/null
+++ b/demo/out/listShop.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/ListShop/main" name="showcase">
+<frame src="listShop.desc.html">
+</frameset>
diff --git a/demo/out/listShop.ur.html b/demo/out/listShop.ur.html
new file mode 100644
index 0000000..deddf77
--- /dev/null
+++ b/demo/out/listShop.ur.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>listShop.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .module-def {
+        /* font-lock-module-def-face */
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+      .type-def {
+        /* font-lock-type-def-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">structure</span> <span class="module-def">I</span> = <span class="keyword">struct</span>
+    <span class="keyword">type</span> <span class="type-def">t</span> = int
+    <span class="keyword">val</span> <span class="variable-name">toString</span> = show
+    <span class="keyword">val</span> <span class="variable-name">fromString</span> = read
+<span class="keyword">end</span>
+
+<span class="keyword">structure</span> <span class="module-def">S</span> = <span class="keyword">struct</span>
+    <span class="keyword">type</span> <span class="type-def">t</span> = string
+    <span class="keyword">val</span> <span class="variable-name">toString</span> = show
+    <span class="keyword">val</span> <span class="variable-name">fromString</span> = read
+<span class="keyword">end</span>
+
+<span class="keyword">structure</span> <span class="module-def">IL</span> = <span class="cvariable">ListFun</span>.<span class="cvariable">Make</span>(<span class="cvariable">I</span>)
+<span class="keyword">structure</span> <span class="module-def">SL</span> = <span class="cvariable">ListFun</span>.<span class="cvariable">Make</span>(<span class="cvariable">S</span>)
+
+<span class="keyword">fun</span> <span class="function-name">main</span> () = return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+  Pick your poison:</span><span class="tag">&lt;br/&gt;</span><span class="string">
+  </span><span class="tag">&lt;li&gt;</span><span class="string"> </span><span class="tag">&lt;a</span> link={<span class="cvariable">IL</span>.main ()}<span class="tag">&gt;</span><span class="string">Integers</span><span class="tag">&lt;/a&gt;&lt;/li&gt;</span><span class="string">
+  </span><span class="tag">&lt;li&gt;</span><span class="string"> </span><span class="tag">&lt;a</span> link={<span class="cvariable">SL</span>.main ()}<span class="tag">&gt;</span><span class="string">Strings</span><span class="tag">&lt;/a&gt;&lt;/li&gt;</span><span class="string">
+</span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/listShop.urp.html b/demo/out/listShop.urp.html
new file mode 100644
index 0000000..cc84150
--- /dev/null
+++ b/demo/out/listShop.urp.html
@@ -0,0 +1,8 @@
+<html><body>
+
+<pre>list
+listFun
+listShop
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/listShop.urs.html b/demo/out/listShop.urs.html
new file mode 100644
index 0000000..e96412e
--- /dev/null
+++ b/demo/out/listShop.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>listShop.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+</pre>
+  </body>
+</html>
diff --git a/demo/out/metaform.ur.html b/demo/out/metaform.ur.html
new file mode 100644
index 0000000..531e573
--- /dev/null
+++ b/demo/out/metaform.ur.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>metaform.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .module-def {
+        /* font-lock-module-def-face */
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+      .type-def {
+        /* font-lock-type-def-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">functor</span> <span class="module-def">Make</span> (<span class="cvariable">M</span> : <span class="keyword">sig</span>
+                  <span class="keyword">con</span> <span class="type-def">fs</span> :: {<span class="keyword">Unit</span>}
+                  <span class="keyword">val</span> <span class="variable-name">fl</span> : folder fs
+                  <span class="keyword">val</span> <span class="variable-name">names</span> : $(mapU string fs)
+              <span class="keyword">end</span>) = <span class="keyword">struct</span>
+
+    <span class="keyword">fun</span> <span class="function-name">handler</span> values = return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+      </span>{@foldURX2 [string] [string] [body]
+        (<span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] [rest :: {<span class="keyword">Unit</span>}] [[nm] ~ rest] name value =&gt; <span class="tag">&lt;xml&gt;</span><span class="string">
+          </span><span class="tag">&lt;li&gt;</span><span class="string"> </span>{[name]}<span class="string"> = </span>{[value]}<span class="tag">&lt;/li&gt;</span><span class="string">
+        </span><span class="tag">&lt;/xml&gt;</span>)
+        <span class="cvariable">M</span>.fl <span class="cvariable">M</span>.names values}<span class="string">
+    </span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+
+    <span class="keyword">fun</span> <span class="function-name">main</span> () = return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+      </span><span class="tag">&lt;form&gt;</span><span class="string">
+        </span>{@foldUR [string] [<span class="keyword">fn</span> cols :: {<span class="keyword">Unit</span>} =&gt; xml form [] (mapU string cols)]
+          (<span class="keyword">fn</span> [nm :: <span class="keyword">Name</span>] [rest :: {<span class="keyword">Unit</span>}] [[nm] ~ rest] name
+                           (acc : xml form [] (mapU string rest)) =&gt; <span class="tag">&lt;xml&gt;</span><span class="string">
+                             </span><span class="tag">&lt;li&gt;</span><span class="string"> </span>{[name]}<span class="string">: </span><span class="tag">&lt;textbox</span>{nm}<span class="tag">/&gt;&lt;/li&gt;</span><span class="string">
+                             </span>{useMore acc}<span class="string">
+                           </span><span class="tag">&lt;/xml&gt;</span>)
+          <span class="tag">&lt;xml/&gt;</span>
+          <span class="cvariable">M</span>.fl <span class="cvariable">M</span>.names}<span class="string">
+        </span><span class="tag">&lt;submit</span> action={handler}<span class="tag">/&gt;</span><span class="string">
+      </span><span class="tag">&lt;/form&gt;</span><span class="string">
+    </span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+
+<span class="keyword">end</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/metaform.urs.html b/demo/out/metaform.urs.html
new file mode 100644
index 0000000..5d3d2f6
--- /dev/null
+++ b/demo/out/metaform.urs.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>metaform.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .module-def {
+        /* font-lock-module-def-face */
+        font-weight: bold;
+      }
+      .type-def {
+        /* font-lock-type-def-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">functor</span> <span class="module-def">Make</span> (<span class="cvariable">M</span> : <span class="keyword">sig</span>
+                  <span class="keyword">con</span> <span class="type-def">fs</span> :: {<span class="keyword">Unit</span>}
+                  <span class="keyword">val</span> <span class="variable-name">fl</span> : folder fs
+                  <span class="keyword">val</span> <span class="variable-name">names</span> : $(mapU string fs)
+              <span class="keyword">end</span>) : <span class="keyword">sig</span>
+    <span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+<span class="keyword">end</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/metaform1.desc.html b/demo/out/metaform1.desc.html
new file mode 100644
index 0000000..f3ff8e5
--- /dev/null
+++ b/demo/out/metaform1.desc.html
@@ -0,0 +1,16 @@
+<html><head>
+<title>Metaform1</title>
+</head><body>
+
+<h1>Metaform1</h1>
+
+<center>[ <a target="showcase" href="/Demo/Metaform1/main">Application</a> | <a target="showcase" href="metaform1.urp.html"><tt>metaform1.urp</tt></a> | <a target="showcase" href="metaform.urs.html"><tt>metaform.urs</tt></a> | <a target="showcase" href="metaform.ur.html"><tt>metaform.ur</tt></a> | <a target="showcase" href="metaform1.urs.html"><tt>metaform1.urs</tt></a> | <a target="showcase" href="metaform1.ur.html"><tt>metaform1.ur</tt></a> ]</center>
+
+
+<p>We can use metaprogramming with row types to build HTML forms (and their handlers) generically.  The functor <tt>Metaform.Make</tt> takes in a unit row <tt>fs</tt> and a value-level record <tt>names</tt> assigning string names to the fields of <tt>fs</tt>.  The functor implementation builds a form handler with a library function <tt>foldURX2</tt>, which runs over two value-level records in parallel, building an XML fragment.</p>
+
+<p>The form itself is generated using the more primitive <tt>foldUR</tt>.  We see the type <tt>xml form [] (mapU string cols)</tt> as the result of the fold.  This is the type of XML fragments that are suitable for inclusion in forms, require no form fields to be defined on entry, and themselves define form fields whose names and types are given by <tt>mapU string cols</tt>.  The <tt>useMore</tt> function "weakens" the type of an XML fragment, so that it "pretends" to require additional fields as input.  This weakening is necessary to accommodate the general typing rule for concatenating bits of XML.</tt>
+<p>The functor use in <tt>Metaform1</tt> is trivial.  The compiler infers the values of the structure members <tt>fs</tt> and <tt>fl</tt> from the type of the value provided for <tt>names</tt>.</p>
+
+
+</body></html>
diff --git a/demo/out/metaform1.html b/demo/out/metaform1.html
new file mode 100644
index 0000000..38c804d
--- /dev/null
+++ b/demo/out/metaform1.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/Metaform1/main" name="showcase">
+<frame src="metaform1.desc.html">
+</frameset>
diff --git a/demo/out/metaform1.ur.html b/demo/out/metaform1.ur.html
new file mode 100644
index 0000000..a552898
--- /dev/null
+++ b/demo/out/metaform1.ur.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>metaform1.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">open</span> <span class="cvariable">Metaform</span>.<span class="cvariable">Make</span>(<span class="keyword">struct</span>
+                       <span class="keyword">val</span> <span class="variable-name">names</span> = {<span class="cvariable">A</span> = <span class="string">"Tic"</span>, <span class="cvariable">B</span> = <span class="string">"Tac"</span>, <span class="cvariable">C</span> = <span class="string">"Toe"</span>}
+                   <span class="keyword">end</span>)
+</pre>
+  </body>
+</html>
diff --git a/demo/out/metaform1.urp.html b/demo/out/metaform1.urp.html
new file mode 100644
index 0000000..f8139eb
--- /dev/null
+++ b/demo/out/metaform1.urp.html
@@ -0,0 +1,7 @@
+<html><body>
+
+<pre>metaform
+metaform1
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/metaform1.urs.html b/demo/out/metaform1.urs.html
new file mode 100644
index 0000000..3c2c147
--- /dev/null
+++ b/demo/out/metaform1.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>metaform1.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+</pre>
+  </body>
+</html>
diff --git a/demo/out/metaform2.desc.html b/demo/out/metaform2.desc.html
new file mode 100644
index 0000000..ba60728
--- /dev/null
+++ b/demo/out/metaform2.desc.html
@@ -0,0 +1,13 @@
+<html><head>
+<title>Metaform2</title>
+</head><body>
+
+<h1>Metaform2</h1>
+
+<center>[ <a target="showcase" href="/Demo/Metaform2/main">Application</a> | <a target="showcase" href="metaform2.urp.html"><tt>metaform2.urp</tt></a> | <a target="showcase" href="metaform.urs.html"><tt>metaform.urs</tt></a> | <a target="showcase" href="metaform.ur.html"><tt>metaform.ur</tt></a> | <a target="showcase" href="metaform2.urs.html"><tt>metaform2.urs</tt></a> | <a target="showcase" href="metaform2.ur.html"><tt>metaform2.ur</tt></a> ]</center>
+
+
+<p>This example showcases code reuse by applying the same functor as in the last example.  The <tt>Metaform2</tt> module mixes pages from the functor with some new pages of its own.</p>
+
+
+</body></html>
diff --git a/demo/out/metaform2.html b/demo/out/metaform2.html
new file mode 100644
index 0000000..a1b3208
--- /dev/null
+++ b/demo/out/metaform2.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/Metaform2/main" name="showcase">
+<frame src="metaform2.desc.html">
+</frameset>
diff --git a/demo/out/metaform2.ur.html b/demo/out/metaform2.ur.html
new file mode 100644
index 0000000..eb81cd5
--- /dev/null
+++ b/demo/out/metaform2.ur.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>metaform2.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .module-def {
+        /* font-lock-module-def-face */
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">structure</span> <span class="module-def">MM</span> = <span class="cvariable">Metaform</span>.<span class="cvariable">Make</span>(<span class="keyword">struct</span>
+                                 <span class="keyword">val</span> <span class="variable-name">names</span> = {<span class="cvariable">X</span> = <span class="string">"x"</span>, <span class="cvariable">Y</span> = <span class="string">"y"</span>}
+                             <span class="keyword">end</span>)
+
+<span class="keyword">fun</span> <span class="function-name">diversion</span> () = return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+  Welcome to the diversion.
+</span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+
+<span class="keyword">fun</span> <span class="function-name">main</span> () = return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+  </span><span class="tag">&lt;li&gt;</span><span class="string"> </span><span class="tag">&lt;a</span> link={diversion ()}<span class="tag">&gt;</span><span class="string">See something shiny!</span><span class="tag">&lt;/a&gt;&lt;/li&gt;</span><span class="string">
+  </span><span class="tag">&lt;li&gt;</span><span class="string"> </span><span class="tag">&lt;a</span> link={<span class="cvariable">MM</span>.main ()}<span class="tag">&gt;</span><span class="string">Fill out a form!</span><span class="tag">&lt;/a&gt;&lt;/li&gt;</span><span class="string">
+</span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/metaform2.urp.html b/demo/out/metaform2.urp.html
new file mode 100644
index 0000000..2538963
--- /dev/null
+++ b/demo/out/metaform2.urp.html
@@ -0,0 +1,7 @@
+<html><body>
+
+<pre>metaform
+metaform2
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/metaform2.urs.html b/demo/out/metaform2.urs.html
new file mode 100644
index 0000000..26e9ba1
--- /dev/null
+++ b/demo/out/metaform2.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>metaform2.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+</pre>
+  </body>
+</html>
diff --git a/demo/out/nested.desc.html b/demo/out/nested.desc.html
new file mode 100644
index 0000000..322b736
--- /dev/null
+++ b/demo/out/nested.desc.html
@@ -0,0 +1,13 @@
+<html><head>
+<title>Nested</title>
+</head><body>
+
+<h1>Nested</h1>
+
+<center>[ <a target="showcase" href="/Demo/Nested/main">Application</a> | <a target="showcase" href="nested.urp.html"><tt>nested.urp</tt></a> | <a target="showcase" href="nested.urs.html"><tt>nested.urs</tt></a> | <a target="showcase" href="nested.ur.html"><tt>nested.ur</tt></a> ]</center>
+
+
+<p>Here is an implementation of the tiny challenge problem from <a href="http://www.accursoft.co.uk/web/">this web framework comparison</a>.  Using nested function definitions, it is easy to persist state across clicks.</p>
+
+
+</body></html>
diff --git a/demo/out/nested.html b/demo/out/nested.html
new file mode 100644
index 0000000..fbd7701
--- /dev/null
+++ b/demo/out/nested.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/Nested/main" name="showcase">
+<frame src="nested.desc.html">
+</frameset>
diff --git a/demo/out/nested.ur.html b/demo/out/nested.ur.html
new file mode 100644
index 0000000..9ffc824
--- /dev/null
+++ b/demo/out/nested.ur.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>nested.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">fun</span> <span class="function-name">pageA</span> () = return <span class="tag">&lt;xml&gt;</span><span class="string">
+  </span><span class="tag">&lt;head&gt;</span><span class="string">
+    </span><span class="tag">&lt;title&gt;</span><span class="string">A</span><span class="tag">&lt;/title&gt;</span><span class="string">
+  </span><span class="tag">&lt;/head&gt;</span><span class="string">
+  </span><span class="tag">&lt;body&gt;</span><span class="string">
+    </span><span class="tag">&lt;form&gt;</span><span class="string">
+      </span><span class="tag">&lt;table&gt;</span><span class="string">
+        </span><span class="tag">&lt;tr&gt;</span><span class="string">
+          </span><span class="tag">&lt;td&gt;</span><span class="string">Forename:</span><span class="tag">&lt;/td&gt;</span><span class="string">
+          </span><span class="tag">&lt;td&gt;&lt;textbox</span>{#<span class="cvariable">Forename</span>}<span class="tag">/&gt;&lt;/td&gt;</span><span class="string">
+        </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+        </span><span class="tag">&lt;tr&gt;</span><span class="string">
+          </span><span class="tag">&lt;td&gt;</span><span class="string">Enter a Surname?</span><span class="tag">&lt;/td&gt;</span><span class="string">
+          </span><span class="tag">&lt;td&gt;&lt;checkbox</span>{#<span class="cvariable">EnterSurname</span>}<span class="tag">/&gt;&lt;/td&gt;</span><span class="string">
+        </span><span class="tag">&lt;/tr&gt;</span><span class="string">
+      </span><span class="tag">&lt;/table&gt;</span><span class="string">
+      </span><span class="tag">&lt;submit</span> action={fromA} <span class="tag">/&gt;</span><span class="string">
+    </span><span class="tag">&lt;/form&gt;</span><span class="string">
+  </span><span class="tag">&lt;/body&gt;</span><span class="string">
+</span><span class="tag">&lt;/xml&gt;</span>
+
+<span class="keyword">and</span> <span class="function-name">fromA</span> r =
+    <span class="keyword">let</span>
+        <span class="keyword">val</span> <span class="variable-name">forename</span> = r.<span class="cvariable">Forename</span>
+
+        <span class="keyword">fun</span> <span class="function-name">pageB</span> () = return <span class="tag">&lt;xml&gt;</span><span class="string">
+          </span><span class="tag">&lt;head&gt;</span><span class="string">
+            </span><span class="tag">&lt;title&gt;</span><span class="string">B</span><span class="tag">&lt;/title&gt;</span><span class="string">
+          </span><span class="tag">&lt;/head&gt;</span><span class="string">
+          </span><span class="tag">&lt;body&gt;</span><span class="string">
+            </span><span class="tag">&lt;form&gt;</span><span class="string">
+              Surname:
+              </span><span class="tag">&lt;textbox</span>{#<span class="cvariable">Surname</span>}<span class="tag">/&gt;</span><span class="string">
+              </span><span class="tag">&lt;submit</span> action={pageC'} <span class="tag">/&gt;</span><span class="string">
+            </span><span class="tag">&lt;/form&gt;</span><span class="string">
+            </span><span class="tag">&lt;a</span> link={pageA ()}<span class="tag">&gt;</span><span class="string">Previous</span><span class="tag">&lt;/a&gt;</span><span class="string">
+          </span><span class="tag">&lt;/body&gt;</span><span class="string">
+        </span><span class="tag">&lt;/xml&gt;</span>
+
+        <span class="keyword">and</span> <span class="function-name">pageC'</span> r = pageC (<span class="cvariable">Some</span> r.<span class="cvariable">Surname</span>)
+
+        <span class="keyword">and</span> <span class="function-name">pageC</span> surname = return <span class="tag">&lt;xml&gt;</span><span class="string">
+          </span><span class="tag">&lt;head&gt;</span><span class="string">
+            </span><span class="tag">&lt;title&gt;</span><span class="string">C</span><span class="tag">&lt;/title&gt;</span><span class="string">
+          </span><span class="tag">&lt;/head&gt;</span><span class="string">
+          </span><span class="tag">&lt;body&gt;</span><span class="string">
+            </span><span class="tag">&lt;p&gt;</span><span class="string">Hello </span>{[forename]}{<span class="keyword">case</span> surname <span class="keyword">of</span>
+                                      <span class="cvariable">None</span> =&gt; <span class="tag">&lt;xml/&gt;</span>
+                                    | <span class="cvariable">Some</span> s =&gt; <span class="tag">&lt;xml&gt;</span><span class="string"> </span>{[s]}<span class="tag">&lt;/xml&gt;</span>}<span class="tag">&lt;/p&gt;</span><span class="string">
+            </span>{<span class="keyword">case</span> surname <span class="keyword">of</span>
+                 <span class="cvariable">None</span> =&gt; <span class="tag">&lt;xml&gt;&lt;a</span> link={pageA ()}<span class="tag">&gt;</span><span class="string">Previous</span><span class="tag">&lt;/a&gt;&lt;/xml&gt;</span>
+               | <span class="cvariable">Some</span> _ =&gt; <span class="tag">&lt;xml&gt;&lt;a</span> link={pageB ()}<span class="tag">&gt;</span><span class="string">Previous</span><span class="tag">&lt;/a&gt;&lt;/xml&gt;</span>}<span class="string">
+          </span><span class="tag">&lt;/body&gt;</span><span class="string">
+        </span><span class="tag">&lt;/xml&gt;</span>
+    <span class="keyword">in</span>
+        <span class="keyword">if</span> r.<span class="cvariable">EnterSurname</span> <span class="keyword">then</span>
+            pageB ()
+        <span class="keyword">else</span>
+            pageC <span class="cvariable">None</span>
+    <span class="keyword">end</span>
+
+<span class="keyword">val</span> <span class="variable-name">main</span> = pageA
+</pre>
+  </body>
+</html>
diff --git a/demo/out/nested.urp.html b/demo/out/nested.urp.html
new file mode 100644
index 0000000..378535d
--- /dev/null
+++ b/demo/out/nested.urp.html
@@ -0,0 +1,6 @@
+<html><body>
+
+<pre>nested
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/nested.urs.html b/demo/out/nested.urs.html
new file mode 100644
index 0000000..8f741a3
--- /dev/null
+++ b/demo/out/nested.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>nested.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+</pre>
+  </body>
+</html>
diff --git a/demo/out/noisy.desc.html b/demo/out/noisy.desc.html
new file mode 100644
index 0000000..5ec81c2
--- /dev/null
+++ b/demo/out/noisy.desc.html
@@ -0,0 +1,13 @@
+<html><head>
+<title>Noisy</title>
+</head><body>
+
+<h1>Noisy</h1>
+
+<center>[ <a target="showcase" href="/Demo/Noisy/main">Application</a> | <a target="showcase" href="noisy.urp.html"><tt>noisy.urp</tt></a> | <a target="showcase" href="noisy.urs.html"><tt>noisy.urs</tt></a> | <a target="showcase" href="noisy.ur.html"><tt>noisy.ur</tt></a> ]</center>
+
+
+<p>This example shows how easy it is to make the flow of control "ping pong" back and forth between the client and the server.  Clicking a button triggers three queries to the server, with an alert generated after each query.</p>
+
+
+</body></html>
diff --git a/demo/out/noisy.html b/demo/out/noisy.html
new file mode 100644
index 0000000..047005f
--- /dev/null
+++ b/demo/out/noisy.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/Noisy/main" name="showcase">
+<frame src="noisy.desc.html">
+</frameset>
diff --git a/demo/out/noisy.ur.html b/demo/out/noisy.ur.html
new file mode 100644
index 0000000..1ddc9fb
--- /dev/null
+++ b/demo/out/noisy.ur.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>noisy.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .sql {
+        /* font-lock-sql-face */
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+      .type-def {
+        /* font-lock-type-def-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">datatype</span> <span class="type-def">list</span> t = <span class="cvariable">Nil</span> | <span class="cvariable">Cons</span> <span class="keyword">of</span> t * list t
+
+<span class="keyword">table</span> <span class="variable-name">t</span> : { <span class="cvariable">Id</span> : int, <span class="cvariable">A</span> : string }
+  <span class="sql">PRIMARY</span> <span class="sql">KEY</span> <span class="cvariable">Id</span>
+
+<span class="keyword">fun</span> <span class="function-name">add</span> id s =
+    dml (<span class="sql">INSERT</span> <span class="sql">INTO</span> t (<span class="cvariable">Id</span>, <span class="cvariable">A</span>) <span class="sql">VALUES</span> ({[id]}, {[s]}))
+
+<span class="keyword">fun</span> <span class="function-name">del</span> id =
+    dml (<span class="sql">DELETE</span> <span class="sql">FROM</span> t <span class="sql">WHERE</span> t.<span class="cvariable">Id</span> = {[id]})
+
+<span class="keyword">fun</span> <span class="function-name">lookup</span> id =
+    ro &lt;- oneOrNoRows (<span class="sql">SELECT</span> t.<span class="cvariable">A</span> <span class="sql">FROM</span> t <span class="sql">WHERE</span> t.<span class="cvariable">Id</span> = {[id]});
+    <span class="keyword">case</span> ro <span class="keyword">of</span>
+        <span class="cvariable">None</span> =&gt; return <span class="cvariable">None</span>
+      | <span class="cvariable">Some</span> r =&gt; return (<span class="cvariable">Some</span> r.<span class="cvariable">T</span>.<span class="cvariable">A</span>)
+
+<span class="keyword">fun</span> <span class="function-name">check</span> ls =
+    <span class="keyword">case</span> ls <span class="keyword">of</span>
+        <span class="cvariable">Nil</span> =&gt; return ()
+      | <span class="cvariable">Cons</span> (id, ls') =&gt;
+        ao &lt;- rpc (lookup id);
+        alert (<span class="keyword">case</span> ao <span class="keyword">of</span>
+                   <span class="cvariable">None</span> =&gt; <span class="string">"Nada"</span>
+                 | <span class="cvariable">Some</span> a =&gt; a);
+        check ls'
+
+<span class="keyword">fun</span> <span class="function-name">main</span> () =
+    idAdd &lt;- source <span class="string">""</span>;
+    aAdd &lt;- source <span class="string">""</span>;
+
+    idDel &lt;- source <span class="string">""</span>;
+
+    return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+      </span><span class="tag">&lt;button</span> value=<span class="string">"Check values of 1, 2, and 3"</span> onclick={check (<span class="cvariable">Cons</span> (1, <span class="cvariable">Cons</span> (2, <span class="cvariable">Cons</span> (3, <span class="cvariable">Nil</span>))))}<span class="tag">/&gt;&lt;br/&gt;</span><span class="string">
+      </span><span class="tag">&lt;br/&gt;</span><span class="string">
+      </span><span class="tag">&lt;button</span> value=<span class="string">"Add"</span> onclick={id &lt;- get idAdd; a &lt;- get aAdd; rpc (add (readError id) a)}<span class="tag">/&gt;</span><span class="string">
+      </span><span class="tag">&lt;ctextbox</span> source={idAdd}<span class="tag">/&gt;</span><span class="string">
+      </span><span class="tag">&lt;ctextbox</span> source={aAdd}<span class="tag">/&gt;&lt;br/&gt;</span><span class="string">
+      </span><span class="tag">&lt;br/&gt;</span><span class="string">
+      </span><span class="tag">&lt;button</span> value=<span class="string">"Delete"</span> onclick={id &lt;- get idDel; rpc (del (readError id))}<span class="tag">/&gt;</span><span class="string">
+      </span><span class="tag">&lt;ctextbox</span> source={idDel}<span class="tag">/&gt;</span><span class="string">
+    </span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+</pre>
+  </body>
+</html>
diff --git a/demo/out/noisy.urp.html b/demo/out/noisy.urp.html
new file mode 100644
index 0000000..fcb6b26
--- /dev/null
+++ b/demo/out/noisy.urp.html
@@ -0,0 +1,9 @@
+<html><body>
+
+<pre>database dbname=test
+sql noisy.sql
+
+noisy
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/noisy.urs.html b/demo/out/noisy.urs.html
new file mode 100644
index 0000000..fff3673
--- /dev/null
+++ b/demo/out/noisy.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>noisy.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">val</span> <span class="variable-name">main</span> : unit -&gt; transaction page
+</pre>
+  </body>
+</html>
diff --git a/demo/out/outer.desc.html b/demo/out/outer.desc.html
new file mode 100644
index 0000000..99f69c4
--- /dev/null
+++ b/demo/out/outer.desc.html
@@ -0,0 +1,13 @@
+<html><head>
+<title>Outer</title>
+</head><body>
+
+<h1>Outer</h1>
+
+<center>[ <a target="showcase" href="/Demo/Outer/main">Application</a> | <a target="showcase" href="outer.urp.html"><tt>outer.urp</tt></a> | <a target="showcase" href="outer.urs.html"><tt>outer.urs</tt></a> | <a target="showcase" href="outer.ur.html"><tt>outer.ur</tt></a> ]</center>
+
+
+<p>SQL outer joins are no problem, as this demo shows.  Unlike with SQL, here we have static type inference determining for us which columns may become nullable as a result of an outer join, and the compiler will reject programs that make the wrong assumptions about that process.  The details of that nullification don't appear in this example, where the magic of type classes determines both the post-join type of each field and the right pretty-printing and parsing function for each of those types.</p>
+
+
+</body></html>
diff --git a/demo/out/outer.html b/demo/out/outer.html
new file mode 100644
index 0000000..0d7bc3b
--- /dev/null
+++ b/demo/out/outer.html
@@ -0,0 +1,4 @@
+<frameset rows="50%,*">
+<frame src="/Demo/Outer/main" name="showcase">
+<frame src="outer.desc.html">
+</frameset>
diff --git a/demo/out/outer.ur.html b/demo/out/outer.ur.html
new file mode 100644
index 0000000..3964981
--- /dev/null
+++ b/demo/out/outer.ur.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>outer.ur</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .cvariable {
+        /* font-lock-cvariable-face */
+        color: #0000ff;
+      }
+      .function-name {
+        /* font-lock-function-name-face */
+        color: #0000ff;
+        font-weight: bold;
+      }
+      .keyword {
+        /* font-lock-keyword-face */
+        color: #00ffff;
+        font-weight: bold;
+      }
+      .sql {
+        /* font-lock-sql-face */
+        font-weight: bold;
+      }
+      .string {
+        /* font-lock-string-face */
+        color: #00ff00;
+      }
+      .tag {
+        /* font-lock-tag-face */
+        font-weight: bold;
+      }
+      .variable-name {
+        /* font-lock-variable-name-face */
+        color: #ffff00;
+      }
+
+      a {
+        color: inherit;
+        background-color: inherit;
+        font: inherit;
+        text-decoration: inherit;
+      }
+      a:hover {
+        text-decoration: underline;
+      }
+    -->
+    </style>
+  </head>
+  <body>
+    <pre>
+<span class="keyword">table</span> <span class="variable-name">t</span> : { <span class="cvariable">Id</span> : int, <span class="cvariable">B</span> : string }
+  <span class="sql">PRIMARY</span> <span class="sql">KEY</span> <span class="cvariable">Id</span>
+
+<span class="keyword">table</span> <span class="variable-name">u</span> : { <span class="cvariable">Id</span> : int, <span class="cvariable">Link</span> : int, <span class="cvariable">C</span> : string, <span class="cvariable">D</span> : option float }
+  <span class="sql">PRIMARY</span> <span class="sql">KEY</span> <span class="cvariable">Id</span>,
+  <span class="sql">CONSTRAINT</span> <span class="cvariable">Link</span> <span class="sql">FOREIGN</span> <span class="sql">KEY</span> <span class="cvariable">Link</span> <span class="sql">REFERENCES</span> t(<span class="cvariable">Id</span>)
+
+<span class="keyword">fun</span> <span class="function-name">main</span> () =
+    xml &lt;- queryX (<span class="sql">SELECT</span> t.<span class="cvariable">Id</span>, t.<span class="cvariable">B</span>, u.<span class="cvariable">Id</span>, u.<span class="cvariable">C</span>, u.<span class="cvariable">D</span>
+                   <span class="sql">FROM</span> t <span class="sql">LEFT</span> <span class="sql">JOIN</span> u <span class="sql">ON</span> t.<span class="cvariable">Id</span> = u.<span class="cvariable">Link</span>)
+                  (<span class="keyword">fn</span> r =&gt; <span class="tag">&lt;xml&gt;&lt;tr&gt;</span><span class="string">
+                    </span><span class="tag">&lt;td&gt;</span>{[r.<span class="cvariable">T</span>.<span class="cvariable">Id</span>]}<span class="tag">&lt;/td&gt;</span><span class="string">
+                    </span><span class="tag">&lt;td&gt;</span>{[r.<span class="cvariable">T</span>.<span class="cvariable">B</span>]}<span class="tag">&lt;/td&gt;</span><span class="string">
+                    </span><span class="tag">&lt;td&gt;</span>{[r.<span class="cvariable">U</span>.<span class="cvariable">Id</span>]}<span class="tag">&lt;/td&gt;</span><span class="string">
+                    </span><span class="tag">&lt;td&gt;</span>{[r.<span class="cvariable">U</span>.<span class="cvariable">C</span>]}<span class="tag">&lt;/td&gt;</span><span class="string">
+                    </span><span class="tag">&lt;td&gt;</span>{[r.<span class="cvariable">U</span>.<span class="cvariable">D</span>]}<span class="tag">&lt;/td&gt;</span><span class="string">
+                  </span><span class="tag">&lt;/tr&gt;&lt;/xml&gt;</span>);
+    return <span class="tag">&lt;xml&gt;&lt;body&gt;</span><span class="string">
+      </span><span class="tag">&lt;table&gt;</span>{xml}<span class="tag">&lt;/table&gt;</span><span class="string">
+
+      </span><span class="tag">&lt;form&gt;</span><span class="string">Insert into t: </span><span class="tag">&lt;textbox</span>{#<span class="cvariable">Id</span>} size={5}<span class="tag">/&gt;</span><span class="string"> </span><span class="tag">&lt;textbox</span>{#<span class="cvariable">B</span>} size={5}<span class="tag">/&gt;</span><span class="string">
+        </span><span class="tag">&lt;submit</span> action={addT}<span class="tag">/&gt;&lt;/form&gt;</span><span class="string">
+      </span><span class="tag">&lt;form&gt;</span><span class="string">
+        Insert into u: </span><span class="tag">&lt;textbox</span>{#<span class="cvariable">Id</span>} size={5}<span class="tag">/&gt;</span><span class="string"> </span><span class="tag">&lt;textbox</span>{#<span class="cvariable">Link</span>} size={5}<span class="tag">/&gt;</span><span class="string"> </span><span class="tag">&lt;textbox</span>{#<span class="cvariable">C</span>} size={5}<span class="tag">/&gt;</span><span class="string">
+        </span><span class="tag">&lt;textbox</span>{#<span class="cvariable">D</span>} size={5}<span class="tag">/&gt;</span><span class="string"> </span><span class="tag">&lt;submit</span> action={addU}<span class="tag">/&gt;</span><span class="string">
+      </span><span class="tag">&lt;/form&gt;</span><span class="string">
+    </span><span class="tag">&lt;/body&gt;&lt;/xml&gt;</span>
+
+<span class="keyword">and</span> <span class="function-name">addT</span> r =
+    dml (<span class="sql">INSERT</span> <span class="sql">INTO</span> t (<span class="cvariable">Id</span>, <span class="cvariable">B</span>) <span class="sql">VALUES</span> ({[readError r.<span class="cvariable">Id</span>]}, {[r.<span class="cvariable">B</span>]}));
+    main ()
+
+<span class="keyword">and</span> <span class="function-name">addU</span> r =
+    dml (<span class="sql">INSERT</span> <span class="sql">INTO</span> u (<span class="cvariable">Id</span>, <span class="cvariable">Link</span>, <span class="cvariable">C</span>, <span class="cvariable">D</span>) <span class="sql">VALUES</span> ({[readError r.<span class="cvariable">Id</span>]}, {[readError r.<span class="cvariable">Link</span>]}, {[r.<span class="cvariable">C</span>]}, {[readError r.<span class="cvariable">D</span>]}));
+    main ()
+</pre>
+  </body>
+</html>
diff --git a/demo/out/outer.urp.html b/demo/out/outer.urp.html
new file mode 100644
index 0000000..002c97b
--- /dev/null
+++ b/demo/out/outer.urp.html
@@ -0,0 +1,9 @@
+<html><body>
+
+<pre>database dbname=test
+sql outer.sql
+
+outer
+</pre>
+
+</body></html>
\ No newline at end of file
diff --git a/demo/out/outer.urs.html b/demo/out/outer.urs.html
new file mode 100644
index 0000000..d8edf64
--- /dev/null
+++ b/demo/out/outer.urs.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<!-- Created by htmlize-1.34 in css mode. -->
+<html>
+  <head>
+    <title>outer.urs</title>
+    <style type="text/css">
+    <!--
+      body {
+        color: #000000;
+        background-color: #ffffff;
+      }
+      .keyword {

Diff truncated because it is very large.