boehmes@34068
|
1 |
(* Title: HOL/Boogie/Tools/boogie_tactics.ML
|
boehmes@34068
|
2 |
Author: Sascha Boehme, TU Muenchen
|
boehmes@34068
|
3 |
|
boehmes@34068
|
4 |
Boogie tactics and Boogie methods.
|
boehmes@34068
|
5 |
*)
|
boehmes@34068
|
6 |
|
boehmes@34068
|
7 |
signature BOOGIE_TACTICS =
|
boehmes@34068
|
8 |
sig
|
boehmes@34181
|
9 |
val unfold_labels_tac: Proof.context -> int -> tactic
|
boehmes@34068
|
10 |
val boogie_tac: Proof.context -> thm list -> int -> tactic
|
boehmes@34068
|
11 |
val boogie_all_tac: Proof.context -> thm list -> tactic
|
boehmes@35351
|
12 |
val split: term -> (term list * term) list
|
boehmes@35351
|
13 |
val split_tac: int -> tactic
|
boehmes@35351
|
14 |
val drop_assert_at_tac: int -> tactic
|
boehmes@34068
|
15 |
val setup: theory -> theory
|
boehmes@34068
|
16 |
end
|
boehmes@34068
|
17 |
|
boehmes@34068
|
18 |
structure Boogie_Tactics: BOOGIE_TACTICS =
|
boehmes@34068
|
19 |
struct
|
boehmes@34068
|
20 |
|
boehmes@34068
|
21 |
fun as_meta_eq eq = eq RS @{thm eq_reflection}
|
boehmes@34068
|
22 |
|
boehmes@34068
|
23 |
val assert_at_def = as_meta_eq @{thm assert_at_def}
|
boehmes@34068
|
24 |
val block_at_def = as_meta_eq @{thm block_at_def}
|
boehmes@34068
|
25 |
val label_eqs = [assert_at_def, block_at_def]
|
boehmes@34068
|
26 |
|
boehmes@34068
|
27 |
fun unfold_labels_tac ctxt =
|
wenzelm@36938
|
28 |
let val unfold = Conv.rewrs_conv label_eqs
|
wenzelm@36938
|
29 |
in CONVERSION (Conv.top_sweep_conv (K unfold) ctxt) end
|
boehmes@34068
|
30 |
|
boehmes@34068
|
31 |
fun boogie_tac ctxt rules =
|
boehmes@34068
|
32 |
unfold_labels_tac ctxt
|
boehmes@34068
|
33 |
THEN' SMT_Solver.smt_tac ctxt (Boogie_Axioms.get ctxt @ rules)
|
boehmes@34068
|
34 |
|
boehmes@34068
|
35 |
fun boogie_all_tac ctxt rules =
|
boehmes@34068
|
36 |
PARALLEL_GOALS (HEADGOAL (boogie_tac ctxt rules))
|
boehmes@34068
|
37 |
|
boehmes@34068
|
38 |
fun boogie_method all =
|
boehmes@34068
|
39 |
Scan.optional Attrib.thms [] >> (fn thms => fn ctxt => METHOD (fn facts =>
|
boehmes@34068
|
40 |
let val tac = if all then boogie_all_tac else HEADGOAL oo boogie_tac
|
boehmes@34068
|
41 |
in tac ctxt (thms @ facts) end))
|
boehmes@34068
|
42 |
|
boehmes@34068
|
43 |
val setup_boogie = Method.setup @{binding boogie} (boogie_method false)
|
boehmes@34068
|
44 |
("Applies an SMT solver to the current goal " ^
|
boehmes@34068
|
45 |
"using the current set of Boogie background axioms")
|
boehmes@34068
|
46 |
|
boehmes@34068
|
47 |
val setup_boogie_all = Method.setup @{binding boogie_all} (boogie_method true)
|
boehmes@34068
|
48 |
("Applies an SMT solver to all goals " ^
|
boehmes@34068
|
49 |
"using the current set of Boogie background axioms")
|
boehmes@34068
|
50 |
|
boehmes@34068
|
51 |
|
boehmes@34068
|
52 |
local
|
boehmes@35351
|
53 |
fun explode_conj (@{term "op &"} $ t $ u) = explode_conj t @ explode_conj u
|
boehmes@35351
|
54 |
| explode_conj t = [t]
|
boehmes@34068
|
55 |
|
haftmann@39019
|
56 |
fun splt (ts, @{term HOL.implies} $ t $ u) = splt (ts @ explode_conj t, u)
|
boehmes@35351
|
57 |
| splt (ts, @{term "op &"} $ t $ u) = splt (ts, t) @ splt (ts, u)
|
boehmes@35351
|
58 |
| splt (ts, @{term assert_at} $ _ $ t) = [(ts, t)]
|
boehmes@35351
|
59 |
| splt (_, @{term True}) = []
|
boehmes@35351
|
60 |
| splt tp = [tp]
|
boehmes@35351
|
61 |
in
|
boehmes@35351
|
62 |
fun split t =
|
boehmes@35351
|
63 |
splt ([], HOLogic.dest_Trueprop t)
|
boehmes@35351
|
64 |
|> map (fn (us, u) => (map HOLogic.mk_Trueprop us, HOLogic.mk_Trueprop u))
|
boehmes@35351
|
65 |
end
|
boehmes@34068
|
66 |
|
boehmes@35351
|
67 |
val split_tac = REPEAT_ALL_NEW (
|
boehmes@35351
|
68 |
Tactic.resolve_tac [@{thm impI}, @{thm conjI}, @{thm TrueI}]
|
boehmes@35351
|
69 |
ORELSE' Tactic.etac @{thm conjE})
|
boehmes@35351
|
70 |
|
boehmes@35351
|
71 |
val drop_assert_at_tac = CONVERSION (Conv.concl_conv ~1 (Conv.try_conv (
|
boehmes@35351
|
72 |
Conv.arg_conv (Conv.rewr_conv assert_at_def))))
|
boehmes@35351
|
73 |
|
boehmes@35351
|
74 |
local
|
boehmes@34068
|
75 |
fun case_name_of t =
|
boehmes@34068
|
76 |
(case HOLogic.dest_Trueprop (Logic.strip_imp_concl t) of
|
boehmes@34068
|
77 |
@{term assert_at} $ Free (n, _) $ _ => n
|
boehmes@34068
|
78 |
| _ => raise TERM ("case_name_of", [t]))
|
boehmes@34068
|
79 |
|
boehmes@34068
|
80 |
fun boogie_cases ctxt = METHOD_CASES (fn facts =>
|
boehmes@35351
|
81 |
ALLGOALS (Method.insert_tac facts THEN' split_tac) #>
|
boehmes@34068
|
82 |
Seq.maps (fn st =>
|
boehmes@34068
|
83 |
st
|
boehmes@35351
|
84 |
|> ALLGOALS drop_assert_at_tac
|
boehmes@34068
|
85 |
|> Seq.map (pair (map (rpair [] o case_name_of) (Thm.prems_of st)))) #>
|
boehmes@34068
|
86 |
Seq.maps (fn (names, st) =>
|
boehmes@34068
|
87 |
CASES
|
berghofe@34916
|
88 |
(Rule_Cases.make_common
|
berghofe@34916
|
89 |
(ProofContext.theory_of ctxt,
|
berghofe@34916
|
90 |
Thm.prop_of (Rule_Cases.internalize_params st)) names)
|
boehmes@34068
|
91 |
Tactical.all_tac st))
|
boehmes@34068
|
92 |
in
|
boehmes@34068
|
93 |
val setup_boogie_cases = Method.setup @{binding boogie_cases}
|
boehmes@34068
|
94 |
(Scan.succeed boogie_cases)
|
boehmes@34068
|
95 |
"Prepares a set of Boogie assertions for case-based proofs"
|
boehmes@34068
|
96 |
end
|
boehmes@34068
|
97 |
|
boehmes@34068
|
98 |
|
boehmes@34068
|
99 |
val setup =
|
boehmes@34068
|
100 |
setup_boogie #>
|
boehmes@34068
|
101 |
setup_boogie_all #>
|
boehmes@34068
|
102 |
setup_boogie_cases
|
boehmes@34068
|
103 |
|
boehmes@34068
|
104 |
end
|