File ‹hoare_tac.ML›
signature HOARE_TAC =
sig
val hoare_rule_tac: Proof.context -> term list * thm -> (int -> tactic) -> bool ->
int -> tactic
val hoare_tac: Proof.context -> (int -> tactic) -> int -> tactic
val hoare_tc_tac: Proof.context -> (int -> tactic) -> int -> tactic
end;
structure Hoare_Tac: HOARE_TAC =
struct
local
fun abs2list \<^Const_>‹case_prod _ _ _ for ‹Abs (x, T, t)›› = Free (x, T) :: abs2list t
| abs2list (Abs (x, T, _)) = [Free (x, T)]
| abs2list _ = [];
fun mk_vars \<^Const_>‹Collect _ for T› = abs2list T
| mk_vars _ = [];
fun mk_abstupleC [] body = absfree ("x", \<^Type>‹unit›) body
| mk_abstupleC [v] body = absfree (dest_Free v) body
| mk_abstupleC (v :: w) body =
let
val (x, T) = dest_Free v;
val z = mk_abstupleC w body;
val T2 =
(case z of
Abs (_, T, _) => T
| Const (_, Type (_, [_, Type (_, [T, _])])) $ _ => T);
in
\<^Const>‹case_prod T T2 \<^Type>‹bool› for ‹absfree (x, T) z››
end;
fun mk_bodyC [] = \<^Const>‹Unity›
| mk_bodyC [x] = x
| mk_bodyC (x :: xs) =
let
val (_, T) = dest_Free x;
val z = mk_bodyC xs;
val T2 =
(case z of
Free (_, T) => T
| \<^Const_>‹Pair A B for _ _› => \<^Type>‹prod A B›);
in \<^Const>‹Pair T T2 for x z› end;
fun get_vars c =
let
val d = Logic.strip_assums_concl c;
val pre =
case HOLogic.dest_Trueprop d of
Const _ $ pre $ _ $ _ $ _ => pre
| Const _ $ pre $ _ $ _ => pre
in mk_vars pre end;
fun mk_CollectC tm =
let val \<^Type>‹fun t _› = fastype_of tm;
in \<^Const>‹Collect t for tm› end;
fun inclt ty = \<^Const>‹less_eq ty›;
in
fun Mset ctxt prop =
let
val [(Mset, _), (P, _)] = Variable.variant_frees ctxt [] [("Mset", ()), ("P", ())];
val vars = get_vars prop;
val varsT = fastype_of (mk_bodyC vars);
val big_Collect =
mk_CollectC (mk_abstupleC vars (Free (P, varsT --> \<^Type>‹bool›) $ mk_bodyC vars));
val small_Collect =
mk_CollectC (Abs ("x", varsT, Free (P, varsT --> \<^Type>‹bool›) $ Bound 0));
val MsetT = fastype_of big_Collect;
fun Mset_incl t = HOLogic.mk_Trueprop (inclt MsetT $ Free (Mset, MsetT) $ t);
val impl = Logic.mk_implies (Mset_incl big_Collect, Mset_incl small_Collect);
val th = Goal.prove ctxt [Mset, P] [] impl (fn _ => blast_tac ctxt 1);
in (vars, th) end;
end;
fun before_set2pred_simp_tac ctxt =
simp_tac (put_simpset HOL_basic_ss ctxt addsimps [Collect_conj_eq RS sym, @{thm Compl_Collect}]);
fun split_simp_tac ctxt =
simp_tac (put_simpset HOL_basic_ss ctxt addsimps [@{thm split_conv}]);
fun set_to_pred_tac ctxt var_names = SUBGOAL (fn (_, i) =>
before_set2pred_simp_tac ctxt i THEN_MAYBE
EVERY [
resolve_tac ctxt [subsetI] i,
resolve_tac ctxt [CollectI] i,
dresolve_tac ctxt [CollectD] i,
TRY (split_all_tac ctxt i) THEN_MAYBE
(rename_tac var_names i THEN
full_simp_tac (put_simpset HOL_basic_ss ctxt addsimps [@{thm split_conv}]) i)]);
fun max_simp_tac ctxt var_names tac =
FIRST' [resolve_tac ctxt [subset_refl],
set_to_pred_tac ctxt var_names THEN_MAYBE' tac];
fun basic_simp_tac ctxt var_names tac =
simp_tac
(put_simpset HOL_basic_ss ctxt
addsimps [mem_Collect_eq, @{thm split_conv}] addsimprocs [Record.simproc])
THEN_MAYBE' max_simp_tac ctxt var_names tac;
fun hoare_rule_tac ctxt (vars, Mlem) tac =
let
val get_thms = Proof_Context.get_thms ctxt;
val var_names = map (fst o dest_Free) vars;
fun wlp_tac i =
resolve_tac ctxt (get_thms \<^named_theorems>‹SeqRule›) i THEN rule_tac false (i + 1)
and rule_tac pre_cond i st = st |>
((wlp_tac i THEN rule_tac pre_cond i)
ORELSE
(FIRST [
resolve_tac ctxt (get_thms \<^named_theorems>‹SkipRule›) i,
resolve_tac ctxt (get_thms \<^named_theorems>‹AbortRule›) i,
EVERY [
resolve_tac ctxt (get_thms \<^named_theorems>‹BasicRule›) i,
resolve_tac ctxt [Mlem] i,
split_simp_tac ctxt i],
EVERY [
resolve_tac ctxt (get_thms \<^named_theorems>‹CondRule›) i,
rule_tac false (i + 2),
rule_tac false (i + 1)],
EVERY [
resolve_tac ctxt (get_thms \<^named_theorems>‹WhileRule›) i,
basic_simp_tac ctxt var_names tac (i + 2),
rule_tac true (i + 1)]]
THEN (
if pre_cond then basic_simp_tac ctxt var_names tac i
else resolve_tac ctxt [subset_refl] i)));
in rule_tac end;
fun hoare_tac ctxt tac = SUBGOAL (fn (goal, i) =>
SELECT_GOAL (hoare_rule_tac ctxt (Mset ctxt goal) tac true 1) i);
fun hoare_tc_rule_tac ctxt (vars, Mlem) tac =
let
val get_thms = Proof_Context.get_thms ctxt;
val var_names = map (fst o dest_Free) vars;
fun wlp_tac i =
resolve_tac ctxt (get_thms \<^named_theorems>‹SeqRuleTC›) i THEN rule_tac false (i + 1)
and rule_tac pre_cond i st = st |>
((wlp_tac i THEN rule_tac pre_cond i)
ORELSE
(FIRST [
resolve_tac ctxt (get_thms \<^named_theorems>‹SkipRuleTC›) i,
EVERY [
resolve_tac ctxt (get_thms \<^named_theorems>‹BasicRuleTC›) i,
resolve_tac ctxt [Mlem] i,
split_simp_tac ctxt i],
EVERY [
resolve_tac ctxt (get_thms \<^named_theorems>‹CondRuleTC›) i,
rule_tac false (i + 2),
rule_tac false (i + 1)],
EVERY [
resolve_tac ctxt (get_thms \<^named_theorems>‹WhileRuleTC›) i,
basic_simp_tac ctxt var_names tac (i + 2),
rule_tac true (i + 1)]]
THEN (
if pre_cond then basic_simp_tac ctxt var_names tac i
else resolve_tac ctxt [subset_refl] i)));
in rule_tac end;
fun hoare_tc_tac ctxt tac = SUBGOAL (fn (goal, i) =>
SELECT_GOAL (hoare_tc_rule_tac ctxt (Mset ctxt goal) tac true 1) i);
end;