src/HOL/Tools/record_package.ML
changeset 12247 9b029789aff6
parent 12129 964f5ffe13d0
child 12255 93d4972238c7
equal deleted inserted replaced
12246:fdb65a05fca8 12247:9b029789aff6
    63 fun message s = if ! quiet_mode then () else writeln s;
    63 fun message s = if ! quiet_mode then () else writeln s;
    64 
    64 
    65 
    65 
    66 (* fundamental syntax *)
    66 (* fundamental syntax *)
    67 
    67 
       
    68 fun prune n xs = Library.drop (n, xs);
       
    69 
    68 fun prefix_base s = NameSpace.map_base (fn bname => s ^ bname);
    70 fun prefix_base s = NameSpace.map_base (fn bname => s ^ bname);
    69 
    71 
    70 val Trueprop = HOLogic.mk_Trueprop;
    72 val Trueprop = HOLogic.mk_Trueprop;
    71 fun All xs t = Term.list_all_free (xs, t);
    73 fun All xs t = Term.list_all_free (xs, t);
    72 
    74 
   319 
   321 
   320 type record_info =
   322 type record_info =
   321  {args: (string * sort) list,
   323  {args: (string * sort) list,
   322   parent: (typ list * string) option,
   324   parent: (typ list * string) option,
   323   fields: (string * typ) list,
   325   fields: (string * typ) list,
   324   simps: thm list, induct: thm, cases: thm};
   326   field_inducts: thm list,
   325 
   327   field_cases: thm list,
   326 fun make_record_info args parent fields simps induct cases =
   328   simps: thm list};
   327  {args = args, parent = parent, fields = fields, simps = simps,
   329 
   328   induct = induct, cases = cases}: record_info;
   330 fun make_record_info args parent fields field_inducts field_cases simps =
       
   331  {args = args, parent = parent, fields = fields, field_inducts = field_inducts,
       
   332   field_cases = field_cases, simps = simps}: record_info;
   329 
   333 
   330 type parent_info =
   334 type parent_info =
   331  {name: string,
   335  {name: string,
   332   fields: (string * typ) list,
   336   fields: (string * typ) list,
   333   simps: thm list, induct: thm, cases: thm};
   337   field_inducts: thm list,
   334 
   338   field_cases: thm list,
   335 fun make_parent_info name fields simps induct cases =
   339   simps: thm list};
   336  {name = name, fields = fields, simps = simps,
   340 
   337   induct = induct, cases = cases}: parent_info;
   341 fun make_parent_info name fields field_inducts field_cases simps =
   338 
   342  {name = name, fields = fields, field_inducts = field_inducts,
       
   343   field_cases = field_cases, simps = simps}: parent_info;
   339 
   344 
   340 
   345 
   341 (* data kind 'HOL/records' *)
   346 (* data kind 'HOL/records' *)
   342 
   347 
   343 type record_data =
   348 type record_data =
   391 
   396 
   392       fun pretty_field (c, T) = Pretty.block
   397       fun pretty_field (c, T) = Pretty.block
   393         [Pretty.str (Sign.cond_extern sg Sign.constK c), Pretty.str " ::",
   398         [Pretty.str (Sign.cond_extern sg Sign.constK c), Pretty.str " ::",
   394           Pretty.brk 1, Pretty.quote (prt_typ T)];
   399           Pretty.brk 1, Pretty.quote (prt_typ T)];
   395 
   400 
   396       fun pretty_record (name, {args, parent, fields, simps = _, induct = _, cases = _}) =
   401       fun pretty_record (name, {args, parent, fields, ...}: record_info) =
   397         Pretty.block (Pretty.fbreaks (Pretty.block
   402         Pretty.block (Pretty.fbreaks (Pretty.block
   398           [prt_typ (Type (name, map TFree args)), Pretty.str " = "] ::
   403           [prt_typ (Type (name, map TFree args)), Pretty.str " = "] ::
   399           pretty_parent parent @ map pretty_field fields));
   404           pretty_parent parent @ map pretty_field fields));
   400     in map pretty_record (Symtab.dest recs) |> Pretty.chunks |> Pretty.writeln end;
   405     in map pretty_record (Symtab.dest recs) |> Pretty.chunks |> Pretty.writeln end;
   401 end;
   406 end;
   450   in RecordsData.put data thy end;
   455   in RecordsData.put data thy end;
   451 
   456 
   452 
   457 
   453 (* parent records *)
   458 (* parent records *)
   454 
   459 
   455 fun inst_record thy (types, name) =
   460 fun add_parents thy None parents = parents
   456   let
   461   | add_parents thy (Some (types, name)) parents =
   457     val sign = Theory.sign_of thy;
   462       let
   458     fun err msg = error (msg ^ " parent record " ^ quote name);
   463         val sign = Theory.sign_of thy;
   459 
   464         fun err msg = error (msg ^ " parent record " ^ quote name);
   460     val {args, parent, fields, simps, induct, cases} =
   465     
   461       (case get_record thy name of Some info => info | None => err "Unknown");
   466         val {args, parent, fields, field_inducts, field_cases, simps} =
   462     val _ = if length types <> length args then err "Bad number of arguments for" else ();
   467           (case get_record thy name of Some info => info | None => err "Unknown");
   463 
   468         val _ = if length types <> length args then err "Bad number of arguments for" else ();
   464     fun bad_inst ((x, S), T) =
   469     
   465       if Sign.of_sort sign (T, S) then None else Some x
   470         fun bad_inst ((x, S), T) =
   466     val bads = mapfilter bad_inst (args ~~ types);
   471           if Sign.of_sort sign (T, S) then None else Some x
   467 
   472         val bads = mapfilter bad_inst (args ~~ types);
   468     val inst = map fst args ~~ types;
   473     
   469     val subst = Term.map_type_tfree (fn (x, _) => the (assoc (inst, x)));
   474         val inst = map fst args ~~ types;
   470   in
   475         val subst = Term.map_type_tfree (fn (x, _) => the (assoc (inst, x)));
   471     if not (null bads) then
   476         val parent' = apsome (apfst (map subst)) parent;
   472       err ("Ill-sorted instantiation of " ^ commas bads ^ " in")
   477         val fields' = map (apsnd subst) fields;
   473     else (apsome (apfst (map subst)) parent, map (apsnd subst) fields, simps, induct, cases)
   478       in
   474   end;
   479         if not (null bads) then
   475 
   480           err ("Ill-sorted instantiation of " ^ commas bads ^ " in")
   476 fun add_parents thy (None, parents) = parents
   481         else add_parents thy parent'
   477   | add_parents thy (Some (types, name), parents) =
   482           (make_parent_info name fields' field_inducts field_cases simps :: parents)
   478       let val (parent, fields, simps, induct, cases) = inst_record thy (types, name)
   483       end;
   479       in add_parents thy (parent, make_parent_info name fields simps induct cases :: parents) end;
       
   480 
   484 
   481 
   485 
   482 
   486 
   483 (** record simproc **)
   487 (** record simproc **)
   484 
   488 
   635 (* record_definition *)
   639 (* record_definition *)
   636 
   640 
   637 fun record_definition (args, bname) parent (parents: parent_info list) bfields thy =
   641 fun record_definition (args, bname) parent (parents: parent_info list) bfields thy =
   638   let
   642   let
   639     val sign = Theory.sign_of thy;
   643     val sign = Theory.sign_of thy;
       
   644 
       
   645     val alphas = map fst args;
       
   646     val name = Sign.full_name sign bname;
   640     val full = Sign.full_name_path sign bname;
   647     val full = Sign.full_name_path sign bname;
   641     val base = Sign.base_name;
   648     val base = Sign.base_name;
   642 
   649 
   643 
   650 
   644     (* basic components *)
   651     (* basic components *)
   645 
   652 
   646     val alphas = map fst args;
   653     val ancestry = map (length o flat o map #fields) (Library.prefixes1 parents);
   647     val name = Sign.full_name sign bname;       (*not made part of record name space!*)
       
   648 
       
   649     val previous = if null parents then None else Some (last_elem parents);
       
   650 
   654 
   651     val parent_fields = flat (map #fields parents);
   655     val parent_fields = flat (map #fields parents);
   652     val parent_names = map fst parent_fields;
   656     val parent_names = map fst parent_fields;
   653     val parent_types = map snd parent_fields;
   657     val parent_types = map snd parent_fields;
   654     val parent_len = length parent_fields;
   658     val parent_len = length parent_fields;
   685     val idxs = 0 upto (len - 1);
   689     val idxs = 0 upto (len - 1);
   686 
   690 
   687     val parentT = if null parent_fields then [] else [mk_recordT (parent_fields, HOLogic.unitT)];
   691     val parentT = if null parent_fields then [] else [mk_recordT (parent_fields, HOLogic.unitT)];
   688     val r_parent = if null parent_fields then [] else [Free (rN, hd parentT)];
   692     val r_parent = if null parent_fields then [] else [Free (rN, hd parentT)];
   689 
   693 
   690     val rec_schemeT = mk_recordT (all_fields, moreT);
   694     fun rec_schemeT n = mk_recordT (prune n all_fields, moreT);
   691     val rec_scheme = mk_record (all_named_vars, more);
   695     fun rec_scheme n = mk_record (prune n all_named_vars, more);
   692     val recT = mk_recordT (all_fields, HOLogic.unitT);
   696     fun recT n = mk_recordT (prune n all_fields, HOLogic.unitT);
   693     val rec_ = mk_record (all_named_vars, HOLogic.unit);
   697     fun rec_ n = mk_record (prune n all_named_vars, HOLogic.unit);    
   694     val r_scheme = Free (rN, rec_schemeT);
   698     fun r_scheme n = Free (rN, rec_schemeT n);
   695     val r = Free (rN, recT);
   699     fun r n = Free (rN, recT n);
   696 
   700 
   697 
   701 
   698     (* prepare print translation functions *)
   702     (* prepare print translation functions *)
   699 
   703 
   700     val field_tr's =
   704     val field_tr's =
   701       print_translation (distinct (flat (map NameSpace.accesses (full_moreN :: names))));
   705       print_translation (distinct (flat (map NameSpace.accesses (full_moreN :: names))));
   702 
   706 
   703 
   707 
   704     (* prepare declarations *)
   708     (* prepare declarations *)
   705 
   709 
   706     val sel_decls = map (mk_selC rec_schemeT) bfields @
   710     val sel_decls = map (mk_selC (rec_schemeT 0)) bfields @
   707       [mk_moreC rec_schemeT (moreN, moreT)];
   711       [mk_moreC (rec_schemeT 0) (moreN, moreT)];
   708     val update_decls = map (mk_updateC rec_schemeT) bfields @
   712     val update_decls = map (mk_updateC (rec_schemeT 0)) bfields @
   709       [mk_more_updateC rec_schemeT (moreN, moreT)];
   713       [mk_more_updateC (rec_schemeT 0) (moreN, moreT)];
   710     val make_decl = (makeN, parentT ---> types ---> recT);
   714     val make_decl = (makeN, parentT ---> types ---> recT 0);
   711     val extend_decl = (extendN, recT --> moreT --> rec_schemeT);
   715     val extend_decl = (extendN, recT 0 --> moreT --> rec_schemeT 0);
   712     val truncate_decl = (truncateN, rec_schemeT --> recT);
   716     val truncate_decl = (truncateN, rec_schemeT 0 --> recT 0);
   713 
   717 
   714 
   718 
   715     (* prepare definitions *)
   719     (* prepare definitions *)
   716 
   720 
   717     (*record (scheme) type abbreviation*)
   721     (*record (scheme) type abbreviation*)
   718     val recordT_specs =
   722     val recordT_specs =
   719       [(suffix schemeN bname, alphas @ [zeta], rec_schemeT, Syntax.NoSyn),
   723       [(suffix schemeN bname, alphas @ [zeta], rec_schemeT 0, Syntax.NoSyn),
   720         (bname, alphas, recT, Syntax.NoSyn)];
   724         (bname, alphas, recT 0, Syntax.NoSyn)];
   721 
   725 
   722     (*selectors*)
   726     (*selectors*)
   723     fun mk_sel_spec (i, c) =
   727     fun mk_sel_spec (i, c) =
   724       mk_sel r_scheme c :== mk_fst (funpow i mk_snd (parent_more r_scheme));
   728       mk_sel (r_scheme 0) c :== mk_fst (funpow i mk_snd (parent_more (r_scheme 0)));
   725     val sel_specs =
   729     val sel_specs =
   726       ListPair.map mk_sel_spec (idxs, names) @
   730       ListPair.map mk_sel_spec (idxs, names) @
   727         [more_part r_scheme :== funpow len mk_snd (parent_more r_scheme)];
   731         [more_part (r_scheme 0) :== funpow len mk_snd (parent_more (r_scheme 0))];
   728 
   732 
   729     (*updates*)
   733     (*updates*)
   730     val all_sels = mk_named_sels all_names r_scheme;
   734     val all_sels = mk_named_sels all_names (r_scheme 0);
   731     fun mk_upd_spec (i, (c, x)) =
   735     fun mk_upd_spec (i, (c, x)) =
   732       mk_update r_scheme (c, x) :==
   736       mk_update (r_scheme 0) (c, x) :==
   733         mk_record (nth_update (c, x) (parent_len + i, all_sels), more_part r_scheme)
   737         mk_record (nth_update (c, x) (parent_len + i, all_sels), more_part (r_scheme 0))
   734     val update_specs =
   738     val update_specs =
   735       ListPair.map mk_upd_spec (idxs, named_vars) @
   739       ListPair.map mk_upd_spec (idxs, named_vars) @
   736         [more_part_update r_scheme more :== mk_record (all_sels, more)];
   740         [more_part_update (r_scheme 0) more :== mk_record (all_sels, more)];
   737 
   741 
   738     (*derived operations*)
   742     (*derived operations*)
   739     val make_spec = Const (full makeN, parentT ---> types ---> recT) $$ r_parent $$ vars :==
   743     val make_spec = Const (full makeN, parentT ---> types ---> recT 0) $$ r_parent $$ vars :==
   740       mk_record (flat (map (mk_named_sels parent_names) r_parent) @ named_vars, HOLogic.unit);
   744       mk_record (flat (map (mk_named_sels parent_names) r_parent) @ named_vars, HOLogic.unit);
   741     val extend_spec = Const (full extendN, recT --> moreT --> rec_schemeT) $ r $ more :==
   745     val extend_spec = Const (full extendN, recT 0 --> moreT --> rec_schemeT 0) $ r 0 $ more :==
   742       mk_record (mk_named_sels all_names r, more);
   746       mk_record (mk_named_sels all_names (r 0), more);
   743     val truncate_spec = Const (full truncateN, rec_schemeT --> recT) $ r_scheme :==
   747     val truncate_spec = Const (full truncateN, rec_schemeT 0 --> recT 0) $ r_scheme 0 :==
   744       mk_record (all_sels, HOLogic.unit);
   748       mk_record (all_sels, HOLogic.unit);
   745 
   749 
   746 
   750 
   747     (* prepare propositions *)
   751     (* prepare propositions *)
   748 
   752 
   749     (*selectors*)
   753     (*selectors*)
   750     val sel_props =
   754     val sel_props =
   751       map (fn (c, x) => mk_sel rec_scheme c === x) named_vars @
   755       map (fn (c, x) => mk_sel (rec_scheme 0) c === x) named_vars @
   752         [more_part rec_scheme === more];
   756         [more_part (rec_scheme 0) === more];
   753 
   757 
   754     (*updates*)
   758     (*updates*)
   755     fun mk_upd_prop (i, (c, T)) =
   759     fun mk_upd_prop (i, (c, T)) =
   756       let val x' = Free (variant all_xs (base c ^ "'"), T) in
   760       let val x' = Free (variant all_xs (base c ^ "'"), T) in
   757         mk_update rec_scheme (c, x') ===
   761         mk_update (rec_scheme 0) (c, x') ===
   758           mk_record (nth_update (c, x') (parent_len + i, all_named_vars), more)
   762           mk_record (nth_update (c, x') (parent_len + i, all_named_vars), more)
   759       end;
   763       end;
   760     val update_props =
   764     val update_props =
   761       ListPair.map mk_upd_prop (idxs, fields) @
   765       ListPair.map mk_upd_prop (idxs, fields) @
   762         let val more' = Free (variant all_xs (moreN ^ "'"), moreT)
   766         let val more' = Free (variant all_xs (moreN ^ "'"), moreT)
   763         in [more_part_update rec_scheme more' === mk_record (all_named_vars, more')] end;
   767         in [more_part_update (rec_scheme 0) more' === mk_record (all_named_vars, more')] end;
   764 
   768 
   765     (*equality*)
   769     (*equality*)
   766     fun mk_sel_eq (t, T) =
   770     fun mk_sel_eq (t, T) =
   767       let val t' = Term.abstract_over (r_scheme, t)
   771       let val t' = Term.abstract_over (r_scheme 0, t)
   768       in Trueprop (HOLogic.eq_const T $ Term.incr_boundvars 1 t' $ t') end;
   772       in Trueprop (HOLogic.eq_const T $ Term.incr_boundvars 1 t' $ t') end;
   769     val sel_eqs =
   773     val sel_eqs = map2 mk_sel_eq
   770       map2 mk_sel_eq (map (mk_sel r_scheme) all_names @ [more_part r_scheme], all_types @ [moreT]);
   774       (map (mk_sel (r_scheme 0)) all_names @ [more_part (r_scheme 0)], all_types @ [moreT]);
   771     val equality_prop =
   775     val equality_prop =
   772       Term.all rec_schemeT $ (Abs ("r", rec_schemeT,
   776       Term.all (rec_schemeT 0) $ (Abs ("r", rec_schemeT 0,
   773         Term.all rec_schemeT $ (Abs ("r'", rec_schemeT,
   777         Term.all (rec_schemeT 0) $ (Abs ("r'", rec_schemeT 0,
   774           Logic.list_implies (sel_eqs,
   778           Logic.list_implies (sel_eqs,
   775             Trueprop (HOLogic.eq_const rec_schemeT $ Bound 1 $ Bound 0))))));
   779             Trueprop (HOLogic.eq_const (rec_schemeT 0) $ Bound 1 $ Bound 0))))));
   776 
   780 
   777     (*induct*)
   781     (*induct*)
   778     val P = Free ("P", rec_schemeT --> HOLogic.boolT);
   782     fun induct_scheme_prop n =
   779     val P' = Free ("P", recT --> HOLogic.boolT);
   783       let val P = Free ("P", rec_schemeT n --> HOLogic.boolT) in
   780     val induct_scheme_assm = All (all_xs_more ~~ all_types_more) (Trueprop (P $ rec_scheme));
   784         (All (prune n all_xs_more ~~ prune n all_types_more)
   781     val induct_scheme_concl = Trueprop (P $ r_scheme);
   785           (Trueprop (P $ rec_scheme n)), Trueprop (P $ r_scheme n))
   782     val induct_assm = All (all_xs ~~ all_types) (Trueprop (P' $ rec_));
   786       end;
   783     val induct_concl = Trueprop (P' $ r);
   787     fun induct_prop n =
       
   788       let val P = Free ("P", recT n --> HOLogic.boolT) in
       
   789         (All (prune n all_xs ~~ prune n all_types) (Trueprop (P $ rec_ n)), Trueprop (P $ r n))
       
   790       end;
   784 
   791 
   785     (*cases*)
   792     (*cases*)
   786     val C = Trueprop (Free (variant all_xs_more "C", HOLogic.boolT));
   793     val C = Trueprop (Free (variant all_xs_more "C", HOLogic.boolT));
   787     val cases_scheme_prop =
   794     fun cases_scheme_prop n =
   788       All (all_xs_more ~~ all_types_more) ((r_scheme === rec_scheme) ==> C) ==> C;
   795       All (prune n all_xs_more ~~ prune n all_types_more)
   789     val cases_prop = All (all_xs ~~ all_types) ((r === rec_) ==> C) ==> C;
   796         ((r_scheme n === rec_scheme n) ==> C) ==> C;
       
   797     fun cases_prop n =
       
   798       All (prune n all_xs ~~ prune n all_types) ((r n === rec_ n) ==> C) ==> C;
   790 
   799 
   791 
   800 
   792     (* 1st stage: fields_thy *)
   801     (* 1st stage: fields_thy *)
   793 
   802 
   794     val (fields_thy, field_simps, field_injects, field_splits, field_inducts, field_cases) =
   803     val (fields_thy, field_simps, field_injects, field_splits, field_inducts, field_cases) =
   795       thy
   804       thy
   796       |> Theory.add_path bname
   805       |> Theory.add_path bname
   797       |> field_definitions fields names xs alphas zeta moreT more vars named_vars;
   806       |> field_definitions fields names xs alphas zeta moreT more vars named_vars;
       
   807 
       
   808     val all_field_inducts = flat (map #field_inducts parents) @ field_inducts;
       
   809     val all_field_cases = flat (map #field_cases parents) @ field_cases;
   798 
   810 
   799     val named_splits = map2 (fn (c, th) => (suffix field_typeN c, th)) (names, field_splits);
   811     val named_splits = map2 (fn (c, th) => (suffix field_typeN c, th)) (names, field_splits);
   800 
   812 
   801 
   813 
   802     (* 2nd stage: defs_thy *)
   814     (* 2nd stage: defs_thy *)
   813       |> (PureThy.add_defs_i false o map Thm.no_attributes) sel_specs
   825       |> (PureThy.add_defs_i false o map Thm.no_attributes) sel_specs
   814       |>>> (PureThy.add_defs_i false o map Thm.no_attributes) update_specs
   826       |>>> (PureThy.add_defs_i false o map Thm.no_attributes) update_specs
   815       |>>> (PureThy.add_defs_i false o map Thm.no_attributes)
   827       |>>> (PureThy.add_defs_i false o map Thm.no_attributes)
   816         [make_spec, extend_spec, truncate_spec];
   828         [make_spec, extend_spec, truncate_spec];
   817 
   829 
   818     val defs_sg = Theory.sign_of defs_thy;
       
   819 
       
   820 
   830 
   821     (* 3rd stage: thms_thy *)
   831     (* 3rd stage: thms_thy *)
   822 
   832 
   823     val prove_standard = Tactic.prove_standard defs_sg;
   833     val prove_standard = Tactic.prove_standard (Theory.sign_of defs_thy);
   824     fun prove_simp simps =
   834     fun prove_simp simps =
   825       let val tac = simp_all_tac HOL_basic_ss simps
   835       let val tac = simp_all_tac HOL_basic_ss simps
   826       in fn prop => prove_standard [] [] prop (K tac) end;
   836       in fn prop => prove_standard [] [] prop (K tac) end;
   827 
   837 
   828     val parent_simps = flat (map #simps parents);
   838     val parent_simps = flat (map #simps parents);
   829     val sel_convs = map (prove_simp (parent_simps @ sel_defs @ field_simps)) sel_props;
   839     val sel_convs = map (prove_simp (parent_simps @ sel_defs @ field_simps)) sel_props;
   830     val update_convs = map (prove_simp (parent_simps @ update_defs @ sel_convs)) update_props;
   840     val update_convs = map (prove_simp (parent_simps @ update_defs @ sel_convs)) update_props;
   831 
   841 
   832     val induct_scheme = prove_standard [] [induct_scheme_assm] induct_scheme_concl (fn prems =>
   842     fun induct_scheme n =
   833         (case previous of Some {induct, ...} => res_inst_tac [(rN, rN)] induct 1
   843       let val (assm, concl) = induct_scheme_prop n in
   834         | None => all_tac)
   844         prove_standard [] [assm] concl (fn prems =>
   835         THEN EVERY (map (fn rule => try_param_tac "p" rN rule 1) field_inducts)
   845           EVERY (map (fn rule => try_param_tac "p" rN rule 1) (prune n all_field_inducts))
   836         THEN resolve_tac prems 1);
   846           THEN resolve_tac prems 1)
   837 
   847       end;
   838     val induct = prove_standard [] [induct_assm] induct_concl (fn prems =>
   848 
   839         res_inst_tac [(rN, rN)] induct_scheme 1
   849     fun cases_scheme n =
   840         THEN try_param_tac "x" "more" unit_induct 1
   850       prove_standard [] [] (cases_scheme_prop n) (fn _ =>
   841         THEN resolve_tac prems 1);
   851         EVERY (map (fn rule => try_param_tac "p" rN rule 1) (prune n all_field_cases))
   842 
       
   843     val cases_scheme = prove_standard [] [] cases_scheme_prop (fn _ =>
       
   844         (case previous of Some {cases, ...} => try_param_tac rN rN cases 1
       
   845         | None => all_tac)
       
   846         THEN EVERY (map (fn rule => try_param_tac "p" rN rule 1) field_cases)
       
   847         THEN simp_all_tac HOL_basic_ss []);
   852         THEN simp_all_tac HOL_basic_ss []);
   848 
   853 
   849     val cases = prove_standard [] [] cases_prop (fn _ =>
   854     val induct_scheme0 = induct_scheme 0;
   850         res_inst_tac [(rN, rN)] cases_scheme 1
   855     val cases_scheme0 = cases_scheme 0;
   851         THEN simp_all_tac HOL_basic_ss [unit_all_eq1]);
   856     val more_induct_scheme = map induct_scheme ancestry;
   852 
   857     val more_cases_scheme = map cases_scheme ancestry;
   853     val (thms_thy, ([sel_convs', update_convs', sel_defs', update_defs', _],
   858 
   854         [induct_scheme', induct', cases_scheme', cases'])) =
   859     val case_names = RuleCases.case_names [fieldsN];
       
   860 
       
   861     val (thms_thy, (([sel_convs', update_convs', sel_defs', update_defs', _],
       
   862         [induct_scheme', cases_scheme']), [more_induct_scheme', more_cases_scheme'])) =
   855       defs_thy
   863       defs_thy
   856       |> (PureThy.add_thmss o map Thm.no_attributes)
   864       |> (PureThy.add_thmss o map Thm.no_attributes)
   857        [("select_convs", sel_convs),
   865        [("select_convs", sel_convs),
   858         ("update_convs", update_convs),
   866         ("update_convs", update_convs),
   859         ("select_defs", sel_defs),
   867         ("select_defs", sel_defs),
   860         ("update_defs", update_defs),
   868         ("update_defs", update_defs),
   861         ("derived_defs", derived_defs)]
   869         ("derived_defs", derived_defs)]
   862       |>>> PureThy.add_thms
   870       |>>> PureThy.add_thms
   863        [(("induct_scheme", induct_scheme), [RuleCases.case_names [fieldsN],
   871        [(("induct_scheme", induct_scheme0),
   864           InductAttrib.induct_type_global (suffix schemeN name)]),
   872          [case_names, InductAttrib.induct_type_global (suffix schemeN name)]),
   865         (("induct", induct), [RuleCases.case_names [fieldsN],
   873         (("cases_scheme", cases_scheme0),
   866           InductAttrib.induct_type_global name]),
   874          [case_names, InductAttrib.cases_type_global (suffix schemeN name)])]
   867         (("cases_scheme", cases_scheme), [RuleCases.case_names [fieldsN],
   875       |>>> (PureThy.add_thmss o map Thm.no_attributes)
   868           InductAttrib.cases_type_global (suffix schemeN name)]),
   876         [("more_induct_scheme", more_induct_scheme),
   869         (("cases", cases), [RuleCases.case_names [fieldsN],
   877          ("more_cases_scheme", more_cases_scheme)];
   870           InductAttrib.cases_type_global name])];
   878 
   871 
   879 
   872     val equality = Tactic.prove_standard (Theory.sign_of thms_thy) [] [] equality_prop (fn _ =>
   880     (* 4th stage: more_thms_thy *)
       
   881 
       
   882     val prove_standard = Tactic.prove_standard (Theory.sign_of thms_thy);
       
   883 
       
   884     fun induct (n, scheme) =
       
   885       let val (assm, concl) = induct_prop n in
       
   886         prove_standard [] [assm] concl (fn prems =>
       
   887           res_inst_tac [(rN, rN)] scheme 1
       
   888           THEN try_param_tac "x" "more" unit_induct 1
       
   889           THEN resolve_tac prems 1)
       
   890       end;
       
   891 
       
   892     fun cases (n, scheme) =
       
   893       prove_standard [] [] (cases_prop n) (fn _ =>
       
   894         res_inst_tac [(rN, rN)] scheme 1
       
   895         THEN simp_all_tac HOL_basic_ss [unit_all_eq1]);
       
   896 
       
   897     val induct0 = induct (0, induct_scheme');
       
   898     val cases0 = cases (0, cases_scheme');
       
   899     val more_induct = map induct (ancestry ~~ more_induct_scheme');
       
   900     val more_cases = map cases (ancestry ~~ more_cases_scheme');
       
   901 
       
   902     val equality = prove_standard [] [] equality_prop (fn _ =>
   873       fn st => let val [r, r'] = map #1 (rev (Tactic.innermost_params 1 st)) in
   903       fn st => let val [r, r'] = map #1 (rev (Tactic.innermost_params 1 st)) in
   874         st |> (res_inst_tac [(rN, r)] cases_scheme' 1
   904         st |> (res_inst_tac [(rN, r)] cases_scheme' 1
   875         THEN res_inst_tac [(rN, r')] cases_scheme' 1
   905         THEN res_inst_tac [(rN, r')] cases_scheme' 1
   876         THEN simp_all_tac HOL_basic_ss (parent_simps @ sel_convs))
   906         THEN simp_all_tac HOL_basic_ss (parent_simps @ sel_convs))
   877       end);
   907       end);
   878 
   908 
   879     val (thms_thy', [equality']) =
   909     val (more_thms_thy, [_, _, equality']) =
   880       thms_thy |> PureThy.add_thms [(("equality", equality), [Classical.xtra_intro_global])];
   910       thms_thy |> PureThy.add_thms
       
   911        [(("induct", induct0), [case_names, InductAttrib.induct_type_global name]),
       
   912         (("cases", cases0), [case_names, InductAttrib.cases_type_global name]),
       
   913         (("equality", equality), [Classical.xtra_intro_global])]
       
   914       |>> (#1 oo (PureThy.add_thmss o map Thm.no_attributes))
       
   915         [("more_induct", more_induct),
       
   916          ("more_cases", more_cases)];
   881 
   917 
   882     val simps = sel_convs' @ update_convs' @ [equality'];
   918     val simps = sel_convs' @ update_convs' @ [equality'];
   883     val iffs = field_injects;
   919     val iffs = field_injects;
   884 
   920 
   885     val thms_thy'' =
   921     val more_thms_thy' =
   886       thms_thy' |> (#1 oo PureThy.add_thmss)
   922       more_thms_thy |> (#1 oo PureThy.add_thmss)
   887         [(("simps", simps), [Simplifier.simp_add_global]),
   923         [(("simps", simps), [Simplifier.simp_add_global]),
   888          (("iffs", iffs), [iff_add_global])];
   924          (("iffs", iffs), [iff_add_global])];
   889 
   925 
   890 
   926 
   891     (* 4th stage: final_thy *)
   927     (* 5th stage: final_thy *)
   892 
   928 
   893     val final_thy =
   929     val final_thy =
   894       thms_thy''
   930       more_thms_thy'
   895       |> put_record name (make_record_info args parent fields (field_simps @ simps)
   931       |> put_record name (make_record_info args parent fields field_inducts field_cases
   896           induct_scheme' cases_scheme')
   932         (field_simps @ simps))
   897       |> put_sel_upd (names @ [full_moreN]) (field_simps @ sel_defs' @ update_defs')
   933       |> put_sel_upd (names @ [full_moreN]) (field_simps @ sel_defs' @ update_defs')
   898       |> Theory.parent_path;
   934       |> Theory.parent_path;
   899 
   935 
   900   in (final_thy, {simps = simps, iffs = iffs}) end;
   936   in (final_thy, {simps = simps, iffs = iffs}) end;
   901 
   937 
   939 
   975 
   940     fun prep_inst T = snd (cert_typ sign ([], T));
   976     fun prep_inst T = snd (cert_typ sign ([], T));
   941 
   977 
   942     val parent = apsome (apfst (map prep_inst) o prep_raw_parent sign) raw_parent
   978     val parent = apsome (apfst (map prep_inst) o prep_raw_parent sign) raw_parent
   943       handle ERROR => error ("The error(s) above in parent record specification");
   979       handle ERROR => error ("The error(s) above in parent record specification");
   944     val parents = add_parents thy (parent, []);
   980     val parents = add_parents thy parent [];
   945 
   981 
   946     val init_env =
   982     val init_env =
   947       (case parent of
   983       (case parent of
   948         None => []
   984         None => []
   949       | Some (types, _) => foldr Term.add_typ_tfrees (types, []));
   985       | Some (types, _) => foldr Term.add_typ_tfrees (types, []));