Mercurial > urweb
diff src/elaborate.sml @ 1270:9fd0cb0ef6e1
Try harder to place wildified 'con' declarations properly
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Tue, 01 Jun 2010 12:50:53 -0400 |
parents | 9f4b9315810d |
children | 74150edf1134 |
line wrap: on
line diff
--- a/src/elaborate.sml Tue Jun 01 10:44:57 2010 -0400 +++ b/src/elaborate.sml Tue Jun 01 12:50:53 2010 -0400 @@ -1655,10 +1655,10 @@ findHead e end -datatype needed = Needed of {Cons : (L'.kind * L'.con option) SM.map, +datatype needed = Needed of {Cons : (string option * L'.kind * L'.con option) SM.map, Constraints : (E.env * (L'.con * L'.con) * ErrorMsg.span) list, Vals : SS.set, - Mods : needed SM.map} + Mods : (E.env * needed) SM.map} fun ncons (Needed r) = #Cons r fun nconstraints (Needed r) = #Constraints r @@ -2162,261 +2162,262 @@ end fun elabSgn_item ((sgi, loc), (env, denv, gs)) = - case sgi of - L.SgiConAbs (x, k) => - let - val k' = elabKind env k - - val (env', n) = E.pushCNamed env x k' NONE - in - ([(L'.SgiConAbs (x, n, k'), loc)], (env', denv, gs)) - end - - | L.SgiCon (x, ko, c) => - let - val k' = case ko of - NONE => kunif loc - | SOME k => elabKind env k - - val (c', ck, gs') = elabCon (env, denv) c - val (env', n) = E.pushCNamed env x k' (SOME c') - in - checkKind env c' ck k'; - - ([(L'.SgiCon (x, n, k', c'), loc)], (env', denv, gs' @ gs)) - end - - | L.SgiDatatype dts => - let - val k = (L'.KType, loc) - - val (dts, env) = ListUtil.foldlMap (fn ((x, xs, xcs), env) => + ((*Print.preface ("elabSgi", SourcePrint.p_sgn_item (sgi, loc));*) + case sgi of + L.SgiConAbs (x, k) => + let + val k' = elabKind env k + + val (env', n) = E.pushCNamed env x k' NONE + in + ([(L'.SgiConAbs (x, n, k'), loc)], (env', denv, gs)) + end + + | L.SgiCon (x, ko, c) => + let + val k' = case ko of + NONE => kunif loc + | SOME k => elabKind env k + + val (c', ck, gs') = elabCon (env, denv) c + val (env', n) = E.pushCNamed env x k' (SOME c') + in + checkKind env c' ck k'; + + ([(L'.SgiCon (x, n, k', c'), loc)], (env', denv, gs' @ gs)) + end + + | L.SgiDatatype dts => + let + val k = (L'.KType, loc) + + val (dts, env) = ListUtil.foldlMap (fn ((x, xs, xcs), env) => + let + val k' = foldl (fn (_, k') => (L'.KArrow (k, k'), loc)) k xs + val (env, n) = E.pushCNamed env x k' NONE + in + ((x, n, xs, xcs), env) + end) + env dts + + val (dts, env) = ListUtil.foldlMap + (fn ((x, n, xs, xcs), env) => + let + val t = (L'.CNamed n, loc) + val nxs = length xs - 1 + val t = ListUtil.foldli (fn (i, _, t) => + (L'.CApp (t, (L'.CRel (nxs - i), loc)), loc)) t xs + + val (env', denv') = foldl (fn (x, (env', denv')) => + (E.pushCRel env' x k, + D.enter denv')) (env, denv) xs + + val (xcs, (used, env, gs)) = + ListUtil.foldlMap + (fn ((x, to), (used, env, gs)) => + let + val (to, t, gs') = case to of + NONE => (NONE, t, gs) + | SOME t' => + let + val (t', tk, gs') = + elabCon (env', denv') t' + in + checkKind env' t' tk k; + (SOME t', + (L'.TFun (t', t), loc), + gs' @ gs) + end + val t = foldl (fn (x, t) => (L'.TCFun (L'.Implicit, x, k, t), loc)) + t xs + + val (env, n') = E.pushENamed env x t + in + if SS.member (used, x) then + strError env (DuplicateConstructor (x, loc)) + else + (); + ((x, n', to), (SS.add (used, x), env, gs')) + end) + (SS.empty, env, []) xcs + in + ((x, n, xs, xcs), E.pushDatatype env n xs xcs) + end) + env dts + in + ([(L'.SgiDatatype dts, loc)], (env, denv, gs)) + end + + | L.SgiDatatypeImp (_, [], _) => raise Fail "Empty SgiDatatypeImp" + + | L.SgiDatatypeImp (x, m1 :: ms, s) => + (case E.lookupStr env m1 of + NONE => (strError env (UnboundStr (loc, m1)); + ([], (env, denv, gs))) + | SOME (n, sgn) => + let + val (str, sgn) = foldl (fn (m, (str, sgn)) => + case E.projectStr env {sgn = sgn, str = str, field = m} of + NONE => (conError env (UnboundStrInCon (loc, m)); + (strerror, sgnerror)) + | SOME sgn => ((L'.StrProj (str, m), loc), sgn)) + ((L'.StrVar n, loc), sgn) ms + in + case hnormCon env (L'.CModProj (n, ms, s), loc) of + (L'.CModProj (n, ms, s), _) => + (case E.projectDatatype env {sgn = sgn, str = str, field = s} of + NONE => (conError env (UnboundDatatype (loc, s)); + ([], (env, denv, []))) + | SOME (xs, xncs) => + let + val k = (L'.KType, loc) + val k' = foldl (fn (_, k') => (L'.KArrow (k, k'), loc)) k xs + + val t = (L'.CModProj (n, ms, s), loc) + val (env, n') = E.pushCNamed env x k' (SOME t) + val env = E.pushDatatype env n' xs xncs + + val t = (L'.CNamed n', loc) + val env = foldl (fn ((x, n, to), env) => let - val k' = foldl (fn (_, k') => (L'.KArrow (k, k'), loc)) k xs - val (env, n) = E.pushCNamed env x k' NONE + val t = case to of + NONE => t + | SOME t' => (L'.TFun (t', t), loc) + + val t = foldr (fn (x, t) => + (L'.TCFun (L'.Implicit, x, k, t), loc)) + t xs in - ((x, n, xs, xcs), env) - end) - env dts - - val (dts, env) = ListUtil.foldlMap - (fn ((x, n, xs, xcs), env) => - let - val t = (L'.CNamed n, loc) - val nxs = length xs - 1 - val t = ListUtil.foldli (fn (i, _, t) => - (L'.CApp (t, (L'.CRel (nxs - i), loc)), loc)) t xs - - val (env', denv') = foldl (fn (x, (env', denv')) => - (E.pushCRel env' x k, - D.enter denv')) (env, denv) xs - - val (xcs, (used, env, gs)) = - ListUtil.foldlMap - (fn ((x, to), (used, env, gs)) => - let - val (to, t, gs') = case to of - NONE => (NONE, t, gs) - | SOME t' => - let - val (t', tk, gs') = - elabCon (env', denv') t' - in - checkKind env' t' tk k; - (SOME t', - (L'.TFun (t', t), loc), - gs' @ gs) - end - val t = foldl (fn (x, t) => (L'.TCFun (L'.Implicit, x, k, t), loc)) - t xs - - val (env, n') = E.pushENamed env x t - in - if SS.member (used, x) then - strError env (DuplicateConstructor (x, loc)) - else - (); - ((x, n', to), (SS.add (used, x), env, gs')) - end) - (SS.empty, env, []) xcs - in - ((x, n, xs, xcs), E.pushDatatype env n xs xcs) - end) - env dts - in - ([(L'.SgiDatatype dts, loc)], (env, denv, gs)) - end - - | L.SgiDatatypeImp (_, [], _) => raise Fail "Empty SgiDatatypeImp" - - | L.SgiDatatypeImp (x, m1 :: ms, s) => - (case E.lookupStr env m1 of - NONE => (strError env (UnboundStr (loc, m1)); - ([], (env, denv, gs))) - | SOME (n, sgn) => - let - val (str, sgn) = foldl (fn (m, (str, sgn)) => - case E.projectStr env {sgn = sgn, str = str, field = m} of - NONE => (conError env (UnboundStrInCon (loc, m)); - (strerror, sgnerror)) - | SOME sgn => ((L'.StrProj (str, m), loc), sgn)) - ((L'.StrVar n, loc), sgn) ms - in - case hnormCon env (L'.CModProj (n, ms, s), loc) of - (L'.CModProj (n, ms, s), _) => - (case E.projectDatatype env {sgn = sgn, str = str, field = s} of - NONE => (conError env (UnboundDatatype (loc, s)); - ([], (env, denv, []))) - | SOME (xs, xncs) => - let - val k = (L'.KType, loc) - val k' = foldl (fn (_, k') => (L'.KArrow (k, k'), loc)) k xs - - val t = (L'.CModProj (n, ms, s), loc) - val (env, n') = E.pushCNamed env x k' (SOME t) - val env = E.pushDatatype env n' xs xncs - - val t = (L'.CNamed n', loc) - val env = foldl (fn ((x, n, to), env) => - let - val t = case to of - NONE => t - | SOME t' => (L'.TFun (t', t), loc) - - val t = foldr (fn (x, t) => - (L'.TCFun (L'.Implicit, x, k, t), loc)) - t xs - in - E.pushENamedAs env x n t - end) env xncs - in - ([(L'.SgiDatatypeImp (x, n', n, ms, s, xs, xncs), loc)], (env, denv, [])) - end) - | _ => (strError env (NotDatatype loc); - ([], (env, denv, []))) - end) - - | L.SgiVal (x, c) => - let - val (c', ck, gs') = elabCon (env, denv) c - - val old = c' - val c' = normClassConstraint env c' - val (env', n) = E.pushENamed env x c' - in - (unifyKinds env ck ktype - handle KUnify ue => strError env (NotType (loc, ck, ue))); - - ([(L'.SgiVal (x, n, c'), loc)], (env', denv, gs' @ gs)) - end - - | L.SgiTable (x, c, pe, ce) => - let - val cstK = (L'.KRecord (L'.KRecord (L'.KUnit, loc), loc), loc) - - val (c', ck, gs') = elabCon (env, denv) c - val pkey = cunif (loc, cstK) - val visible = cunif (loc, cstK) - val (env', ds, uniques) = - case (#1 pe, #1 ce) of - (L.EVar (["Basis"], "no_primary_key", _), L.EVar (["Basis"], "no_constraint", _)) => - let - val x' = x ^ "_hidden_constraints" - val (env', hidden_n) = E.pushCNamed env x' cstK NONE - val hidden = (L'.CNamed hidden_n, loc) - in - (env', [(L'.SgiConAbs (x', hidden_n, cstK), loc)], (L'.CConcat (visible, hidden), loc)) - end - | _ => (env, [], visible) - - val ct = tableOf () - val ct = (L'.CApp (ct, c'), loc) - val ct = (L'.CApp (ct, (L'.CConcat (pkey, uniques), loc)), loc) - - val (pe', pet, gs'') = elabExp (env', denv) pe - val gs'' = List.mapPartial (fn Disjoint x => SOME x + E.pushENamedAs env x n t + end) env xncs + in + ([(L'.SgiDatatypeImp (x, n', n, ms, s, xs, xncs), loc)], (env, denv, [])) + end) + | _ => (strError env (NotDatatype loc); + ([], (env, denv, []))) + end) + + | L.SgiVal (x, c) => + let + val (c', ck, gs') = elabCon (env, denv) c + + val old = c' + val c' = normClassConstraint env c' + val (env', n) = E.pushENamed env x c' + in + (unifyKinds env ck ktype + handle KUnify ue => strError env (NotType (loc, ck, ue))); + + ([(L'.SgiVal (x, n, c'), loc)], (env', denv, gs' @ gs)) + end + + | L.SgiTable (x, c, pe, ce) => + let + val cstK = (L'.KRecord (L'.KRecord (L'.KUnit, loc), loc), loc) + + val (c', ck, gs') = elabCon (env, denv) c + val pkey = cunif (loc, cstK) + val visible = cunif (loc, cstK) + val (env', ds, uniques) = + case (#1 pe, #1 ce) of + (L.EVar (["Basis"], "no_primary_key", _), L.EVar (["Basis"], "no_constraint", _)) => + let + val x' = x ^ "_hidden_constraints" + val (env', hidden_n) = E.pushCNamed env x' cstK NONE + val hidden = (L'.CNamed hidden_n, loc) + in + (env', [(L'.SgiConAbs (x', hidden_n, cstK), loc)], (L'.CConcat (visible, hidden), loc)) + end + | _ => (env, [], visible) + + val ct = tableOf () + val ct = (L'.CApp (ct, c'), loc) + val ct = (L'.CApp (ct, (L'.CConcat (pkey, uniques), loc)), loc) + + val (pe', pet, gs'') = elabExp (env', denv) pe + val gs'' = List.mapPartial (fn Disjoint x => SOME x | _ => NONE) gs'' - val pst = (L'.CModProj (!basis_r, [], "primary_key"), loc) - val pst = (L'.CApp (pst, c'), loc) - val pst = (L'.CApp (pst, pkey), loc) - - val (env', n) = E.pushENamed env' x ct - - val (ce', cet, gs''') = elabExp (env', denv) ce - val gs''' = List.mapPartial (fn Disjoint x => SOME x - | _ => NONE) gs''' - - val cst = (L'.CModProj (!basis_r, [], "sql_constraints"), loc) - val cst = (L'.CApp (cst, c'), loc) - val cst = (L'.CApp (cst, visible), loc) - in - checkKind env c' ck (L'.KRecord (L'.KType, loc), loc); - checkCon env' pe' pet pst; - checkCon env' ce' cet cst; - - (ds @ [(L'.SgiVal (x, n, ct), loc)], (env', denv, gs''' @ gs'' @ gs' @ gs)) - end - - | L.SgiStr (x, sgn) => - let - val (sgn', gs') = elabSgn (env, denv) sgn - val (env', n) = E.pushStrNamed env x sgn' - in - ([(L'.SgiStr (x, n, sgn'), loc)], (env', denv, gs' @ gs)) - end - - | L.SgiSgn (x, sgn) => - let - val (sgn', gs') = elabSgn (env, denv) sgn - val (env', n) = E.pushSgnNamed env x sgn' - in - ([(L'.SgiSgn (x, n, sgn'), loc)], (env', denv, gs' @ gs)) - end - - | L.SgiInclude sgn => - let - val (sgn', gs') = elabSgn (env, denv) sgn - in - case #1 (hnormSgn env sgn') of - L'.SgnConst sgis => - (sgis, (foldl (fn (sgi, env) => E.sgiBinds env sgi) env sgis, denv, gs' @ gs)) - | _ => (sgnError env (NotIncludable sgn'); - ([], (env, denv, []))) - end - - | L.SgiConstraint (c1, c2) => - let - val (c1', k1, gs1) = elabCon (env, denv) c1 - val (c2', k2, gs2) = elabCon (env, denv) c2 - - val denv = D.assert env denv (c1', c2') - in - checkKind env c1' k1 (L'.KRecord (kunif loc), loc); - checkKind env c2' k2 (L'.KRecord (kunif loc), loc); - - ([(L'.SgiConstraint (c1', c2'), loc)], (env, denv, gs1 @ gs2)) - end - - | L.SgiClassAbs (x, k) => - let - val k = elabKind env k - val (env, n) = E.pushCNamed env x k NONE - val env = E.pushClass env n - in - ([(L'.SgiClassAbs (x, n, k), loc)], (env, denv, [])) - end - - | L.SgiClass (x, k, c) => - let - val k = elabKind env k - val (c', ck, gs) = elabCon (env, denv) c - val (env, n) = E.pushCNamed env x k (SOME c') - val env = E.pushClass env n - in - checkKind env c' ck k; - ([(L'.SgiClass (x, n, k, c'), loc)], (env, denv, [])) - end + val pst = (L'.CModProj (!basis_r, [], "primary_key"), loc) + val pst = (L'.CApp (pst, c'), loc) + val pst = (L'.CApp (pst, pkey), loc) + + val (env', n) = E.pushENamed env' x ct + + val (ce', cet, gs''') = elabExp (env', denv) ce + val gs''' = List.mapPartial (fn Disjoint x => SOME x + | _ => NONE) gs''' + + val cst = (L'.CModProj (!basis_r, [], "sql_constraints"), loc) + val cst = (L'.CApp (cst, c'), loc) + val cst = (L'.CApp (cst, visible), loc) + in + checkKind env c' ck (L'.KRecord (L'.KType, loc), loc); + checkCon env' pe' pet pst; + checkCon env' ce' cet cst; + + (ds @ [(L'.SgiVal (x, n, ct), loc)], (env', denv, gs''' @ gs'' @ gs' @ gs)) + end + + | L.SgiStr (x, sgn) => + let + val (sgn', gs') = elabSgn (env, denv) sgn + val (env', n) = E.pushStrNamed env x sgn' + in + ([(L'.SgiStr (x, n, sgn'), loc)], (env', denv, gs' @ gs)) + end + + | L.SgiSgn (x, sgn) => + let + val (sgn', gs') = elabSgn (env, denv) sgn + val (env', n) = E.pushSgnNamed env x sgn' + in + ([(L'.SgiSgn (x, n, sgn'), loc)], (env', denv, gs' @ gs)) + end + + | L.SgiInclude sgn => + let + val (sgn', gs') = elabSgn (env, denv) sgn + in + case #1 (hnormSgn env sgn') of + L'.SgnConst sgis => + (sgis, (foldl (fn (sgi, env) => E.sgiBinds env sgi) env sgis, denv, gs' @ gs)) + | _ => (sgnError env (NotIncludable sgn'); + ([], (env, denv, []))) + end + + | L.SgiConstraint (c1, c2) => + let + val (c1', k1, gs1) = elabCon (env, denv) c1 + val (c2', k2, gs2) = elabCon (env, denv) c2 + + val denv = D.assert env denv (c1', c2') + in + checkKind env c1' k1 (L'.KRecord (kunif loc), loc); + checkKind env c2' k2 (L'.KRecord (kunif loc), loc); + + ([(L'.SgiConstraint (c1', c2'), loc)], (env, denv, gs1 @ gs2)) + end + + | L.SgiClassAbs (x, k) => + let + val k = elabKind env k + val (env, n) = E.pushCNamed env x k NONE + val env = E.pushClass env n + in + ([(L'.SgiClassAbs (x, n, k), loc)], (env, denv, [])) + end + + | L.SgiClass (x, k, c) => + let + val k = elabKind env k + val (c', ck, gs) = elabCon (env, denv) c + val (env, n) = E.pushCNamed env x k (SOME c') + val env = E.pushClass env n + in + checkKind env c' ck k; + ([(L'.SgiClass (x, n, k, c'), loc)], (env, denv, [])) + end) and elabSgn (env, denv) (sgn, loc) = case sgn of @@ -3185,6 +3186,20 @@ (case #1 str of L.StrConst ds => let + fun cname d = + case d of + L'.SgiCon (x, _, _, _) => SOME x + | L'.SgiConAbs (x, _, _) => SOME x + | L'.SgiClass (x, _, _, _) => SOME x + | L'.SgiClassAbs (x, _, _) => SOME x + | _ => NONE + + fun dname (d, _) = + case d of + L.DCon (x, _, _) => SOME x + | L.DClass (x, _, _) => SOME x + | _ => NONE + fun decompileKind (k, loc) = case k of L'.KType => SOME (L.KType, loc) @@ -3259,15 +3274,15 @@ | _ => NONE fun buildNeeded env sgis = - #1 (foldl (fn ((sgi, loc), (nd, env')) => + #1 (foldl (fn ((sgi, loc), (nd, env', lastCon)) => (case sgi of - L'.SgiCon (x, _, k, c) => naddCon (nd, x, (k, SOME c)) - | L'.SgiConAbs (x, _, k) => naddCon (nd, x, (k, NONE)) + L'.SgiCon (x, _, k, c) => naddCon (nd, x, (lastCon, k, SOME c)) + | L'.SgiConAbs (x, _, k) => naddCon (nd, x, (lastCon, k, NONE)) | L'.SgiConstraint cs => naddConstraint (nd, (env', cs, loc)) | L'.SgiVal (x, _, t) => let val t = normClassConstraint env' t - in + in case #1 t of L'.CApp (f, _) => if isClassOrFolder env' f then @@ -3277,12 +3292,15 @@ | _ => nd end | L'.SgiStr (x, _, s) => - (case #1 (hnormSgn env s) of - L'.SgnConst sgis' => naddMod (nd, x, buildNeeded env sgis') + (case #1 (hnormSgn env' s) of + L'.SgnConst sgis' => naddMod (nd, x, (env', buildNeeded env' sgis')) | _ => nd) | _ => nd, - E.sgiBinds env' (sgi, loc))) - (nempty, env) sgis) + E.sgiBinds env' (sgi, loc), + case cname sgi of + NONE => lastCon + | v => v)) + (nempty, env, NONE) sgis) val nd = buildNeeded env sgis @@ -3296,13 +3314,13 @@ | L.DStr (x, _, (L.StrConst ds', _)) => (case SM.find (nmods nd, x) of NONE => nd - | SOME nd' => naddMod (nd, x, removeUsed (nd', ds'))) + | SOME (env, nd') => naddMod (nd, x, (env, removeUsed (nd', ds')))) | _ => nd) nd ds val nd = removeUsed (nd, ds) - fun extend (nd, ds) = + fun extend (env, nd, ds) = let val ds' = List.mapPartial (fn (env', (c1, c2), loc) => case (decompileCon env' c1, decompileCon env' c2) of @@ -3321,43 +3339,60 @@ ds'' @ ds' end - val ds' = + val ds = ds @ ds' + + val ds = case SM.listItemsi (ncons nd) of - [] => ds' + [] => ds | xs => let - val ds'' = map (fn (x, (k, co)) => - let - val k = - case decompileKind k of - NONE => (L.KWild, #2 str) - | SOME k => k - - val cwild = (L.CWild k, #2 str) - val c = - case co of - NONE => cwild - | SOME c => - case decompileCon env c of - NONE => cwild - | SOME c' => c' - in - (L.DCon (x, NONE, c), #2 str) - end) xs + fun findPlace ((x, (lastCon, k, co)), ds') = + let + val k = + case decompileKind k of + NONE => (L.KWild, #2 str) + | SOME k => k + + val cwild = (L.CWild k, #2 str) + val c = + case co of + NONE => cwild + | SOME c => + case decompileCon env c of + NONE => cwild + | SOME c' => c' + + val d = (L.DCon (x, NONE, c), #2 str) + in + case lastCon of + NONE => d :: ds' + | _ => + let + fun seek (ds'', passed) = + case ds'' of + [] => d :: ds' + | d1 :: ds'' => + if dname d1 = lastCon then + List.revAppend (passed, d1 :: d :: ds'') + else + seek (ds'', d1 :: passed) + in + seek (ds', []) + end + end in - ds'' @ ds' + foldl findPlace ds xs end - - val ds = map (fn d as (L.DStr (x, s, (L.StrConst ds', loc')), loc) => - (case SM.find (nmods nd, x) of - NONE => d - | SOME nd' => (L.DStr (x, s, (L.StrConst (extend (nd', ds')), loc')), loc)) - | d => d) ds in - ds @ ds' + map (fn d as (L.DStr (x, s, (L.StrConst ds', loc')), loc) => + (case SM.find (nmods nd, x) of + NONE => d + | SOME (env, nd') => + (L.DStr (x, s, (L.StrConst (extend (env, nd', ds')), loc')), loc)) + | d => d) ds end in - (L.StrConst (extend (nd, ds)), #2 str) + (L.StrConst (extend (env, nd, ds)), #2 str) end | _ => str) | _ => str @@ -4007,7 +4042,7 @@ wildifyStr env (str2, dom) | _ => str2 val (str2', sgn2, gs2) = elabStr (env, denv) str2 - in + in case #1 (hnormSgn env sgn1) of L'.SgnError => (strerror, sgnerror, []) | L'.SgnFun (m, n, dom, ran) =>