From 3cb644caeed50e5c82778b5ed7c165950655109a Mon Sep 17 00:00:00 2001 From: Adam Chlipala Date: Thu, 28 May 2009 10:16:50 -0400 Subject: fn-pattern code in but not tested yet; hello compiles --- lib/ur/list.ur | 26 ++++++++++++ lib/ur/list.urs | 5 +++ lib/ur/top.ur | 90 +++++++++++++++++++-------------------- src/elaborate.sml | 10 ++++- src/source.sml | 1 + src/source_print.sml | 6 +++ src/urweb.grm | 118 ++++++++++++++++++++++----------------------------- 7 files changed, 143 insertions(+), 113 deletions(-) diff --git a/lib/ur/list.ur b/lib/ur/list.ur index 7527362d..90729f5c 100644 --- a/lib/ur/list.ur +++ b/lib/ur/list.ur @@ -83,3 +83,29 @@ fun filter (a ::: Type) f = in fil [] end + +fun exists (a ::: Type) f = + let + fun ex ls = + case ls of + [] => False + | x :: ls => + if f x then + True + else + ex ls + in + ex + end + +fun foldlMap (a ::: Type) (b ::: Type) (c ::: Type) f = + let + fun fold ls' st ls = + case ls of + [] => (rev ls', st) + | x :: ls => + case f x st of + (y, st) => fold (y :: ls') st ls + in + fold [] + end diff --git a/lib/ur/list.urs b/lib/ur/list.urs index fb3407ae..28f08317 100644 --- a/lib/ur/list.urs +++ b/lib/ur/list.urs @@ -18,3 +18,8 @@ val mapM : m ::: (Type -> Type) -> monad m -> a ::: Type -> b ::: Type -> (a -> m b) -> list a -> m (list b) val filter : a ::: Type -> (a -> bool) -> t a -> t a + +val exists : a ::: Type -> (a -> bool) -> t a -> bool + +val foldlMap : a ::: Type -> b ::: Type -> c ::: Type + -> (a -> b -> c * b) -> b -> t a -> t c * b diff --git a/lib/ur/top.ur b/lib/ur/top.ur index f9b3d033..785a9c8c 100644 --- a/lib/ur/top.ur +++ b/lib/ur/top.ur @@ -6,44 +6,44 @@ con folder = K ==> fn r :: {K} => tf r -> tf ([nm = v] ++ r)) -> tf [] -> tf r -fun fold K (tf :: {K} -> Type) +fun fold [K] [tf :: {K} -> Type] (f : (nm :: Name -> v :: K -> r :: {K} -> [[nm] ~ r] => tf r -> tf ([nm = v] ++ r))) - (i : tf []) (r :: {K}) (fl : folder r) = fl [tf] f i + (i : tf []) [r :: {K}] (fl : folder r) = fl [tf] f i structure Folder = struct - fun nil K (tf :: {K} -> Type) + fun nil [K] [tf :: {K} -> Type] (f : nm :: Name -> v :: K -> r :: {K} -> [[nm] ~ r] => tf r -> tf ([nm = v] ++ r)) (i : tf []) = i - fun cons K (r ::: {K}) (nm :: Name) (v :: K) [[nm] ~ r] (fold : folder r) - (tf :: {K} -> Type) + fun cons [K] [r ::: {K}] [nm :: Name] [v :: K] [[nm] ~ r] (fold : folder r) + [tf :: {K} -> Type] (f : nm :: Name -> v :: K -> r :: {K} -> [[nm] ~ r] => tf r -> tf ([nm = v] ++ r)) (i : tf []) = f [nm] [v] [r] ! (fold [tf] f i) - fun concat K (r1 ::: {K}) (r2 ::: {K}) [r1 ~ r2] + fun concat [K] [r1 ::: {K}] [r2 ::: {K}] [r1 ~ r2] (f1 : folder r1) (f2 : folder r2) - (tf :: {K} -> Type) + [tf :: {K} -> Type] (f : nm :: Name -> v :: K -> r :: {K} -> [[nm] ~ r] => tf r -> tf ([nm = v] ++ r)) (i : tf []) = f1 [fn r1' => [r1' ~ r2] => tf (r1' ++ r2)] - (fn (nm :: Name) (v :: K) (r1' :: {K}) [[nm] ~ r1'] + (fn [nm :: Name] [v :: K] [r1' :: {K}] [[nm] ~ r1'] (acc : [r1' ~ r2] => tf (r1' ++ r2)) [[nm = v] ++ r1' ~ r2] => f [nm] [v] [r1' ++ r2] ! acc) (fn [[] ~ r2] => f2 [tf] f i) ! - fun mp K1 K2 (f ::: K1 -> K2) (r ::: {K1}) + fun mp [K1] [K2] [f ::: K1 -> K2] [r ::: {K1}] (fold : folder r) - (tf :: {K2} -> Type) + [tf :: {K2} -> Type] (f : nm :: Name -> v :: K2 -> r :: {K2} -> [[nm] ~ r] => tf r -> tf ([nm = v] ++ r)) (i : tf []) = fold [fn r => tf (map f r)] - (fn (nm :: Name) (v :: K1) (rest :: {K1}) [[nm] ~ rest] (acc : tf (map f rest)) => + (fn [nm :: Name] [v :: K1] [rest :: {K1}] [[nm] ~ rest] (acc : tf (map f rest)) => f [nm] [f v] [map f rest] ! acc) i end @@ -64,20 +64,20 @@ con mapU = K ==> fn f :: K => map (fn _ :: Unit => f) con ex = fn tf :: (Type -> Type) => res ::: Type -> (choice :: Type -> tf choice -> res) -> res -fun ex (tf :: (Type -> Type)) (choice :: Type) (body : tf choice) : ex tf = - fn (res ::: Type) (f : choice :: Type -> tf choice -> res) => +fun ex [tf :: (Type -> Type)] [choice :: Type] (body : tf choice) : ex tf = + fn [res] (f : choice :: Type -> tf choice -> res) => f [choice] body -fun compose (t1 ::: Type) (t2 ::: Type) (t3 ::: Type) +fun compose [t1 ::: Type] [t2 ::: Type] [t3 ::: Type] (f1 : t2 -> t3) (f2 : t1 -> t2) (x : t1) = f1 (f2 x) -fun show_option (t ::: Type) (_ : show t) = +fun show_option [t ::: Type] (_ : show t) = mkShow (fn opt : option t => case opt of None => "" | Some x => show x) -fun read_option (t ::: Type) (_ : read t) = +fun read_option [t ::: Type] (_ : read t) = mkRead (fn s => case s of "" => None @@ -89,79 +89,79 @@ fun read_option (t ::: Type) (_ : read t) = None => None | v => Some v) -fun txt (t ::: Type) (ctx ::: {Unit}) (use ::: {Type}) (_ : show t) (v : t) = +fun txt [t] [ctx ::: {Unit}] [use ::: {Type}] (_ : show t) (v : t) = cdata (show v) -fun foldUR (tf :: Type) (tr :: {Unit} -> Type) +fun foldUR [tf :: Type] [tr :: {Unit} -> Type] (f : nm :: Name -> rest :: {Unit} -> [[nm] ~ rest] => tf -> tr rest -> tr ([nm] ++ rest)) - (i : tr []) (r :: {Unit}) (fl : folder r)= + (i : tr []) [r :: {Unit}] (fl : folder r)= fl [fn r :: {Unit} => $(mapU tf r) -> tr r] - (fn (nm :: Name) (t :: Unit) (rest :: {Unit}) [[nm] ~ rest] acc r => + (fn [nm :: Name] [t :: Unit] [rest :: {Unit}] [[nm] ~ rest] acc r => f [nm] [rest] ! r.nm (acc (r -- nm))) (fn _ => i) -fun foldUR2 (tf1 :: Type) (tf2 :: Type) (tr :: {Unit} -> Type) +fun foldUR2 [tf1 :: Type] [tf2 :: Type] [tr :: {Unit} -> Type] (f : nm :: Name -> rest :: {Unit} -> [[nm] ~ rest] => tf1 -> tf2 -> tr rest -> tr ([nm] ++ rest)) - (i : tr []) (r :: {Unit}) (fl : folder r) = + (i : tr []) [r :: {Unit}] (fl : folder r) = fl [fn r :: {Unit} => $(mapU tf1 r) -> $(mapU tf2 r) -> tr r] - (fn (nm :: Name) (t :: Unit) (rest :: {Unit}) [[nm] ~ rest] acc r1 r2 => + (fn [nm :: Name] [t :: Unit] [rest :: {Unit}] [[nm] ~ rest] acc r1 r2 => f [nm] [rest] ! r1.nm r2.nm (acc (r1 -- nm) (r2 -- nm))) (fn _ _ => i) -fun foldURX2 (tf1 :: Type) (tf2 :: Type) (ctx :: {Unit}) +fun foldURX2 [tf1 :: Type] [tf2 :: Type] [ctx :: {Unit}] (f : nm :: Name -> rest :: {Unit} -> [[nm] ~ rest] => tf1 -> tf2 -> xml ctx [] []) = foldUR2 [tf1] [tf2] [fn _ => xml ctx [] []] - (fn (nm :: Name) (rest :: {Unit}) [[nm] ~ rest] v1 v2 acc => + (fn [nm :: Name] [rest :: {Unit}] [[nm] ~ rest] v1 v2 acc => {f [nm] [rest] ! v1 v2}{acc}) -fun foldR K (tf :: K -> Type) (tr :: {K} -> Type) +fun foldR [K] [tf :: K -> Type] [tr :: {K} -> Type] (f : nm :: Name -> t :: K -> rest :: {K} -> [[nm] ~ rest] => tf t -> tr rest -> tr ([nm = t] ++ rest)) - (i : tr []) (r :: {K}) (fl : folder r) = + (i : tr []) [r :: {K}] (fl : folder r) = fl [fn r :: {K} => $(map tf r) -> tr r] - (fn (nm :: Name) (t :: K) (rest :: {K}) [[nm] ~ rest] (acc : _ -> tr rest) r => + (fn [nm :: Name] [t :: K] [rest :: {K}] [[nm] ~ rest] (acc : _ -> tr rest) r => f [nm] [t] [rest] ! r.nm (acc (r -- nm))) (fn _ => i) -fun foldR2 K (tf1 :: K -> Type) (tf2 :: K -> Type) (tr :: {K} -> Type) +fun foldR2 [K] [tf1 :: K -> Type] [tf2 :: K -> Type] [tr :: {K} -> Type] (f : nm :: Name -> t :: K -> rest :: {K} -> [[nm] ~ rest] => tf1 t -> tf2 t -> tr rest -> tr ([nm = t] ++ rest)) - (i : tr []) (r :: {K}) (fl : folder r) = + (i : tr []) [r :: {K}] (fl : folder r) = fl [fn r :: {K} => $(map tf1 r) -> $(map tf2 r) -> tr r] - (fn (nm :: Name) (t :: K) (rest :: {K}) [[nm] ~ rest] + (fn [nm :: Name] [t :: K] [rest :: {K}] [[nm] ~ rest] (acc : _ -> _ -> tr rest) r1 r2 => f [nm] [t] [rest] ! r1.nm r2.nm (acc (r1 -- nm) (r2 -- nm))) (fn _ _ => i) -fun foldRX K (tf :: K -> Type) (ctx :: {Unit}) +fun foldRX [K] [tf :: K -> Type] [ctx :: {Unit}] (f : nm :: Name -> t :: K -> rest :: {K} -> [[nm] ~ rest] => tf t -> xml ctx [] []) = foldR [tf] [fn _ => xml ctx [] []] - (fn (nm :: Name) (t :: K) (rest :: {K}) [[nm] ~ rest] r acc => + (fn [nm :: Name] [t :: K] [rest :: {K}] [[nm] ~ rest] r acc => {f [nm] [t] [rest] ! r}{acc}) -fun foldRX2 K (tf1 :: K -> Type) (tf2 :: K -> Type) (ctx :: {Unit}) +fun foldRX2 [K] [tf1 :: K -> Type] [tf2 :: K -> Type] [ctx :: {Unit}] (f : nm :: Name -> t :: K -> rest :: {K} -> [[nm] ~ rest] => tf1 t -> tf2 t -> xml ctx [] []) = foldR2 [tf1] [tf2] [fn _ => xml ctx [] []] - (fn (nm :: Name) (t :: K) (rest :: {K}) [[nm] ~ rest] + (fn [nm :: Name] [t :: K] [rest :: {K}] [[nm] ~ rest] r1 r2 acc => {f [nm] [t] [rest] ! r1 r2}{acc}) -fun queryI (tables ::: {{Type}}) (exps ::: {Type}) +fun queryI [tables ::: {{Type}}] [exps ::: {Type}] [tables ~ exps] (q : sql_query tables exps) (f : $(exps ++ map (fn fields :: {Type} => $fields) tables) -> transaction unit) = @@ -169,7 +169,7 @@ fun queryI (tables ::: {{Type}}) (exps ::: {Type}) (fn fs _ => f fs) () -fun queryX (tables ::: {{Type}}) (exps ::: {Type}) (ctx ::: {Unit}) +fun queryX [tables ::: {{Type}}] [exps ::: {Type}] [ctx ::: {Unit}] [tables ~ exps] (q : sql_query tables exps) (f : $(exps ++ map (fn fields :: {Type} => $fields) tables) -> xml ctx [] []) = @@ -177,7 +177,7 @@ fun queryX (tables ::: {{Type}}) (exps ::: {Type}) (ctx ::: {Unit}) (fn fs acc => return {acc}{f fs}) -fun queryX' (tables ::: {{Type}}) (exps ::: {Type}) (ctx ::: {Unit}) +fun queryX' [tables ::: {{Type}}] [exps ::: {Type}] [ctx ::: {Unit}] [tables ~ exps] (q : sql_query tables exps) (f : $(exps ++ map (fn fields :: {Type} => $fields) tables) -> transaction (xml ctx [] [])) = @@ -187,28 +187,28 @@ fun queryX' (tables ::: {{Type}}) (exps ::: {Type}) (ctx ::: {Unit}) return {acc}{r}) -fun oneOrNoRows (tables ::: {{Type}}) (exps ::: {Type}) +fun oneOrNoRows [tables ::: {{Type}}] [exps ::: {Type}] [tables ~ exps] (q : sql_query tables exps) = query q (fn fs _ => return (Some fs)) None -fun oneRow (tables ::: {{Type}}) (exps ::: {Type}) - [tables ~ exps] (q : sql_query tables exps) = +fun oneRow [tables ::: {{Type}}] [exps ::: {Type}] + [tables ~ exps] (q : sql_query tables exps) = o <- oneOrNoRows q; return (case o of None => error Query returned no rows | Some r => r) -fun eqNullable (tables ::: {{Type}}) (agg ::: {{Type}}) (exps ::: {Type}) - (t ::: Type) (_ : sql_injectable (option t)) +fun eqNullable [tables ::: {{Type}}] [agg ::: {{Type}}] [exps ::: {Type}] + [t ::: Type] (_ : sql_injectable (option t)) (e1 : sql_exp tables agg exps (option t)) (e2 : sql_exp tables agg exps (option t)) = (SQL ({e1} IS NULL AND {e2} IS NULL) OR {e1} = {e2}) -fun eqNullable' (tables ::: {{Type}}) (agg ::: {{Type}}) (exps ::: {Type}) - (t ::: Type) (_ : sql_injectable (option t)) +fun eqNullable' [tables ::: {{Type}}] [agg ::: {{Type}}] [exps ::: {Type}] + [t ::: Type] (_ : sql_injectable (option t)) (e1 : sql_exp tables agg exps (option t)) (e2 : option t) = case e2 of diff --git a/src/elaborate.sml b/src/elaborate.sml index 49b826eb..6f8575db 100644 --- a/src/elaborate.sml +++ b/src/elaborate.sml @@ -1291,7 +1291,15 @@ fun elabPat (pAll as (p, loc), (env, bound)) = (L'.TRecord c, loc)), (env, bound)) end - + + | L.PAnnot (p, t) => + let + val ((p', pt), (env, bound)) = elabPat (p, (env, bound)) + val (t', k, _) = elabCon (env, D.empty) t + in + checkPatCon env p' pt t'; + ((p', t'), (env, bound)) + end end (* This exhaustiveness checking follows Luc Maranget's paper "Warnings for pattern matching." *) diff --git a/src/source.sml b/src/source.sml index 0f62cadd..bfa270d8 100644 --- a/src/source.sml +++ b/src/source.sml @@ -109,6 +109,7 @@ and pat' = | PPrim of Prim.t | PCon of string list * string * pat option | PRecord of (string * pat) list * bool + | PAnnot of pat * con and exp' = EAnnot of exp * con diff --git a/src/source_print.sml b/src/source_print.sml index b4f9bfd3..a16b5bb1 100644 --- a/src/source_print.sml +++ b/src/source_print.sml @@ -207,6 +207,12 @@ fun p_pat' par (p, _) = string "}"] end + | PAnnot (p, t) => box [p_pat p, + space, + string ":", + space, + p_con t] + and p_pat x = p_pat' false x fun p_exp' par (e, _) = diff --git a/src/urweb.grm b/src/urweb.grm index bfb230a6..638ede12 100644 --- a/src/urweb.grm +++ b/src/urweb.grm @@ -178,6 +178,11 @@ datatype prop_kind = Delete | Update datatype attr = Class of exp | Normal of con * exp +fun patType loc (p : pat) = + case #1 p of + PAnnot (_, t) => t + | _ => (CWild (KType, loc), loc) + %% %header (functor UrwebLrValsFn(structure Token : TOKEN)) @@ -290,6 +295,7 @@ datatype attr = Class of exp | Normal of con * exp | earg of exp * con -> exp * con | eargp of exp * con -> exp * con + | earga of exp * con -> exp * con | eargs of exp * con -> exp * con | eargl of exp * con -> exp * con | eargl2 of exp * con -> exp * con @@ -297,6 +303,7 @@ datatype attr = Class of exp | Normal of con * exp | branch of pat * exp | branchs of (pat * exp) list | pat of pat + | patS of pat | pterm of pat | rpat of (string * pat) list * bool | ptuple of pat list @@ -971,79 +978,53 @@ eargl : eargp eargp (eargp1 o eargp2) eargl2 : (fn x => x) | eargp eargl2 (eargp o eargl2) -earg : SYMBOL kcolon kind (fn (e, t) => - let - val loc = s (SYMBOLleft, kindright) - in - ((ECAbs (kcolon, SYMBOL, kind, e), loc), - (TCFun (kcolon, SYMBOL, kind, t), loc)) - end) - | SYMBOL COLON cexp (fn (e, t) => +earg : patS (fn (e, t) => let - val loc = s (SYMBOLleft, cexpright) + val loc = s (patSleft, patSright) + val pt = patType loc patS + + val e' = case #1 patS of + PVar x => (EAbs (x, NONE, e), loc) + | _ => (EAbs ("$x", SOME pt, + (ECase ((EVar ([], "$x", DontInfer), + loc), + [(patS, e)]), loc)), loc) in - ((EAbs (SYMBOL, SOME cexp, e), loc), - (TFun (cexp, t), loc)) + (e', (TFun (pt, t), loc)) end) - | UNDER COLON cexp (fn (e, t) => - let - val loc = s (UNDERleft, cexpright) - in - ((EAbs ("_", SOME cexp, e), loc), - (TFun (cexp, t), loc)) - end) - | eargp (eargp) + | earga (earga) -eargp : SYMBOL (fn (e, t) => - let - val loc = s (SYMBOLleft, SYMBOLright) - in - ((EAbs (SYMBOL, NONE, e), loc), - (TFun ((CWild (KType, loc), loc), t), loc)) - end) - | UNIT (fn (e, t) => +eargp : pterm (fn (e, t) => let - val loc = s (UNITleft, UNITright) - val t' = (TRecord (CRecord [], loc), loc) + val loc = s (ptermleft, ptermright) + val pt = patType loc pterm + + val e' = case #1 pterm of + PVar x => (EAbs (x, NONE, e), loc) + | _ => (EAbs ("$x", SOME pt, + (ECase ((EVar ([], "$x", DontInfer), + loc), + [(pterm, e)]), loc)), loc) in - ((EAbs ("_", SOME t', e), loc), - (TFun (t', t), loc)) + (e', (TFun (pt, t), loc)) end) - | UNDER (fn (e, t) => - let - val loc = s (UNDERleft, UNDERright) - in - ((EAbs ("_", NONE, e), loc), - (TFun ((CWild (KType, loc), loc), t), loc)) - end) - | LPAREN SYMBOL kcolon kind RPAREN(fn (e, t) => + | earga (earga) + +earga : LBRACK SYMBOL RBRACK (fn (e, t) => let - val loc = s (LPARENleft, RPARENright) + val loc = s (LBRACKleft, RBRACKright) + val kind = (KWild, loc) + in + ((ECAbs (Implicit, SYMBOL, kind, e), loc), + (TCFun (Implicit, SYMBOL, kind, t), loc)) + end) + | LBRACK SYMBOL kcolon kind RBRACK(fn (e, t) => + let + val loc = s (LBRACKleft, RBRACKright) in ((ECAbs (kcolon, SYMBOL, kind, e), loc), (TCFun (kcolon, SYMBOL, kind, t), loc)) end) - | LPAREN SYMBOL COLON cexp RPAREN (fn (e, t) => - let - val loc = s (LPARENleft, RPARENright) - in - ((EAbs (SYMBOL, SOME cexp, e), loc), - (TFun (cexp, t), loc)) - end) - | LPAREN UNDER COLON cexp RPAREN (fn (e, t) => - let - val loc = s (LPARENleft, RPARENright) - in - ((EAbs ("_", SOME cexp, e), loc), - (TFun (cexp, t), loc)) - end) - | LPAREN cexp TWIDDLE cexp RPAREN (fn (e, t) => - let - val loc = s (LPARENleft, RPARENright) - in - ((EDisjoint (cexp1, cexp2, e), loc), - (TDisjoint (cexp1, cexp2, t), loc)) - end) | LBRACK cexp TWIDDLE cexp RBRACK(fn (e, t) => let val loc = s (LBRACKleft, RBRACKright) @@ -1051,7 +1032,7 @@ eargp : SYMBOL (fn (e, t) => ((EDisjoint (cexp1, cexp2, e), loc), (TDisjoint (cexp1, cexp2, t), loc)) end) - | CSYMBOL (fn (e, t) => + | LBRACK CSYMBOL RBRACK (fn (e, t) => let val loc = s (CSYMBOLleft, CSYMBOLright) in @@ -1214,15 +1195,18 @@ branch : pat DARROW eexp (pat, eexp) branchs: ([]) | BAR branch branchs (branch :: branchs) -pat : pterm (pterm) - | cpath pterm (PCon (#1 cpath, #2 cpath, SOME pterm), s (cpathleft, ptermright)) - | pterm DCOLON pat (let - val loc = s (ptermleft, patright) +patS : pterm (pterm) + | pterm DCOLON patS (let + val loc = s (ptermleft, patSright) in (PCon (["Basis"], "Cons", SOME (PRecord ([("1", pterm), - ("2", pat)], false), loc)), + ("2", patS)], false), loc)), loc) end) + | patS COLON cexp (PAnnot (patS, cexp), s (patSleft, cexpright)) + +pat : patS (patS) + | cpath pterm (PCon (#1 cpath, #2 cpath, SOME pterm), s (cpathleft, ptermright)) pterm : SYMBOL (PVar SYMBOL, s (SYMBOLleft, SYMBOLright)) | cpath (PCon (#1 cpath, #2 cpath, NONE), s (cpathleft, cpathright)) -- cgit v1.2.3