src/HOL/Tools/inductive_package.ML
changeset 7710 bf8cb3fc5d64
parent 7349 228b711ad68c
child 7798 42e94b618f34
equal deleted inserted replaced
7709:545637744a85 7710:bf8cb3fc5d64
    34   val unify_consts: Sign.sg -> term list -> term list -> term list * term list
    34   val unify_consts: Sign.sg -> term list -> term list -> term list * term list
    35   val get_inductive: theory -> string ->
    35   val get_inductive: theory -> string ->
    36     {names: string list, coind: bool} * {defs: thm list, elims: thm list, raw_induct: thm,
    36     {names: string list, coind: bool} * {defs: thm list, elims: thm list, raw_induct: thm,
    37       induct: thm, intrs: thm list, mk_cases: string -> thm, mono: thm, unfold: thm}
    37       induct: thm, intrs: thm list, mk_cases: string -> thm, mono: thm, unfold: thm}
    38   val print_inductives: theory -> unit
    38   val print_inductives: theory -> unit
       
    39   val mono_add_global: theory attribute
       
    40   val mono_del_global: theory attribute
       
    41   val get_monos: theory -> thm list
    39   val add_inductive_i: bool -> bool -> bstring -> bool -> bool -> bool -> term list ->
    42   val add_inductive_i: bool -> bool -> bstring -> bool -> bool -> bool -> term list ->
    40     theory attribute list -> ((bstring * term) * theory attribute list) list ->
    43     theory attribute list -> ((bstring * term) * theory attribute list) list ->
    41       thm list -> thm list -> theory -> theory *
    44       thm list -> thm list -> theory -> theory *
    42       {defs: thm list, elims: thm list, raw_induct: thm, induct: thm,
    45       {defs: thm list, elims: thm list, raw_induct: thm, induct: thm,
    43        intrs: thm list, mk_cases: string -> thm, mono: thm, unfold: thm}
    46        intrs: thm list, mk_cases: string -> thm, mono: thm, unfold: thm}
    53   val setup: (theory -> theory) list
    56   val setup: (theory -> theory) list
    54 end;
    57 end;
    55 
    58 
    56 structure InductivePackage: INDUCTIVE_PACKAGE =
    59 structure InductivePackage: INDUCTIVE_PACKAGE =
    57 struct
    60 struct
       
    61 
       
    62 (*** theory data ***)
       
    63 
       
    64 (* data kind 'HOL/inductive' *)
       
    65 
       
    66 type inductive_info =
       
    67   {names: string list, coind: bool} * {defs: thm list, elims: thm list, raw_induct: thm,
       
    68     induct: thm, intrs: thm list, mk_cases: string -> thm, mono: thm, unfold: thm};
       
    69 
       
    70 structure InductiveArgs =
       
    71 struct
       
    72   val name = "HOL/inductive";
       
    73   type T = inductive_info Symtab.table * thm list;
       
    74 
       
    75   val empty = (Symtab.empty, []);
       
    76   val copy = I;
       
    77   val prep_ext = I;
       
    78   fun merge ((tab1, monos1), (tab2, monos2)) = (Symtab.merge (K true) (tab1, tab2),
       
    79     Library.generic_merge Thm.eq_thm I I monos1 monos2);
       
    80 
       
    81   fun print sg (tab, monos) =
       
    82     (Pretty.writeln (Pretty.strs ("(co)inductives:" ::
       
    83        map #1 (Sign.cond_extern_table sg Sign.constK tab)));
       
    84      Pretty.writeln (Pretty.big_list "monotonicity rules:" (map Display.pretty_thm monos)));
       
    85 end;
       
    86 
       
    87 structure InductiveData = TheoryDataFun(InductiveArgs);
       
    88 val print_inductives = InductiveData.print;
       
    89 
       
    90 
       
    91 (* get and put data *)
       
    92 
       
    93 fun get_inductive thy name =
       
    94   (case Symtab.lookup (fst (InductiveData.get thy), name) of
       
    95     Some info => info
       
    96   | None => error ("Unknown (co)inductive set " ^ quote name));
       
    97 
       
    98 fun put_inductives names info thy =
       
    99   let
       
   100     fun upd ((tab, monos), name) = (Symtab.update_new ((name, info), tab), monos);
       
   101     val tab_monos = foldl upd (InductiveData.get thy, names)
       
   102       handle Symtab.DUP name => error ("Duplicate definition of (co)inductive set " ^ quote name);
       
   103   in InductiveData.put tab_monos thy end;
       
   104 
       
   105 val get_monos = snd o InductiveData.get;
       
   106 
       
   107 fun put_monos thms thy = InductiveData.put (fst (InductiveData.get thy), thms) thy;
       
   108 
       
   109 (** monotonicity rules **)
       
   110 
       
   111 fun mk_mono thm =
       
   112   let
       
   113     fun eq2mono thm' = [standard (thm' RS (thm' RS eq_to_mono))] @
       
   114       (case concl_of thm of
       
   115           (_ $ (_ $ (Const ("Not", _) $ _) $ _)) => []
       
   116         | _ => [standard (thm' RS (thm' RS eq_to_mono2))]);
       
   117     val concl = concl_of thm
       
   118   in
       
   119     if Logic.is_equals concl then
       
   120       eq2mono (thm RS meta_eq_to_obj_eq)
       
   121     else if can (HOLogic.dest_eq o HOLogic.dest_Trueprop) concl then
       
   122       eq2mono thm
       
   123     else [thm]
       
   124   end;
       
   125 
       
   126 (* mono add/del *)
       
   127 
       
   128 local
       
   129 
       
   130 fun map_rules_global f thy = put_monos (f (get_monos thy)) thy;
       
   131 
       
   132 fun add_mono thm rules = Library.gen_union Thm.eq_thm (mk_mono thm, rules);
       
   133 fun del_mono thm rules = Library.gen_rems Thm.eq_thm (rules, mk_mono thm);
       
   134 
       
   135 fun mk_att f g (x, thm) = (f (g thm) x, thm);
       
   136 
       
   137 in
       
   138 
       
   139 val mono_add_global = mk_att map_rules_global add_mono;
       
   140 val mono_del_global = mk_att map_rules_global del_mono;
       
   141 
       
   142 end;
       
   143 
       
   144 
       
   145 (* concrete syntax *)
       
   146 
       
   147 val monoN = "mono";
       
   148 val addN = "add";
       
   149 val delN = "del";
       
   150 
       
   151 fun mono_att add del =
       
   152   Attrib.syntax (Scan.lift (Args.$$$ addN >> K add || Args.$$$ delN >> K del || Scan.succeed add));
       
   153 
       
   154 val mono_attr =
       
   155   (mono_att mono_add_global mono_del_global, mono_att Attrib.undef_local_attribute Attrib.undef_local_attribute);
       
   156 
    58 
   157 
    59 
   158 
    60 (** utilities **)
   159 (** utilities **)
    61 
   160 
    62 (* messages *)
   161 (* messages *)
    99     (warning "Occurrences of recursive constant have non-unifiable types"; (cs, intr_ts));
   198     (warning "Occurrences of recursive constant have non-unifiable types"; (cs, intr_ts));
   100 
   199 
   101 
   200 
   102 (* misc *)
   201 (* misc *)
   103 
   202 
   104 (*for proving monotonicity of recursion operator*)
       
   105 val default_monos = basic_monos @ [vimage_mono];
       
   106 
       
   107 val Const _ $ (vimage_f $ _) $ _ = HOLogic.dest_Trueprop (concl_of vimageD);
   203 val Const _ $ (vimage_f $ _) $ _ = HOLogic.dest_Trueprop (concl_of vimageD);
   108 
   204 
   109 (*Delete needless equality assumptions*)
   205 (*Delete needless equality assumptions*)
   110 val refl_thin = prove_goal HOL.thy "!!P. [| a=a;  P |] ==> P"
   206 val refl_thin = prove_goal HOL.thy "!!P. [| a=a;  P |] ==> P"
   111      (fn _ => [assume_tac 1]);
   207      (fn _ => [assume_tac 1]);
   155   (Sign.string_of_term sign p) ^ "\nin introduction rule\n" ^
   251   (Sign.string_of_term sign p) ^ "\nin introduction rule\n" ^
   156   (Sign.string_of_term sign t) ^ "\n" ^ msg);
   252   (Sign.string_of_term sign t) ^ "\n" ^ msg);
   157 
   253 
   158 val msg1 = "Conclusion of introduction rule must have form\
   254 val msg1 = "Conclusion of introduction rule must have form\
   159           \ ' t : S_i '";
   255           \ ' t : S_i '";
   160 val msg2 = "Premises mentioning recursive sets must have form\
   256 val msg2 = "Non-atomic premise";
   161           \ ' t : M S_i '";
       
   162 val msg3 = "Recursion term on left of member symbol";
   257 val msg3 = "Recursion term on left of member symbol";
   163 
   258 
   164 fun check_rule sign cs r =
   259 fun check_rule sign cs r =
   165   let
   260   let
   166     fun check_prem prem = if exists (Logic.occs o (rpair prem)) cs then
   261     fun check_prem prem = if can HOLogic.dest_Trueprop prem then ()
   167          (case prem of
   262       else err_in_prem sign r prem msg2;
   168            (Const ("op :", _) $ t $ u) =>
   263 
   169              if exists (Logic.occs o (rpair t)) cs then
   264   in (case HOLogic.dest_Trueprop (Logic.strip_imp_concl r) of
   170                err_in_prem sign r prem msg3 else ()
   265         (Const ("op :", _) $ t $ u) =>
   171          | _ => err_in_prem sign r prem msg2)
   266           if u mem cs then
   172         else ()
   267             if exists (Logic.occs o (rpair t)) cs then
   173 
   268               err_in_rule sign r msg3
   174   in (case (HOLogic.dest_Trueprop o Logic.strip_imp_concl) r of
   269             else
   175         (Const ("op :", _) $ _ $ u) =>
   270               seq check_prem (Logic.strip_imp_prems r)
   176           if u mem cs then seq (check_prem o HOLogic.dest_Trueprop)
       
   177             (Logic.strip_imp_prems r)
       
   178           else err_in_rule sign r msg1
   271           else err_in_rule sign r msg1
   179       | _ => err_in_rule sign r msg1)
   272       | _ => err_in_rule sign r msg1)
   180   end;
   273   end;
   181 
   274 
   182 fun try' f msg sign t = (case (try f t) of
   275 fun try' f msg sign t = (case (try f t) of
   183       Some x => x
   276       Some x => x
   184     | None => error (msg ^ Sign.string_of_term sign t));
   277     | None => error (msg ^ Sign.string_of_term sign t));
   185 
       
   186 
       
   187 
       
   188 (*** theory data ***)
       
   189 
       
   190 (* data kind 'HOL/inductive' *)
       
   191 
       
   192 type inductive_info =
       
   193   {names: string list, coind: bool} * {defs: thm list, elims: thm list, raw_induct: thm,
       
   194     induct: thm, intrs: thm list, mk_cases: string -> thm, mono: thm, unfold: thm};
       
   195 
       
   196 structure InductiveArgs =
       
   197 struct
       
   198   val name = "HOL/inductive";
       
   199   type T = inductive_info Symtab.table;
       
   200 
       
   201   val empty = Symtab.empty;
       
   202   val copy = I;
       
   203   val prep_ext = I;
       
   204   val merge: T * T -> T = Symtab.merge (K true);
       
   205 
       
   206   fun print sg tab =
       
   207     Pretty.writeln (Pretty.strs ("(co)inductives:" ::
       
   208       map #1 (Sign.cond_extern_table sg Sign.constK tab)));
       
   209 end;
       
   210 
       
   211 structure InductiveData = TheoryDataFun(InductiveArgs);
       
   212 val print_inductives = InductiveData.print;
       
   213 
       
   214 
       
   215 (* get and put data *)
       
   216 
       
   217 fun get_inductive thy name =
       
   218   (case Symtab.lookup (InductiveData.get thy, name) of
       
   219     Some info => info
       
   220   | None => error ("Unknown (co)inductive set " ^ quote name));
       
   221 
       
   222 fun put_inductives names info thy =
       
   223   let
       
   224     fun upd (tab, name) = Symtab.update_new ((name, info), tab);
       
   225     val tab = foldl upd (InductiveData.get thy, names)
       
   226       handle Symtab.DUP name => error ("Duplicate definition of (co)inductive set " ^ quote name);
       
   227   in InductiveData.put tab thy end;
       
   228 
   278 
   229 
   279 
   230 
   280 
   231 (*** properties of (co)inductive sets ***)
   281 (*** properties of (co)inductive sets ***)
   232 
   282 
   278 
   328 
   279     fun mk_ind_prem r =
   329     fun mk_ind_prem r =
   280       let
   330       let
   281         val frees = map dest_Free ((add_term_frees (r, [])) \\ params);
   331         val frees = map dest_Free ((add_term_frees (r, [])) \\ params);
   282 
   332 
   283         fun subst (prem as (Const ("op :", T) $ t $ u), prems) =
   333         val pred_of = curry (Library.gen_assoc (op aconv)) (cs ~~ preds);
   284               let val n = find_index_eq u cs in
   334 
   285                 if n >= 0 then prem :: (nth_elem (n, preds)) $ t :: prems else
   335         fun subst (s as ((m as Const ("op :", T)) $ t $ u)) =
   286                   (subst_free (map (fn (c, P) => (c, HOLogic.mk_binop "op Int"
   336               (case pred_of u of
   287                     (c, HOLogic.Collect_const (HOLogic.dest_setT
   337                   None => (m $ fst (subst t) $ fst (subst u), None)
   288                       (fastype_of c)) $ P))) (cs ~~ preds)) prem)::prems
   338                 | Some P => (HOLogic.conj $ s $ (P $ t), Some (s, P $ t)))
   289               end
   339           | subst s =
   290           | subst (prem, prems) = prem::prems;
   340               (case pred_of s of
   291 
   341                   Some P => (HOLogic.mk_binop "op Int"
       
   342                     (s, HOLogic.Collect_const (HOLogic.dest_setT
       
   343                       (fastype_of s)) $ P), None)
       
   344                 | None => (case s of
       
   345                      (t $ u) => (fst (subst t) $ fst (subst u), None)
       
   346                    | (Abs (a, T, t)) => (Abs (a, T, fst (subst t)), None)
       
   347                    | _ => (s, None)));
       
   348 
       
   349         fun mk_prem (s, prems) = (case subst s of
       
   350               (_, Some (t, u)) => t :: u :: prems
       
   351             | (t, _) => t :: prems);
       
   352           
   292         val Const ("op :", _) $ t $ u =
   353         val Const ("op :", _) $ t $ u =
   293           HOLogic.dest_Trueprop (Logic.strip_imp_concl r)
   354           HOLogic.dest_Trueprop (Logic.strip_imp_concl r)
   294 
   355 
   295       in list_all_free (frees,
   356       in list_all_free (frees,
   296            Logic.list_implies (map HOLogic.mk_Trueprop (foldr subst
   357            Logic.list_implies (map HOLogic.mk_Trueprop (foldr mk_prem
   297              (map HOLogic.dest_Trueprop (Logic.strip_imp_prems r), [])),
   358              (map HOLogic.dest_Trueprop (Logic.strip_imp_prems r), [])),
   298                HOLogic.mk_Trueprop (nth_elem (find_index_eq u cs, preds) $ t)))
   359                HOLogic.mk_Trueprop (the (pred_of u) $ t)))
   299       end;
   360       end;
   300 
   361 
   301     val ind_prems = map mk_ind_prem intr_ts;
   362     val ind_prems = map mk_ind_prem intr_ts;
   302 
   363 
   303     (* make conclusions for induction rules *)
   364     (* make conclusions for induction rules *)
   310           val tuple = HOLogic.mk_tuple T frees;
   371           val tuple = HOLogic.mk_tuple T frees;
   311       in ((HOLogic.mk_binop "op -->"
   372       in ((HOLogic.mk_binop "op -->"
   312         (HOLogic.mk_mem (tuple, c), P $ tuple))::ts, x')
   373         (HOLogic.mk_mem (tuple, c), P $ tuple))::ts, x')
   313       end;
   374       end;
   314 
   375 
   315     val mutual_ind_concl = HOLogic.mk_Trueprop (foldr1 (app HOLogic.conj)
   376     val mutual_ind_concl = HOLogic.mk_Trueprop (foldr1 HOLogic.mk_conj
   316         (fst (foldr mk_ind_concl (cs ~~ preds, ([], "xa")))))
   377         (fst (foldr mk_ind_concl (cs ~~ preds, ([], "xa")))))
   317 
   378 
   318   in (preds, ind_prems, mutual_ind_concl)
   379   in (preds, ind_prems, mutual_ind_concl)
   319   end;
   380   end;
   320 
   381 
   328   let
   389   let
   329     val _ = message "  Proving monotonicity ...";
   390     val _ = message "  Proving monotonicity ...";
   330 
   391 
   331     val mono = prove_goalw_cterm [] (cterm_of (Theory.sign_of thy) (HOLogic.mk_Trueprop
   392     val mono = prove_goalw_cterm [] (cterm_of (Theory.sign_of thy) (HOLogic.mk_Trueprop
   332       (Const (mono_name, (setT --> setT) --> HOLogic.boolT) $ fp_fun)))
   393       (Const (mono_name, (setT --> setT) --> HOLogic.boolT) $ fp_fun)))
   333         (fn _ => [rtac monoI 1, REPEAT (ares_tac (default_monos @ monos) 1)])
   394         (fn _ => [rtac monoI 1, REPEAT (ares_tac (get_monos thy @ flat (map mk_mono monos)) 1)])
   334 
   395 
   335   in mono end;
   396   in mono end;
   336 
   397 
   337 
   398 
   338 
   399 
   372 
   433 
   373 fun prove_elims cs cTs params intr_ts unfold rec_sets_defs thy =
   434 fun prove_elims cs cTs params intr_ts unfold rec_sets_defs thy =
   374   let
   435   let
   375     val _ = message "  Proving the elimination rules ...";
   436     val _ = message "  Proving the elimination rules ...";
   376 
   437 
   377     val rules1 = [CollectE, disjE, make_elim vimageD];
   438     val rules1 = [CollectE, disjE, make_elim vimageD, exE];
   378     val rules2 = [exE, conjE, Inl_neq_Inr, Inr_neq_Inl] @
   439     val rules2 = [conjE, Inl_neq_Inr, Inr_neq_Inl] @
   379       map make_elim [Inl_inject, Inr_inject];
   440       map make_elim [Inl_inject, Inr_inject];
   380 
   441 
   381     val elims = map (fn t => prove_goalw_cterm rec_sets_defs
   442     val elims = map (fn t => prove_goalw_cterm rec_sets_defs
   382       (cterm_of (Theory.sign_of thy) t) (fn prems =>
   443       (cterm_of (Theory.sign_of thy) t) (fn prems =>
   383         [cut_facts_tac [hd prems] 1,
   444         [cut_facts_tac [hd prems] 1,
   491 
   552 
   492     val induct = prove_goalw_cterm [] (cterm_of sign
   553     val induct = prove_goalw_cterm [] (cterm_of sign
   493       (Logic.list_implies (ind_prems, ind_concl))) (fn prems =>
   554       (Logic.list_implies (ind_prems, ind_concl))) (fn prems =>
   494         [rtac (impI RS allI) 1,
   555         [rtac (impI RS allI) 1,
   495          DETERM (etac (mono RS (fp_def RS def_induct)) 1),
   556          DETERM (etac (mono RS (fp_def RS def_induct)) 1),
   496          rewrite_goals_tac (map mk_meta_eq (vimage_Int::vimage_simps)),
   557          rewrite_goals_tac (map mk_meta_eq (vimage_Int::Int_Collect::vimage_simps)),
   497          fold_goals_tac rec_sets_defs,
   558          fold_goals_tac rec_sets_defs,
   498          (*This CollectE and disjE separates out the introduction rules*)
   559          (*This CollectE and disjE separates out the introduction rules*)
   499          REPEAT (FIRSTGOAL (eresolve_tac [CollectE, disjE])),
   560          REPEAT (FIRSTGOAL (eresolve_tac [CollectE, disjE, exE])),
   500          (*Now break down the individual cases.  No disjE here in case
   561          (*Now break down the individual cases.  No disjE here in case
   501            some premise involves disjunction.*)
   562            some premise involves disjunction.*)
   502          REPEAT (FIRSTGOAL (eresolve_tac [IntE, CollectE, exE, conjE] 
   563          REPEAT (FIRSTGOAL (etac conjE ORELSE' hyp_subst_tac)),
   503                      ORELSE' hyp_subst_tac)),
       
   504          rewrite_goals_tac sum_case_rewrites,
   564          rewrite_goals_tac sum_case_rewrites,
   505          EVERY (map (fn prem =>
   565          EVERY (map (fn prem =>
   506            DEPTH_SOLVE_1 (ares_tac [prem, conjI, refl] 1)) prems)]);
   566            DEPTH_SOLVE_1 (ares_tac [prem, conjI, refl] 1)) prems)]);
   507 
   567 
   508     val lemma = prove_goalw_cterm rec_sets_defs (cterm_of sign
   568     val lemma = prove_goalw_cterm rec_sets_defs (cterm_of sign
   552           (cs ~~ (map (mk_vimage cs sumT (Free (sname, setT))) cs));
   612           (cs ~~ (map (mk_vimage cs sumT (Free (sname, setT))) cs));
   553         val Const ("op :", _) $ t $ u =
   613         val Const ("op :", _) $ t $ u =
   554           HOLogic.dest_Trueprop (Logic.strip_imp_concl r)
   614           HOLogic.dest_Trueprop (Logic.strip_imp_concl r)
   555 
   615 
   556       in foldr (fn ((x, T), P) => HOLogic.mk_exists (x, T, P))
   616       in foldr (fn ((x, T), P) => HOLogic.mk_exists (x, T, P))
   557         (frees, foldr1 (app HOLogic.conj)
   617         (frees, foldr1 HOLogic.mk_conj
   558           (((HOLogic.eq_const sumT) $ Free (xname, sumT) $ (mk_inj cs sumT u t))::
   618           (((HOLogic.eq_const sumT) $ Free (xname, sumT) $ (mk_inj cs sumT u t))::
   559             (map (subst o HOLogic.dest_Trueprop)
   619             (map (subst o HOLogic.dest_Trueprop)
   560               (Logic.strip_imp_prems r))))
   620               (Logic.strip_imp_prems r))))
   561       end
   621       end
   562 
   622 
   563     (* make a disjunction of all introduction rules *)
   623     (* make a disjunction of all introduction rules *)
   564 
   624 
   565     val fp_fun = absfree (sname, setT, (HOLogic.Collect_const sumT) $
   625     val fp_fun = absfree (sname, setT, (HOLogic.Collect_const sumT) $
   566       absfree (xname, sumT, foldr1 (app HOLogic.disj) (map transform_rule intr_ts)));
   626       absfree (xname, sumT, foldr1 HOLogic.mk_disj (map transform_rule intr_ts)));
   567 
   627 
   568     (* add definiton of recursive sets to theory *)
   628     (* add definiton of recursive sets to theory *)
   569 
   629 
   570     val rec_name = if alt_name = "" then space_implode "_" cnames else alt_name;
   630     val rec_name = if alt_name = "" then space_implode "_" cnames else alt_name;
   571     val full_rec_name = Sign.full_name (Theory.sign_of thy) rec_name;
   631     val full_rec_name = Sign.full_name (Theory.sign_of thy) rec_name;
   649             Theory.add_consts_i
   709             Theory.add_consts_i
   650               (map (fn (c, n) => (n, paramTs ---> fastype_of c, NoSyn)) (cs ~~ cnames))
   710               (map (fn (c, n) => (n, paramTs ---> fastype_of c, NoSyn)) (cs ~~ cnames))
   651          else I)
   711          else I)
   652       |> Theory.add_path rec_name
   712       |> Theory.add_path rec_name
   653       |> PureThy.add_axiomss_i [(("intrs", intr_ts), atts), (("elims", elim_ts), [])]
   713       |> PureThy.add_axiomss_i [(("intrs", intr_ts), atts), (("elims", elim_ts), [])]
   654       |> (if coind then I else PureThy.add_axioms_i [(("internal_induct", ind_t), [])]);
   714       |> (if coind then I else
       
   715             PureThy.add_axioms_i [(("raw_induct", ind_t), [apsnd (standard o split_rule)])]);
   655 
   716 
   656     val intrs = PureThy.get_thms thy' "intrs";
   717     val intrs = PureThy.get_thms thy' "intrs";
   657     val elims = PureThy.get_thms thy' "elims";
   718     val elims = PureThy.get_thms thy' "elims";
   658     val raw_induct = if coind then TrueI else
   719     val raw_induct = if coind then TrueI else PureThy.get_thm thy' "raw_induct";
   659       standard (split_rule (PureThy.get_thm thy' "internal_induct"));
       
   660     val induct = if coind orelse length cs > 1 then raw_induct
   720     val induct = if coind orelse length cs > 1 then raw_induct
   661       else standard (raw_induct RSN (2, rev_mp));
   721       else standard (raw_induct RSN (2, rev_mp));
   662 
   722 
   663     val thy'' =
   723     val thy'' =
   664       thy'
   724       thy'
   696 
   756 
   697     val full_cnames = map (try' (fst o dest_Const o head_of)
   757     val full_cnames = map (try' (fst o dest_Const o head_of)
   698       "Recursive set not previously declared as constant: " sign) cs;
   758       "Recursive set not previously declared as constant: " sign) cs;
   699     val cnames = map Sign.base_name full_cnames;
   759     val cnames = map Sign.base_name full_cnames;
   700 
   760 
   701     val _ = assert_all Syntax.is_identifier cnames	(* FIXME why? *)
       
   702        (fn a => "Base name of recursive set not an identifier: " ^ a);
       
   703     val _ = seq (check_rule sign cs o snd o fst) intros;
   761     val _ = seq (check_rule sign cs o snd o fst) intros;
   704 
   762 
   705     val (thy1, result) =
   763     val (thy1, result) =
   706       (if ! quick_and_dirty then add_ind_axm else add_ind_def)
   764       (if ! quick_and_dirty then add_ind_axm else add_ind_def)
   707         verbose declare_consts alt_name coind no_elim no_ind cs atts intros monos
   765         verbose declare_consts alt_name coind no_elim no_ind cs atts intros monos
   714 (** external interface **)
   772 (** external interface **)
   715 
   773 
   716 fun add_inductive verbose coind c_strings srcs intro_srcs raw_monos raw_con_defs thy =
   774 fun add_inductive verbose coind c_strings srcs intro_srcs raw_monos raw_con_defs thy =
   717   let
   775   let
   718     val sign = Theory.sign_of thy;
   776     val sign = Theory.sign_of thy;
   719     val cs = map (readtm (Theory.sign_of thy) HOLogic.termTVar) c_strings;
   777     val cs = map (term_of o Thm.read_cterm sign o rpair HOLogic.termTVar) c_strings;
   720 
   778 
   721     val atts = map (Attrib.global_attribute thy) srcs;
   779     val atts = map (Attrib.global_attribute thy) srcs;
   722     val intr_names = map (fst o fst) intro_srcs;
   780     val intr_names = map (fst o fst) intro_srcs;
   723     val intr_ts = map (readtm (Theory.sign_of thy) propT o snd o fst) intro_srcs;
   781     val intr_ts = map (term_of o Thm.read_cterm sign o rpair propT o snd o fst) intro_srcs;
   724     val intr_atts = map (map (Attrib.global_attribute thy) o snd) intro_srcs;
   782     val intr_atts = map (map (Attrib.global_attribute thy) o snd) intro_srcs;
   725     val (cs', intr_ts') = unify_consts sign cs intr_ts;
   783     val (cs', intr_ts') = unify_consts sign cs intr_ts;
   726 
   784 
   727     val ((thy', con_defs), monos) = thy
   785     val ((thy', con_defs), monos) = thy
   728       |> IsarThy.apply_theorems raw_monos
   786       |> IsarThy.apply_theorems raw_monos
   736 
   794 
   737 (** package setup **)
   795 (** package setup **)
   738 
   796 
   739 (* setup theory *)
   797 (* setup theory *)
   740 
   798 
   741 val setup = [InductiveData.init];
   799 val setup = [InductiveData.init,
       
   800              Attrib.add_attributes [(monoN, mono_attr, "monotonicity rule")]];
   742 
   801 
   743 
   802 
   744 (* outer syntax *)
   803 (* outer syntax *)
   745 
   804 
   746 local structure P = OuterParse and K = OuterSyntax.Keyword in
   805 local structure P = OuterParse and K = OuterSyntax.Keyword in