diff src/elaborate.sml @ 207:cc68da3801bc

Non-star SELECT
author Adam Chlipala <adamc@hcoop.net>
date Thu, 14 Aug 2008 18:35:08 -0400
parents cb8493759a7b
children 1487c712eb12
line wrap: on
line diff
--- a/src/elaborate.sml	Thu Aug 14 15:27:35 2008 -0400
+++ b/src/elaborate.sml	Thu Aug 14 18:35:08 2008 -0400
@@ -86,6 +86,9 @@
              unifyKinds' r1 r2)
           | (L'.KName, L'.KName) => ()
           | (L'.KRecord k1, L'.KRecord k2) => unifyKinds' k1 k2
+          | (L'.KTuple ks1, L'.KTuple ks2) =>
+            ((ListPair.appEq (fn (k1, k2) => unifyKinds' k1 k2) (ks1, ks2))
+             handle ListPair.UnequalLengths => err KIncompatible)
 
           | (L'.KError, _) => ()
           | (_, L'.KError) => ()
@@ -125,6 +128,8 @@
        | UnboundStrInCon of ErrorMsg.span * string
        | WrongKind of L'.con * L'.kind * L'.kind * kunify_error
        | DuplicateField of ErrorMsg.span * string
+       | ProjBounds of L'.con * int
+       | ProjMismatch of L'.con * L'.kind
 
 fun conError env err =
     case err of
@@ -142,6 +147,14 @@
          kunifyError kerr)
       | DuplicateField (loc, s) =>
         ErrorMsg.errorAt loc ("Duplicate record field " ^ s)
+      | ProjBounds (c, n) =>
+        (ErrorMsg.errorAt (#2 c) "Out of bounds constructor projection";
+         eprefaces' [("Constructor", p_con env c),
+                     ("Index", Print.PD.string (Int.toString n))])
+      | ProjMismatch (c, k) =>
+        (ErrorMsg.errorAt (#2 c) "Projection from non-tuple constructor";
+         eprefaces' [("Constructor", p_con env c),
+                     ("Kind", p_kind k)])
 
 fun checkKind env c k1 k2 =
     unifyKinds k1 k2
@@ -212,6 +225,7 @@
       | L.KName => (L'.KName, loc)
       | L.KRecord k => (L'.KRecord (elabKind k), loc)
       | L.KUnit => (L'.KUnit, loc)
+      | L.KTuple ks => (L'.KTuple (map elabKind ks), loc)
       | L.KWild => kunif loc
 
 fun foldKind (dom, ran, loc)=
@@ -222,6 +236,11 @@
                             (L'.KArrow ((L'.KRecord dom, loc),
                                         ran), loc)), loc)), loc)
 
+fun hnormKind (kAll as (k, _)) =
+    case k of
+        L'.KUnif (_, _, ref (SOME k)) => hnormKind k
+      | _ => kAll
+
 fun elabCon (env, denv) (c, loc) =
     case c of
         L.CAnnot (c, k) =>
@@ -411,6 +430,32 @@
 
       | L.CUnit => ((L'.CUnit, loc), (L'.KUnit, loc), [])
 
+      | L.CTuple cs =>
+        let
+            val (cs', ks, gs) = foldl (fn (c, (cs', ks, gs)) =>
+                                          let
+                                              val (c', k, gs') = elabCon (env, denv) c
+                                          in
+                                              (c' :: cs', k :: ks, gs' @ gs)
+                                          end) ([], [], []) cs
+        in
+            ((L'.CTuple (rev cs'), loc), (L'.KTuple (rev ks), loc), gs)
+        end
+      | L.CProj (c, n) =>
+        let
+            val (c', k, gs) = elabCon (env, denv) c
+        in
+            case hnormKind k of
+                (L'.KTuple ks, _) =>
+                if n <= 0 orelse n > length ks then
+                    (conError env (ProjBounds (c', n));
+                     (cerror, kerror, []))
+                else
+                    ((L'.CProj (c', n), loc), List.nth (ks, n - 1), gs)
+              | k => (conError env (ProjMismatch (c', k));
+                      (cerror, kerror, []))
+        end
+
       | L.CWild k =>
         let
             val k' = elabKind k
@@ -509,11 +554,6 @@
 
 exception CUnify of L'.con * L'.con * cunify_error
 
-fun hnormKind (kAll as (k, _)) =
-    case k of
-        L'.KUnif (_, _, ref (SOME k)) => hnormKind k
-      | _ => kAll
-
 fun kindof env (c, loc) =
     case c of
         L'.TFun _ => ktype
@@ -553,6 +593,12 @@
 
       | L'.CUnit => (L'.KUnit, loc)
 
+      | L'.CTuple cs => (L'.KTuple (map (kindof env) cs), loc)
+      | L'.CProj (c, n) =>
+        (case hnormKind (kindof env c) of
+             (L'.KTuple ks, _) => List.nth (ks, n - 1)
+           | k => raise CUnify' (CKindof (k, c)))
+
       | L'.CError => kerror
       | L'.CUnif (_, k, _, _) => k
 
@@ -862,6 +908,20 @@
             else
                 err CIncompatible
 
+          | (L'.CTuple cs1, L'.CTuple cs2) =>
+            ((ListPair.foldlEq (fn (c1, c2, gs) =>
+                                   let
+                                       val gs' = unifyCons' (env, denv) c1 c2
+                                   in
+                                       gs' @ gs
+                                   end) [] (cs1, cs2))
+             handle ListPair.UnequalLengths => err CIncompatible)
+          | (L'.CProj (c1, n1), L'.CProj (c2, n2)) =>
+            if n1 = n2 then
+                unifyCons' (env, denv) c1 c2
+            else
+                err CIncompatible
+
           | (L'.CError, _) => []
           | (_, L'.CError) => []
 
@@ -869,8 +929,6 @@
           | (_, L'.CRecord _) => isRecord ()
           | (L'.CConcat _, _) => isRecord ()
           | (_, L'.CConcat _) => isRecord ()
-          (*| (L'.CUnif (_, (L'.KRecord _, _), _, _), _) => isRecord ()
-          | (_, L'.CUnif (_, (L'.KRecord _, _), _, _)) => isRecord ()*)
 
           | (L'.CUnif (_, k1, _, r1), L'.CUnif (_, k2, _, r2)) =>
             if r1 = r2 then
@@ -2908,7 +2966,11 @@
         val (sgn, gs) = elabSgn (env, D.empty) (L.SgnConst basis, ErrorMsg.dummySpan)
         val () = case gs of
                      [] => ()
-                   | _ => raise Fail "Unresolved disjointness constraints in Basis"
+                   | _ => (app (fn (_, env, _, c1, c2) =>
+                                   prefaces "Unresolved"
+                                   [("c1", p_con env c1),
+                                    ("c2", p_con env c2)]) gs;
+                           raise Fail "Unresolved disjointness constraints in Basis")
 
         val (env', basis_n) = E.pushStrNamed env "Basis" sgn