| author | berghofe |
| Mon, 22 Oct 2001 14:52:43 +0200 | |
| changeset 11874 | 83c97febc828 |
| parent 11808 | c724a9093ebe |
| child 11984 | 324f69149895 |
| permissions | -rw-r--r-- |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
1 |
(* Title: Provers/induct_method.ML |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
2 |
ID: $Id$ |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
3 |
Author: Markus Wenzel, TU Muenchen |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
4 |
License: GPL (GNU GENERAL PUBLIC LICENSE) |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
5 |
|
| 11735 | 6 |
Proof by cases and induction on sets and types. |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
7 |
*) |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
8 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
9 |
signature INDUCT_METHOD_DATA = |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
10 |
sig |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
11 |
val dest_concls: term -> term list |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
12 |
val cases_default: thm |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
13 |
val conjI: thm |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
14 |
val atomize: thm list |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
15 |
val rulify1: thm list |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
16 |
val rulify2: thm list |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
17 |
end; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
18 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
19 |
signature INDUCT_METHOD = |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
20 |
sig |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
21 |
val setup: (theory -> theory) list |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
22 |
end; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
23 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
24 |
functor InductMethodFun(Data: INDUCT_METHOD_DATA): INDUCT_METHOD = |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
25 |
struct |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
26 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
27 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
28 |
(** misc utils **) |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
29 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
30 |
(* align lists *) |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
31 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
32 |
fun align_left msg xs ys = |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
33 |
let val m = length xs and n = length ys |
| 11735 | 34 |
in if m < n then raise ERROR_MESSAGE msg else (Library.take (n, xs) ~~ ys) end; |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
35 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
36 |
fun align_right msg xs ys = |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
37 |
let val m = length xs and n = length ys |
| 11735 | 38 |
in if m < n then raise ERROR_MESSAGE msg else (Library.drop (m - n, xs) ~~ ys) end; |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
39 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
40 |
|
| 11735 | 41 |
(* prep_inst *) |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
42 |
|
| 11735 | 43 |
fun prep_inst align cert tune (tm, ts) = |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
44 |
let |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
45 |
fun prep_var (x, Some t) = |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
46 |
let |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
47 |
val cx = cert x; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
48 |
val {T = xT, sign, ...} = Thm.rep_cterm cx;
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
49 |
val orig_ct = cert t; |
| 11735 | 50 |
val ct = tune orig_ct; |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
51 |
in |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
52 |
if Sign.typ_instance sign (#T (Thm.rep_cterm ct), xT) then Some (cx, ct) |
| 11735 | 53 |
else raise ERROR_MESSAGE (Pretty.string_of (Pretty.block |
54 |
[Pretty.str "Ill-typed instantiation:", Pretty.fbrk, |
|
55 |
Display.pretty_cterm ct, Pretty.str " ::", Pretty.brk 1, |
|
56 |
Display.pretty_ctyp (#T (Thm.crep_cterm ct))])) |
|
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
57 |
end |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
58 |
| prep_var (_, None) = None; |
| 11735 | 59 |
val xs = InductAttrib.vars_of tm; |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
60 |
in |
| 11735 | 61 |
align "Rule has fewer variables than instantiations given" xs ts |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
62 |
|> mapfilter prep_var |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
63 |
end; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
64 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
65 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
66 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
67 |
(** cases method **) |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
68 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
69 |
(* |
| 11735 | 70 |
rule selection scheme: |
71 |
cases - classical case split |
|
72 |
<x:A> cases ... - set cases |
|
73 |
cases t - type cases |
|
74 |
... cases ... R - explicit rule |
|
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
75 |
*) |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
76 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
77 |
local |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
78 |
|
|
11790
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
79 |
fun resolveq_cases_tac make ruleq i st = |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
80 |
ruleq |> Seq.map (fn (rule, (cases, facts)) => |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
81 |
(Method.insert_tac facts THEN' Tactic.rtac rule) i st |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
82 |
|> Seq.map (rpair (make rule cases))) |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
83 |
|> Seq.flat; |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
84 |
|
| 11735 | 85 |
fun find_casesT ctxt ((Some t :: _) :: _) = InductAttrib.find_casesT ctxt (fastype_of t) |
86 |
| find_casesT _ _ = []; |
|
87 |
||
88 |
fun find_casesS ctxt (fact :: _) = InductAttrib.find_casesS ctxt fact |
|
89 |
| find_casesS _ _ = []; |
|
90 |
||
91 |
fun cases_tac (ctxt, (open_parms, (insts, opt_rule))) facts = |
|
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
92 |
let |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
93 |
val sg = ProofContext.sign_of ctxt; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
94 |
val cert = Thm.cterm_of sg; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
95 |
|
| 11735 | 96 |
fun inst_rule r = |
97 |
if null insts then RuleCases.add r |
|
98 |
else (align_left "Rule has fewer premises than arguments given" (Thm.prems_of r) insts |
|
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
99 |
|> (flat o map (prep_inst align_left cert I)) |
| 11735 | 100 |
|> Drule.cterm_instantiate) r |> rpair (RuleCases.get r); |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
101 |
|
| 11735 | 102 |
val ruleq = |
103 |
(case (facts, insts, opt_rule) of |
|
104 |
([], [], None) => Seq.single (RuleCases.add Data.cases_default) |
|
105 |
| (_, _, None) => |
|
106 |
let val rules = find_casesS ctxt facts @ find_casesT ctxt insts in |
|
107 |
if null rules then error "Unable to figure out cases rule" else (); |
|
108 |
Method.trace rules; |
|
109 |
Seq.flat (Seq.map (Seq.try inst_rule) (Seq.of_list rules)) |
|
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
110 |
end |
| 11735 | 111 |
| (_, _, Some r) => Seq.single (inst_rule r)); |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
112 |
|
| 11735 | 113 |
fun prep_rule (th, (cases, n)) = Seq.map (apsnd (rpair (drop (n, facts))) o rpair cases) |
114 |
(Method.multi_resolves (take (n, facts)) [th]); |
|
|
11790
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
115 |
in resolveq_cases_tac (RuleCases.make open_parms) (Seq.flat (Seq.map prep_rule ruleq)) end; |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
116 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
117 |
in |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
118 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
119 |
val cases_meth = Method.METHOD_CASES o (HEADGOAL oo cases_tac); |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
120 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
121 |
end; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
122 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
123 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
124 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
125 |
(** induct method **) |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
126 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
127 |
(* |
| 11735 | 128 |
rule selection scheme: |
129 |
<x:A> induct ... - set induction |
|
130 |
induct x - type induction |
|
131 |
... induct ... R - explicit rule |
|
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
132 |
*) |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
133 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
134 |
local |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
135 |
|
|
11790
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
136 |
|
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
137 |
(* atomize and rulify *) |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
138 |
|
| 11756 | 139 |
fun atomize_cterm ct = |
| 11781 | 140 |
Thm.cterm_fun (ObjectLogic.drop_judgment (#sign (Thm.rep_cterm ct))) |
141 |
(Tactic.rewrite_cterm true Data.atomize ct); |
|
| 11756 | 142 |
|
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
143 |
val atomize_tac = Tactic.rewrite_goal_tac Data.atomize; |
| 11781 | 144 |
val rulify_cterm = Tactic.rewrite_cterm true Data.rulify2 o Tactic.rewrite_cterm true Data.rulify1; |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
145 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
146 |
val rulify_tac = |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
147 |
Tactic.rewrite_goal_tac Data.rulify1 THEN' |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
148 |
Tactic.rewrite_goal_tac Data.rulify2 THEN' |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
149 |
Tactic.norm_hhf_tac; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
150 |
|
| 11756 | 151 |
fun rulify_cases sg cert = |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
152 |
let |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
153 |
val ruly = Thm.term_of o rulify_cterm o cert; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
154 |
fun ruly_case {fixes, assumes, binds} =
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
155 |
{fixes = fixes, assumes = map ruly assumes,
|
| 11756 | 156 |
binds = map (apsnd (apsome (ObjectLogic.drop_judgment sg o ruly))) binds}; |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
157 |
in map (apsnd ruly_case) ooo RuleCases.make_raw end; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
158 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
159 |
|
|
11790
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
160 |
(* join multi-rules *) |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
161 |
|
| 11735 | 162 |
val eq_prems = curry (Term.aconvs o pairself Thm.prems_of); |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
163 |
|
| 11735 | 164 |
fun join_rules [] = [] |
165 |
| join_rules [th] = [th] |
|
166 |
| join_rules (rules as r :: rs) = |
|
167 |
if not (forall (eq_prems r) rs) then [] |
|
168 |
else |
|
169 |
let |
|
170 |
val th :: ths = map Drule.freeze_all rules; |
|
171 |
val cprems = Drule.cprems_of th; |
|
172 |
val asms = map Thm.assume cprems; |
|
173 |
in |
|
174 |
[foldr1 (fn (x, x') => [x, x'] MRS Data.conjI) |
|
175 |
(map (fn x => Drule.implies_elim_list x asms) (th :: ths)) |
|
176 |
|> Drule.implies_intr_list cprems |
|
177 |
|> Drule.standard'] |
|
178 |
end; |
|
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
179 |
|
|
11790
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
180 |
|
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
181 |
(* divinate rule instantiation (cannot handle pending goal parameters) *) |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
182 |
|
| 11808 | 183 |
fun dest_env sign (env as Envir.Envir {asol, iTs, ...}) =
|
|
11790
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
184 |
let |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
185 |
val pairs = Vartab.dest asol; |
| 11808 | 186 |
val ts = map (Thm.cterm_of sign o Envir.norm_term env o #2) pairs; |
|
11790
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
187 |
val xs = map2 (Thm.cterm_of sign o Var) (map #1 pairs, map (#T o Thm.rep_cterm) ts); |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
188 |
in (map (apsnd (Thm.ctyp_of sign)) (Vartab.dest iTs), xs ~~ ts) end; |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
189 |
|
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
190 |
fun divinate_inst rule i st = |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
191 |
let |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
192 |
val {sign, maxidx, ...} = Thm.rep_thm st;
|
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
193 |
val goal = List.nth (Thm.prems_of st, i - 1); (*exception Subscript*) |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
194 |
val params = rev (rename_wrt_term goal (Logic.strip_params goal)); (*as they are printed :-*) |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
195 |
in |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
196 |
if not (null params) then |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
197 |
(warning ("Cannot determine rule instantiation due to pending parameter(s): " ^
|
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
198 |
commas (map (Sign.string_of_term sign o Syntax.mark_boundT) params)); |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
199 |
Seq.single rule) |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
200 |
else |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
201 |
let |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
202 |
val rule' = Thm.incr_indexes (maxidx + 1) rule; |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
203 |
val concl = Logic.strip_assums_concl goal; |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
204 |
in |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
205 |
Unify.smash_unifiers (sign, Envir.empty (#maxidx (Thm.rep_thm rule')), |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
206 |
[(Thm.concl_of rule', concl)]) |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
207 |
|> Seq.map (fn env => Thm.instantiate (dest_env sign env) rule') |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
208 |
end |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
209 |
end handle Subscript => Seq.empty; |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
210 |
|
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
211 |
|
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
212 |
(* compose tactics with cases *) |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
213 |
|
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
214 |
fun resolveq_cases_tac' make ruleq i st = |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
215 |
ruleq |> Seq.map (fn (rule, (cases, facts)) => st |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
216 |
|> (Method.insert_tac facts THEN' atomize_tac) i |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
217 |
|> Seq.map (fn st' => divinate_inst rule i st' |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
218 |
|> Seq.map (fn rule' => st' |> Tactic.rtac rule' i |> Seq.map (rpair (make rule' cases))) |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
219 |
|> Seq.flat) |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
220 |
|> Seq.flat) |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
221 |
|> Seq.flat; |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
222 |
|
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
223 |
infix 1 THEN_ALL_NEW_CASES; |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
224 |
|
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
225 |
fun (tac1 THEN_ALL_NEW_CASES tac2) i st = |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
226 |
st |> Seq.THEN (tac1 i, (fn (st', cases) => |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
227 |
Seq.map (rpair cases) (Seq.INTERVAL tac2 i (i + nprems_of st' - nprems_of st) st'))); |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
228 |
|
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
229 |
|
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
230 |
(* find rules *) |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
231 |
|
| 11735 | 232 |
fun find_inductT ctxt insts = |
233 |
foldr multiply (insts |> mapfilter (fn [] => None | ts => last_elem ts) |
|
234 |
|> map (InductAttrib.find_inductT ctxt o fastype_of), [[]]) |
|
235 |
|> map join_rules |> flat; |
|
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
236 |
|
| 11735 | 237 |
fun find_inductS ctxt (fact :: _) = InductAttrib.find_inductS ctxt fact |
238 |
| find_inductS _ _ = []; |
|
239 |
||
|
11790
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
240 |
|
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
241 |
(* main tactic *) |
|
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
242 |
|
| 11735 | 243 |
fun induct_tac (ctxt, (open_parms, (insts, opt_rule))) facts = |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
244 |
let |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
245 |
val sg = ProofContext.sign_of ctxt; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
246 |
val cert = Thm.cterm_of sg; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
247 |
|
| 11735 | 248 |
fun inst_rule r = |
249 |
if null insts then RuleCases.add r |
|
250 |
else (align_right "Rule has fewer conclusions than arguments given" |
|
251 |
(Data.dest_concls (Thm.concl_of r)) insts |
|
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
252 |
|> (flat o map (prep_inst align_right cert atomize_cterm)) |
| 11735 | 253 |
|> Drule.cterm_instantiate) r |> rpair (RuleCases.get r); |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
254 |
|
| 11735 | 255 |
val ruleq = |
256 |
(case opt_rule of |
|
257 |
None => |
|
258 |
let val rules = find_inductS ctxt facts @ find_inductT ctxt insts in |
|
259 |
if null rules then error "Unable to figure out induct rule" else (); |
|
260 |
Method.trace rules; |
|
261 |
Seq.flat (Seq.map (Seq.try inst_rule) (Seq.of_list rules)) |
|
262 |
end |
|
263 |
| Some r => Seq.single (inst_rule r)); |
|
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
264 |
|
| 11735 | 265 |
fun prep_rule (th, (cases, n)) = |
266 |
Seq.map (rpair (cases, drop (n, facts))) (Method.multi_resolves (take (n, facts)) [th]); |
|
|
11790
42393a11642d
simplified resolveq_cases_tac for cases, separate version for induct;
wenzelm
parents:
11781
diff
changeset
|
267 |
val tac = resolveq_cases_tac' (rulify_cases sg cert open_parms) |
| 11735 | 268 |
(Seq.flat (Seq.map prep_rule ruleq)); |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
269 |
in tac THEN_ALL_NEW_CASES rulify_tac end; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
270 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
271 |
in |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
272 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
273 |
val induct_meth = Method.METHOD_CASES o (HEADGOAL oo induct_tac); |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
274 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
275 |
end; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
276 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
277 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
278 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
279 |
(** concrete syntax **) |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
280 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
281 |
val openN = "open"; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
282 |
val ruleN = "rule"; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
283 |
val ofN = "of"; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
284 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
285 |
local |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
286 |
|
| 11735 | 287 |
fun check k get name = |
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
288 |
(case get name of Some x => x |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
289 |
| None => error ("No rule for " ^ k ^ " " ^ quote name));
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
290 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
291 |
fun spec k = (Args.$$$ k -- Args.colon) |-- Args.!!! Args.name; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
292 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
293 |
fun rule get_type get_set = |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
294 |
Scan.depend (fn ctxt => |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
295 |
let val sg = ProofContext.sign_of ctxt in |
| 11735 | 296 |
spec InductAttrib.typeN >> (check InductAttrib.typeN (get_type ctxt) o |
297 |
Sign.certify_tyname sg o Sign.intern_tycon sg) || |
|
298 |
spec InductAttrib.setN >> (check InductAttrib.setN (get_set ctxt) o |
|
299 |
Sign.certify_const sg o Sign.intern_const sg) |
|
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
300 |
end >> pair ctxt) || |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
301 |
Scan.lift (Args.$$$ ruleN -- Args.colon) |-- Attrib.local_thm; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
302 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
303 |
val cases_rule = rule InductAttrib.lookup_casesT InductAttrib.lookup_casesS; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
304 |
val induct_rule = rule InductAttrib.lookup_inductT InductAttrib.lookup_inductS; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
305 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
306 |
val kind_inst = |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
307 |
(Args.$$$ InductAttrib.typeN || Args.$$$ InductAttrib.setN || Args.$$$ ruleN || Args.$$$ ofN) |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
308 |
-- Args.colon; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
309 |
val term = Scan.unless (Scan.lift kind_inst) Args.local_term; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
310 |
val term_dummy = Scan.unless (Scan.lift kind_inst) |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
311 |
(Scan.lift (Args.$$$ "_") >> K None || Args.local_term >> Some); |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
312 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
313 |
val instss = Args.and_list (Scan.repeat1 term_dummy); |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
314 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
315 |
in |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
316 |
|
| 11735 | 317 |
val cases_args = Method.syntax (Args.mode openN -- (instss -- Scan.option cases_rule)); |
318 |
val induct_args = Method.syntax (Args.mode openN -- (instss -- Scan.option induct_rule)); |
|
|
11670
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
319 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
320 |
end; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
321 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
322 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
323 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
324 |
(** theory setup **) |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
325 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
326 |
val setup = |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
327 |
[Method.add_methods |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
328 |
[(InductAttrib.casesN, cases_meth oo cases_args, "case analysis on types or sets"), |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
329 |
(InductAttrib.inductN, induct_meth oo induct_args, "induction on types or sets")]]; |
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
330 |
|
|
59f79df42d1f
proof by cases and induction on types and sets (used to be specific for HOL);
wenzelm
parents:
diff
changeset
|
331 |
end; |