changeset 757:fa2019a63ea4

Basis.list
author Adam Chlipala <adamc@hcoop.net>
date Thu, 30 Apr 2009 11:07:29 -0400
parents 8ce31c052dce
children 8323c1beef2e
files include/types.h lib/ur/basis.urs src/cjr.sml src/cjr_print.sml src/cjrize.sml src/core_print.sig src/core_print.sml src/mono.sml src/mono_print.sml src/mono_util.sml src/monoize.sml tests/list.ur tests/list.urp tests/list.urs
diffstat 14 files changed, 152 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/include/types.h	Tue Apr 28 17:26:53 2009 -0400
+++ b/include/types.h	Thu Apr 30 11:07:29 2009 -0400
@@ -21,6 +21,7 @@
 
 typedef uw_Basis_string uw_Basis_xhtml;
 typedef uw_Basis_string uw_Basis_page;
+typedef uw_Basis_string uw_Basis_xbody;
 typedef uw_Basis_string uw_Basis_css_class;
 
 typedef unsigned uw_Basis_client;
--- a/lib/ur/basis.urs	Tue Apr 28 17:26:53 2009 -0400
+++ b/lib/ur/basis.urs	Thu Apr 30 11:07:29 2009 -0400
@@ -10,6 +10,8 @@
 
 datatype option t = None | Some of t
 
+datatype list t = Nil | Cons of t * list t
+
 
 (** Basic type classes *)
 
--- a/src/cjr.sml	Tue Apr 28 17:26:53 2009 -0400
+++ b/src/cjr.sml	Thu Apr 30 11:07:29 2009 -0400
@@ -37,6 +37,7 @@
        | TDatatype of datatype_kind * int * (string * int * typ option) list ref
        | TFfi of string * string
        | TOption of typ
+       | TList of typ * int
 
 withtype typ = typ' located
 
--- a/src/cjr_print.sml	Tue Apr 28 17:26:53 2009 -0400
+++ b/src/cjr_print.sml	Thu Apr 30 11:07:29 2009 -0400
@@ -102,6 +102,11 @@
         else
             box [p_typ' par env t,
                  string "*"]
+      | TList (_, i) => box [string "struct",
+                             space,
+                             string "__uws_",
+                             string (Int.toString i),
+                             string "*"]
 
 and p_typ env = p_typ' false env
 
@@ -147,7 +152,7 @@
         PConVar n => p_con_named env n
       | PConFfi {mod = m, con, ...} => string ("uw_" ^ ident m ^ "_" ^ ident con)
 
-fun p_pat (env, exit, depth) (p, _) =
+fun p_pat (env, exit, depth) (p, loc) =
     case p of
         PWild =>
         (box [], env)
@@ -328,6 +333,10 @@
                 in
                     (box [string "{",
                           newline,
+                          string "/* ",
+                          string (ErrorMsg.spanToString loc),
+                          string "*/",
+                          newline,
                           p_typ env t,
                           space,
                           string "disc",
@@ -574,6 +583,7 @@
               | TFfi ("Basis", "blob") => allowHeapAllocated
               | TFfi _ => true
               | TOption t => allowHeapAllocated andalso nl ok t
+              | TList (t, _) => allowHeapAllocated andalso nl ok t
     in
         nl IS.empty
     end
--- a/src/cjrize.sml	Tue Apr 28 17:26:53 2009 -0400
+++ b/src/cjrize.sml	Thu Apr 30 11:07:29 2009 -0400
@@ -37,6 +37,7 @@
 
     val empty : t
     val find : t * (string * L.typ) list * (string * L'.typ) list -> t * int
+    val findList : t * L.typ * L'.typ -> t * int
 
     val declares : t -> (int * (string * L'.typ) list) list
     val clearDeclares : t -> t
@@ -47,22 +48,54 @@
                            val compare = MonoUtil.Typ.compare
                            end)
 
-type t = int * int FM.map * (int * (string * L'.typ) list) list
+type t = {
+     count : int,
+     normal : int FM.map,
+     lists : int FM.map,
+     decls : (int * (string * L'.typ) list) list
+}
 
-val empty : t = (1, FM.insert (FM.empty, (L.TRecord [], ErrorMsg.dummySpan), 0), [])
+val empty : t = {
+    count = 1,
+    normal = FM.insert (FM.empty, (L.TRecord [], ErrorMsg.dummySpan), 0),
+    lists = FM.empty,
+    decls = []
+}
 
-fun find ((n, m, ds), xts, xts') =
+fun find (v as {count, normal, decls, lists}, xts, xts') =
     let
         val t = (L.TRecord xts, ErrorMsg.dummySpan)
     in
-        case FM.find (m, t) of
-            NONE => ((n+1, FM.insert (m, t, n), (n, xts') :: ds), n)
-          | SOME i => ((n, m, ds), i)
+        case FM.find (normal, t) of
+            SOME i => (v, i)
+          | NONE => ({count = count+1,
+                      normal = FM.insert (normal, t, count),
+                      lists = lists,
+                      decls = (count, xts') :: decls},
+                     count)
     end
 
-fun declares (_, _, ds) = ds
+fun findList (v as {count, normal, decls, lists}, t, t') =
+    case FM.find (lists, t) of
+        SOME i => (v, i)
+      | NONE =>
+        let
+            val xts = [("1", t), ("2", (L.TList t, #2 t))]
+            val xts' = [("1", t'), ("2", (L'.TList (t', count), #2 t'))]
+        in
+            ({count = count+1,
+              normal = FM.insert (normal, (L.TRecord xts, ErrorMsg.dummySpan), count),
+              lists = FM.insert (lists, t, count),
+              decls = (count, xts') :: decls},
+             count)
+    end
 
-fun clearDeclares (n, m, _) = (n, m, [])
+fun declares (v : t) = #decls v
+
+fun clearDeclares (v : t) = {count = #count v,
+                             normal = #normal v,
+                             lists = #lists v,
+                             decls = []}
 
 end
 
@@ -120,6 +153,13 @@
                 in
                     ((L'.TOption t, loc), sm)
                 end
+              | L.TList t =>
+                let
+                    val (t', sm) = cify dtmap (t, sm)
+                    val (sm, si) = Sm.findList (sm, t, t')
+                in
+                    ((L'.TList (t', si), loc), sm)
+                end
               | L.TSource => ((L'.TFfi ("Basis", "int"), loc), sm)
               | L.TSignal _ => raise Fail "Cjrize: TSignal remains"
     in
--- a/src/core_print.sig	Tue Apr 28 17:26:53 2009 -0400
+++ b/src/core_print.sig	Thu Apr 30 11:07:29 2009 -0400
@@ -30,6 +30,7 @@
 signature CORE_PRINT = sig
     val p_kind : CoreEnv.env -> Core.kind Print.printer
     val p_con : CoreEnv.env -> Core.con Print.printer
+    val p_patCon : CoreEnv.env -> Core.patCon Print.printer
     val p_pat : CoreEnv.env -> Core.pat Print.printer
     val p_exp : CoreEnv.env -> Core.exp Print.printer
     val p_decl : CoreEnv.env -> Core.decl Print.printer
--- a/src/core_print.sml	Tue Apr 28 17:26:53 2009 -0400
+++ b/src/core_print.sml	Thu Apr 30 11:07:29 2009 -0400
@@ -198,11 +198,23 @@
 fun p_patCon env pc =
     case pc of
         PConVar n => p_con_named env n
-      | PConFfi {mod = m, con, ...} => box [string "FFIC(",
-                                            string m,
-                                            string ".",
-                                            string con,
-                                            string ")"]
+      | PConFfi {mod = m, con, arg, ...} =>
+        if !debug then
+            box [string "FFIC[",
+                 case arg of
+                     NONE => box []
+                   | SOME t => p_con env t,
+                 string "](",
+                 string m,
+                 string ".",
+                 string con,
+                 string ")"]
+        else
+            box [string "FFIC(",
+                 string m,
+                 string ".",
+                 string con,
+                 string ")"]
 
 fun p_pat' par env (p, _) =
     case p of
--- a/src/mono.sml	Tue Apr 28 17:26:53 2009 -0400
+++ b/src/mono.sml	Thu Apr 30 11:07:29 2009 -0400
@@ -37,6 +37,7 @@
        | TDatatype of int * (datatype_kind * (string * int * typ option) list) ref
        | TFfi of string * string
        | TOption of typ
+       | TList of typ
        | TSource
        | TSignal of typ
 
--- a/src/mono_print.sml	Tue Apr 28 17:26:53 2009 -0400
+++ b/src/mono_print.sml	Thu Apr 30 11:07:29 2009 -0400
@@ -65,6 +65,9 @@
       | TOption t => box [string "option(",
                           p_typ env t,
                           string ")"]
+      | TList t => box [string "list(",
+                        p_typ env t,
+                        string ")"]
       | TSource => string "source"
       | TSignal t => box [string "signal(",
                           p_typ env t,
@@ -114,9 +117,17 @@
                                                            p_pat env p]) xps,
              string "}"]
       | PNone _ => string "None"
-      | PSome (_, p) => box [string "Some",
-                             space,
-                             p_pat' true env p]
+      | PSome (t, p) =>
+        if !debug then
+            box [string "Some[",
+                 p_typ env t,
+                 string "]",
+                 space,
+                 p_pat' true env p]
+        else
+            box [string "Some",
+                 space,
+                 p_pat' true env p]
 
 and p_pat x = p_pat' false x
 
--- a/src/mono_util.sml	Tue Apr 28 17:26:53 2009 -0400
+++ b/src/mono_util.sml	Thu Apr 30 11:07:29 2009 -0400
@@ -51,6 +51,7 @@
       | (TDatatype (n1, _), TDatatype (n2, _)) => Int.compare (n1, n2)
       | (TFfi (m1, x1), TFfi (m2, x2)) => join (String.compare (m1, m2), fn () => String.compare (x1, x2))
       | (TOption t1, TOption t2) => compare (t1, t2)
+      | (TList t1, TList t2) => compare (t1, t2)
       | (TSource, TSource) => EQUAL
       | (TSignal t1, TSignal t2) => compare (t1, t2)
 
@@ -69,6 +70,9 @@
       | (TOption _, _) => LESS
       | (_, TOption _) => GREATER
 
+      | (TList _, _) => LESS
+      | (_, TList _) => GREATER
+
       | (TSource, _) => LESS
       | (_, TSource) => GREATER
 
@@ -104,6 +108,10 @@
                 S.map2 (mft t,
                         fn t' =>
                            (TOption t, loc))
+              | TList t =>
+                S.map2 (mft t,
+                        fn t' =>
+                           (TList t, loc))
               | TSource => S.return2 cAll
               | TSignal t =>
                 S.map2 (mft t,
--- a/src/monoize.sml	Tue Apr 28 17:26:53 2009 -0400
+++ b/src/monoize.sml	Thu Apr 30 11:07:29 2009 -0400
@@ -94,6 +94,8 @@
 
                   | L.CApp ((L.CFfi ("Basis", "option"), _), t) =>
                     (L'.TOption (mt env dtmap t), loc)
+                  | L.CApp ((L.CFfi ("Basis", "list"), _), t) =>
+                    (L'.TList (mt env dtmap t), loc)
 
                   | L.CApp ((L.CFfi ("Basis", "eq"), _), t) =>
                     let
@@ -494,6 +496,9 @@
 
 val dummyPat = (L'.PPrim (Prim.Int 0), ErrorMsg.dummySpan)
 
+
+fun listify t = (L'.TRecord [("1", t), ("2", (L'.TList t, #2 t))], #2 t)
+
 fun monoPat env (all as (p, loc)) =
     let
         fun poly () =
@@ -506,8 +511,12 @@
           | L.PVar (x, t) => (L'.PVar (x, monoType env t), loc)
           | L.PPrim p => (L'.PPrim p, loc)
           | L.PCon (dk, pc, [], po) => (L'.PCon (dk, monoPatCon env pc, Option.map (monoPat env) po), loc)
+          | L.PCon (L.Option, L.PConFfi {mod = "Basis", datatyp = "list", ...}, [t], NONE) =>
+            (L'.PNone (listify (monoType env t)), loc)
+          | L.PCon (L.Option, L.PConFfi {mod = "Basis", datatyp = "list", ...}, [t], SOME p) =>
+            (L'.PSome (listify (monoType env t), monoPat env p), loc)
           | L.PCon (L.Option, _, [t], NONE) => (L'.PNone (monoType env t), loc)
-          | L.PCon (L.Option, _, [t], SOME p) => (L'.PSome (monoType env t, monoPat env p), loc)
+          | L.PCon (L.Option, pc, [t], SOME p) => (L'.PSome (monoType env t, monoPat env p), loc)
           | L.PCon _ => poly ()
           | L.PRecord xps => (L'.PRecord (map (fn (x, p, t) => (x, monoPat env p, monoType env t)) xps), loc)
     end
@@ -613,6 +622,14 @@
             in
                 ((L'.ECon (dk, monoPatCon env pc, eo), loc), fm)
             end
+          | L.ECon (L.Option, L.PConFfi {mod = "Basis", datatyp = "list", ...}, [t], NONE) =>
+            ((L'.ENone (listify (monoType env t)), loc), fm)
+          | L.ECon (L.Option, L.PConFfi {mod = "Basis", datatyp = "list", ...}, [t], SOME e) =>
+            let
+                val (e, fm) = monoExp (env, st, fm) e
+            in
+                ((L'.ESome (listify (monoType env t), e), loc), fm)
+            end
           | L.ECon (L.Option, _, [t], NONE) =>
             ((L'.ENone (monoType env t), loc), fm)
           | L.ECon (L.Option, _, [t], SOME e) =>
@@ -2892,6 +2909,18 @@
             in
                 SOME (env', fm, [d])
             end
+          | L.DDatatype ("list", n, [_], [("Nil", _, NONE),
+                                          ("Cons", _, SOME (L.TRecord (L.CRecord (_,
+                                                                                  [((L.CName "1", _),
+                                                                                    (L.CRel 0, _)),
+                                                                                   ((L.CName "2", _),
+                                                                                    (L.CApp ((L.CNamed n', _),
+                                                                                             (L.CRel 0, _)),
+                                                                                     _))]), _), _))]) =>
+            if n = n' then
+                NONE
+            else
+                poly ()
           | L.DDatatype _ => poly ()
           | L.DVal (x, n, t, e, s) =>
             let
--- a/tests/list.ur	Tue Apr 28 17:26:53 2009 -0400
+++ b/tests/list.ur	Thu Apr 30 11:07:29 2009 -0400
@@ -1,19 +1,17 @@
-datatype list a = Nil | Cons of a * list a
+fun isNil (t ::: Type) (ls : list t) =
+    case ls of
+        Nil => True
+      | _ => False
 
-val isNil = fn t ::: Type => fn ls : list t =>
-        case ls of Nil => True | _ => False
+fun delist (ls : list string) : xbody =
+        case ls of
+            Nil => <xml>Nil</xml>
+          | Cons (h, t) => <xml>{[h]} :: {delist t}</xml>
 
-val show = fn b => if b then "True" else "False"
+fun main () = return <xml><body>
+  {[isNil (Nil : list bool)]},
+  {[isNil (Cons (1, Nil))]},
+  {[isNil (Cons ("A", Cons ("B", Nil)))]}
 
-val rec delist : list string -> xml body [] [] = fn x =>
-        case x of
-          Nil => <body>Nil</body>
-        | Cons (h, t) => <body>{cdata h} :: {delist t}</body>
-
-val main : unit -> page = fn () => <html><body>
-        {cdata (show (isNil (Nil : list bool)))},
-        {cdata (show (isNil (Cons (1, Nil))))},
-        {cdata (show (isNil (Cons ("A", Cons ("B", Nil)))))}
-
-        <p>{delist (Cons ("X", Cons ("Y", Cons ("Z", Nil))))}</p>
-</body></html>
+  <p>{delist (Cons ("X", Cons ("Y", Cons ("Z", Nil))))}</p>
+</body></xml>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/list.urp	Thu Apr 30 11:07:29 2009 -0400
@@ -0,0 +1,3 @@
+debug
+
+list
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/list.urs	Thu Apr 30 11:07:29 2009 -0400
@@ -0,0 +1,1 @@
+val main : unit -> transaction page