src/HOL/Tools/datatype_package.ML
changeset 21045 66d6d1b0ddfa
parent 20820 58693343905f
child 21127 c8e862897d13
equal deleted inserted replaced
21044:9690be52ee5d 21045:66d6d1b0ddfa
   165 
   165 
   166 (*Warn if the (induction) variable occurs Free among the premises, which
   166 (*Warn if the (induction) variable occurs Free among the premises, which
   167   usually signals a mistake.  But calls the tactic either way!*)
   167   usually signals a mistake.  But calls the tactic either way!*)
   168 fun occs_in_prems tacf vars =
   168 fun occs_in_prems tacf vars =
   169   SUBGOAL (fn (Bi, i) =>
   169   SUBGOAL (fn (Bi, i) =>
   170            (if  exists (fn Free (a, _) => a mem vars)
   170            (if exists (fn (a, _) => member (op =) vars a)
   171                       (foldr add_term_frees [] (#2 (strip_context Bi)))
   171                       (fold Term.add_frees (#2 (strip_context Bi)) [])
   172              then warning "Induction variable occurs also among premises!"
   172              then warning "Induction variable occurs also among premises!"
   173              else ();
   173              else ();
   174             tacf i));
   174             tacf i));
   175 
   175 
   176 
   176 
   179 local
   179 local
   180 
   180 
   181 fun prep_var (Var (ixn, _), SOME x) = SOME (ixn, x)
   181 fun prep_var (Var (ixn, _), SOME x) = SOME (ixn, x)
   182   | prep_var _ = NONE;
   182   | prep_var _ = NONE;
   183 
   183 
   184 fun prep_inst (concl, xs) =	(*exception Library.UnequalLengths *)
   184 fun prep_inst (concl, xs) = (*exception Library.UnequalLengths*)
   185   let val vs = InductAttrib.vars_of concl
   185   let val vs = InductAttrib.vars_of concl
   186   in List.mapPartial prep_var (Library.drop (length vs - length xs, vs) ~~ xs) end;
   186   in map_filter prep_var (Library.drop (length vs - length xs, vs) ~~ xs) end;
   187 
   187 
   188 in
   188 in
   189 
   189 
   190 fun gen_induct_tac inst_tac (varss, opt_rule) i state = 
   190 fun gen_induct_tac inst_tac (varss, opt_rule) i state = 
   191   SUBGOAL (fn (Bi,_) =>
   191   SUBGOAL (fn (Bi,_) =>
   192   let
   192   let
   193     val (rule, rule_name) =
   193     val (rule, rule_name) =
   194       case opt_rule of
   194       case opt_rule of
   195 	  SOME r => (r, "Induction rule")
   195           SOME r => (r, "Induction rule")
   196 	| NONE =>
   196         | NONE =>
   197 	    let val tn = find_tname (hd (List.mapPartial I (List.concat varss))) Bi
   197             let val tn = find_tname (hd (map_filter I (flat varss))) Bi
   198                 val {sign, ...} = Thm.rep_thm state
   198                 val {sign, ...} = Thm.rep_thm state
   199 	    in (#induction (the_datatype sign tn), "Induction rule for type " ^ tn) 
   199             in (#induction (the_datatype sign tn), "Induction rule for type " ^ tn) 
   200 	    end
   200             end
   201     val concls = HOLogic.dest_concls (Thm.concl_of rule);
   201     val concls = HOLogic.dest_concls (Thm.concl_of rule);
   202     val insts = List.concat (map prep_inst (concls ~~ varss)) handle Library.UnequalLengths =>
   202     val insts = maps prep_inst (concls ~~ varss) handle Library.UnequalLengths =>
   203       error (rule_name ^ " has different numbers of variables");
   203       error (rule_name ^ " has different numbers of variables");
   204   in occs_in_prems (inst_tac insts rule) (map #2 insts) i end)
   204   in occs_in_prems (inst_tac insts rule) (map #2 insts) i end)
   205   i state;
   205   i state;
   206 
   206 
   207 fun induct_tac s =
   207 fun induct_tac s =
   208   gen_induct_tac Tactic.res_inst_tac'
   208   gen_induct_tac Tactic.res_inst_tac'
   209     (map (Library.single o SOME) (Syntax.read_idents s), NONE);
   209     (map (single o SOME) (Syntax.read_idents s), NONE);
   210 
   210 
   211 fun induct_thm_tac th s =
   211 fun induct_thm_tac th s =
   212   gen_induct_tac Tactic.res_inst_tac'
   212   gen_induct_tac Tactic.res_inst_tac'
   213     ([map SOME (Syntax.read_idents s)], SOME th);
   213     ([map SOME (Syntax.read_idents s)], SOME th);
   214 
   214 
   271 (* case names *)
   271 (* case names *)
   272 
   272 
   273 local
   273 local
   274 
   274 
   275 fun dt_recs (DtTFree _) = []
   275 fun dt_recs (DtTFree _) = []
   276   | dt_recs (DtType (_, dts)) = List.concat (map dt_recs dts)
   276   | dt_recs (DtType (_, dts)) = maps dt_recs dts
   277   | dt_recs (DtRec i) = [i];
   277   | dt_recs (DtRec i) = [i];
   278 
   278 
   279 fun dt_cases (descr: descr) (_, args, constrs) =
   279 fun dt_cases (descr: descr) (_, args, constrs) =
   280   let
   280   let
   281     fun the_bname i = Sign.base_name (#1 (valOf (AList.lookup (op =) descr i)));
   281     fun the_bname i = Sign.base_name (#1 (the (AList.lookup (op =) descr i)));
   282     val bnames = map the_bname (distinct (op =) (List.concat (map dt_recs args)));
   282     val bnames = map the_bname (distinct (op =) (maps dt_recs args));
   283   in map (fn (c, _) => space_implode "_" (Sign.base_name c :: bnames)) constrs end;
   283   in map (fn (c, _) => space_implode "_" (Sign.base_name c :: bnames)) constrs end;
   284 
   284 
   285 
   285 
   286 fun induct_cases descr =
   286 fun induct_cases descr =
   287   DatatypeProp.indexify_names (List.concat (map (dt_cases descr) (map #2 descr)));
   287   DatatypeProp.indexify_names (maps (dt_cases descr) (map #2 descr));
   288 
   288 
   289 fun exhaust_cases descr i = dt_cases descr (valOf (AList.lookup (op =) descr i));
   289 fun exhaust_cases descr i = dt_cases descr (the (AList.lookup (op =) descr i));
   290 
   290 
   291 in
   291 in
   292 
   292 
   293 fun mk_case_names_induct descr = RuleCases.case_names (induct_cases descr);
   293 fun mk_case_names_induct descr = RuleCases.case_names (induct_cases descr);
   294 
   294 
   295 fun mk_case_names_exhausts descr new =
   295 fun mk_case_names_exhausts descr new =
   296   map (RuleCases.case_names o exhaust_cases descr o #1)
   296   map (RuleCases.case_names o exhaust_cases descr o #1)
   297     (List.filter (fn ((_, (name, _, _))) => name mem_string new) descr);
   297     (filter (fn ((_, (name, _, _))) => member (op =) new name) descr);
   298 
   298 
   299 end;
   299 end;
   300 
   300 
   301 (*Name management for ATP linkup. The suffix here must agree with the one given
   301 (*Name management for ATP linkup. The suffix here must agree with the one given
   302   for notE in Clasimp.addIff*)
   302   for notE in Clasimp.addIff*)
   304     Thm.name_thm (Thm.name_of_thm th ^ "_iff1", th RS notE);
   304     Thm.name_thm (Thm.name_of_thm th ^ "_iff1", th RS notE);
   305       
   305       
   306 fun add_rules simps case_thms size_thms rec_thms inject distinct
   306 fun add_rules simps case_thms size_thms rec_thms inject distinct
   307                   weak_case_congs cong_att =
   307                   weak_case_congs cong_att =
   308   (snd o PureThy.add_thmss [(("simps", simps), []),
   308   (snd o PureThy.add_thmss [(("simps", simps), []),
   309     (("", List.concat case_thms @ size_thms @ 
   309     (("", flat case_thms @ size_thms @ 
   310           List.concat distinct  @ rec_thms), [Simplifier.simp_add]),
   310           flat distinct @ rec_thms), [Simplifier.simp_add]),
   311     (("", size_thms @ rec_thms),             [setmp CodegenData.strict_functyp false (RecfunCodegen.add NONE)]),
   311     (("", size_thms @ rec_thms),             [setmp CodegenData.strict_functyp false (RecfunCodegen.add NONE)]),
   312     (("", List.concat inject),               [iff_add]),
   312     (("", flat inject),               [iff_add]),
   313     (("", map name_notE (List.concat distinct)),  [Classical.safe_elim NONE]),
   313     (("", map name_notE (flat distinct)),  [Classical.safe_elim NONE]),
   314     (("", weak_case_congs),                  [cong_att])]);
   314     (("", weak_case_congs),                  [cong_att])]);
   315 
   315 
   316 
   316 
   317 (* add_cases_induct *)
   317 (* add_cases_induct *)
   318 
   318 
   325        (("", exhaustion), [InductAttrib.cases_type name])];
   325        (("", exhaustion), [InductAttrib.cases_type name])];
   326     fun unnamed_rule i =
   326     fun unnamed_rule i =
   327       (("", nth inducts i), [PureThy.kind_internal, InductAttrib.induct_type ""]);
   327       (("", nth inducts i), [PureThy.kind_internal, InductAttrib.induct_type ""]);
   328   in
   328   in
   329     thy |> PureThy.add_thms
   329     thy |> PureThy.add_thms
   330       (List.concat (map named_rules infos) @
   330       (maps named_rules infos @
   331         map unnamed_rule (length infos upto length inducts - 1)) |> snd
   331         map unnamed_rule (length infos upto length inducts - 1)) |> snd
   332     |> PureThy.add_thmss [(("inducts", inducts), [])] |> snd
   332     |> PureThy.add_thmss [(("inducts", inducts), [])] |> snd
   333   end;
   333   end;
   334 
   334 
   335 
   335 
   394   (fn thy => ((change_simpset_of thy) (fn ss => ss addsimprocs [distinct_simproc]); thy));
   394   (fn thy => ((change_simpset_of thy) (fn ss => ss addsimprocs [distinct_simproc]); thy));
   395 
   395 
   396 
   396 
   397 (**** translation rules for case ****)
   397 (**** translation rules for case ****)
   398 
   398 
   399 fun find_first f = Library.find_first f;
       
   400 
       
   401 fun case_tr context [t, u] =
   399 fun case_tr context [t, u] =
   402     let
   400     let
   403       val thy = Context.theory_of context;
   401       val thy = Context.theory_of context;
   404       fun case_error s name ts = raise TERM ("Error in case expression" ^
   402       fun case_error s name ts = raise TERM ("Error in case expression" ^
   405         getOpt (Option.map (curry op ^ " for datatype ") name, "") ^ ":\n" ^ s, ts);
   403         getOpt (Option.map (curry op ^ " for datatype ") name, "") ^ ":\n" ^ s, ts);
   413       val cases as ((cname, _), _) :: _ = map dest_case1 (dest_case2 u);
   411       val cases as ((cname, _), _) :: _ = map dest_case1 (dest_case2 u);
   414       val tab = Symtab.dest (get_datatypes thy);
   412       val tab = Symtab.dest (get_datatypes thy);
   415       val (cases', default) = (case split_last cases of
   413       val (cases', default) = (case split_last cases of
   416           (cases', (("dummy_pattern", []), t)) => (cases', SOME t)
   414           (cases', (("dummy_pattern", []), t)) => (cases', SOME t)
   417         | _ => (cases, NONE))
   415         | _ => (cases, NONE))
   418       fun abstr (Free (x, T), body) = Term.absfree (x, T, body)
   416       fun abstr (Free (x, T)) body = Term.absfree (x, T, body)
   419         | abstr (Const ("_constrain", _) $ Free (x, T) $ tT, body) =
   417         | abstr (Const ("_constrain", _) $ Free (x, T) $ tT) body =
   420             Syntax.const Syntax.constrainAbsC $ Term.absfree (x, T, body) $ tT
   418             Syntax.const Syntax.constrainAbsC $ Term.absfree (x, T, body) $ tT
   421         | abstr (Const ("Pair", _) $ x $ y, body) =
   419         | abstr (Const ("Pair", _) $ x $ y) body =
   422             Syntax.const "split" $ abstr (x, abstr (y, body))
   420             Syntax.const "split" $ (abstr x o abstr y) body
   423         | abstr (t, _) = case_error "Illegal pattern" NONE [t];
   421         | abstr t _ = case_error "Illegal pattern" NONE [t];
   424     in case find_first (fn (_, {descr, index, ...}) =>
   422     in case find_first (fn (_, {descr, index, ...}) =>
   425       exists (equal cname o fst) (#3 (snd (List.nth (descr, index))))) tab of
   423       exists (equal cname o fst) (#3 (snd (nth descr index)))) tab of
   426         NONE => case_error ("Not a datatype constructor: " ^ cname) NONE [u]
   424         NONE => case_error ("Not a datatype constructor: " ^ cname) NONE [u]
   427       | SOME (tname, {descr, sorts, case_name, index, ...}) =>
   425       | SOME (tname, {descr, sorts, case_name, index, ...}) =>
   428         let
   426         let
   429           val _ = if exists (equal "dummy_pattern" o fst o fst) cases' then
   427           val _ = if exists (equal "dummy_pattern" o fst o fst) cases' then
   430             case_error "Illegal occurrence of '_' dummy pattern" (SOME tname) [u] else ();
   428             case_error "Illegal occurrence of '_' dummy pattern" (SOME tname) [u] else ();
   431           val (_, (_, dts, constrs)) = List.nth (descr, index);
   429           val (_, (_, dts, constrs)) = nth descr index;
   432           fun find_case (cases, (s, dt)) =
   430           fun find_case (s, dt) cases =
   433             (case find_first (equal s o fst o fst) cases' of
   431             (case find_first (equal s o fst o fst) cases' of
   434                NONE => (cases, list_abs (map (rpair dummyT)
   432                NONE => (list_abs (map (rpair dummyT)
   435                  (DatatypeProp.make_tnames (map (typ_of_dtyp descr sorts) dt)),
   433                  (DatatypeProp.make_tnames (map (typ_of_dtyp descr sorts) dt)),
   436                  case default of
   434                  case default of
   437                    NONE => (warning ("No clause for constructor " ^ s ^
   435                    NONE => (warning ("No clause for constructor " ^ s ^
   438                      " in case expression"); Const ("undefined", dummyT))
   436                      " in case expression"); Const ("undefined", dummyT))
   439                  | SOME t => t))
   437                  | SOME t => t), cases)
   440              | SOME (c as ((_, vs), t)) =>
   438              | SOME (c as ((_, vs), t)) =>
   441                  if length dt <> length vs then
   439                  if length dt <> length vs then
   442                     case_error ("Wrong number of arguments for constructor " ^ s)
   440                     case_error ("Wrong number of arguments for constructor " ^ s)
   443                       (SOME tname) vs
   441                       (SOME tname) vs
   444                  else (cases \ c, foldr abstr t vs))
   442                  else (fold_rev abstr vs t, remove (op =) c cases))
   445           val (cases'', fs) = foldl_map find_case (cases', constrs)
   443           val (fs, cases'') = fold_map find_case constrs cases'
   446         in case (cases'', length constrs = length cases', default) of
   444         in case (cases'', length constrs = length cases', default) of
   447             ([], true, SOME _) =>
   445             ([], true, SOME _) =>
   448               case_error "Extra '_' dummy pattern" (SOME tname) [u]
   446               case_error "Extra '_' dummy pattern" (SOME tname) [u]
   449           | (_ :: _, _, _) =>
   447           | (_ :: _, _, _) =>
   450               let val extra = distinct (op =) (map (fst o fst) cases'')
   448               let val extra = distinct (op =) (map (fst o fst) cases'')
   476       end;
   474       end;
   477     val cases = map (fn ((cname, dts), t) =>
   475     val cases = map (fn ((cname, dts), t) =>
   478       (Sign.extern_const (Context.theory_of context) cname,
   476       (Sign.extern_const (Context.theory_of context) cname,
   479        strip_abs (length dts) t, is_dependent (length dts) t))
   477        strip_abs (length dts) t, is_dependent (length dts) t))
   480       (constrs ~~ fs);
   478       (constrs ~~ fs);
   481     fun count_cases (cs, (_, _, true)) = cs
   479     fun count_cases (_, _, true) = I
   482       | count_cases (cs, (cname, (_, body), false)) =
   480       | count_cases (cname, (_, body), false) =
   483           case AList.lookup (op = : term * term -> bool) cs body
   481           AList.map_default (op = : term * term -> bool)
   484            of NONE => (body, [cname]) :: cs
   482             (body, []) (cons cname)
   485             | SOME cnames => AList.update (op =) (body, cnames @ [cname]) cs;
   483     val cases' = sort (int_ord o swap o pairself (length o snd))
   486     val cases' = sort (int_ord o Library.swap o pairself (length o snd))
   484       (fold_rev count_cases cases []);
   487       (Library.foldl count_cases ([], cases));
       
   488     fun mk_case1 (cname, (vs, body), _) = Syntax.const "_case1" $
   485     fun mk_case1 (cname, (vs, body), _) = Syntax.const "_case1" $
   489       list_comb (Syntax.const cname, vs) $ body;
   486       list_comb (Syntax.const cname, vs) $ body;
   490     fun is_undefined (Const ("undefined", _)) = true
   487     fun is_undefined (Const ("undefined", _)) = true
   491       | is_undefined _ = false;
   488       | is_undefined _ = false;
   492   in
   489   in
   501          | (default, cnames) :: _ =>
   498          | (default, cnames) :: _ =>
   502            if length cnames = 1 then cases
   499            if length cnames = 1 then cases
   503            else if length cnames = length constrs then
   500            else if length cnames = length constrs then
   504              [hd cases, ("dummy_pattern", ([], default), false)]
   501              [hd cases, ("dummy_pattern", ([], default), false)]
   505            else
   502            else
   506              filter_out (fn (cname, _, _) => cname mem cnames) cases @
   503              filter_out (fn (cname, _, _) => member (op =) cnames cname) cases @
   507              [("dummy_pattern", ([], default), false)]))
   504              [("dummy_pattern", ([], default), false)]))
   508   end;
   505   end;
   509 
   506 
   510 fun make_case_tr' case_names descr = List.concat (map
   507 fun make_case_tr' case_names descr = maps
   511   (fn ((_, (_, _, constrs)), case_name) => map (rpair (case_tr' constrs))
   508   (fn ((_, (_, _, constrs)), case_name) =>
   512     (NameSpace.accesses' case_name)) (descr ~~ case_names));
   509     map (rpair (case_tr' constrs)) (NameSpace.accesses' case_name))
       
   510       (descr ~~ case_names);
   513 
   511 
   514 val trfun_setup =
   512 val trfun_setup =
   515   Theory.add_advanced_trfuns ([], [("_case_syntax", case_tr)], [], []);
   513   Theory.add_advanced_trfuns ([], [("_case_syntax", case_tr)], [], []);
   516 
   514 
   517 
   515 
   597   end;
   595   end;
   598 
   596 
   599 fun add_datatype_axm flat_names new_type_names descr sorts types_syntax constr_syntax dt_info
   597 fun add_datatype_axm flat_names new_type_names descr sorts types_syntax constr_syntax dt_info
   600     case_names_induct case_names_exhausts thy =
   598     case_names_induct case_names_exhausts thy =
   601   let
   599   let
   602     val descr' = List.concat descr;
   600     val descr' = flat descr;
   603     val recTs = get_rec_types descr' sorts;
   601     val recTs = get_rec_types descr' sorts;
   604     val used = foldr add_typ_tfree_names [] recTs;
   602     val used = map fst (fold Term.add_tfreesT recTs []);
   605     val newTs = Library.take (length (hd descr), recTs);
   603     val newTs = Library.take (length (hd descr), recTs);
   606 
   604 
   607     val no_size = exists (fn (_, (_, _, constrs)) => exists (fn (_, cargs) => exists
   605     val no_size = exists (fn (_, (_, _, constrs)) => exists (fn (_, cargs) => exists
   608       (fn dt => is_rec_type dt andalso not (null (fst (strip_dtyp dt))))
   606       (fn dt => is_rec_type dt andalso not (null (fst (strip_dtyp dt))))
   609         cargs) constrs) descr';
   607         cargs) constrs) descr';
   633         let val Ts = map (typ_of_dtyp descr' sorts) cargs
   631         let val Ts = map (typ_of_dtyp descr' sorts) cargs
   634         in Ts ---> freeT end) constrs) (hd descr);
   632         in Ts ---> freeT end) constrs) (hd descr);
   635 
   633 
   636     val case_names = map (fn s => (s ^ "_case")) new_type_names;
   634     val case_names = map (fn s => (s ^ "_case")) new_type_names;
   637 
   635 
   638     val thy2' = thy |>
   636     val thy2' = thy
   639 
   637 
   640       (** new types **)
   638       (** new types **)
   641 
   639       |> fold (fn ((name, mx), tvs) => TypedefPackage.add_typedecls [(name, tvs, mx)])
   642       curry (Library.foldr (fn (((name, mx), tvs), thy') => thy' |>
   640            (types_syntax ~~ tyvars)
   643           TypedefPackage.add_typedecls [(name, tvs, mx)]))
   641       |> add_path flat_names (space_implode "_" new_type_names)
   644         (types_syntax ~~ tyvars) |>
       
   645       add_path flat_names (space_implode "_" new_type_names) |>
       
   646 
   642 
   647       (** primrec combinators **)
   643       (** primrec combinators **)
   648 
   644 
   649       specify_consts (map (fn ((name, T), T') =>
   645       |> specify_consts (map (fn ((name, T), T') =>
   650         (name, reccomb_fn_Ts @ [T] ---> T', NoSyn)) (reccomb_names ~~ recTs ~~ rec_result_Ts)) |>
   646            (name, reccomb_fn_Ts @ [T] ---> T', NoSyn)) (reccomb_names ~~ recTs ~~ rec_result_Ts))
   651 
   647 
   652       (** case combinators **)
   648       (** case combinators **)
   653 
   649 
   654       specify_consts (map (fn ((name, T), Ts) =>
   650       |> specify_consts (map (fn ((name, T), Ts) =>
   655         (name, Ts @ [T] ---> freeT, NoSyn)) (case_names ~~ newTs ~~ case_fn_Ts));
   651            (name, Ts @ [T] ---> freeT, NoSyn)) (case_names ~~ newTs ~~ case_fn_Ts));
   656 
   652 
   657     val reccomb_names' = map (Sign.full_name thy2') reccomb_names;
   653     val reccomb_names' = map (Sign.full_name thy2') reccomb_names;
   658     val case_names' = map (Sign.full_name thy2') case_names;
   654     val case_names' = map (Sign.full_name thy2') case_names;
   659 
   655 
   660     val thy2 = thy2' |>
   656     val thy2 = thy2'
   661 
   657 
   662       (** size functions **)
   658       (** size functions **)
   663 
   659 
   664       (if no_size then I else specify_consts (map (fn (s, T) =>
   660       |> (if no_size then I else specify_consts (map (fn (s, T) =>
   665         (Sign.base_name s, T --> HOLogic.natT, NoSyn))
   661         (Sign.base_name s, T --> HOLogic.natT, NoSyn))
   666           (size_names ~~ Library.drop (length (hd descr), recTs)))) |>
   662           (size_names ~~ Library.drop (length (hd descr), recTs))))
   667 
   663 
   668       (** constructors **)
   664       (** constructors **)
   669 
   665 
   670       parent_path flat_names |>
   666       |> parent_path flat_names
   671       curry (Library.foldr (fn (((((_, (_, _, constrs)), T), tname),
   667       |> fold (fn ((((_, (_, _, constrs)), T), tname),
   672         constr_syntax'), thy') => thy' |>
   668         constr_syntax') =>
   673           add_path flat_names tname |>
   669           add_path flat_names tname #>
   674             specify_consts (map (fn ((_, cargs), (cname, mx)) =>
   670             specify_consts (map (fn ((_, cargs), (cname, mx)) =>
   675               (cname, map (typ_of_dtyp descr' sorts) cargs ---> T, mx))
   671               (cname, map (typ_of_dtyp descr' sorts) cargs ---> T, mx))
   676                 (constrs ~~ constr_syntax')) |>
   672                 (constrs ~~ constr_syntax')) #>
   677           parent_path flat_names))
   673           parent_path flat_names)
   678             (hd descr ~~ newTs ~~ new_type_names ~~ constr_syntax);
   674             (hd descr ~~ newTs ~~ new_type_names ~~ constr_syntax);
   679 
   675 
   680     (**** introduction of axioms ****)
   676     (**** introduction of axioms ****)
   681 
   677 
   682     val rec_axs = DatatypeProp.make_primrecs new_type_names descr sorts thy2;
   678     val rec_axs = DatatypeProp.make_primrecs new_type_names descr sorts thy2;
   715     val dt_infos = map (make_dt_info descr' sorts induct reccomb_names' rec_thms)
   711     val dt_infos = map (make_dt_info descr' sorts induct reccomb_names' rec_thms)
   716       ((0 upto length (hd descr) - 1) ~~ (hd descr) ~~ case_names' ~~ case_thms ~~
   712       ((0 upto length (hd descr) - 1) ~~ (hd descr) ~~ case_names' ~~ case_thms ~~
   717         exhaustion ~~ replicate (length (hd descr)) QuickAndDirty ~~ inject ~~
   713         exhaustion ~~ replicate (length (hd descr)) QuickAndDirty ~~ inject ~~
   718           nchotomys ~~ case_congs ~~ weak_case_congs);
   714           nchotomys ~~ case_congs ~~ weak_case_congs);
   719 
   715 
   720     val simps = List.concat (distinct @ inject @ case_thms) @ size_thms @ rec_thms;
   716     val simps = flat (distinct @ inject @ case_thms) @ size_thms @ rec_thms;
   721     val split_thms = split ~~ split_asm;
   717     val split_thms = split ~~ split_asm;
   722 
   718 
   723     val thy12 =
   719     val thy12 =
   724       thy11
   720       thy11
   725       |> Theory.add_advanced_trfuns ([], [], make_case_tr' case_names' (hd descr), [])
   721       |> Theory.add_advanced_trfuns ([], [], make_case_tr' case_names' (hd descr), [])
   773     val (weak_case_congs, thy10) = DatatypeAbsProofs.prove_weak_case_congs new_type_names
   769     val (weak_case_congs, thy10) = DatatypeAbsProofs.prove_weak_case_congs new_type_names
   774       descr sorts thy9;
   770       descr sorts thy9;
   775     val (size_thms, thy11) = DatatypeAbsProofs.prove_size_thms flat_names new_type_names
   771     val (size_thms, thy11) = DatatypeAbsProofs.prove_size_thms flat_names new_type_names
   776       descr sorts reccomb_names rec_thms thy10;
   772       descr sorts reccomb_names rec_thms thy10;
   777 
   773 
   778     val dt_infos = map (make_dt_info (List.concat descr) sorts induct reccomb_names rec_thms)
   774     val dt_infos = map (make_dt_info (flat descr) sorts induct reccomb_names rec_thms)
   779       ((0 upto length (hd descr) - 1) ~~ (hd descr) ~~ case_names ~~ case_thms ~~
   775       ((0 upto length (hd descr) - 1) ~~ (hd descr) ~~ case_names ~~ case_thms ~~
   780         casedist_thms ~~ simproc_dists ~~ inject ~~ nchotomys ~~ case_congs ~~ weak_case_congs);
   776         casedist_thms ~~ simproc_dists ~~ inject ~~ nchotomys ~~ case_congs ~~ weak_case_congs);
   781 
   777 
   782     val simps = List.concat (distinct @ inject @ case_thms) @ size_thms @ rec_thms;
   778     val simps = flat (distinct @ inject @ case_thms) @ size_thms @ rec_thms;
   783 
   779 
   784     val thy12 =
   780     val thy12 =
   785       thy11
   781       thy11
   786       |> Theory.add_advanced_trfuns ([], [], make_case_tr' case_names (hd descr), [])
   782       |> Theory.add_advanced_trfuns ([], [], make_case_tr' case_names (hd descr), [])
   787       |> Theory.add_path (space_implode "_" new_type_names)
   783       |> Theory.add_path (space_implode "_" new_type_names)
   850     val dt_info = get_datatypes thy1;
   846     val dt_info = get_datatypes thy1;
   851 
   847 
   852     val (case_names_induct, case_names_exhausts) = case RuleCases.get induction
   848     val (case_names_induct, case_names_exhausts) = case RuleCases.get induction
   853      of (("1", _) :: _, _) => (mk_case_names_induct descr, mk_case_names_exhausts descr (map #1 dtnames))
   849      of (("1", _) :: _, _) => (mk_case_names_induct descr, mk_case_names_exhausts descr (map #1 dtnames))
   854       | (cases, _) => (RuleCases.case_names (map fst cases),
   850       | (cases, _) => (RuleCases.case_names (map fst cases),
   855           replicate (length ((List.filter (fn ((_, (name, _, _))) => member (op =)
   851           replicate (length ((filter (fn ((_, (name, _, _))) => member (op =)
   856             (map #1 dtnames) name) descr)))
   852             (map #1 dtnames) name) descr)))
   857             (RuleCases.case_names (map fst cases)));
   853             (RuleCases.case_names (map fst cases)));
   858     
   854     
   859 
   855 
   860     val _ = message ("Proofs for datatype(s) " ^ commas_quote new_type_names);
   856     val _ = message ("Proofs for datatype(s) " ^ commas_quote new_type_names);
   890 
   886 
   891     val dt_infos = map (make_dt_info descr sorts induction' reccomb_names rec_thms)
   887     val dt_infos = map (make_dt_info descr sorts induction' reccomb_names rec_thms)
   892       ((0 upto length descr - 1) ~~ descr ~~ case_names ~~ case_thms ~~ casedist_thms ~~
   888       ((0 upto length descr - 1) ~~ descr ~~ case_names ~~ case_thms ~~ casedist_thms ~~
   893         map FewConstrs distinct ~~ inject ~~ nchotomys ~~ case_congs ~~ weak_case_congs);
   889         map FewConstrs distinct ~~ inject ~~ nchotomys ~~ case_congs ~~ weak_case_congs);
   894 
   890 
   895     val simps = List.concat (distinct @ inject @ case_thms) @ size_thms @ rec_thms;
   891     val simps = flat (distinct @ inject @ case_thms) @ size_thms @ rec_thms;
   896 
   892 
   897     val thy11 =
   893     val thy11 =
   898       thy10
   894       thy10
   899       |> Theory.add_advanced_trfuns ([], [], make_case_tr' case_names descr, [])
   895       |> Theory.add_advanced_trfuns ([], [], make_case_tr' case_names descr, [])
   900       |> add_rules simps case_thms size_thms rec_thms inject distinct
   896       |> add_rules simps case_thms size_thms rec_thms inject distinct
   947       end) dts);
   943       end) dts);
   948 
   944 
   949     val _ = (case duplicates (op =) (map fst new_dts) @ duplicates (op =) new_type_names of
   945     val _ = (case duplicates (op =) (map fst new_dts) @ duplicates (op =) new_type_names of
   950       [] => () | dups => error ("Duplicate datatypes: " ^ commas dups));
   946       [] => () | dups => error ("Duplicate datatypes: " ^ commas dups));
   951 
   947 
   952     fun prep_dt_spec ((dts', constr_syntax, sorts, i), (tvs, tname, mx, constrs)) =
   948     fun prep_dt_spec (tvs, tname, mx, constrs) (dts', constr_syntax, sorts, i) =
   953       let
   949       let
   954         fun prep_constr ((constrs, constr_syntax', sorts'), (cname, cargs, mx')) =
   950         fun prep_constr (cname, cargs, mx') (constrs, constr_syntax', sorts') =
   955           let
   951           let
   956             val (cargs', sorts'') = Library.foldl (prep_typ tmp_thy) (([], sorts'), cargs);
   952             val (cargs', sorts'') = Library.foldl (prep_typ tmp_thy) (([], sorts'), cargs);
   957             val _ = (case foldr add_typ_tfree_names [] cargs' \\ tvs of
   953             val _ = (case fold (curry add_typ_tfree_names) cargs' [] \\ tvs of
   958                 [] => ()
   954                 [] => ()
   959               | vs => error ("Extra type variables on rhs: " ^ commas vs))
   955               | vs => error ("Extra type variables on rhs: " ^ commas vs))
   960           in (constrs @ [((if flat_names then Sign.full_name tmp_thy else
   956           in (constrs @ [((if flat_names then Sign.full_name tmp_thy else
   961                 Sign.full_name_path tmp_thy tname) (Syntax.const_name cname mx'),
   957                 Sign.full_name_path tmp_thy tname) (Syntax.const_name cname mx'),
   962                    map (dtyp_of_typ new_dts) cargs')],
   958                    map (dtyp_of_typ new_dts) cargs')],
   964           end handle ERROR msg =>
   960           end handle ERROR msg =>
   965             cat_error msg ("The error above occured in constructor " ^ cname ^
   961             cat_error msg ("The error above occured in constructor " ^ cname ^
   966               " of datatype " ^ tname);
   962               " of datatype " ^ tname);
   967 
   963 
   968         val (constrs', constr_syntax', sorts') =
   964         val (constrs', constr_syntax', sorts') =
   969           Library.foldl prep_constr (([], [], sorts), constrs)
   965           fold prep_constr constrs ([], [], sorts)
   970 
   966 
   971       in
   967       in
   972         case duplicates (op =) (map fst constrs') of
   968         case duplicates (op =) (map fst constrs') of
   973            [] =>
   969            [] =>
   974              (dts' @ [(i, (Sign.full_name tmp_thy (Syntax.type_name tname mx),
   970              (dts' @ [(i, (Sign.full_name tmp_thy (Syntax.type_name tname mx),
   976               constr_syntax @ [constr_syntax'], sorts', i + 1)
   972               constr_syntax @ [constr_syntax'], sorts', i + 1)
   977          | dups => error ("Duplicate constructors " ^ commas dups ^
   973          | dups => error ("Duplicate constructors " ^ commas dups ^
   978              " in datatype " ^ tname)
   974              " in datatype " ^ tname)
   979       end;
   975       end;
   980 
   976 
   981     val (dts', constr_syntax, sorts', i) = Library.foldl prep_dt_spec (([], [], [], 0), dts);
   977     val (dts', constr_syntax, sorts', i) = fold prep_dt_spec dts ([], [], [], 0);
   982     val sorts = sorts' @ (map (rpair (Sign.defaultS tmp_thy)) (tyvars \\ map fst sorts'));
   978     val sorts = sorts' @ (map (rpair (Sign.defaultS tmp_thy)) (tyvars \\ map fst sorts'));
   983     val dt_info = get_datatypes thy;
   979     val dt_info = get_datatypes thy;
   984     val (descr, _) = unfold_datatypes tmp_thy dts' sorts dt_info dts' i;
   980     val (descr, _) = unfold_datatypes tmp_thy dts' sorts dt_info dts' i;
   985     val _ = check_nonempty descr handle (exn as Datatype_Empty s) =>
   981     val _ = check_nonempty descr handle (exn as Datatype_Empty s) =>
   986       if err then error ("Nonemptiness check failed for datatype " ^ s)
   982       if err then error ("Nonemptiness check failed for datatype " ^ s)
   987       else raise exn;
   983       else raise exn;
   988 
   984 
   989     val descr' = List.concat descr;
   985     val descr' = flat descr;
   990     val case_names_induct = mk_case_names_induct descr';
   986     val case_names_induct = mk_case_names_induct descr';
   991     val case_names_exhausts = mk_case_names_exhausts descr' (map #1 new_dts);
   987     val case_names_exhausts = mk_case_names_exhausts descr' (map #1 new_dts);
   992   in
   988   in
   993     (if (!quick_and_dirty) then add_datatype_axm else add_datatype_def)
   989     (if (!quick_and_dirty) then add_datatype_axm else add_datatype_def)
   994       flat_names new_type_names descr sorts types_syntax constr_syntax dt_info
   990       flat_names new_type_names descr sorts types_syntax constr_syntax dt_info