summaryrefslogtreecommitdiff
path: root/src/elaborate.sml
diff options
context:
space:
mode:
Diffstat (limited to 'src/elaborate.sml')
-rw-r--r--src/elaborate.sml95
1 files changed, 94 insertions, 1 deletions
diff --git a/src/elaborate.sml b/src/elaborate.sml
index d19dcfce..e59cb9d2 100644
--- a/src/elaborate.sml
+++ b/src/elaborate.sml
@@ -809,6 +809,11 @@ datatype exp_error =
| Unif of string * L'.con
| WrongForm of string * L'.exp * L'.con
| IncompatibleCons of L'.con * L'.con
+ | DuplicatePatternVariable of ErrorMsg.span * string
+ | PatUnify of L'.pat * L'.con * L'.con * cunify_error
+ | UnboundConstructor of ErrorMsg.span * string
+ | PatHasArg of ErrorMsg.span
+ | PatHasNoArg of ErrorMsg.span
fun expError env err =
case err of
@@ -833,6 +838,20 @@ fun expError env err =
(ErrorMsg.errorAt (#2 c1) "Incompatible constructors";
eprefaces' [("Con 1", p_con env c1),
("Con 2", p_con env c2)])
+ | DuplicatePatternVariable (loc, s) =>
+ ErrorMsg.errorAt loc ("Duplicate pattern variable " ^ s)
+ | PatUnify (p, c1, c2, uerr) =>
+ (ErrorMsg.errorAt (#2 p) "Unification failure for pattern";
+ eprefaces' [("Pattern", p_pat env p),
+ ("Have con", p_con env c1),
+ ("Need con", p_con env c2)];
+ cunifyError env uerr)
+ | UnboundConstructor (loc, s) =>
+ ErrorMsg.errorAt loc ("Unbound constructor " ^ s ^ " in pattern")
+ | PatHasArg loc =>
+ ErrorMsg.errorAt loc "Constructor expects no argument but is used with argument"
+ | PatHasNoArg loc =>
+ ErrorMsg.errorAt loc "Constructor expects argument but is used with no argument"
fun checkCon (env, denv) e c1 c2 =
unifyCons (env, denv) c1 c2
@@ -840,6 +859,12 @@ fun checkCon (env, denv) e c1 c2 =
(expError env (Unify (e, c1, c2, err));
[])
+fun checkPatCon (env, denv) p c1 c2 =
+ unifyCons (env, denv) c1 c2
+ handle CUnify (c1, c2, err) =>
+ (expError env (PatUnify (p, c1, c2, err));
+ [])
+
fun primType env p =
case p of
P.Int _ => !int
@@ -903,6 +928,8 @@ fun typeof env (e, loc) =
| L'.ECut (_, _, {rest, ...}) => (L'.TRecord rest, loc)
| L'.EFold dom => foldType (dom, loc)
+ | L'.ECase (_, _, t) => t
+
| L'.EError => cerror
fun elabHead (env, denv) (e as (_, loc)) t =
@@ -927,6 +954,52 @@ fun elabHead (env, denv) (e as (_, loc)) t =
unravel (t, e)
end
+fun elabPat (pAll as (p, loc), (env, bound)) =
+ let
+ val perror = (L'.PWild, loc)
+ val terror = (L'.CError, loc)
+ val pterror = (perror, terror)
+ val rerror = (pterror, (env, bound))
+
+ fun pcon (pc, po, to, dn) =
+
+ case (po, to) of
+ (NONE, SOME _) => (expError env (PatHasNoArg loc);
+ rerror)
+ | (SOME _, NONE) => (expError env (PatHasArg loc);
+ rerror)
+ | (NONE, NONE) => (((L'.PCon (pc, NONE), loc), (L'.CNamed dn, loc)),
+ (env, bound))
+ | (SOME p, SOME t) =>
+ let
+ val ((p', pt), (env, bound)) = elabPat (p, (env, bound))
+ in
+ (((L'.PCon (pc, SOME p'), loc), (L'.CNamed dn, loc)),
+ (env, bound))
+ end
+ in
+ case p of
+ L.PWild => (((L'.PWild, loc), cunif (loc, (L'.KType, loc))),
+ (env, bound))
+ | L.PVar x =>
+ let
+ val t = if SS.member (bound, x) then
+ (expError env (DuplicatePatternVariable (loc, x));
+ terror)
+ else
+ cunif (loc, (L'.KType, loc))
+ in
+ (((L'.PVar x, loc), t),
+ (E.pushERel env x t, SS.add (bound, x)))
+ end
+ | L.PCon ([], x, po) =>
+ (case E.lookupConstructor env x of
+ NONE => (expError env (UnboundConstructor (loc, x));
+ rerror)
+ | SOME (n, to, dn) => pcon (L'.PConVar n, po, to, dn))
+ | L.PCon _ => raise Fail "uhoh"
+ end
+
fun elabExp (env, denv) (eAll as (e, loc)) =
let
@@ -1138,7 +1211,25 @@ fun elabExp (env, denv) (eAll as (e, loc)) =
((L'.EFold dom, loc), foldType (dom, loc), [])
end
- | L.ECase _ => raise Fail "Elaborate ECase"
+ | L.ECase (e, pes) =>
+ let
+ val (e', et, gs1) = elabExp (env, denv) e
+ val result = cunif (loc, (L'.KType, loc))
+ val (pes', gs) = ListUtil.foldlMap
+ (fn ((p, e), gs) =>
+ let
+ val ((p', pt), (env, _)) = elabPat (p, (env, SS.empty))
+
+ val gs1 = checkPatCon (env, denv) p' pt et
+ val (e', et, gs2) = elabExp (env, denv) e
+ val gs3 = checkCon (env, denv) e' et result
+ in
+ ((p', e'), gs1 @ gs2 @ gs3 @ gs)
+ end)
+ gs1 pes
+ in
+ ((L'.ECase (e', pes', result), loc), result, gs)
+ end
end
@@ -1961,6 +2052,8 @@ fun elabDecl ((d, loc), (env, denv, gs)) =
((x, n', to), (SS.add (used, x), env, gs'))
end)
(SS.empty, env, []) xcs
+
+ val env = E.pushDatatype env n xcs
in
([(L'.DDatatype (x, n, xcs), loc)], (env, denv, gs))
end