src/HOL/Tools/BNF/bnf_fp_n2m_sugar.ML
changeset 56485 008634379465
parent 56484 c451cf8b29c8
child 56521 20cfb18a53ba
--- a/src/HOL/Tools/BNF/bnf_fp_n2m_sugar.ML	Wed Apr 09 18:22:11 2014 +0200
+++ b/src/HOL/Tools/BNF/bnf_fp_n2m_sugar.ML	Wed Apr 09 18:40:21 2014 +0200
@@ -353,14 +353,15 @@
         fold (fold_subtype_pairs maybe_insert) (ctr_Ts ~~ gen_ctr_Ts) []
       end;
 
-    fun gather_types _ _ num_groups seen gen_seen [] = (num_groups, seen, gen_seen)
-      | gather_types lthy rho num_groups seen gen_seen ((T as Type (_, tyargs)) :: Ts) =
+    fun gather_types _ _ rev_seens gen_seen [] = (rev rev_seens, gen_seen)
+      | gather_types lthy rho rev_seens gen_seen ((T as Type (_, tyargs)) :: Ts) =
         let
           val {fp_res = {Ts = mutual_Ts0, ...}, ...} = the_fp_sugar_of T;
           val mutual_Ts = map (retypargs tyargs) mutual_Ts0;
 
-          val _ = seen = [] orelse exists (exists_strict_subtype_in seen) mutual_Ts orelse
-            not_mutually_nested_rec mutual_Ts seen;
+          val rev_seen = flat rev_seens;
+          val _ = null rev_seens orelse exists (exists_strict_subtype_in rev_seen) mutual_Ts orelse
+            not_mutually_nested_rec mutual_Ts rev_seen;
 
           fun fresh_tyargs () =
             let
@@ -374,7 +375,7 @@
             end;
 
           val (rho', gen_tyargs, gen_seen', lthy') =
-            if exists (exists_subtype_in seen) mutual_Ts then
+            if exists (exists_subtype_in rev_seen) mutual_Ts then
               (case gen_rhss_in gen_seen rho mutual_Ts of
                 [] => fresh_tyargs ()
               | gen_tyargs :: gen_tyargss_tl =>
@@ -393,12 +394,14 @@
           val other_mutual_Ts = remove1 (op =) T mutual_Ts;
           val Ts' = fold (remove1 (op =)) other_mutual_Ts Ts;
         in
-          gather_types lthy' rho' (num_groups + 1) (seen @ mutual_Ts) (gen_seen' @ gen_mutual_Ts)
-            Ts'
+          gather_types lthy' rho' (mutual_Ts :: rev_seens) (gen_seen' @ gen_mutual_Ts) Ts'
         end
-      | gather_types _ _ _ _ _ (T :: _) = not_co_datatype T;
+      | gather_types _ _ _ _ (T :: _) = not_co_datatype T;
 
-    val (num_groups, perm_Ts, perm_gen_Ts) = gather_types lthy [] 0 [] [] sorted_actual_Ts;
+    val (perm_Tss, perm_gen_Ts) = gather_types lthy [] [] [] sorted_actual_Ts;
+    val (perm_cliques, perm_Ts) =
+      split_list (flat (map_index (fn (i, perm_Ts) => map (pair i) perm_Ts) perm_Tss));
+
     val perm_frozen_gen_Ts = map Logic.unvarifyT_global perm_gen_Ts;
 
     val missing_Ts = fold (remove1 (op =)) actual_Ts perm_Ts;
@@ -416,6 +419,10 @@
     fun permute xs = permute_like (op =) Ts perm_Ts xs;
     fun unpermute perm_xs = permute_like (op =) perm_Ts Ts perm_xs;
 
+    (* The assignment of callers to cliques is incorrect in general. This code would need to inspect
+       the actual calls to discover the correct cliques in the presence of type duplicates. However,
+       the naive scheme implemented here supports "prim(co)rec" specifications following reasonable
+       ordering of the duplicates (e.g., keeping the cliques together). *)
     val perm_bs = permute bs;
     val perm_callers = permute callers;
     val perm_kks = permute kks;
@@ -424,14 +431,12 @@
 
     val perm_callssss = map2 (indexify_callsss o #ctrs o #ctr_sugar) perm_fp_sugars0 perm_callssss0;
 
-    val perm_cliques = [] (*###*)
-
     val ((perm_fp_sugars, fp_sugar_thms), lthy) =
-      if num_groups > 1 then
+      if can the_single perm_Tss then
+        ((perm_fp_sugars0, (NONE, NONE)), lthy)
+      else
         mutualize_fp_sugars fp perm_cliques perm_bs perm_frozen_gen_Ts perm_callers perm_callssss
-          perm_fp_sugars0 lthy
-      else
-        ((perm_fp_sugars0, (NONE, NONE)), lthy);
+          perm_fp_sugars0 lthy;
 
     val fp_sugars = unpermute perm_fp_sugars;
   in