| author | wenzelm | 
| Mon, 06 Apr 2015 17:06:48 +0200 | |
| changeset 59936 | b8ffc3dc9e24 | 
| parent 59650 | ba26118128b7 | 
| child 60354 | 235d65be79c9 | 
| 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  | 
|
| 
54401
 
f6950854855d
ported 'Simps_Case_Conv' to use new 'Ctr_Sugar' abstraction
 
blanchet 
parents: 
53433 
diff
changeset
 | 
25  | 
fun get_split_ths ctxt = collect_Tcons  | 
| 
53426
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
26  | 
#> distinct (op =)  | 
| 
54401
 
f6950854855d
ported 'Simps_Case_Conv' to use new 'Ctr_Sugar' abstraction
 
blanchet 
parents: 
53433 
diff
changeset
 | 
27  | 
#> map_filter (Ctr_Sugar.ctr_sugar_of ctxt)  | 
| 
53426
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
28  | 
#> map #split  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
29  | 
|
| 59582 | 30  | 
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
 | 
31  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
32  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
33  | 
local  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
34  | 
|
| 53429 | 35  | 
fun transpose [] = []  | 
36  | 
| transpose ([] :: xss) = transpose xss  | 
|
37  | 
| transpose xss = map hd xss :: transpose (map tl xss);  | 
|
38  | 
||
39  | 
fun same_fun (ts as _ $ _ :: _) =  | 
|
40  | 
let  | 
|
41  | 
val (fs, argss) = map strip_comb ts |> split_list  | 
|
42  | 
val f = hd fs  | 
|
43  | 
in if forall (fn x => f = x) fs then SOME (f, argss) else NONE end  | 
|
44  | 
| same_fun _ = NONE  | 
|
45  | 
||
46  | 
(* pats must be non-empty *)  | 
|
47  | 
fun split_pat pats ctxt =  | 
|
48  | 
case same_fun pats of  | 
|
49  | 
NONE =>  | 
|
50  | 
let  | 
|
51  | 
val (name, ctxt') = yield_singleton Variable.variant_fixes "x" ctxt  | 
|
52  | 
val var = Free (name, fastype_of (hd pats))  | 
|
53  | 
in (((var, [var]), map single pats), ctxt') end  | 
|
54  | 
| SOME (f, argss) =>  | 
|
55  | 
let  | 
|
56  | 
val (((def_pats, def_frees), case_patss), ctxt') =  | 
|
57  | 
split_pats argss ctxt  | 
|
58  | 
val def_pat = list_comb (f, def_pats)  | 
|
59  | 
in (((def_pat, flat def_frees), case_patss), ctxt') end  | 
|
60  | 
and  | 
|
61  | 
split_pats patss ctxt =  | 
|
62  | 
let  | 
|
63  | 
val (splitted, ctxt') = fold_map split_pat (transpose patss) ctxt  | 
|
64  | 
val r = splitted |> split_list |> apfst split_list |> apsnd (transpose #> map flat)  | 
|
65  | 
in (r, ctxt') end  | 
|
66  | 
||
67  | 
(*  | 
|
68  | 
Takes a list lhss of left hand sides (which are lists of patterns)  | 
|
69  | 
and a list rhss of right hand sides. Returns  | 
|
70  | 
- a single equation with a (nested) case-expression on the rhs  | 
|
71  | 
- a list of all split-thms needed to split the rhs  | 
|
72  | 
Patterns which have the same outer context in all lhss remain  | 
|
73  | 
on the lhs of the computed equation.  | 
|
74  | 
*)  | 
|
75  | 
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
 | 
76  | 
let  | 
| 53429 | 77  | 
val (((def_pats, def_frees), case_patss), ctxt') =  | 
78  | 
split_pats lhss ctxt  | 
|
79  | 
val pattern = map HOLogic.mk_tuple case_patss  | 
|
80  | 
val case_arg = HOLogic.mk_tuple (flat def_frees)  | 
|
81  | 
val cases = Case_Translation.make_case ctxt' Case_Translation.Warning Name.context  | 
|
82  | 
case_arg (pattern ~~ rhss)  | 
|
| 
54401
 
f6950854855d
ported 'Simps_Case_Conv' to use new 'Ctr_Sugar' abstraction
 
blanchet 
parents: 
53433 
diff
changeset
 | 
83  | 
val split_thms = get_split_ths ctxt' (fastype_of case_arg)  | 
| 53429 | 84  | 
val t = (list_comb (fun_t, def_pats), cases)  | 
85  | 
|> HOLogic.mk_eq  | 
|
86  | 
|> HOLogic.mk_Trueprop  | 
|
87  | 
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
 | 
88  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
89  | 
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
 | 
90  | 
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
 | 
91  | 
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
 | 
92  | 
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
 | 
93  | 
THEN safe_tac ctxt'  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
94  | 
end  | 
| 
 
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 import [] ctxt = ([], ctxt)  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
97  | 
| import (thm :: thms) ctxt =  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
98  | 
let  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
99  | 
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
 | 
100  | 
#> 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
 | 
101  | 
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
 | 
102  | 
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
 | 
103  | 
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
 | 
104  | 
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
 | 
105  | 
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
 | 
106  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
107  | 
in  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
108  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
109  | 
(*  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
110  | 
For a list  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
111  | 
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
 | 
112  | 
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
 | 
113  | 
...  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
114  | 
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
 | 
115  | 
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
 | 
116  | 
f x1 ... xn = t  | 
| 53429 | 117  | 
where t is a (nested) case expression. f must not be a function  | 
118  | 
application. Moreover, the terms p_11, ..., p_mn must be non-overlapping  | 
|
119  | 
datatype patterns. The patterns must be exhausting up to common constructor  | 
|
120  | 
contexts.  | 
|
| 
53426
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
121  | 
*)  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
122  | 
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
 | 
123  | 
let  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
124  | 
val (iths, ctxt') = import ths ctxt  | 
| 53429 | 125  | 
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
 | 
126  | 
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
 | 
127  | 
|
| 59650 | 128  | 
fun hide_rhs ((pat, rhs), name) lthy =  | 
129  | 
let  | 
|
| 
53426
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
130  | 
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
 | 
131  | 
val abs_rhs = fold absfree frees rhs  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
132  | 
val ((f,def), lthy') = Local_Defs.add_def  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
133  | 
((Binding.name name, Mixfix.NoSyn), abs_rhs) lthy  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
134  | 
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
 | 
135  | 
|
| 59650 | 136  | 
val ((def_ts, def_thms), ctxt2) =  | 
137  | 
let val names = Name.invent (Variable.names_of ctxt') "rhs" (length eqs)  | 
|
| 53429 | 138  | 
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
 | 
139  | 
|
| 53429 | 140  | 
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
 | 
141  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
142  | 
    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
 | 
143  | 
          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
 | 
144  | 
in th  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
145  | 
|> singleton (Proof_Context.export ctxt3 ctxt)  | 
| 
54883
 
dd04a8b654fc
proper context for norm_hhf and derived operations;
 
wenzelm 
parents: 
54401 
diff
changeset
 | 
146  | 
|> 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
 | 
147  | 
end  | 
| 
 
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  | 
end  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
150  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
151  | 
local  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
152  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
153  | 
fun was_split t =  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
154  | 
let  | 
| 56252 | 155  | 
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
 | 
156  | 
val get_conjs = HOLogic.dest_conj o HOLogic.dest_Trueprop  | 
| 56252 | 157  | 
    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
 | 
158  | 
| dest_alls t = t  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
159  | 
in forall (is_free_eq_imp o dest_alls) (get_conjs t) end  | 
| 56252 | 160  | 
handle TERM _ => false  | 
| 
53426
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
161  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
162  | 
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
 | 
163  | 
let val ((_,thm'), ctxt') = Variable.import false [thm] ctxt in  | 
| 59582 | 164  | 
(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
 | 
165  | 
end  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
166  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
167  | 
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
 | 
168  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
169  | 
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
 | 
170  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
171  | 
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
 | 
172  | 
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
 | 
173  | 
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
 | 
174  | 
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
 | 
175  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
176  | 
fun do_split ctxt split =  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
177  | 
let  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
178  | 
val split' = split RS iffD1;  | 
| 59582 | 179  | 
val split_rhs = Thm.concl_of (hd (snd (fst (Variable.import false [split'] ctxt))))  | 
| 
53426
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
180  | 
in if was_split split_rhs  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
181  | 
then DETERM (apply_split ctxt split') THEN get_rules_once_split  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
182  | 
     else raise TERM ("malformed split rule", [split_rhs])
 | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
183  | 
end  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
184  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
185  | 
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
 | 
186  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
187  | 
in  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
188  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
189  | 
fun gen_to_simps ctxt splitthms thm =  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
190  | 
Seq.list_of ((TRY atomize_meta_eq  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
191  | 
THEN (REPEAT (FIRST (map (do_split ctxt) splitthms)))) thm)  | 
| 
 
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  | 
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
 | 
194  | 
let  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
195  | 
val T = thm |> strip_eq |> fst |> strip_comb |> fst |> fastype_of  | 
| 
54401
 
f6950854855d
ported 'Simps_Case_Conv' to use new 'Ctr_Sugar' abstraction
 
blanchet 
parents: 
53433 
diff
changeset
 | 
196  | 
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
 | 
197  | 
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
 | 
198  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
199  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
200  | 
end  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
201  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
202  | 
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
 | 
203  | 
let  | 
| 
55997
 
9dc5ce83202c
modernized Attrib.check_name/check_src similar to methods (see also a989bdaf8121);
 
wenzelm 
parents: 
54883 
diff
changeset
 | 
204  | 
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
 | 
205  | 
val thm = (Attrib.eval_thms lthy) thms_ref |> to_case lthy  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
206  | 
in  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
207  | 
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
 | 
208  | 
end  | 
| 
 
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  | 
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
 | 
211  | 
let  | 
| 
55997
 
9dc5ce83202c
modernized Attrib.check_name/check_src similar to methods (see also a989bdaf8121);
 
wenzelm 
parents: 
54883 
diff
changeset
 | 
212  | 
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
 | 
213  | 
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
 | 
214  | 
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
 | 
215  | 
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
 | 
216  | 
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
 | 
217  | 
in  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
218  | 
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
 | 
219  | 
end  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
220  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
221  | 
val _ =  | 
| 
59936
 
b8ffc3dc9e24
@{command_spec} is superseded by @{command_keyword};
 
wenzelm 
parents: 
59650 
diff
changeset
 | 
222  | 
  Outer_Syntax.local_theory @{command_keyword case_of_simps}
 | 
| 57628 | 223  | 
"turn a list of equations into a case expression"  | 
| 
58028
 
e4250d370657
tuned signature -- define some elementary operations earlier;
 
wenzelm 
parents: 
57628 
diff
changeset
 | 
224  | 
(Parse_Spec.opt_thm_name ":" -- Parse.xthms1 >> 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
 | 
225  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
226  | 
val parse_splits = @{keyword "("} |-- Parse.reserved "splits" |-- @{keyword ":"} |--
 | 
| 
58028
 
e4250d370657
tuned signature -- define some elementary operations earlier;
 
wenzelm 
parents: 
57628 
diff
changeset
 | 
227  | 
  Parse.xthms1 --| @{keyword ")"}
 | 
| 
53426
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
228  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
229  | 
val _ =  | 
| 
59936
 
b8ffc3dc9e24
@{command_spec} is superseded by @{command_keyword};
 
wenzelm 
parents: 
59650 
diff
changeset
 | 
230  | 
  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
 | 
231  | 
"perform case split on rule"  | 
| 
58028
 
e4250d370657
tuned signature -- define some elementary operations earlier;
 
wenzelm 
parents: 
57628 
diff
changeset
 | 
232  | 
(Parse_Spec.opt_thm_name ":" -- Parse.xthm --  | 
| 
53426
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
233  | 
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
 | 
234  | 
|
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
235  | 
end  | 
| 
 
92db671e0ac6
added simps_of_case and case_of_simps to convert between simps and case rules
 
noschinl 
parents:  
diff
changeset
 | 
236  |