86 thm list -> int -> cases_tactic |
86 thm list -> int -> cases_tactic |
87 val gen_induct_setup: binding -> |
87 val gen_induct_setup: binding -> |
88 (Proof.context -> bool -> (binding option * (term * bool)) option list list -> |
88 (Proof.context -> bool -> (binding option * (term * bool)) option list list -> |
89 (string * typ) list list -> term option list -> thm list option -> |
89 (string * typ) list list -> term option list -> thm list option -> |
90 thm list -> int -> cases_tactic) -> |
90 thm list -> int -> cases_tactic) -> |
91 theory -> theory |
91 local_theory -> local_theory |
92 end; |
92 end; |
93 |
93 |
94 functor Induct(Induct_Args: INDUCT_ARGS): INDUCT = |
94 functor Induct(Induct_Args: INDUCT_ARGS): INDUCT = |
95 struct |
95 struct |
96 |
96 |
361 Scan.lift Args.del >> K del; |
361 Scan.lift Args.del >> K del; |
362 |
362 |
363 in |
363 in |
364 |
364 |
365 val _ = |
365 val _ = |
366 Theory.setup |
366 Theory.local_setup |
367 (Attrib.setup @{binding cases} (attrib cases_type cases_pred cases_del) |
367 (Attrib.local_setup @{binding cases} (attrib cases_type cases_pred cases_del) |
368 "declaration of cases rule" #> |
368 "declaration of cases rule" #> |
369 Attrib.setup @{binding induct} (attrib induct_type induct_pred induct_del) |
369 Attrib.local_setup @{binding induct} (attrib induct_type induct_pred induct_del) |
370 "declaration of induction rule" #> |
370 "declaration of induction rule" #> |
371 Attrib.setup @{binding coinduct} (attrib coinduct_type coinduct_pred coinduct_del) |
371 Attrib.local_setup @{binding coinduct} (attrib coinduct_type coinduct_pred coinduct_del) |
372 "declaration of coinduction rule" #> |
372 "declaration of coinduction rule" #> |
373 Attrib.setup @{binding induct_simp} (Attrib.add_del induct_simp_add induct_simp_del) |
373 Attrib.local_setup @{binding induct_simp} (Attrib.add_del induct_simp_add induct_simp_del) |
374 "declaration of rules for simplifying induction or cases rules"); |
374 "declaration of rules for simplifying induction or cases rules"); |
375 |
375 |
376 end; |
376 end; |
377 |
377 |
378 |
378 |
735 |
735 |
736 fun gen_induct_tac mod_cases ctxt simp def_insts arbitrary taking opt_rule facts = |
736 fun gen_induct_tac mod_cases ctxt simp def_insts arbitrary taking opt_rule facts = |
737 SUBGOAL_CASES (fn (_, i, st) => |
737 SUBGOAL_CASES (fn (_, i, st) => |
738 let |
738 let |
739 val thy = Proof_Context.theory_of ctxt; |
739 val thy = Proof_Context.theory_of ctxt; |
740 |
740 |
741 val ((insts, defs), defs_ctxt) = fold_map add_defs def_insts ctxt |>> split_list; |
741 val ((insts, defs), defs_ctxt) = fold_map add_defs def_insts ctxt |>> split_list; |
742 val atomized_defs = map (map (Conv.fconv_rule (atomize_cterm defs_ctxt))) defs; |
742 val atomized_defs = map (map (Conv.fconv_rule (atomize_cterm defs_ctxt))) defs; |
743 |
743 |
744 fun inst_rule (concls, r) = |
744 fun inst_rule (concls, r) = |
745 (if null insts then `Rule_Cases.get r |
745 (if null insts then `Rule_Cases.get r |
746 else (align_left "Rule has fewer conclusions than arguments given" |
746 else (align_left "Rule has fewer conclusions than arguments given" |
747 (map Logic.strip_imp_concl (Logic.dest_conjunctions (Thm.concl_of r))) insts |
747 (map Logic.strip_imp_concl (Logic.dest_conjunctions (Thm.concl_of r))) insts |
748 |> maps (prep_inst ctxt align_right (atomize_term thy)) |
748 |> maps (prep_inst ctxt align_right (atomize_term thy)) |
749 |> Drule.cterm_instantiate) r |> pair (Rule_Cases.get r)) |
749 |> Drule.cterm_instantiate) r |> pair (Rule_Cases.get r)) |
750 |> mod_cases thy |
750 |> mod_cases thy |
751 |> (fn ((cases, consumes), th) => (((cases, concls), consumes), th)); |
751 |> (fn ((cases, consumes), th) => (((cases, concls), consumes), th)); |
752 |
752 |
753 val ruleq = |
753 val ruleq = |
754 (case opt_rule of |
754 (case opt_rule of |
755 SOME rs => Seq.single (inst_rule (Rule_Cases.strict_mutual_rule ctxt rs)) |
755 SOME rs => Seq.single (inst_rule (Rule_Cases.strict_mutual_rule ctxt rs)) |
756 | NONE => |
756 | NONE => |
757 (get_inductP ctxt facts @ |
757 (get_inductP ctxt facts @ |
758 map (special_rename_params defs_ctxt insts) (get_inductT ctxt insts)) |
758 map (special_rename_params defs_ctxt insts) (get_inductT ctxt insts)) |
759 |> map_filter (Rule_Cases.mutual_rule ctxt) |
759 |> map_filter (Rule_Cases.mutual_rule ctxt) |
760 |> tap (trace_rules ctxt inductN o map #2) |
760 |> tap (trace_rules ctxt inductN o map #2) |
761 |> Seq.of_list |> Seq.maps (Seq.try inst_rule)); |
761 |> Seq.of_list |> Seq.maps (Seq.try inst_rule)); |
762 |
762 |
763 fun rule_cases ctxt rule cases = |
763 fun rule_cases ctxt rule cases = |
764 let |
764 let |
765 val rule' = Rule_Cases.internalize_params rule; |
765 val rule' = Rule_Cases.internalize_params rule; |
766 val rule'' = rule' |> simp ? simplified_rule ctxt; |
766 val rule'' = rule' |> simp ? simplified_rule ctxt; |
767 val nonames = map (fn ((cn, _), cls) => ((cn, []), cls)); |
767 val nonames = map (fn ((cn, _), cls) => ((cn, []), cls)); |
908 val taking = Scan.optional (Scan.lift (Args.$$$ takingN -- Args.colon) |-- |
908 val taking = Scan.optional (Scan.lift (Args.$$$ takingN -- Args.colon) |-- |
909 Scan.repeat1 (unless_more_args inst)) []; |
909 Scan.repeat1 (unless_more_args inst)) []; |
910 |
910 |
911 in |
911 in |
912 |
912 |
913 val _ = |
|
914 Theory.setup |
|
915 (Method.setup @{binding cases} |
|
916 (Scan.lift (Args.mode no_simpN) -- |
|
917 (Parse.and_list' (Scan.repeat (unless_more_args inst)) -- Scan.option cases_rule) >> |
|
918 (fn (no_simp, (insts, opt_rule)) => fn ctxt => |
|
919 METHOD_CASES (fn facts => Seq.DETERM (HEADGOAL |
|
920 (cases_tac ctxt (not no_simp) insts opt_rule facts))))) |
|
921 "case analysis on types or predicates/sets"); |
|
922 |
|
923 fun gen_induct_setup binding tac = |
913 fun gen_induct_setup binding tac = |
924 Method.setup binding |
914 Method.local_setup binding |
925 (Scan.lift (Args.mode no_simpN) -- |
915 (Scan.lift (Args.mode no_simpN) -- |
926 (Parse.and_list' (Scan.repeat (unless_more_args def_inst)) -- |
916 (Parse.and_list' (Scan.repeat (unless_more_args def_inst)) -- |
927 (arbitrary -- taking -- Scan.option induct_rule)) >> |
917 (arbitrary -- taking -- Scan.option induct_rule)) >> |
928 (fn (no_simp, (insts, ((arbitrary, taking), opt_rule))) => fn ctxt => fn facts => |
918 (fn (no_simp, (insts, ((arbitrary, taking), opt_rule))) => fn ctxt => fn facts => |
929 Seq.DETERM (HEADGOAL (tac ctxt (not no_simp) insts arbitrary taking opt_rule facts)))) |
919 Seq.DETERM (HEADGOAL (tac ctxt (not no_simp) insts arbitrary taking opt_rule facts)))) |
930 "induction on types or predicates/sets"; |
920 "induction on types or predicates/sets"; |
931 |
921 |
932 val _ = Theory.setup (gen_induct_setup @{binding induct} induct_tac); |
|
933 |
|
934 val _ = |
922 val _ = |
935 Theory.setup |
923 Theory.local_setup |
936 (Method.setup @{binding coinduct} |
924 (Method.local_setup @{binding cases} |
|
925 (Scan.lift (Args.mode no_simpN) -- |
|
926 (Parse.and_list' (Scan.repeat (unless_more_args inst)) -- Scan.option cases_rule) >> |
|
927 (fn (no_simp, (insts, opt_rule)) => fn ctxt => |
|
928 METHOD_CASES (fn facts => Seq.DETERM (HEADGOAL |
|
929 (cases_tac ctxt (not no_simp) insts opt_rule facts))))) |
|
930 "case analysis on types or predicates/sets" #> |
|
931 gen_induct_setup @{binding induct} induct_tac #> |
|
932 Method.local_setup @{binding coinduct} |
937 (Scan.repeat (unless_more_args inst) -- taking -- Scan.option coinduct_rule >> |
933 (Scan.repeat (unless_more_args inst) -- taking -- Scan.option coinduct_rule >> |
938 (fn ((insts, taking), opt_rule) => fn ctxt => fn facts => |
934 (fn ((insts, taking), opt_rule) => fn ctxt => fn facts => |
939 Seq.DETERM (HEADGOAL (coinduct_tac ctxt insts taking opt_rule facts)))) |
935 Seq.DETERM (HEADGOAL (coinduct_tac ctxt insts taking opt_rule facts)))) |
940 "coinduction on types or predicates/sets"); |
936 "coinduction on types or predicates/sets"); |
941 |
937 |