diff src/elaborate.sml @ 402:ebf27030ae3b

Recursive unurlify for Default datatypes
author Adam Chlipala <adamc@hcoop.net>
date Tue, 21 Oct 2008 15:11:42 -0400
parents 4d519baf357c
children 8084fa9216de
line wrap: on
line diff
--- a/src/elaborate.sml	Tue Oct 21 13:56:38 2008 -0400
+++ b/src/elaborate.sml	Tue Oct 21 15:11:42 2008 -0400
@@ -1159,6 +1159,17 @@
 
 fun exhaustive (env, denv, t, ps) =
     let
+        fun depth (p, _) =
+            case p of
+                L'.PWild => 0
+              | L'.PVar _ => 0
+              | L'.PPrim _ => 0
+              | L'.PCon (_, _, _, NONE) => 1
+              | L'.PCon (_, _, _, SOME p) => 1 + depth p
+              | L'.PRecord xps => foldl (fn ((_, p, _), n) => Int.max (depth p, n)) 0 xps
+
+        val depth = 1 + foldl (fn (p, n) => Int.max (depth p, n)) 0 ps
+
         fun pcCoverage pc =
             case pc of
                 L'.PConVar n => n
@@ -1201,51 +1212,54 @@
               | [p] => coverage p
               | p :: ps => merge (coverage p, combinedCoverage ps)
 
-        fun enumerateCases t =
-            let
-                fun dtype cons =
-                    ListUtil.mapConcat (fn (_, n, to) =>
-                                           case to of
-                                               NONE => [Datatype (IM.insert (IM.empty, n, Wild))]
-                                             | SOME t => map (fn c => Datatype (IM.insert (IM.empty, n, c)))
-                                                         (enumerateCases t)) cons
-            in
-                case #1 (#1 (hnormCon (env, denv) t)) of
-                    L'.CNamed n =>
-                    (let
-                         val dt = E.lookupDatatype env n
-                         val cons = E.constructors dt
-                     in
-                         dtype cons
-                     end handle E.UnboundNamed _ => [Wild])
-                  | L'.TRecord c =>
-                    (case #1 (#1 (hnormCon (env, denv) c)) of
-                         L'.CRecord (_, xts) =>
-                         let
-                             val xts = map (fn (x, t) => (#1 (hnormCon (env, denv) x), t)) xts
-
-                             fun exponentiate fs =
-                                 case fs of
-                                     [] => [SM.empty]
-                                   | ((L'.CName x, _), t) :: rest =>
-                                     let
-                                         val this = enumerateCases t
-                                         val rest = exponentiate rest
-                                     in
-                                         ListUtil.mapConcat (fn fmap =>
-                                                                map (fn c => SM.insert (fmap, x, c)) this) rest
-                                     end
-                                   | _ => raise Fail "exponentiate: Not CName"
+        fun enumerateCases depth t =
+            if depth = 0 then
+                [Wild]
+            else
+                let
+                    fun dtype cons =
+                        ListUtil.mapConcat (fn (_, n, to) =>
+                                               case to of
+                                                   NONE => [Datatype (IM.insert (IM.empty, n, Wild))]
+                                                 | SOME t => map (fn c => Datatype (IM.insert (IM.empty, n, c)))
+                                                                 (enumerateCases (depth-1) t)) cons
+                in
+                    case #1 (#1 (hnormCon (env, denv) t)) of
+                        L'.CNamed n =>
+                        (let
+                             val dt = E.lookupDatatype env n
+                             val cons = E.constructors dt
                          in
-                             if List.exists (fn ((L'.CName _, _), _) => false
-                                              | (c, _) => true) xts then
-                                 [Wild]
-                             else
-                                 map (fn ls => Record [ls]) (exponentiate xts)
-                         end
-                       | _ => [Wild])
-                  | _ => [Wild]
-            end
+                             dtype cons
+                         end handle E.UnboundNamed _ => [Wild])
+                      | L'.TRecord c =>
+                        (case #1 (#1 (hnormCon (env, denv) c)) of
+                             L'.CRecord (_, xts) =>
+                             let
+                                 val xts = map (fn (x, t) => (#1 (hnormCon (env, denv) x), t)) xts
+
+                                 fun exponentiate fs =
+                                     case fs of
+                                         [] => [SM.empty]
+                                       | ((L'.CName x, _), t) :: rest =>
+                                         let
+                                             val this = enumerateCases depth t
+                                             val rest = exponentiate rest
+                                         in
+                                             ListUtil.mapConcat (fn fmap =>
+                                                                    map (fn c => SM.insert (fmap, x, c)) this) rest
+                                         end
+                                       | _ => raise Fail "exponentiate: Not CName"
+                             in
+                                 if List.exists (fn ((L'.CName _, _), _) => false
+                                                  | (c, _) => true) xts then
+                                     [Wild]
+                                 else
+                                     map (fn ls => Record [ls]) (exponentiate xts)
+                             end
+                           | _ => [Wild])
+                      | _ => [Wild]
+                end
 
         fun coverageImp (c1, c2) =
             let
@@ -1331,7 +1345,7 @@
                         (prefaces "Not a datatype" [("c", p_con env (c, ErrorMsg.dummySpan))];
                          raise Fail "isTotal: Not a datatype")
                 end
-              | Record _ => (List.all (fn c2 => coverageImp (c, c2)) (enumerateCases t), [])
+              | Record _ => (List.all (fn c2 => coverageImp (c, c2)) (enumerateCases depth t), [])
     in
         isTotal (combinedCoverage ps, t)
     end
@@ -1640,11 +1654,8 @@
 
                 ((L'.ECase (e', pes', {disc = et, result = result}), loc), result, enD gs' @ gs)
             end
-
-        (*val tcs = List.filter (fn TypeClass _ => true | _ => false) (#3 r)*)
     in
-        (*prefaces "elabExp" [("e", SourcePrint.p_exp eAll),
-                            ("|tcs|", PD.string (Int.toString (length tcs)))];*)
+        (*prefaces "/elabExp" [("e", SourcePrint.p_exp eAll)];*)
         r
     end