author | nipkow |
Wed, 10 Jan 2018 15:25:09 +0100 | |
changeset 67399 | eab6ce8368fa |
parent 63352 | 4eaf35781b23 |
child 69568 | de09a7261120 |
permissions | -rw-r--r-- |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
1 |
(* Title: HOL/Library/simps_case_conv.ML |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
2 |
Author: Lars Noschinski, TU Muenchen |
53433 | 3 |
Author: Gerwin Klein, NICTA |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
4 |
|
53433 | 5 |
Convert function specifications between the representation as a list |
6 |
of equations (with patterns on the lhs) and a single equation (with a |
|
7 |
nested case expression on the rhs). |
|
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
8 |
*) |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
9 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
10 |
signature SIMPS_CASE_CONV = |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
11 |
sig |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
12 |
val to_case: Proof.context -> thm list -> thm |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
13 |
val gen_to_simps: Proof.context -> thm list -> thm -> thm list |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
14 |
val to_simps: Proof.context -> thm -> thm list |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
15 |
end |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
16 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
17 |
structure Simps_Case_Conv: SIMPS_CASE_CONV = |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
18 |
struct |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
19 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
20 |
(* Collects all type constructors in a type *) |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
21 |
fun collect_Tcons (Type (name,Ts)) = name :: maps collect_Tcons Ts |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
22 |
| collect_Tcons (TFree _) = [] |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
23 |
| collect_Tcons (TVar _) = [] |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
24 |
|
60702
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
25 |
fun get_type_infos ctxt = |
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
26 |
maps collect_Tcons |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
27 |
#> distinct (op =) |
54401
f6950854855d
ported 'Simps_Case_Conv' to use new 'Ctr_Sugar' abstraction
blanchet
parents:
53433
diff
changeset
|
28 |
#> map_filter (Ctr_Sugar.ctr_sugar_of ctxt) |
60702
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
29 |
|
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
30 |
fun get_split_ths ctxt = get_type_infos ctxt #> map #split |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
31 |
|
59582 | 32 |
val strip_eq = Thm.prop_of #> HOLogic.dest_Trueprop #> HOLogic.dest_eq |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
33 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
34 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
35 |
local |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
36 |
|
53429 | 37 |
fun transpose [] = [] |
38 |
| transpose ([] :: xss) = transpose xss |
|
39 |
| transpose xss = map hd xss :: transpose (map tl xss); |
|
40 |
||
60702
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
41 |
fun same_fun single_ctrs (ts as _ $ _ :: _) = |
53429 | 42 |
let |
43 |
val (fs, argss) = map strip_comb ts |> split_list |
|
44 |
val f = hd fs |
|
60702
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
45 |
fun is_single_ctr (Const (name, _)) = member (op =) single_ctrs name |
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
46 |
| is_single_ctr _ = false |
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
47 |
in if not (is_single_ctr f) andalso forall (fn x => f = x) fs then SOME (f, argss) else NONE end |
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
48 |
| same_fun _ _ = NONE |
53429 | 49 |
|
50 |
(* pats must be non-empty *) |
|
60702
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
51 |
fun split_pat single_ctrs pats ctxt = |
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
52 |
case same_fun single_ctrs pats of |
53429 | 53 |
NONE => |
54 |
let |
|
55 |
val (name, ctxt') = yield_singleton Variable.variant_fixes "x" ctxt |
|
56 |
val var = Free (name, fastype_of (hd pats)) |
|
57 |
in (((var, [var]), map single pats), ctxt') end |
|
58 |
| SOME (f, argss) => |
|
59 |
let |
|
60 |
val (((def_pats, def_frees), case_patss), ctxt') = |
|
60702
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
61 |
split_pats single_ctrs argss ctxt |
53429 | 62 |
val def_pat = list_comb (f, def_pats) |
63 |
in (((def_pat, flat def_frees), case_patss), ctxt') end |
|
64 |
and |
|
60702
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
65 |
split_pats single_ctrs patss ctxt = |
53429 | 66 |
let |
60702
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
67 |
val (splitted, ctxt') = fold_map (split_pat single_ctrs) (transpose patss) ctxt |
53429 | 68 |
val r = splitted |> split_list |> apfst split_list |> apsnd (transpose #> map flat) |
69 |
in (r, ctxt') end |
|
70 |
||
71 |
(* |
|
72 |
Takes a list lhss of left hand sides (which are lists of patterns) |
|
73 |
and a list rhss of right hand sides. Returns |
|
74 |
- a single equation with a (nested) case-expression on the rhs |
|
75 |
- a list of all split-thms needed to split the rhs |
|
76 |
Patterns which have the same outer context in all lhss remain |
|
77 |
on the lhs of the computed equation. |
|
78 |
*) |
|
79 |
fun build_case_t fun_t lhss rhss ctxt = |
|
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
80 |
let |
60702
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
81 |
val single_ctrs = |
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
82 |
get_type_infos ctxt (map fastype_of (flat lhss)) |
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
83 |
|> map_filter (fn ti => case #ctrs ti of [Const (name, _)] => SOME name | _ => NONE) |
53429 | 84 |
val (((def_pats, def_frees), case_patss), ctxt') = |
60702
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
85 |
split_pats single_ctrs lhss ctxt |
53429 | 86 |
val pattern = map HOLogic.mk_tuple case_patss |
87 |
val case_arg = HOLogic.mk_tuple (flat def_frees) |
|
88 |
val cases = Case_Translation.make_case ctxt' Case_Translation.Warning Name.context |
|
89 |
case_arg (pattern ~~ rhss) |
|
60702
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
90 |
val split_thms = get_split_ths ctxt' [fastype_of case_arg] |
53429 | 91 |
val t = (list_comb (fun_t, def_pats), cases) |
92 |
|> HOLogic.mk_eq |
|
93 |
|> HOLogic.mk_Trueprop |
|
94 |
in ((t, split_thms), ctxt') end |
|
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
95 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
96 |
fun tac ctxt {splits, intros, defs} = |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
97 |
let val ctxt' = Classical.addSIs (ctxt, intros) in |
58956
a816aa3ff391
proper context for compose_tac, Splitter.split_tac (relevant for unify trace options);
wenzelm
parents:
58028
diff
changeset
|
98 |
REPEAT_DETERM1 (FIRSTGOAL (split_tac ctxt splits)) |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
99 |
THEN Local_Defs.unfold_tac ctxt defs |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
100 |
THEN safe_tac ctxt' |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
101 |
end |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
102 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
103 |
fun import [] ctxt = ([], ctxt) |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
104 |
| import (thm :: thms) ctxt = |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
105 |
let |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
106 |
val fun_ct = strip_eq #> fst #> strip_comb #> fst #> Logic.mk_term |
59621
291934bac95e
Thm.cterm_of and Thm.ctyp_of operate on local context;
wenzelm
parents:
59582
diff
changeset
|
107 |
#> Thm.cterm_of ctxt |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
108 |
val ct = fun_ct thm |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
109 |
val cts = map fun_ct thms |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
110 |
val pairs = map (fn s => (s,ct)) cts |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
111 |
val thms' = map (fn (th,p) => Thm.instantiate (Thm.match p) th) (thms ~~ pairs) |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
112 |
in Variable.import true (thm :: thms') ctxt |> apfst snd end |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
113 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
114 |
in |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
115 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
116 |
(* |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
117 |
For a list |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
118 |
f p_11 ... p_1n = t1 |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
119 |
f p_21 ... p_2n = t2 |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
120 |
... |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
121 |
f p_mn ... p_mn = tm |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
122 |
of theorems, prove a single theorem |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
123 |
f x1 ... xn = t |
53429 | 124 |
where t is a (nested) case expression. f must not be a function |
125 |
application. Moreover, the terms p_11, ..., p_mn must be non-overlapping |
|
126 |
datatype patterns. The patterns must be exhausting up to common constructor |
|
127 |
contexts. |
|
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
128 |
*) |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
129 |
fun to_case ctxt ths = |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
130 |
let |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
131 |
val (iths, ctxt') = import ths ctxt |
53429 | 132 |
val fun_t = hd iths |> strip_eq |> fst |> head_of |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
133 |
val eqs = map (strip_eq #> apfst (snd o strip_comb)) iths |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
134 |
|
59650 | 135 |
fun hide_rhs ((pat, rhs), name) lthy = |
136 |
let |
|
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
137 |
val frees = fold Term.add_frees pat [] |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
138 |
val abs_rhs = fold absfree frees rhs |
63344 | 139 |
val ([(f, (_, def))], lthy') = lthy |
63352 | 140 |
|> Local_Defs.define [((Binding.name name, NoSyn), (Binding.empty_atts, abs_rhs))] |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
141 |
in ((list_comb (f, map Free (rev frees)), def), lthy') end |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
142 |
|
59650 | 143 |
val ((def_ts, def_thms), ctxt2) = |
144 |
let val names = Name.invent (Variable.names_of ctxt') "rhs" (length eqs) |
|
53429 | 145 |
in fold_map hide_rhs (eqs ~~ names) ctxt' |> apfst split_list end |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
146 |
|
53429 | 147 |
val ((t, split_thms), ctxt3) = build_case_t fun_t (map fst eqs) def_ts ctxt2 |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
148 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
149 |
val th = Goal.prove ctxt3 [] [] t (fn {context=ctxt, ...} => |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
150 |
tac ctxt {splits=split_thms, intros=ths, defs=def_thms}) |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
151 |
in th |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
152 |
|> singleton (Proof_Context.export ctxt3 ctxt) |
54883
dd04a8b654fc
proper context for norm_hhf and derived operations;
wenzelm
parents:
54401
diff
changeset
|
153 |
|> Goal.norm_result ctxt |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
154 |
end |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
155 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
156 |
end |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
157 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
158 |
local |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
159 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
160 |
fun was_split t = |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
161 |
let |
56252 | 162 |
val is_free_eq_imp = is_Free o fst o HOLogic.dest_eq o fst o HOLogic.dest_imp |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
163 |
val get_conjs = HOLogic.dest_conj o HOLogic.dest_Trueprop |
56252 | 164 |
fun dest_alls (Const (@{const_name All}, _) $ Abs (_, _, t)) = dest_alls t |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
165 |
| dest_alls t = t |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
166 |
in forall (is_free_eq_imp o dest_alls) (get_conjs t) end |
56252 | 167 |
handle TERM _ => false |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
168 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
169 |
fun apply_split ctxt split thm = Seq.of_list |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
170 |
let val ((_,thm'), ctxt') = Variable.import false [thm] ctxt in |
59582 | 171 |
(Variable.export ctxt' ctxt) (filter (was_split o Thm.prop_of) (thm' RL [split])) |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
172 |
end |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
173 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
174 |
fun forward_tac rules t = Seq.of_list ([t] RL rules) |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
175 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
176 |
val refl_imp = refl RSN (2, mp) |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
177 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
178 |
val get_rules_once_split = |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
179 |
REPEAT (forward_tac [conjunct1, conjunct2]) |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
180 |
THEN REPEAT (forward_tac [spec]) |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
181 |
THEN (forward_tac [refl_imp]) |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
182 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
183 |
fun do_split ctxt split = |
60355
ccafd7d193e7
simps_of_case: Better error if split rule is not an equality
noschinl
parents:
60354
diff
changeset
|
184 |
case try op RS (split, iffD1) of |
ccafd7d193e7
simps_of_case: Better error if split rule is not an equality
noschinl
parents:
60354
diff
changeset
|
185 |
NONE => raise TERM ("malformed split rule", [Thm.prop_of split]) |
ccafd7d193e7
simps_of_case: Better error if split rule is not an equality
noschinl
parents:
60354
diff
changeset
|
186 |
| SOME split' => |
ccafd7d193e7
simps_of_case: Better error if split rule is not an equality
noschinl
parents:
60354
diff
changeset
|
187 |
let val split_rhs = Thm.concl_of (hd (snd (fst (Variable.import false [split'] ctxt)))) |
ccafd7d193e7
simps_of_case: Better error if split rule is not an equality
noschinl
parents:
60354
diff
changeset
|
188 |
in if was_split split_rhs |
ccafd7d193e7
simps_of_case: Better error if split rule is not an equality
noschinl
parents:
60354
diff
changeset
|
189 |
then DETERM (apply_split ctxt split') THEN get_rules_once_split |
ccafd7d193e7
simps_of_case: Better error if split rule is not an equality
noschinl
parents:
60354
diff
changeset
|
190 |
else raise TERM ("malformed split rule", [split_rhs]) |
ccafd7d193e7
simps_of_case: Better error if split rule is not an equality
noschinl
parents:
60354
diff
changeset
|
191 |
end |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
192 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
193 |
val atomize_meta_eq = forward_tac [meta_eq_to_obj_eq] |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
194 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
195 |
in |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
196 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
197 |
fun gen_to_simps ctxt splitthms thm = |
60354
235d65be79c9
simps_of_case: allow Drule.dummy_thm as ignored split rule
noschinl
parents:
59936
diff
changeset
|
198 |
let val splitthms' = filter (fn t => not (Thm.eq_thm (t, Drule.dummy_thm))) splitthms |
235d65be79c9
simps_of_case: allow Drule.dummy_thm as ignored split rule
noschinl
parents:
59936
diff
changeset
|
199 |
in |
235d65be79c9
simps_of_case: allow Drule.dummy_thm as ignored split rule
noschinl
parents:
59936
diff
changeset
|
200 |
Seq.list_of ((TRY atomize_meta_eq THEN (REPEAT (FIRST (map (do_split ctxt) splitthms')))) thm) |
235d65be79c9
simps_of_case: allow Drule.dummy_thm as ignored split rule
noschinl
parents:
59936
diff
changeset
|
201 |
end |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
202 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
203 |
fun to_simps ctxt thm = |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
204 |
let |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
205 |
val T = thm |> strip_eq |> fst |> strip_comb |> fst |> fastype_of |
60702
5e03e1bd1be0
case_of_simps: do not split for types with a single constructor
noschinl
parents:
60355
diff
changeset
|
206 |
val splitthms = get_split_ths ctxt [T] |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
207 |
in gen_to_simps ctxt splitthms thm end |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
208 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
209 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
210 |
end |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
211 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
212 |
fun case_of_simps_cmd (bind, thms_ref) lthy = |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
213 |
let |
55997
9dc5ce83202c
modernized Attrib.check_name/check_src similar to methods (see also a989bdaf8121);
wenzelm
parents:
54883
diff
changeset
|
214 |
val bind' = apsnd (map (Attrib.check_src lthy)) bind |
61813 | 215 |
val thm = Attrib.eval_thms lthy thms_ref |> to_case lthy |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
216 |
in |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
217 |
Local_Theory.note (bind', [thm]) lthy |> snd |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
218 |
end |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
219 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
220 |
fun simps_of_case_cmd ((bind, thm_ref), splits_ref) lthy = |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
221 |
let |
55997
9dc5ce83202c
modernized Attrib.check_name/check_src similar to methods (see also a989bdaf8121);
wenzelm
parents:
54883
diff
changeset
|
222 |
val bind' = apsnd (map (Attrib.check_src lthy)) bind |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
223 |
val thm = singleton (Attrib.eval_thms lthy) thm_ref |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
224 |
val simps = if null splits_ref |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
225 |
then to_simps lthy thm |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
226 |
else gen_to_simps lthy (Attrib.eval_thms lthy splits_ref) thm |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
227 |
in |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
228 |
Local_Theory.note (bind', simps) lthy |> snd |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
229 |
end |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
230 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
231 |
val _ = |
59936
b8ffc3dc9e24
@{command_spec} is superseded by @{command_keyword};
wenzelm
parents:
59650
diff
changeset
|
232 |
Outer_Syntax.local_theory @{command_keyword case_of_simps} |
57628 | 233 |
"turn a list of equations into a case expression" |
62969 | 234 |
(Parse_Spec.opt_thm_name ":" -- Parse.thms1 >> case_of_simps_cmd) |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
235 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
236 |
val parse_splits = @{keyword "("} |-- Parse.reserved "splits" |-- @{keyword ":"} |-- |
62969 | 237 |
Parse.thms1 --| @{keyword ")"} |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
238 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
239 |
val _ = |
59936
b8ffc3dc9e24
@{command_spec} is superseded by @{command_keyword};
wenzelm
parents:
59650
diff
changeset
|
240 |
Outer_Syntax.local_theory @{command_keyword simps_of_case} |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
241 |
"perform case split on rule" |
62969 | 242 |
(Parse_Spec.opt_thm_name ":" -- Parse.thm -- |
53426
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
243 |
Scan.optional parse_splits [] >> simps_of_case_cmd) |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
244 |
|
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
245 |
end |
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
noschinl
parents:
diff
changeset
|
246 |