src/HOL/Tools/inductive_package.ML
changeset 23762 24eef53a9ad3
parent 23577 c5b93c69afd3
child 23881 851c74f1bb69
equal deleted inserted replaced
23761:9cebbaccf8a2 23762:24eef53a9ad3
    17   Q x is any side condition on the free variables
    17   Q x is any side condition on the free variables
    18   ti, t are any terms
    18   ti, t are any terms
    19   Pj, Pk are two of the predicates being defined in mutual recursion
    19   Pj, Pk are two of the predicates being defined in mutual recursion
    20 *)
    20 *)
    21 
    21 
    22 signature INDUCTIVE_PACKAGE =
    22 signature BASIC_INDUCTIVE_PACKAGE =
    23 sig
    23 sig
    24   val quiet_mode: bool ref
    24   val quiet_mode: bool ref
    25   type inductive_result
    25   type inductive_result
    26   val morph_result: morphism -> inductive_result -> inductive_result
    26   val morph_result: morphism -> inductive_result -> inductive_result
    27   type inductive_info
    27   type inductive_info
    55   val unpartition_rules: thm list -> (string * 'a list) list -> 'a list
    55   val unpartition_rules: thm list -> (string * 'a list) list -> 'a list
    56   val infer_intro_vars: thm -> int -> thm list -> term list list
    56   val infer_intro_vars: thm -> int -> thm list -> term list list
    57   val setup: theory -> theory
    57   val setup: theory -> theory
    58 end;
    58 end;
    59 
    59 
       
    60 signature INDUCTIVE_PACKAGE =
       
    61 sig
       
    62   include BASIC_INDUCTIVE_PACKAGE
       
    63   type add_ind_def
       
    64   val declare_rules: bstring -> bool -> bool -> string list ->
       
    65     thm list -> bstring list -> Attrib.src list list -> (thm * string list) list ->
       
    66     thm -> local_theory -> thm list * thm list * thm * local_theory
       
    67   val add_ind_def: add_ind_def
       
    68   val gen_add_inductive_i: add_ind_def ->
       
    69     bool -> bstring -> bool -> bool -> bool ->
       
    70     (string * typ option * mixfix) list ->
       
    71     (string * typ option) list -> ((bstring * Attrib.src list) * term) list -> thm list ->
       
    72       local_theory -> inductive_result * local_theory
       
    73   val gen_add_inductive: add_ind_def ->
       
    74     bool -> bool -> (string * string option * mixfix) list ->
       
    75     (string * string option * mixfix) list ->
       
    76     ((bstring * Attrib.src list) * string) list -> (thmref * Attrib.src list) list ->
       
    77     local_theory -> inductive_result * local_theory
       
    78   val gen_ind_decl: add_ind_def ->
       
    79     bool -> OuterParse.token list ->
       
    80     (Toplevel.transition -> Toplevel.transition) * OuterParse.token list
       
    81 end;
       
    82 
    60 structure InductivePackage: INDUCTIVE_PACKAGE =
    83 structure InductivePackage: INDUCTIVE_PACKAGE =
    61 struct
    84 struct
    62 
    85 
    63 
    86 
    64 (** theory context references **)
    87 (** theory context references **)
    87 
   110 
    88 
   111 
    89 (** context data **)
   112 (** context data **)
    90 
   113 
    91 type inductive_result =
   114 type inductive_result =
    92   {preds: term list, defs: thm list, elims: thm list, raw_induct: thm,
   115   {preds: term list, elims: thm list, raw_induct: thm,
    93    induct: thm, intrs: thm list, mono: thm, unfold: thm};
   116    induct: thm, intrs: thm list};
    94 
   117 
    95 fun morph_result phi {preds, defs, elims, raw_induct: thm, induct, intrs, mono, unfold} =
   118 fun morph_result phi {preds, elims, raw_induct: thm, induct, intrs} =
    96   let
   119   let
    97     val term = Morphism.term phi;
   120     val term = Morphism.term phi;
    98     val thm = Morphism.thm phi;
   121     val thm = Morphism.thm phi;
    99     val fact = Morphism.fact phi;
   122     val fact = Morphism.fact phi;
   100   in
   123   in
   101    {preds = map term preds, defs = fact defs, elims = fact elims, raw_induct = thm raw_induct,
   124    {preds = map term preds, elims = fact elims, raw_induct = thm raw_induct,
   102     induct = thm induct, intrs = fact intrs, mono = thm mono, unfold = thm unfold}
   125     induct = thm induct, intrs = fact intrs}
   103   end;
   126   end;
   104 
   127 
   105 type inductive_info =
   128 type inductive_info =
   106   {names: string list, coind: bool} * inductive_result;
   129   {names: string list, coind: bool} * inductive_result;
   107 
   130 
   160     | _ $ (Const ("op =", _) $ _ $ _) => eq2mono thm
   183     | _ $ (Const ("op =", _) $ _ $ _) => eq2mono thm
   161     | _ $ (Const ("Orderings.ord_class.less_eq", _) $ _ $ _) =>
   184     | _ $ (Const ("Orderings.ord_class.less_eq", _) $ _ $ _) =>
   162       [dest_less_concl (Seq.hd (REPEAT (FIRSTGOAL
   185       [dest_less_concl (Seq.hd (REPEAT (FIRSTGOAL
   163          (resolve_tac [le_funI, le_boolI'])) thm))]
   186          (resolve_tac [le_funI, le_boolI'])) thm))]
   164     | _ => [thm]
   187     | _ => [thm]
   165   end;
   188   end handle THM _ => error ("Bad monotonicity theorem:\n" ^ string_of_thm thm);
   166 
   189 
   167 val mono_add = Thm.declaration_attribute (map_monos o fold Drule.add_rule o mk_mono);
   190 val mono_add = Thm.declaration_attribute (map_monos o fold Drule.add_rule o mk_mono);
   168 val mono_del = Thm.declaration_attribute (map_monos o fold Drule.del_rule o mk_mono);
   191 val mono_del = Thm.declaration_attribute (map_monos o fold Drule.del_rule o mk_mono);
   169 
   192 
   170 
   193 
   225 
   248 
   226 (** process rules **)
   249 (** process rules **)
   227 
   250 
   228 local
   251 local
   229 
   252 
   230 fun err_in_rule thy name t msg =
   253 fun err_in_rule ctxt name t msg =
   231   error (cat_lines ["Ill-formed introduction rule " ^ quote name,
   254   error (cat_lines ["Ill-formed introduction rule " ^ quote name,
   232     Sign.string_of_term thy t, msg]);
   255     ProofContext.string_of_term ctxt t, msg]);
   233 
   256 
   234 fun err_in_prem thy name t p msg =
   257 fun err_in_prem ctxt name t p msg =
   235   error (cat_lines ["Ill-formed premise", Sign.string_of_term thy p,
   258   error (cat_lines ["Ill-formed premise", ProofContext.string_of_term ctxt p,
   236     "in introduction rule " ^ quote name, Sign.string_of_term thy t, msg]);
   259     "in introduction rule " ^ quote name, ProofContext.string_of_term ctxt t, msg]);
   237 
   260 
   238 val bad_concl = "Conclusion of introduction rule must be an inductive predicate";
   261 val bad_concl = "Conclusion of introduction rule must be an inductive predicate";
   239 
   262 
   240 val bad_ind_occ = "Inductive predicate occurs in argument of inductive predicate";
   263 val bad_ind_occ = "Inductive predicate occurs in argument of inductive predicate";
   241 
   264 
   243 
   266 
   244 fun atomize_term thy = MetaSimplifier.rewrite_term thy inductive_atomize [];
   267 fun atomize_term thy = MetaSimplifier.rewrite_term thy inductive_atomize [];
   245 
   268 
   246 in
   269 in
   247 
   270 
   248 fun check_rule thy cs params ((name, att), rule) =
   271 fun check_rule ctxt cs params ((name, att), rule) =
   249   let
   272   let
   250     val params' = Term.variant_frees rule (Logic.strip_params rule);
   273     val params' = Term.variant_frees rule (Logic.strip_params rule);
   251     val frees = rev (map Free params');
   274     val frees = rev (map Free params');
   252     val concl = subst_bounds (frees, Logic.strip_assums_concl rule);
   275     val concl = subst_bounds (frees, Logic.strip_assums_concl rule);
   253     val prems = map (curry subst_bounds frees) (Logic.strip_assums_hyp rule);
   276     val prems = map (curry subst_bounds frees) (Logic.strip_assums_hyp rule);
   254     val aprems = map (atomize_term thy) prems;
   277     val rule' = Logic.list_implies (prems, concl);
       
   278     val aprems = map (atomize_term (ProofContext.theory_of ctxt)) prems;
   255     val arule = list_all_free (params', Logic.list_implies (aprems, concl));
   279     val arule = list_all_free (params', Logic.list_implies (aprems, concl));
   256 
   280 
   257     fun check_ind err t = case dest_predicate cs params t of
   281     fun check_ind err t = case dest_predicate cs params t of
   258         NONE => err (bad_app ^
   282         NONE => err (bad_app ^
   259           commas (map (Sign.string_of_term thy) params))
   283           commas (map (ProofContext.string_of_term ctxt) params))
   260       | SOME (_, _, ys, _) =>
   284       | SOME (_, _, ys, _) =>
   261           if exists (fn c => exists (fn t => Logic.occs (c, t)) ys) cs
   285           if exists (fn c => exists (fn t => Logic.occs (c, t)) ys) cs
   262           then err bad_ind_occ else ();
   286           then err bad_ind_occ else ();
   263 
   287 
   264     fun check_prem' prem t =
   288     fun check_prem' prem t =
   265       if head_of t mem cs then
   289       if head_of t mem cs then
   266         check_ind (err_in_prem thy name rule prem) t
   290         check_ind (err_in_prem ctxt name rule prem) t
   267       else (case t of
   291       else (case t of
   268           Abs (_, _, t) => check_prem' prem t
   292           Abs (_, _, t) => check_prem' prem t
   269         | t $ u => (check_prem' prem t; check_prem' prem u)
   293         | t $ u => (check_prem' prem t; check_prem' prem u)
   270         | _ => ());
   294         | _ => ());
   271 
   295 
   272     fun check_prem (prem, aprem) =
   296     fun check_prem (prem, aprem) =
   273       if can HOLogic.dest_Trueprop aprem then check_prem' prem prem
   297       if can HOLogic.dest_Trueprop aprem then check_prem' prem prem
   274       else err_in_prem thy name rule prem "Non-atomic premise";
   298       else err_in_prem ctxt name rule prem "Non-atomic premise";
   275   in
   299   in
   276     (case concl of
   300     (case concl of
   277        Const ("Trueprop", _) $ t =>
   301        Const ("Trueprop", _) $ t =>
   278          if head_of t mem cs then
   302          if head_of t mem cs then
   279            (check_ind (err_in_rule thy name rule) t;
   303            (check_ind (err_in_rule ctxt name rule') t;
   280             List.app check_prem (prems ~~ aprems))
   304             List.app check_prem (prems ~~ aprems))
   281          else err_in_rule thy name rule bad_concl
   305          else err_in_rule ctxt name rule' bad_concl
   282      | _ => err_in_rule thy name rule bad_concl);
   306      | _ => err_in_rule ctxt name rule' bad_concl);
   283     ((name, att), arule)
   307     ((name, att), arule)
   284   end;
   308   end;
   285 
   309 
   286 val rulify =  (* FIXME norm_hhf *)
   310 val rulify =  (* FIXME norm_hhf *)
   287   hol_simplify inductive_conj
   311   hol_simplify inductive_conj
   398   (Sign.read_prop HOL.thy "!!P. a = a ==> P ==> P")
   422   (Sign.read_prop HOL.thy "!!P. a = a ==> P ==> P")
   399   (fn _ => assume_tac 1);
   423   (fn _ => assume_tac 1);
   400 val elim_rls = [asm_rl, FalseE, refl_thin, conjE, exE];
   424 val elim_rls = [asm_rl, FalseE, refl_thin, conjE, exE];
   401 val elim_tac = REPEAT o Tactic.eresolve_tac elim_rls;
   425 val elim_tac = REPEAT o Tactic.eresolve_tac elim_rls;
   402 
   426 
   403 fun simp_case_tac solved ss i =
   427 fun simp_case_tac ss i =
   404   EVERY' [elim_tac, asm_full_simp_tac ss, elim_tac, REPEAT o bound_hyp_subst_tac] i
   428   EVERY' [elim_tac, asm_full_simp_tac ss, elim_tac, REPEAT o bound_hyp_subst_tac] i;
   405   THEN_MAYBE (if solved then no_tac else all_tac);  (* FIXME !? *)
       
   406 
   429 
   407 in
   430 in
   408 
   431 
   409 fun mk_cases ctxt prop =
   432 fun mk_cases ctxt prop =
   410   let
   433   let
   413 
   436 
   414     fun err msg =
   437     fun err msg =
   415       error (Pretty.string_of (Pretty.block
   438       error (Pretty.string_of (Pretty.block
   416         [Pretty.str msg, Pretty.fbrk, ProofContext.pretty_term ctxt prop]));
   439         [Pretty.str msg, Pretty.fbrk, ProofContext.pretty_term ctxt prop]));
   417 
   440 
   418     val P = HOLogic.dest_Trueprop (Logic.strip_imp_concl prop) handle TERM _ =>
   441     val elims = InductAttrib.find_casesS ctxt prop;
   419       err "Object-logic proposition expected";
       
   420     val c = Term.head_name_of P;
       
   421     val (_, {elims, ...}) = the_inductive ctxt c;
       
   422 
   442 
   423     val cprop = Thm.cterm_of thy prop;
   443     val cprop = Thm.cterm_of thy prop;
   424     val tac = ALLGOALS (simp_case_tac false ss) THEN prune_params_tac;
   444     val tac = ALLGOALS (simp_case_tac ss) THEN prune_params_tac;
   425     fun mk_elim rl =
   445     fun mk_elim rl =
   426       Thm.implies_intr cprop (Tactic.rule_by_tactic tac (Thm.assume cprop RS rl))
   446       Thm.implies_intr cprop (Tactic.rule_by_tactic tac (Thm.assume cprop RS rl))
   427       |> singleton (Variable.export (Variable.auto_fixes prop ctxt) ctxt);
   447       |> singleton (Variable.export (Variable.auto_fixes prop ctxt) ctxt);
   428   in
   448   in
   429     (case get_first (try mk_elim) elims of
   449     (case get_first (try mk_elim) elims of
   484         fun subst s = (case dest_predicate cs params s of
   504         fun subst s = (case dest_predicate cs params s of
   485             SOME (_, i, ys, (_, Ts)) =>
   505             SOME (_, i, ys, (_, Ts)) =>
   486               let
   506               let
   487                 val k = length Ts;
   507                 val k = length Ts;
   488                 val bs = map Bound (k - 1 downto 0);
   508                 val bs = map Bound (k - 1 downto 0);
   489                 val P = list_comb (List.nth (preds, i), ys @ bs);
   509                 val P = list_comb (List.nth (preds, i),
       
   510                   map (incr_boundvars k) ys @ bs);
   490                 val Q = list_abs (mk_names "x" k ~~ Ts,
   511                 val Q = list_abs (mk_names "x" k ~~ Ts,
   491                   HOLogic.mk_binop inductive_conj_name (list_comb (s, bs), P))
   512                   HOLogic.mk_binop inductive_conj_name
       
   513                     (list_comb (incr_boundvars k s, bs), P))
   492               in (Q, case Ts of [] => SOME (s, P) | _ => NONE) end
   514               in (Q, case Ts of [] => SOME (s, P) | _ => NONE) end
   493           | NONE => (case s of
   515           | NONE => (case s of
   494               (t $ u) => (fst (subst t) $ fst (subst u), NONE)
   516               (t $ u) => (fst (subst t) $ fst (subst u), NONE)
   495             | (Abs (a, T, t)) => (Abs (a, T, fst (subst t)), NONE)
   517             | (Abs (a, T, t)) => (Abs (a, T, fst (subst t)), NONE)
   496             | _ => (s, NONE)));
   518             | _ => (s, NONE)));
   583     val bs = map Free (Variable.variant_frees ctxt (p :: xs @ intr_ts)
   605     val bs = map Free (Variable.variant_frees ctxt (p :: xs @ intr_ts)
   584       (map (rpair HOLogic.boolT) (mk_names "b" k)));
   606       (map (rpair HOLogic.boolT) (mk_names "b" k)));
   585 
   607 
   586     fun subst t = (case dest_predicate cs params t of
   608     fun subst t = (case dest_predicate cs params t of
   587         SOME (_, i, ts, (Ts, Us)) =>
   609         SOME (_, i, ts, (Ts, Us)) =>
   588           let val zs = map Bound (length Us - 1 downto 0)
   610           let
       
   611             val l = length Us;
       
   612             val zs = map Bound (l - 1 downto 0)
   589           in
   613           in
   590             list_abs (map (pair "z") Us, list_comb (p,
   614             list_abs (map (pair "z") Us, list_comb (p,
   591               make_bool_args' bs i @ make_args argTs ((ts ~~ Ts) @ (zs ~~ Us))))
   615               make_bool_args' bs i @ make_args argTs
       
   616                 ((map (incr_boundvars l) ts ~~ Ts) @ (zs ~~ Us))))
   592           end
   617           end
   593       | NONE => (case t of
   618       | NONE => (case t of
   594           t1 $ t2 => subst t1 $ subst t2
   619           t1 $ t2 => subst t1 $ subst t2
   595         | Abs (x, T, u) => Abs (x, T, subst u)
   620         | Abs (x, T, u) => Abs (x, T, subst u)
   596         | _ => t));
   621         | _ => t));
   640         in
   665         in
   641           (name_mx, (("", []), fold_rev lambda (params @ xs)
   666           (name_mx, (("", []), fold_rev lambda (params @ xs)
   642             (list_comb (rec_const, params @ make_bool_args' bs i @
   667             (list_comb (rec_const, params @ make_bool_args' bs i @
   643               make_args argTs (xs ~~ Ts)))))
   668               make_args argTs (xs ~~ Ts)))))
   644         end) (cnames_syn ~~ cs);
   669         end) (cnames_syn ~~ cs);
   645     val (consts_defs, ctxt'') = fold_map (LocalTheory.def Thm.internalK) specs ctxt';
   670     val (consts_defs, ctxt'') = LocalTheory.defs Thm.internalK specs ctxt';
   646     val preds = (case cs of [_] => [rec_const] | _ => map #1 consts_defs);
   671     val preds = (case cs of [_] => [rec_const] | _ => map #1 consts_defs);
   647 
   672 
   648     val mono = prove_mono predT fp_fun monos ctxt''
   673     val mono = prove_mono predT fp_fun monos ctxt''
   649 
   674 
   650   in (ctxt'', rec_name, mono, fp_def', map (#2 o #2) consts_defs,
   675   in (ctxt'', rec_name, mono, fp_def', map (#2 o #2) consts_defs,
   651     list_comb (rec_const, params), preds, argTs, bs, xs)
   676     list_comb (rec_const, params), preds, argTs, bs, xs)
   652   end;
   677   end;
   653 
   678 
   654 fun add_ind_def verbose alt_name coind no_elim no_ind cs
   679 fun declare_rules rec_name coind no_ind cnames intrs intr_names intr_atts
   655     intros monos params cnames_syn ctxt =
   680       elims raw_induct ctxt =
   656   let
   681   let
   657     val _ =
   682     val ind_case_names = RuleCases.case_names intr_names;
   658       if verbose then message ("Proofs for " ^ coind_prefix coind ^ "inductive predicate(s) " ^
       
   659         commas_quote (map fst cnames_syn)) else ();
       
   660 
       
   661     val cnames = map (Sign.full_name (ProofContext.theory_of ctxt) o #1) cnames_syn;  (* FIXME *)
       
   662     val ((intr_names, intr_atts), intr_ts) = apfst split_list (split_list intros);
       
   663 
       
   664     val (ctxt1, rec_name, mono, fp_def, rec_preds_defs, rec_const, preds,
       
   665       argTs, bs, xs) = mk_ind_def alt_name coind cs intr_ts
       
   666         monos params cnames_syn ctxt;
       
   667 
       
   668     val (intrs, unfold) = prove_intrs coind mono fp_def (length bs + length xs)
       
   669       params intr_ts rec_preds_defs ctxt1;
       
   670     val elims = if no_elim then [] else
       
   671       cnames ~~ prove_elims cs params intr_ts intr_names unfold rec_preds_defs ctxt1;
       
   672     val raw_induct = zero_var_indexes
       
   673       (if no_ind then Drule.asm_rl else
       
   674        if coind then ObjectLogic.rulify (rule_by_tactic
       
   675          (rewrite_tac [le_fun_def, le_bool_def] THEN
       
   676            fold_tac rec_preds_defs) (mono RS (fp_def RS def_coinduct)))
       
   677        else
       
   678          prove_indrule cs argTs bs xs rec_const params intr_ts mono fp_def
       
   679            rec_preds_defs ctxt1);
       
   680     val induct_cases = map (#1 o #1) intros;
       
   681     val ind_case_names = RuleCases.case_names induct_cases;
       
   682     val induct =
   683     val induct =
   683       if coind then
   684       if coind then
   684         (raw_induct, [RuleCases.case_names [rec_name],
   685         (raw_induct, [RuleCases.case_names [rec_name],
   685           RuleCases.case_conclusion (rec_name, induct_cases),
   686           RuleCases.case_conclusion (rec_name, intr_names),
   686           RuleCases.consumes 1])
   687           RuleCases.consumes 1, InductAttrib.coinduct_set (hd cnames)])
   687       else if no_ind orelse length cs > 1 then
   688       else if no_ind orelse length cnames > 1 then
   688         (raw_induct, [ind_case_names, RuleCases.consumes 0])
   689         (raw_induct, [ind_case_names, RuleCases.consumes 0])
   689       else (raw_induct RSN (2, rev_mp), [ind_case_names, RuleCases.consumes 1]);
   690       else (raw_induct RSN (2, rev_mp), [ind_case_names, RuleCases.consumes 1]);
   690 
   691 
   691     val (intrs', ctxt2) =
   692     val (intrs', ctxt1) =
   692       ctxt1 |>
   693       ctxt |>
   693       note_theorems
   694       note_theorems
   694         (map (NameSpace.qualified rec_name) intr_names ~~
   695         (map (NameSpace.qualified rec_name) intr_names ~~
   695          intr_atts ~~ map (fn th => [([th],
   696          intr_atts ~~ map (fn th => [([th],
   696            [Attrib.internal (K (ContextRules.intro_query NONE))])]) intrs) |>>
   697            [Attrib.internal (K (ContextRules.intro_query NONE))])]) intrs) |>>
   697       map (hd o snd); (* FIXME? *)
   698       map (hd o snd); (* FIXME? *)
   698     val (((_, elims'), (_, [induct'])), ctxt3) =
   699     val (((_, elims'), (_, [induct'])), ctxt2) =
   699       ctxt2 |>
   700       ctxt1 |>
   700       note_theorem ((NameSpace.qualified rec_name "intros", []), intrs') ||>>
   701       note_theorem ((NameSpace.qualified rec_name "intros", []), intrs') ||>>
   701       fold_map (fn (name, (elim, cases)) =>
   702       fold_map (fn (name, (elim, cases)) =>
   702         note_theorem ((NameSpace.qualified (Sign.base_name name) "cases",
   703         note_theorem ((NameSpace.qualified (Sign.base_name name) "cases",
   703           [Attrib.internal (K (RuleCases.case_names cases)),
   704           [Attrib.internal (K (RuleCases.case_names cases)),
   704            Attrib.internal (K (RuleCases.consumes 1)),
   705            Attrib.internal (K (RuleCases.consumes 1)),
   705            Attrib.internal (K (InductAttrib.cases_set name)),
   706            Attrib.internal (K (InductAttrib.cases_set name)),
   706            Attrib.internal (K (ContextRules.elim_query NONE))]), [elim]) #>
   707            Attrib.internal (K (ContextRules.elim_query NONE))]), [elim]) #>
   707         apfst (hd o snd)) elims ||>>
   708         apfst (hd o snd)) (if null elims then [] else cnames ~~ elims) ||>>
   708       note_theorem ((NameSpace.qualified rec_name (coind_prefix coind ^ "induct"),
   709       note_theorem ((NameSpace.qualified rec_name (coind_prefix coind ^ "induct"),
   709         map (Attrib.internal o K) (#2 induct)), [rulify (#1 induct)]);
   710         map (Attrib.internal o K) (#2 induct)), [rulify (#1 induct)]);
   710 
   711 
   711     val induct_att = if coind then InductAttrib.coinduct_set else InductAttrib.induct_set;
   712     val ctxt3 = if no_ind orelse coind then ctxt2 else
   712     val ctxt4 = if no_ind then ctxt3 else
   713       let val inducts = cnames ~~ ProjectRule.projects ctxt2 (1 upto length cnames) induct'
   713       let val inducts = cnames ~~ ProjectRule.projects ctxt (1 upto length cnames) induct'
       
   714       in
   714       in
   715         ctxt3 |>
   715         ctxt2 |>
   716         note_theorems [((NameSpace.qualified rec_name (coind_prefix coind ^ "inducts"), []),
   716         note_theorems [((NameSpace.qualified rec_name "inducts", []),
   717           inducts |> map (fn (name, th) => ([th],
   717           inducts |> map (fn (name, th) => ([th],
   718             [Attrib.internal (K ind_case_names),
   718             [Attrib.internal (K ind_case_names),
   719              Attrib.internal (K (RuleCases.consumes 1)),
   719              Attrib.internal (K (RuleCases.consumes 1)),
   720              Attrib.internal (K (induct_att name))])))] |> snd
   720              Attrib.internal (K (InductAttrib.induct_set name))])))] |> snd
   721       end;
   721       end
       
   722   in (intrs', elims', induct', ctxt3) end;
       
   723 
       
   724 type add_ind_def = bool -> bstring -> bool -> bool -> bool ->
       
   725   term list -> ((string * Attrib.src list) * term) list -> thm list ->
       
   726   term list -> (string * mixfix) list ->
       
   727   local_theory -> inductive_result * local_theory
       
   728 
       
   729 fun add_ind_def verbose alt_name coind no_elim no_ind cs
       
   730     intros monos params cnames_syn ctxt =
       
   731   let
       
   732     val _ =
       
   733       if verbose then message ("Proofs for " ^ coind_prefix coind ^ "inductive predicate(s) " ^
       
   734         commas_quote (map fst cnames_syn)) else ();
       
   735 
       
   736     val cnames = map (Sign.full_name (ProofContext.theory_of ctxt) o #1) cnames_syn;  (* FIXME *)
       
   737     val ((intr_names, intr_atts), intr_ts) =
       
   738       apfst split_list (split_list (map (check_rule ctxt cs params) intros));
       
   739 
       
   740     val (ctxt1, rec_name, mono, fp_def, rec_preds_defs, rec_const, preds,
       
   741       argTs, bs, xs) = mk_ind_def alt_name coind cs intr_ts
       
   742         monos params cnames_syn ctxt;
       
   743 
       
   744     val (intrs, unfold) = prove_intrs coind mono fp_def (length bs + length xs)
       
   745       params intr_ts rec_preds_defs ctxt1;
       
   746     val elims = if no_elim then [] else
       
   747       prove_elims cs params intr_ts intr_names unfold rec_preds_defs ctxt1;
       
   748     val raw_induct = zero_var_indexes
       
   749       (if no_ind then Drule.asm_rl else
       
   750        if coind then
       
   751          singleton (ProofContext.export
       
   752            (snd (Variable.add_fixes (map (fst o dest_Free) params) ctxt1)) ctxt1)
       
   753            (rotate_prems ~1 (ObjectLogic.rulify (rule_by_tactic
       
   754              (rewrite_tac [le_fun_def, le_bool_def, sup_fun_eq, sup_bool_eq] THEN
       
   755                fold_tac rec_preds_defs) (mono RS (fp_def RS def_coinduct)))))
       
   756        else
       
   757          prove_indrule cs argTs bs xs rec_const params intr_ts mono fp_def
       
   758            rec_preds_defs ctxt1);
       
   759 
       
   760     val (intrs', elims', induct, ctxt2) = declare_rules rec_name coind no_ind
       
   761       cnames intrs intr_names intr_atts elims raw_induct ctxt1;
   722 
   762 
   723     val names = map #1 cnames_syn;
   763     val names = map #1 cnames_syn;
   724     val result =
   764     val result =
   725       {preds = preds,
   765       {preds = preds,
   726        defs = fp_def :: rec_preds_defs,
       
   727        mono = mono,
       
   728        unfold = unfold,
       
   729        intrs = intrs',
   766        intrs = intrs',
   730        elims = elims',
   767        elims = elims',
   731        raw_induct = rulify raw_induct,
   768        raw_induct = rulify raw_induct,
   732        induct = induct'};
   769        induct = induct};
   733 
   770 
   734     val ctxt5 = ctxt4
   771     val ctxt3 = ctxt2
   735       |> Context.proof_map (put_inductives names ({names = names, coind = coind}, result))
   772       |> Context.proof_map (put_inductives names ({names = names, coind = coind}, result))
   736       |> LocalTheory.declaration (fn phi =>
   773       |> LocalTheory.declaration (fn phi =>
   737         let
   774         let
   738           val names' = map (LocalTheory.target_name ctxt4 o Morphism.name phi) names;
   775           val names' = map (LocalTheory.target_name ctxt2 o Morphism.name phi) names;
   739           val result' = morph_result phi result;
   776           val result' = morph_result phi result;
   740         in put_inductives names' ({names = names', coind = coind}, result') end);
   777         in put_inductives names' ({names = names', coind = coind}, result') end);
   741   in (result, ctxt5) end;
   778   in (result, ctxt3) end;
   742 
   779 
   743 
   780 
   744 (* external interfaces *)
   781 (* external interfaces *)
   745 
   782 
   746 fun add_inductive_i verbose alt_name coind no_elim no_ind cnames_syn pnames pre_intros monos ctxt =
   783 fun gen_add_inductive_i mk_def verbose alt_name coind no_elim no_ind
       
   784     cnames_syn pnames pre_intros monos ctxt =
   747   let
   785   let
   748     val thy = ProofContext.theory_of ctxt;
   786     val thy = ProofContext.theory_of ctxt;
   749     val _ = Theory.requires thy "Inductive" (coind_prefix coind ^ "inductive definitions");
   787     val _ = Theory.requires thy "Inductive" (coind_prefix coind ^ "inductive definitions");
   750 
   788 
   751     val frees = fold (Term.add_frees o snd) pre_intros [];
   789     val frees = fold (Term.add_frees o snd) pre_intros [];
   795       (fn t as Free (v as (s, _)) =>
   833       (fn t as Free (v as (s, _)) =>
   796             if Variable.is_fixed ctxt s orelse member op = cs t orelse
   834             if Variable.is_fixed ctxt s orelse member op = cs t orelse
   797               member op = params t then I else insert op = v
   835               member op = params t then I else insert op = v
   798         | _ => I) r []), r));
   836         | _ => I) r []), r));
   799 
   837 
   800     val intros = map (apsnd (expand abbrevs') #>
   838     val intros = map (apsnd (expand abbrevs') #> close_rule) pre_intros';
   801       check_rule thy cs params #> close_rule) pre_intros';
       
   802   in
   839   in
   803     ctxt |>
   840     ctxt |>
   804     add_ind_def verbose alt_name coind no_elim no_ind cs intros monos
   841     mk_def verbose alt_name coind no_elim no_ind cs intros monos
   805       params cnames_syn'' ||>
   842       params cnames_syn'' ||>
   806     fold (snd oo LocalTheory.abbrev Syntax.default_mode) abbrevs''
   843     fold (snd oo LocalTheory.abbrev Syntax.default_mode) abbrevs''
   807   end;
   844   end;
   808 
   845 
   809 fun add_inductive verbose coind cnames_syn pnames_syn intro_srcs raw_monos ctxt =
   846 fun gen_add_inductive mk_def verbose coind cnames_syn pnames_syn intro_srcs raw_monos ctxt =
   810   let
   847   let
   811     val (_, ctxt') = Specification.read_specification (cnames_syn @ pnames_syn) [] ctxt;
   848     val (_, ctxt') = Specification.read_specification (cnames_syn @ pnames_syn) [] ctxt;
   812     val intrs = map (fn ((name, att), s) => apsnd hd (hd (snd (fst
   849     val intrs = map (fn ((name, att), s) => apsnd hd (hd (snd (fst
   813       (Specification.read_specification [] [((name, att), [s])] ctxt'))))
   850       (Specification.read_specification [] [((name, att), [s])] ctxt'))))
   814       handle ERROR msg =>
   851       handle ERROR msg =>
   818       (s, SOME (ProofContext.infer_type ctxt' s))) pnames_syn;
   855       (s, SOME (ProofContext.infer_type ctxt' s))) pnames_syn;
   819     val cnames_syn' = map (fn (s, _, mx) =>
   856     val cnames_syn' = map (fn (s, _, mx) =>
   820       (s, SOME (ProofContext.infer_type ctxt' s), mx)) cnames_syn;
   857       (s, SOME (ProofContext.infer_type ctxt' s), mx)) cnames_syn;
   821     val (monos, ctxt'') = LocalTheory.theory_result (IsarCmd.apply_theorems raw_monos) ctxt;
   858     val (monos, ctxt'') = LocalTheory.theory_result (IsarCmd.apply_theorems raw_monos) ctxt;
   822   in
   859   in
   823     add_inductive_i verbose "" coind false false cnames_syn' pnames intrs monos ctxt''
   860     gen_add_inductive_i mk_def verbose "" coind false false cnames_syn' pnames intrs monos ctxt''
   824   end;
   861   end;
       
   862 
       
   863 val add_inductive_i = gen_add_inductive_i add_ind_def;
       
   864 val add_inductive = gen_add_inductive add_ind_def;
   825 
   865 
   826 fun add_inductive_global verbose alt_name coind no_elim no_ind cnames_syn pnames pre_intros monos =
   866 fun add_inductive_global verbose alt_name coind no_elim no_ind cnames_syn pnames pre_intros monos =
   827   TheoryTarget.init NONE #>
   867   TheoryTarget.init NONE #>
   828   add_inductive_i verbose alt_name coind no_elim no_ind cnames_syn pnames pre_intros monos #>
   868   add_inductive_i verbose alt_name coind no_elim no_ind cnames_syn pnames pre_intros monos #>
   829   (fn (_, lthy) =>
   869   (fn (_, lthy) =>
   888 (** package setup **)
   928 (** package setup **)
   889 
   929 
   890 (* setup theory *)
   930 (* setup theory *)
   891 
   931 
   892 val setup =
   932 val setup =
   893   Method.add_methods [("ind_cases2", ind_cases,   (* FIXME "ind_cases" (?) *)
   933   Method.add_methods [("ind_cases", ind_cases,
   894     "dynamic case analysis on predicates")] #>
   934     "dynamic case analysis on predicates")] #>
   895   Attrib.add_attributes [("mono2", Attrib.add_del_args mono_add mono_del,   (* FIXME "mono" *)
   935   Attrib.add_attributes [("mono", Attrib.add_del_args mono_add mono_del,
   896     "declaration of monotonicity rule")];
   936     "declaration of monotonicity rule")];
   897 
   937 
   898 
   938 
   899 (* outer syntax *)
   939 (* outer syntax *)
   900 
   940 
   908               else if b = "" then ((a, atts), B)
   948               else if b = "" then ((a, atts), B)
   909               else error ("Illegal nested case names " ^ quote (NameSpace.append a b))
   949               else error ("Illegal nested case names " ^ quote (NameSpace.append a b))
   910           | ((b, _), _) => error ("Illegal simultaneous specification " ^ quote b))
   950           | ((b, _), _) => error ("Illegal simultaneous specification " ^ quote b))
   911     | (a, _) => error ("Illegal local specification parameters for " ^ quote a));
   951     | (a, _) => error ("Illegal local specification parameters for " ^ quote a));
   912 
   952 
   913 fun ind_decl coind =
   953 fun gen_ind_decl mk_def coind =
   914   P.opt_target --
   954   P.opt_target --
   915   P.fixes -- P.for_fixes --
   955   P.fixes -- P.for_fixes --
   916   Scan.optional (P.$$$ "where" |-- P.!!! SpecParse.specification) [] --
   956   Scan.optional (P.$$$ "where" |-- P.!!! SpecParse.specification) [] --
   917   Scan.optional (P.$$$ "monos" |-- P.!!! SpecParse.xthms1) []
   957   Scan.optional (P.$$$ "monos" |-- P.!!! SpecParse.xthms1) []
   918   >> (fn ((((loc, preds), params), specs), monos) =>
   958   >> (fn ((((loc, preds), params), specs), monos) =>
   919     Toplevel.local_theory loc
   959     Toplevel.local_theory loc
   920       (fn lthy => lthy
   960       (fn lthy => lthy |> gen_add_inductive mk_def true coind preds params
   921         |> add_inductive true coind preds params (flatten_specification specs) monos |> snd));
   961          (flatten_specification specs) monos |> snd));
       
   962 
       
   963 val ind_decl = gen_ind_decl add_ind_def;
   922 
   964 
   923 val inductiveP =
   965 val inductiveP =
   924   OuterSyntax.command "inductive2" "define inductive predicates" K.thy_decl (ind_decl false);
   966   OuterSyntax.command "inductive" "define inductive predicates" K.thy_decl (ind_decl false);
   925 
   967 
   926 val coinductiveP =
   968 val coinductiveP =
   927   OuterSyntax.command "coinductive2" "define coinductive predicates" K.thy_decl (ind_decl true);
   969   OuterSyntax.command "coinductive" "define coinductive predicates" K.thy_decl (ind_decl true);
   928 
   970 
   929 
   971 
   930 val inductive_casesP =
   972 val inductive_casesP =
   931   OuterSyntax.command "inductive_cases2"
   973   OuterSyntax.command "inductive_cases"
   932     "create simplified instances of elimination rules (improper)" K.thy_script
   974     "create simplified instances of elimination rules (improper)" K.thy_script
   933     (P.opt_target -- P.and_list1 SpecParse.spec
   975     (P.opt_target -- P.and_list1 SpecParse.spec
   934       >> (fn (loc, specs) => Toplevel.local_theory loc (snd o inductive_cases specs)));
   976       >> (fn (loc, specs) => Toplevel.local_theory loc (snd o inductive_cases specs)));
   935 
   977 
   936 val _ = OuterSyntax.add_keywords ["monos"];
   978 val _ = OuterSyntax.add_keywords ["monos"];