11 val coinduction_tac: Proof.context -> term list -> thm option -> thm list -> cases_tactic |
11 val coinduction_tac: Proof.context -> term list -> thm option -> thm list -> cases_tactic |
12 end; |
12 end; |
13 |
13 |
14 structure Coinduction : COINDUCTION = |
14 structure Coinduction : COINDUCTION = |
15 struct |
15 struct |
16 |
|
17 open Ctr_Sugar_Util |
|
18 open Ctr_Sugar_General_Tactics |
|
19 |
16 |
20 fun filter_in_out _ [] = ([], []) |
17 fun filter_in_out _ [] = ([], []) |
21 | filter_in_out P (x :: xs) = |
18 | filter_in_out P (x :: xs) = |
22 let |
19 let |
23 val (ins, outs) = filter_in_out P xs; |
20 val (ins, outs) = filter_in_out P xs; |
77 HOLogic.mk_eq (Free (name, T), rhs)) |
74 HOLogic.mk_eq (Free (name, T), rhs)) |
78 names Ts raw_eqs; |
75 names Ts raw_eqs; |
79 val phi = eqs @ map (HOLogic.dest_Trueprop o prop_of) prems |
76 val phi = eqs @ map (HOLogic.dest_Trueprop o prop_of) prems |
80 |> try (Library.foldr1 HOLogic.mk_conj) |
77 |> try (Library.foldr1 HOLogic.mk_conj) |
81 |> the_default @{term True} |
78 |> the_default @{term True} |
82 |> list_exists_free vars |
79 |> Ctr_Sugar_Util.list_exists_free vars |
83 |> Term.map_abs_vars (Variable.revert_fixed ctxt) |
80 |> Term.map_abs_vars (Variable.revert_fixed ctxt) |
84 |> fold_rev Term.absfree (names ~~ Ts) |
81 |> fold_rev Term.absfree (names ~~ Ts) |
85 |> certify ctxt; |
82 |> Ctr_Sugar_Util.certify ctxt; |
86 val thm = cterm_instantiate_pos [SOME phi] raw_thm; |
83 val thm = Ctr_Sugar_Util.cterm_instantiate_pos [SOME phi] raw_thm; |
87 val e = length eqs; |
84 val e = length eqs; |
88 val p = length prems; |
85 val p = length prems; |
89 in |
86 in |
90 HEADGOAL (EVERY' [resolve_tac [thm], |
87 HEADGOAL (EVERY' [resolve_tac [thm], |
91 EVERY' (map (fn var => |
88 EVERY' (map (fn var => |
92 resolve_tac [cterm_instantiate_pos [NONE, SOME (certify ctxt var)] exI]) vars), |
89 resolve_tac |
93 if p = 0 then CONJ_WRAP' (K (resolve_tac [refl])) eqs |
90 [Ctr_Sugar_Util.cterm_instantiate_pos |
|
91 [NONE, SOME (Ctr_Sugar_Util.certify ctxt var)] exI]) vars), |
|
92 if p = 0 then Ctr_Sugar_Util.CONJ_WRAP' (K (resolve_tac [refl])) eqs |
94 else |
93 else |
95 REPEAT_DETERM_N e o (resolve_tac [conjI] THEN' resolve_tac [refl]) THEN' |
94 REPEAT_DETERM_N e o (resolve_tac [conjI] THEN' resolve_tac [refl]) THEN' |
96 CONJ_WRAP' (resolve_tac o single) prems, |
95 Ctr_Sugar_Util.CONJ_WRAP' (resolve_tac o single) prems, |
97 K (ALLGOALS_SKIP skip |
96 K (ALLGOALS_SKIP skip |
98 (REPEAT_DETERM_N (length vars) o (eresolve_tac [exE] THEN' rotate_tac ~1) THEN' |
97 (REPEAT_DETERM_N (length vars) o (eresolve_tac [exE] THEN' rotate_tac ~1) THEN' |
99 DELETE_PREMS_AFTER 0 (Subgoal.FOCUS (fn {prems, params, context = ctxt, ...} => |
98 DELETE_PREMS_AFTER 0 (Subgoal.FOCUS (fn {prems, params, context = ctxt, ...} => |
100 (case prems of |
99 (case prems of |
101 [] => all_tac |
100 [] => all_tac |
108 member (fn (t, (_, t')) => t aconv (term_of t')) params t; |
107 member (fn (t, (_, t')) => t aconv (term_of t')) params t; |
109 val (eqs, assms') = filter_in_out (is_local_var o lhs_of_eq o prop_of) eqs; |
108 val (eqs, assms') = filter_in_out (is_local_var o lhs_of_eq o prop_of) eqs; |
110 val assms = assms' @ drop e inv_thms |
109 val assms = assms' @ drop e inv_thms |
111 in |
110 in |
112 HEADGOAL (Method.insert_tac (assms @ case_prems)) THEN |
111 HEADGOAL (Method.insert_tac (assms @ case_prems)) THEN |
113 unfold_thms_tac ctxt eqs |
112 Ctr_Sugar_General_Tactics.unfold_thms_tac ctxt eqs |
114 end)) ctxt)))]) |
113 end)) ctxt)))]) |
115 end) ctxt) THEN' |
114 end) ctxt) THEN' |
116 K (prune_params_tac ctxt)) |
115 K (prune_params_tac ctxt)) |
117 #> Seq.maps (fn st => |
116 #> Seq.maps (fn st => |
118 CASES (Rule_Cases.make_common (Proof_Context.theory_of ctxt, prop_of st) cases) all_tac st) |
117 CASES (Rule_Cases.make_common (Proof_Context.theory_of ctxt, prop_of st) cases) all_tac st) |
135 named_rule Induct.typeN (Args.type_name {proper = false, strict = false}) get_type || |
134 named_rule Induct.typeN (Args.type_name {proper = false, strict = false}) get_type || |
136 named_rule Induct.predN (Args.const {proper = false, strict = false}) get_pred || |
135 named_rule Induct.predN (Args.const {proper = false, strict = false}) get_pred || |
137 named_rule Induct.setN (Args.const {proper = false, strict = false}) get_pred || |
136 named_rule Induct.setN (Args.const {proper = false, strict = false}) get_pred || |
138 Scan.lift (Args.$$$ ruleN -- Args.colon) |-- Attrib.thms; |
137 Scan.lift (Args.$$$ ruleN -- Args.colon) |-- Attrib.thms; |
139 |
138 |
140 val coinduct_rule = rule Induct.lookup_coinductT Induct.lookup_coinductP >> single_rule; |
139 val coinduct_rule = |
|
140 rule Induct.lookup_coinductT Induct.lookup_coinductP >> single_rule; |
141 |
141 |
142 fun unless_more_args scan = Scan.unless (Scan.lift |
142 fun unless_more_args scan = Scan.unless (Scan.lift |
143 ((Args.$$$ arbitraryN || Args.$$$ Induct.typeN || |
143 ((Args.$$$ arbitraryN || Args.$$$ Induct.typeN || |
144 Args.$$$ Induct.predN || Args.$$$ Induct.setN || Args.$$$ ruleN) -- Args.colon)) scan; |
144 Args.$$$ Induct.predN || Args.$$$ Induct.setN || Args.$$$ ruleN) -- Args.colon)) scan; |
145 |
145 |