theory Polish imports HeapLift WordPolish TypeStrengthen begin
context heap_typing_state begin
lemma unchanged_typing_bind[unchanged_typing]: assumes [runs_to_vcg]: "f ∙ s ?{ λr. unchanged_typing_on S s }""(∧r s. g r ∙ s ?{ λr. unchanged_typing_on S s })" shows"(bind f g) ∙ s ?{ λr. unchanged_typing_on S s }" apply (runs_to_vcg) using unchanged_typing_on_trans by blast
lemma unchanged_typing_while[unchanged_typing]: assumes B: "∧r s. C r s ==> (B r) ∙ s ?{ λr. unchanged_typing_on S s}" shows"(whileLoop C B i) ∙ s ?{ λr. unchanged_typing_on S s}" apply (rule runs_to_partial_whileLoop [where I = "λ_. unchanged_typing_on S s"])
subgoal by simp
subgoal by simp
subgoal by simp
subgoal apply (rule runs_to_partial_weaken [OF B]) apply (simp) by (rule unchanged_typing_on_trans) done
lemma unchanged_typing_finally[unchanged_typing]: assumes [runs_to_vcg]: "f ∙ s ?{ λr. unchanged_typing_on S s}" shows"finally f ∙ s ?{ λr. unchanged_typing_on S s}" by (runs_to_vcg)
lemma unchanged_typing_try[unchanged_typing]: assumes [runs_to_vcg]: "f ∙ s ?{ λr. unchanged_typing_on S s}" shows"try f ∙ s ?{ λr. unchanged_typing_on S s}" by (runs_to_vcg)
lemma runs_to_partial_catch[unchanged_typing]: assumes [runs_to_vcg]: "f ∙ s ?{λr. unchanged_typing_on S s}" assumes [runs_to_vcg]: "∧r s. (g r) ∙ s ?{λr. unchanged_typing_on S s}" shows"(catch f g) ∙ s ?{λr. unchanged_typing_on S s}" by (runs_to_vcg) (auto simp add: unchanged_typing_on_simps)
lemma runs_to_partial_bind_handle[unchanged_typing]: assumes [runs_to_vcg]: "f ∙ s ?{λr. unchanged_typing_on S s}" assumes [runs_to_vcg]: "∧r s. (g r) ∙ s ?{λr. unchanged_typing_on S s}" assumes [runs_to_vcg]: "∧r s. (h r) ∙ s ?{λr. unchanged_typing_on S s}" shows"(bind_handle f g h) ∙ s ?{λr. unchanged_typing_on S s}" by (runs_to_vcg) (auto simp add: unchanged_typing_on_simps)
lemma unchanged_typing_liftE[unchanged_typing]: assumes [runs_to_vcg]: "f ∙ s ?{ λr. unchanged_typing_on S s}" shows"liftE f ∙ s ?{ λr. unchanged_typing_on S s}" by (runs_to_vcg)
end
context open_types_heap_typing_state begin
lemma unchanged_typing_ptr_valid_preserved: "ptr_valid (heap_typing t1) p ==> unchanged_typing_on UNIV t1 t2 ==> ptr_valid (heap_typing t2) p" by (simp add: unchanged_typing_on_UNIV_iff)
lemma reaches_unchanged_typing_ptr_valid_preserved: "reaches f s r t ==> ptr_valid (heap_typing s) p ==> f ∙ s ?{λ_ t. unchanged_typing_on UNIV s t}==> ptr_valid (heap_typing t) p" using unchanged_typing_ptr_valid_preserved by (simp add: runs_to_partial_def_old reaches_succeeds unchanged_typing_on_UNIV_iff) thm unchanged_typing [no_vars] end
locale typ_heap_simulation_open_types_stack =
typ_heap_simulation_open_types T st r w v t_hrs t_hrs_update heap_typing heap_typing_upd for Tand
st:: "'s ==> 't"and
r:: "'t ==> ('a::{xmem_type, stack_type}) ptr ==> 'a"and
w:: "'a ptr ==> ('a ==> 'a) ==> 't ==> 't"and
v:: "'t ==> 'a ptr ==> bool"and
t_hrs :: "'s ==> heap_raw_state"and
t_hrs_update:: "(heap_raw_state ==> heap_raw_state) ==> 's ==> 's"and
heap_typing :: "'t ==> heap_typ_desc"and
heap_typing_upd :: "(heap_typ_desc ==> heap_typ_desc) ==> 't ==> 't" + fixesS:: "addr set" begin sublocale typ_heap_typing r w heap_typing heap_typing_upd S by intro_locales
lemma unchanged_typing_on_with_fresh_stack_ptr[unchanged_typing]: fixes f::"'a ptr ==> ('e::default, 'b, 't) spec_monad" assumes [runs_to_vcg]:"∧p t. (f p) ∙ t ?{λ_ t'. unchanged_typing_on A t t'}" shows"(with_fresh_stack_ptr n init f) ∙ t ?{λ_ t'. unchanged_typing_on A t t'}" unfolding with_fresh_stack_ptr_def on_exit_def stack_ptr_acquire_def assume_stack_alloc_def apply runs_to_vcg
subgoal for x d vs t' apply (subst (asm) typing_eq_left_unchanged_typing_on [of _ "(heap_typing_upd (λ_. d) t)"]) apply (simp add: heap_typing_fold_upd_write) apply (simp add: unchanged_typing_on_def stack_ptr_release_def heap_typing_fold_upd_write stack_allocs_releases_equal_on_typing) done done
lemma unchanged_typing_on_assume_with_fresh_stack_ptr[unchanged_typing]: fixes f::"'a ptr ==> ('e::default, 'b, 't) spec_monad" assumes [runs_to_vcg]:"∧p t. (f p) ∙ t ?{λ_ t'. unchanged_typing_on A t t'}" shows"(assume_with_fresh_stack_ptr n init f) ∙ t ?{λ_ t'. unchanged_typing_on A t t'}" unfolding assume_with_fresh_stack_ptr_def stack_ptr_acquire_def assume_stack_alloc_def apply runs_to_vcg
subgoal for x d vs t' apply (subst (asm) typing_eq_left_unchanged_typing_on [of _ "(heap_typing_upd (λ_. d) t)"]) apply (simp add: heap_typing_fold_upd_write) apply (simp add: unchanged_typing_on_def stack_ptr_release_def heap_typing_fold_upd_write stack_allocs_releases_equal_on_typing) done done
lemma unchanged_typing_on_guard_with_fresh_stack_ptr[unchanged_typing]: fixes f::"'a ptr ==> ('e::default, 'b, 't) spec_monad" assumes [runs_to_vcg]:"∧p t. (f p) ∙ t ?{λ_ t'. unchanged_typing_on A t t'}" shows"(guard_with_fresh_stack_ptr n init f) ∙ t ?{λ_ t'. unchanged_typing_on A t t'}" unfolding guard_with_fresh_stack_ptr_def stack_ptr_acquire_def assume_stack_alloc_def apply runs_to_vcg
subgoal for x d vs t' apply (subst (asm) typing_eq_left_unchanged_typing_on [of _ "(heap_typing_upd (λ_. d) t)"]) apply (simp add: heap_typing_fold_upd_write) apply (simp add: unchanged_typing_on_def stack_ptr_release_def heap_typing_fold_upd_write stack_allocs_releases_equal_on_typing) done done
end
(* Final simplification after type strengthening. *)
named_theorems polish
named_theorems polish_cong and state_fold_congs
declare map_value_id[polish]
(* Remove the Hoare modifies constants after heap abstraction, as they have *verybuggyprinttranslations. *Inparticular,applyingabs_spec_modify_globalreplacestheboundvariableby"x"
* and confuses the print translation into producing "may_only_modify_globals [x]". *) lemmas [polish] = mex_def meq_def
declare WORD_values_fold [polish] (* Clean up "WORD_MAX TYPE(32)", etc. after word abstraction. *) lemmas WORD_bound_simps [polish] =
WORD_MAX_simps
WORD_MIN_simps
UWORD_MAX_simps
WORD_signed_to_unsigned
INT_MIN_MAX_lemmas
lemma ocondition_ret_ret [polish]: "ocondition P (oreturn A) (oreturn B) = ogets (λs. if P s then A else B)" by (auto simp: ocondition_def ogets_def)
lemma ocondition_gets_ret [polish]: "ocondition P (ogets A) (oreturn B) = ogets (λs. if P s then A s else B)" by (auto simp: ocondition_def ogets_def)
lemma ocondition_ret_gets [polish]: "ocondition P (oreturn A) (ogets B) = ogets (λs. if P s then A else B s)" by (auto simp: ocondition_def ogets_def)
lemma ocondition_gets_gets [polish]: "ocondition P (ogets A) (ogets B) = ogets (λs. if P s then A s else B s)" by (auto simp: ocondition_def ogets_def)
lemma case_prod_trivial[]: "NO_MATCH (g::('e::default, 'a, 's) spec_monad) f ==>(λ(x,y). f) = (λ_. f)"
― ‹We avoid this rule during polish to keep brittle tuple structure ( const‹case_prod› ) and
bound variable names in eg. const‹bind›. With the const‹NO_MATCH› setup the
simplification might still trigger e.g. on conditions of while loops› by auto
(* Avoid things like \<lambda>(x,y,z). f x \<rightarrow> \<lambda>(x, _). f x *) lemma bind_case_prod_trivial[polish]: "bind f (λ(x, y). g) = bind f (λ_. g)" by (rule spec_monad_ext) (simp add: run_bind)
lemma condition_to_if [polish]: "condition (λs. C) (return a) (return b) = return (if C then a else b)" by (rule spec_monad_ext) (simp add: run_condition)
lemma guard_merge_bind: "guard P >>= (λ_. guard Q >>= M) = guard (P and Q) >>= M" apply (rule spec_monad_ext) apply (simp add: run_bind run_guard) done
lemma guard_merge_bind': "guard P >>= (λ_. guard Q >>= M) = guard (λs. P s ∧ Q s) >>= M" apply (rule spec_monad_ext) apply (simp add: run_bind run_guard) done
lemma condition_common_suffix: "condition (λ_. FUN_PTR b) (bind f g) (bind h g) = bind (condition (λ_. FUN_PTR b) f h) g" apply (rule spec_monad_eqI) apply (auto simp add: runs_to_iff) done
lemma condition_bind_fail': "NO_MATCH (gets x) f ==> NO_MATCH (guard y) f ==> NO_MATCH (bind (liftE (do {guard z; f1})) f2) f ==> condition (λ_. FUN_PTR b) (bind f g) fail = bind (condition (λ_. FUN_PTR b) f fail) g" apply (rule spec_monad_eqI) apply (auto simp add: runs_to_iff) done
lemma condition_common_catch: "condition (λ_. FUN_PTR b) (catch f g) (catch h g) = catch (condition (λ_. FUN_PTR b) f h) g" apply (rule spec_monad_eqI) apply (auto simp add: runs_to_iff) done
lemma condition_catch_fail: "condition (λ_. FUN_PTR b) (catch f g) fail = catch (condition (λ_. FUN_PTR b) f fail) g" apply (rule spec_monad_eqI) apply (auto simp add: runs_to_iff) done
lemmas prepare_fold_map_of_default[polish] =
― ‹These lemmas are used as preparation for folding function pointer calls to const‹map_of_default›, the
complex structure of nested @{const condition}, @{const guard}, @{const gets} and @{const fail}, @{const bind} and @{const catch}
might evolve during the IO phase. This collection tries to factor out the common wrapper parts and isolate the core
function calls that should result in const‹map_of_default› and in a program environment term‹P››
condition_fail_rhs_no_fun_ptr
condition_common_guard_prefix
condition_guard_bind_fail
condition_common_liftE_guard_prefix
condition_liftE_guard_bind_fail
condition_guard_fail
condition_common_gets_prefix
condition_gets_fail
condition_common_suffix
condition_bind_fail'
condition_common_catch
condition_catch_fail
declare oreturn_bind [polish] declare obind_return [polish] lemma infinite_option_while': "(Some x, Some y) ∉ option_while' (λ_. True) B" apply (rule notI) apply (induct "Some x :: 'a option""Some y :: 'a option"
arbitrary: x y rule: option_while'.induct) apply auto done
lemma expand_guard_conj [polish]: "guard (λs. A s ∧ B s) = (do {guard (λs. A s); guard (λs. B s) })" apply (rule spec_monad_ext) apply (simp add: run_guard run_bind) done
lemma oguard_K_bind_cong [polish_cong]: "g = g' ==> (∧s. g' s ==> c s = c' s) ==> (oguard g >>= (λ_. c)) = (oguard g' >>= (λ_. c')) " apply (rule ext) apply (auto simp add: oguard_def obind_def) done
lemma oguard_obind_cong: "g = g' ==> (∧s. g' s ==> c s = c' s) ==> do {_ <- oguard g ; c} = do {_ <- oguard g'; c'}" by (auto simp add: oguard_def obind_def)
lemma return_if_P_1_0_bind [polish]: "(return (if P then 1 else 0) >>= (λx. Q x)) = (return P >>= (λx. Q (if x then 1 else 0)))" apply simp done
lemma gets_if_P_1_0_bind [polish]: "(gets (λs. if P s then 1 else 0) >>= (λx. Q x)) = (gets P >>= (λx. Q (if x then 1 else 0)))" apply (rule spec_monad_ext) apply (simp add: run_bind) done
lemma if_P_1_0_neq_0 [polish, simp]: "((if P then 1 else (0::('a::{zero_neq_one}))) ≠ 0) = P" apply simp done
lemma if_P_1_0_eq_0 [polish, simp]: "((if P then 1 else (0::('a::{zero_neq_one}))) = 0) = (¬ P)" apply simp done
lemma if_if_same_output [polish]: "(if a then if b then x else y else y) = (if a ∧ b then x else y)" "(if a then x else if b then x else y) = (if a ∨ b then x else y)" by auto
(* C-parser turns a C expression into a chain of guarded statements ifsomeofthesubexpressionscanfail.Thisgetsannoyingwhen theexpressionwasbeingusedasacondition.
Herewetrytorewritethestatementstoonebigguardfollowedby theactualexpression.
TODO: this should be in L2Opt or something *) lemma collect_guarded_conj[polish]: "condition C1 (do { guard G; gets (λs. if C2 s then 1 else 0) }) (return 0) = do { guard (λs. C1 s ⟶ G s); gets (λs. if C1 s ∧ C2 s then 1 else 0) }" apply (rule spec_monad_ext) apply (simp add: run_bind run_guard run_condition) done
lemma collect_guarded_disj[polish]: "condition C1 (return 1) (do {guard G; gets (λs. if C2 s then 1 else 0) }) = do {guard (λs. ¬ C1 s ⟶ G s); gets (λs. if C1 s ∨ C2 s then 1 else 0) }" apply (rule spec_monad_ext) apply (simp add: run_bind run_guard run_condition) done
(* Need this to merge the new statements into the program *) lemmas [polish] = bind_assoc obind_assoc
(* Need this because collect_guarded_disj generates nots *) declare not_not [polish]
(* Normally the boolean result from above is used in a condition,
simplify that as well. *) lemma collect_then_cond_1_0[polish]: "do {cond ← gets (λs. if P s then (1::('a::{zero_neq_one})) else 0); condition (λ_. cond ≠ 0) L R } = condition P L R" apply (rule spec_monad_ext) apply (simp add: run_bind run_guard run_condition) done
lemma collect_then_cond_1_0_assoc[polish]: "(do {cond ← gets (λs. if P s then (1::('a::{zero_neq_one})) else 0); condition (λ_. cond ≠ 0) L R >>= f }) = (condition P L R >>= f)" apply (rule spec_monad_ext) apply (simp add: run_bind run_guard run_condition) done
lemma bind_return_bind [polish]: "(A >>= (λx. (return x >>= (λy. B x y)))) = (A >>= (λx. B x x))" by simp
lemma obind_oreturn_obind [polish]: "(A |>> (λx. (oreturn x |>> (λy. B x y)))) = (A |>> (λx. B x x))" by simp
lemma bind_fixup_1: "(bind A (λx. case y of (a, b) ==> B a b x)) = (case y of (a, b) ==> bind A (λx. B a b x))" by (auto simp: split_def) lemma bind_fixup_2: "(bind (case y of (a, b) ==> B a b) A) = (case y of (a, b) ==> bind (B a b) A)" by (auto simp: split_def) lemma finally_fixup: "(λx. finally (case x of (a, b) ==> f a b)) = (λ(a,b). finally (f a b))" by (simp add: fun_eq_iff split: prod.splits) lemma try_fixup: "(λx. try (case x of (a, b) ==> f a b)) = (λ(a,b). try (f a b))" by (simp add: fun_eq_iff split: prod.splits) lemma liftE_fixup: "(λx. liftE (case x of (a, b) ==> f a b)) = (λ(a,b). liftE (f a b))" by (simp add: fun_eq_iff split: prod.splits)
lemmas spec_monad_split_fixup [polish]= ― ‹should we even take more from @{thm L2_split_fixups} ?›
bind_fixup_1
bind_fixup_2
finally_fixup
try_fixup
liftE_fixup
(* simplify constructs like "p +\<^sub>p int (unat k)" to "p +\<^sub>p uint k",
* generated by unsigned word abstraction *) declare uint_nat[symmetric, polish]
lemma bind_post_state_map_post_state: "bind_post_state (map_post_state f g) h = bind_post_state g (λx. h (f x))" by (simp flip: bind_post_state_pure_post_state2)
lemma map_post_state_case_exception_or_result_distrib: "map_post_state f (case_exception_or_result g h v) = (case_exception_or_result (λx. map_post_state f (g x)) (λx. map_post_state f (h x)) v)" by (auto simp add: map_post_state_def split: exception_or_result_splits)
lemma map_post_state_case_exception_or_result_prod_distrib: "map_post_state f ((case v of (Exception e, t) ==> g e t | (Result v, t) ==> h v t)) = ((case v of (Exception e, t) ==> map_post_state f (g e t) | (Result v, t) ==> map_post_state f (h v t)))" by (auto simp add: map_post_state_def split: prod.splits exception_or_result_splits)
lemma do_bind_assoc: "∧f fa fb. do { u <- f::(unit, _) res_monad; fa::(unit, _) res_monad } >>= fb = do {u <- f; fa >>= fb::(unit, _) res_monad }" using bind_assoc by blast
section"Support to normalise guards and array index expressions"
lemmas whileLoop_congs_tupled =
whileLoop_cong
whileLoop_cong [split_tuple C and C' and B and B' arity: 2]
whileLoop_cong [split_tuple C and C' and B and B' arity: 3]
whileLoop_cong [split_tuple C and C' and B and B' arity: 4]
whileLoop_cong [split_tuple C and C' and B and B' arity: 5]
whileLoop_cong [split_tuple C and C' and B and B' arity: 6]
whileLoop_cong [split_tuple C and C' and B and B' arity: 7]
whileLoop_cong [split_tuple C and C' and B and B' arity: 8]
whileLoop_cong [split_tuple C and C' and B and B' arity: 9]
whileLoop_cong [split_tuple C and C' and B and B' arity: 10]
whileLoop_cong [split_tuple C and C' and B and B' arity: 11]
whileLoop_cong [split_tuple C and C' and B and B' arity: 12]
whileLoop_cong [split_tuple C and C' and B and B' arity: 13]
lemma runs_to_partial_case_prod : "(∧a b. (f a b) ∙ s ?{Q} ) ==> (case x of (a, b) ==> f a b) ∙ s ?{Q}" by (cases x) simp
section"Monad simplification with custom congruence rules"
context open_types begin text‹We supply a custom simplification method for spec monad expressions that gathers and propagates
from conditions and guards while descending into the term. The core motivation is
clean up repeated occurrences of @{term "ptr_valid (heap_typing s) p"}. Allthough this is a
dependent predicate it stays invariant as long as the typing does not change. So the goal
the simplification method is to prove preservation of such predicates while descending into
term. Supplying congruence rules to the simplifier is unfortunately not enough as we want to
control over what kind of invariants are propagated. Unfortunately the simplifier has no
of a ‹congprocs› that are triggered when descending into the term only the ‹simprocs› which are
by the usual bottom up simplifier strategy.
work around this limitation we implement ‹congprocs› by ‹simprocs›:
▪ We block the simplifier to descend into compound terms by adding trivial congruence rules to the
simplifier, like @{prop "bind f g ≡ bind f g"}
▪ We add a simproc that then triggers on the @{term "bind f g"} and manually extends the context
invokes the simplifier on the subterms. › end
definition ADD_FACT:: "('a ==> bool) ==> 'a ==> bool"where "ADD_FACT P s = P s" definition PRESERVED_FACTS:: "('e::default, 'a, 's) spec_monad ==> 's ==> ('e, 'a) exception_or_result ==> 's ==> bool "where "PRESERVED_FACTS f s r t = (reaches f s r t)" definition PRESERVED_FACTS_WHILE :: "('a ==> 's ==> bool) ==> ('a ==> ('e::default, 'a, 's) spec_monad) ==> 'a ==> 's ==> 'a ==> 's ==> bool"where "PRESERVED_FACTS_WHILE C B i s r t = whileLoop_unroll_reachable C B i s r t"
definition RUN_CASE_PROD :: "('a ==> 'b ==> ('c::default, 'd, 'e) spec_monad) ==> 'a × 'b ==> 'e ==> ('f ==> 'g ==> ('c, 'd, 'e) spec_monad) ==> 'f × 'g ==> bool"where "RUN_CASE_PROD f x s f' x' ⟷ run (case_prod f x) s = run (case_prod f' x') s"
lemma ADD_FACT_D: "ADD_FACT P s ==> P s" by (simp add: ADD_FACT_def)
lemma RUN_CASE_PROD_I:"x ≡ x' ==> run (case_prod f x') s ≡ run (case_prod f' x') s ==> RUN_CASE_PROD f x s f' x'" by (auto simp add: RUN_CASE_PROD_def)
named_theorems
monad_simp_simp "simplification rules to derive facts"and
monad_simp_augment_rule "conditional rules to augment facts"and
monad_simp_split_tuple_cong "congruence rules to control tuple expansion"
lemma PRESERVED_FACTS_runs_to_partial: "PRESERVED_FACTS f s r t ==> f ∙ s ?{Q}==> Q r t" by (auto simp add: runs_to_partial_def_old PRESERVED_FACTS_def reaches_succeeds)
lemma STOPI: "x ≡ y ==> x ≡ STOP y"by (simp add: STOP_def)
lemma expand_unused_case_prod: "(λ(x,y::('c * 'd)). f x) = (λ(x, y1, y2). f x)" by auto
lemma PRESERVED_FACTS_return_eq: "PRESERVED_FACTS (return x) s (Result y) t ==> y = x" by (auto simp add: PRESERVED_FACTS_def)
merge_rules (n1, n2) =
if pointer_eq (n1, n2) then n1
else if Net.is_empty n2 then n1
else if Net.is_empty n1 then n2
else Net.merge rule_eq (n1, n2)
merge_cond_rules (n1, n2) =
if pointer_eq (n1, n2) then n1
else if Net.is_empty n2 then n1
else if Net.is_empty n1 then n2
else Net.merge cond_rule_eq (n1, n2)
monad_simp_active ctxt = not (null (states_of ctxt))
lhs_of = Thm.dest_equals_lhs o Thm.cconcl_of
rhs_of = Thm.dest_equals_rhs o Thm.cconcl_of
lhs_of_rule = #apply_thm #> lhs_of
cong_lhs rule =
let
val lhs = lhs_of rule
val {f, ...} = @{cterm_match (fo) "run ?f ?s"} lhs
in
f
end
stop_cong rule =
Thm.reflexive (cong_lhs rule)
mk_rule ctxt name split_vars thm =
let
val eq = Simplifier.mk_cong ctxt thm
val apply_thm = eq |> Drule.zero_var_indexes
val lhs = lhs_of apply_thm
val stop_thm = stop_cong apply_thm
val rule = {apply_thm = Thm.trim_context apply_thm, stop_thm = Thm.trim_context stop_thm, split_vars = split_vars, name = name}
in
(Thm.term_of lhs, rule)
end
mk_cond_rule name thm =
let
val prem = Thm.major_prem_of thm
val rule = {thm = Thm.trim_context thm, name = name}
in
(prem, rule)
end
compare_congs (thm1, thm2) =
let
val maxidx1 = Thm.maxidx_of thm1
val lhs1 = lhs_of thm1
val lhs2 = lhs_of thm2 |> Thm.incr_indexes_cterm (maxidx1 + 1)
val result =
if is_some (try Thm.match (lhs1, lhs2)) then
SOME GREATER
else if is_some (try Thm.match (lhs2, lhs1)) then
SOME LESS
else NONE
in
result
end
equiv_congs (thm1, thm2) =
compare_congs (thm1, thm2) = SOME GREATER andalso compare_congs (thm2, thm1) = SOME GREATER
more_general thm1 thm2 =
(case compare_congs (thm1, thm2) of
SOME GREATER => SOME thm1
| SOME LESS => SOME thm2
| NONE => NONE)
more_specific thm1 thm2 =
(case compare_congs (thm1, thm2) of
SOME GREATER => SOME thm2
| SOME LESS => SOME thm1
| NONE => NONE)
insert_cong thm [] = [Thm.trim_context thm]
| insert_cong thm (thms as (thm1::thms')) =
(case compare_congs (thm1, thm) of
SOME GREATER => thms
| SOME LESS => insert_cong thm thms'
| NONE => thm1 :: insert_cong thm thms')
del_rule thm context =
let
val ctxt = Context.proof_of context
in
context
|> map_rules (Net.delete_term_safe rule_eq (mk_rule ctxt Binding.empty [] thm))
|> rebuild_stop_congs
end
del_rule' thm = Context.proof_map (del_rule thm)
add_derive_rule thm0 context =
let
val ctxt = Context.proof_of context
val thm = Simplifier.simplify ctxt thm0
val name = Utils.guess_binding_of_thm ctxt thm
val rule = mk_cond_rule name thm
in
context |> map_derive_rules (Net.insert_term_safe (* (K true) *) cond_rule_eq rule) end
fun del_derive_rule thm0 context = let
val ctxt = Context.proof_of context
val thm = Simplifier.simplify ctxt thm0 in context
|> map_derive_rules (Net.delete_term_safe cond_rule_eq (mk_cond_rule Binding.empty thm)) end
fun map_theory_rules f thy = let
val ctxt' = f (Proof_Context.init_global thy);
val thy' = Proof_Context.theory_of ctxt'; in Context.theory_map (Data.map (K (rules_of ctxt'))) thy' end
fun mk_fact thm = let
val {P, ... } = @{cterm_match ‹Trueprop (ADD_FACT ?P ?s)›} (Thm.cconcl_of thm) in
{pred = P, thms = [@{thm ADD_FACT_D} OF [thm]]}:fact end
fun derive_facts ctxt thm = let
val derive_rules = Net.match_term (#derive_rules (Data.get (Context.Proof ctxt))) (Thm.concl_of thm)
val derived = map_filter (try (fn rule => rule OF [thm])) (map (Thm.transfer' ctxt o #thm) derive_rules) in
map mk_fact derived end
fun get_more_specific [] = NONE
| get_more_specific [rule] = SOME rule
| get_more_specific (rule1::rules) = let fun get_more_specific' (lhs0, rule0) [] = SOME rule0
| get_more_specific' (lhs0, rule0) (rule1::rules) = let
val lhs1 = lhs_of_rule rule1 in if is_some (try Thm.match (lhs0, lhs1)) then
get_more_specific' (lhs1, rule1) rules
else
get_more_specific' (lhs0, rule0) rules end in
get_more_specific' (lhs_of_rule rule1, rule1) rules end
fun matching_rule ctxt trm = let
val rules = Data.get (Context.Proof ctxt) |> #rules
val matches = Net.match_term rules trm in get_more_specific matches |> Option.map (transfer_rule ctxt) end
fun lookup_by_name tvars x = let
val xs = Vars.dest tvars |> map (apfst fst) in
AList.lookup (op =) xs (x, 0) end
fun lhs_concl_conv cv thm = let
val n = Thm.nprems_of thm in
Conv.fconv_rule
(Conv.concl_conv n
(Conv.arg1_conv cv)) thm end
(* Plain Conv.rewr_conv did not work in our setting. The matching of lhs and ct fails. ButSimplifier.simplifywouldwork. SoConv.rewr_convseemstodo"toomuch"forourexactmatchbutnotasmuchassimplifier. (Maybesomekindofweiredeta-conversionstuff?) Butaswehaveanexactmatchanywaythereisnoneedtomatchagain.
*) fun rewr_exact_conv eq ct = let
val eq2 = ifThm.lhs_of eq aconvc ct then eq
else let val ceq = Thm.dest_fun2 (Thm.cprop_of eq)
val eq1 = Thm.trivial (Thm.mk_binop ceq ct (Thm.rhs_of eq)) in eq COMP eq1 end; inThm.transitive eq2 (Thm.beta_conversion true (Thm.rhs_of eq2)) end;
fun inst_split_rule ctxt ({apply_thm, split_vars, ...}:rule) ct = let
val lhs_rule = lhs_of apply_thm
val env as (Tvars, tvars) = Thm.match (lhs_rule, ct) in if null split_vars then
(Thm.instantiate env apply_thm, 0, [])
else let
val orig_var = hd split_vars
val bdy = the (lookup_by_name tvars orig_var)
val domT = Thm.typ_of_cterm bdy |> domain_type
val arity = domT |> HOLogic.flatten_tupleT |> length
val names = Tuple_Tools.strip_case_prod' (Thm.term_of bdy)
val split_ctxt = Proof_Context.init_global (Proof_Context.theory_of ctxt)
val (no_split, splitted_thm) = if length names = 1 andalso arity > 1then
(true, apply_thm) (* corner case of trivial \<open>\<lambda>(_::('a * ...)). f\<close> *)
else
(false, Tuple_Tools.split_rule split_ctxt split_vars apply_thm arity)
val tvars_eta = Vars.map (fn _ => Tuple_Tools.eta_expand_tuple ctxt) tvars
val eta_inst_rule = Thm.instantiate (Tvars, tvars_eta) apply_thm
val lhs_eta_inst_rule = lhs_of eta_inst_rule
val (inst_rule, names') = if arity <= 1then (eta_inst_rule, names)
else let
val env1 = Thm.match (lhs_of splitted_thm, lhs_eta_inst_rule)
val inst_thm1 = Thm.instantiate env1 splitted_thm
val inst_thm2 = if Utils.cterm_eq (lhs_eta_inst_rule, ct) then inst_thm1
else let
val _ = warning ("eta expanding case prod from:\n " ^ string_of_cterm ctxt ct ^ " to:\n " ^
string_of_cterm ctxt lhs_eta_inst_rule)
val eta_eq_prop = 🚫‹eta_lhs = lhs_eta_inst_rule and orig_lhs = ct
in cterm ‹eta_lhs ≡ orig_lhs›› ctxt
val eta_eq = Goal.prove_internal ctxt [] eta_eq_prop
(fn _ => asm_full_simp_tac ((Simplifier.clear_simpset ctxt) addsimps
@{thms case_prod_eta bind_case_prod_trivial case_prod_beta
case_prod_beta' prod.sel prod.collapse}) 1)
val obj = Thm.term_of (Thm.lhs_of eta_eq)
val pat = Thm.term_of (Utils.clhs_of (Thm.cconcl_of inst_thm1))
val inst_thm' = lhs_concl_conv (rewr_exact_conv eta_eq) inst_thm1 (* Preserve bound names *)
val inst_thm'' = Thm.rename_boundvars pat obj inst_thm' in inst_thm'' end
val bdy' = the (lookup_by_name tvars_eta orig_var)
val names' = if no_split then names else Tuple_Tools.strip_case_prod' (Thm.term_of bdy') in
(inst_thm2, names') end
val names'' = if arity = 1 andalso null names' then
[("r", domT)] (* make up name for eta-contracted corner case*)
else names' in
(inst_rule, arity, names'') end end
fun strip_all_fix names ct ctxt = let
val n = length names
val (bounds, _) = Utils.strip_all_open [] (Thm.term_of ct) |> apfst rev
val _ = if n <> length bounds then raise CTERM ("strip_all_fix: unequal length: " ^ @{make_string} (names, bounds), [ct]) else ()
val vars = names ~~ (map snd (take n bounds))
val (fixes, ctxt') = Utils.fix_variant_cfrees vars ctxt
val thm = Goal.prove_internal ctxt [] ct (fn _ => ALLGOALS (Skip_Proof.cheat_tac ctxt))
val thm' = thm |> fold Thm.forall_elim fixes
val ct' = Thm.cprop_of thm' in
((fixes, ct'), ctxt') end
fun fix_import_state_and_names ctxt names ct = let
val states = Prf_Data.get ctxt |> #states
val nstates = length states
val ((fixes, ct'), ctxt') = strip_all_fix (("s" ^ string_of_int nstates)::names) ct ctxt in ((fixes, ct'), ctxt') end
fun match_preserved_facts ctxt names ct = let
val ((fixes, ct'), ctxt') = fix_import_state_and_names ctxt names ct
handle CTERM _ => raise Match
val {f, s, r, t, lhs, rhs, ... } = @{cterm_match ‹PRESERVED_FACTS ?f ?s ?r ?t ==> ?lhs ≡ ?rhs›} ct'
val {g', ...} = @{cterm_match ‹run ?g' ?s›} rhs in
{f = f, s = s, t = t, r = r, results = tl fixes, lhs = lhs, g' = g', ctxt' = ctxt'} end
fun match_preserved_facts_while ctxt names ct = let
val ((fixes, ct'), ctxt') = fix_import_state_and_names ctxt names ct
handle CTERM _ => raise Match
val {C, B, i, s, r, t, C_lhs, C_rhs, B_lhs, B_rhs, ... } =
@{cterm_match ‹PRESERVED_FACTS_WHILE ?C ?B ?i ?s ?r ?t ==>
((?C_lhs ≡ ?C_rhs) &&& (?C_rhs ==> (?B_lhs ≡ ?B_rhs)))›} ct'
val C' = fst (Utils.strip_comb_cterm C_rhs)
val {B', ...} = @{cterm_match ‹run ?B' ?t›} B_rhs in
{C = C, C' = C', B = B, B' = B', i = i, s = s, r = r, t =t, results = tl fixes,
C_lhs = C_lhs, B_lhs = B_lhs, ctxt' = ctxt' } end
fun rhs_conv conv = Conv.fconv_rule (Conv.arg_conv conv) fun STOP_conv ctxt eq = let in
Utils.timeit_msg 4 ctxt (fn _ => "STOP_conv: ")
(fn _ => rhs_conv (Conv.try_conv (Conv.rewr_conv @{thm STOP_def})) eq) end
fun rewr_conv rules ct = let
val thms = Net.match_term rules (Thm.term_of ct) in
Conv.rewrs_conv thms ct end
fun mk_rewr_conv eqs = let fun prep eq = let val eq' = safe_mk_meta_eq eq in (Utils.rhs_of_eq (Thm.prop_of eq'), eq') end
val rules = Net.empty |> fold (Net.insert_term (Thm.eq_thm) o prep) eqs in
rewr_conv rules end
fun dest_abs_fresh (n, x) f =
snd (Thm.dest_abs_fresh n f) handle CTERM _ => Thm.apply f x
fun strip_case_prod_cterm ctxt ct = let
val args = Tuple_Tools.strip_case_prod' (Thm.term_of ct)
val (fixes, ctxt1) = Utils.fix_variant_cfrees args ctxt
val orig_names = map fst args
val names = map (fst o dest_Free o Thm.term_of) fixes
val named_fixes = names ~~ fixes fun strip [x, y] ct = let
val {f, ...} = @{cterm_match (fo) "case_prod ?f"} ct in dest_abs_fresh y (dest_abs_fresh x f) end
| strip [x] ct = dest_abs_fresh x ct
| strip [] ct = ct
| strip (x::xs) ct = let
val {f, ...} = @{cterm_match (fo) "case_prod ?f"} ct
val ct' = dest_abs_fresh x f in strip xs ct' end
val bdy = strip named_fixes ct in
((names ~~ fixes, orig_names, bdy), ctxt1) end
fun case_prod_bdy_conv ctxt ct = let
val ((fixes, orig_names, bdy), ctxt') = strip_case_prod_cterm ctxt ct
val bdy_eq = Simplifier.rewrite ctxt' bdy
val lhs = bdy_eq |> Thm.lhs_of
val rhs = bdy_eq |> Thm.rhs_of
val fixes' = map2 (fn (_, x) => fn n => (n, x)) fixes orig_names
val f = Utils.lambdas_tupled fixes' lhs
val g = Utils.lambdas_tupled fixes' rhs
val eq_prop = 🚫‹f = f and g = g in cprop "f ≡ g"› ctxt
val simps = if (Thm.term_of f) aconv (Thm.term_of g) then [] else (Proof_Context.export ctxt' ctxt [bdy_eq])
val simp_ctxt = Simplifier.clear_simpset ctxt addsimps (@{thms fun_eq_iff} @ simps)
val eq = Goal.prove_internal simp_ctxt [] eq_prop
(fn _ => simp_tac simp_ctxt 1) in
eq end
val case_prod_cong = @{lemma"x ≡ x' ==> case_prod f ≡ g ==> case_prod f x = g x'"for x x' f g by auto } fun case_prod_apply_conv ctxt = Match_Cterm.switch [
@{cterm_match "case_prod ?f ?x"} #> (fn {f, x, ct_, ...} => let
val x_eq = Simplifier.rewrite ctxt x
val cp = 🚫‹f = f in cterm ‹case_prod f›› ctxt
val cp_eq = case_prod_bdy_conv ctxt cp in case_prod_cong OF [x_eq, cp_eq] end)]
val pure_eqD = @{lemma"P ≡ True ==> P"by simp}
val pure_eqI = @{lemma"P ==> P ≡ True"by simp}
fun augment_rule_format thm = let
val thm1 = the_default thm (try (fn thm => thm RSN (1, pure_eqI) ―‹‹thm [then pure_eqI]››) thm)
val thm2 = the_default thm1 (try (fn thm => thm OF [pure_eqD]) thm1) in
thm2 end
(* e.g. avoid substition with \<open>n = global_variable s\<close> *) fun state_dependent_rhs ctxt thm = case states_of ctxt of
[] => false
| (s::_) => let val s' = Thm.term_of s in exists_subterm (fn t => t = s') (Utils.rhs_of (Thm.concl_of thm)) end
fun gen_mksimps do_simp ctxt thm = let
val augment_rules = Named_Theorems.get ctxt @{named_theorems monad_simp_augment_rule} fun augment thm = let
val augs = map_filter (fn rule => try (fn rule => rule OF [thm]) rule) augment_rules
|> map (Simplifier.simplify ctxt) |> filter_out Utils.trivial_meta_eq_thm
val _ = Utils.verbose_msg 7 ctxt (fn _ => "augmenting " ^ Thm.string_of_thm ctxt thm ^ " with " ^ string_of_thms ctxt augs) in thm :: augs end
val thm' = if do_simp then Simplifier.asm_full_simplify ctxt thm else thm in thm' |> Simplifier.mksimps ctxt |> filter_out ( Utils.trivial_meta_eq_thm orf (state_dependent_rhs ctxt)) (* avoid loops *)
|> maps augment end
fun new_from_defs ctxt defs thms = let
val lhss = map (Thm.term_of o lhs_of) defs in
thms |> map (Local_Defs.fold ctxt defs)
|> filter (exists_subterm (member (aconv) lhss) o Thm.prop_of) end
fun new_facts_from_defs ctxt defs ({pred, thms}:fact) = case new_from_defs ctxt defs thms of
[] => NONE
| thms' => let val pred' = Drule.mk_term pred |> Local_Defs.fold ctxt defs |> Drule.dest_term in SOME ({pred=pred', thms=thms'}:fact) end
fun monad_state_conv (rule as {split_vars, ...}) ctxt ct = let
val _ = Utils.verbose_msg 4 ctxt (fn _ => ("rule:\n " ^ Thm.string_of_thm ctxt (#apply_thm rule)))
fun monad_state_conv' (rules: rules) ctxt ct = let
val matches0 = Net.match_term rules (Thm.term_of ct) in case get_more_specific matches0 of
NONE => Thm.reflexive ct
| SOME rule => monad_state_conv rule ctxt ct end
fun monad_run_simproc rule ctxt ct = let
val eq = monad_state_conv rule ctxt ct in if Utils.is_reflexive ctxt eq then
NONE
else
SOME (Utils.timeit_msg 3 ctxt (fn _ => "STOPI: ") (fn _ => @{thm STOPI} OF [eq])) end
simproc_setupmonad_run_simproc(\<open>runfs\<close>)=\<open>fn_=>fnctxt=>fnct=> Monad_Cong_Simp.matching_rulectxt(Thm.term_ofct)|>Option.mapPartial(fnrule=> let val_=Utils.verbose_msg7ctxt(fn_=>"monad_run_simproc:\n"^string_of_ctermctxtct) in Monad_Cong_Simp.monad_run_simprocrulectxtct end)\<close> declare[[simprocdel:monad_run_simproc]]
fungen_monad_conv{stop}ctxtct= let valcT=Thm.ctyp_of_ctermct val{stateT,exnT,regT}=Thm.typ_of_ctermct|>dest_spec_monadT val{rules,...}=Data.get(Context.Proofctxt) val([s],ctxt1)=Utils.fix_variant_cfrees[("s",stateT)]ctxt valctxt2=map_states(K[s])ctxt1 vallhs=\<^infer_instantiate>\<open>f=ctands=\<open>s\<close> incterm\<open>runfs\<close>forf::\<open>('e::default,'a,'s)spec_monad\<close>\<close>ctxt valeq=monad_state_conv'rulesctxt2lhs valeq'=singleton(Proof_Context.exportctxt2ctxt)eq valeq'=@{thmspec_monad_ext'}OF[eq'] in ifstopthen(@{thmSTOPI}OF[eq'])|>Drule.zero_var_indexeselseeq' end
simproc_setupunchanged_typing_spec_monad(\<open>c\<bullet>s?\<lbrace>\<lambda>r.heap_typing_state.unchanged_typing_onhtd\<S>s\<rbrace>\<close>)=\<open> let valis_assume_stack_alloc=Match_Cterm.switch[ @{cterm_match(fo)"typ_heap_typing.assume_stack_alloc?r?w?ht?ht_upd?S?n?X\<bullet>?s?\<lbrace>?Q\<rbrace>"}#> (fn_=>true), (fn_=>false)]
valactive=Config.declare_bool("active",Position.none)(Kfalse); valprop_to_meta_eq=@{lemma\<open>P\<Longrightarrow>(P\<equiv>True)\<close>forPbyauto} funtry_provectxtprop= caseMonad_Cong_Simp.lookup_cachectxtpropof []=> let valctxt'=Context.proof_map(Named_Rules.add_thm@{named_rulesruns_to_vcg}@{thmruns_to_partial_case_prod})ctxt in casetry(Goal.prove_internalctxt'[]prop)(fn_=>Unchanged_Typing.unchanged_typing_tacNONEctxt')of NONE=>(warning("unchanged_typingprooffailed:"^string_of_ctermctxtprop);NONE) |SOMEthm=>(Monad_Cong_Simp.add_to_cachectxtthm;SOMEthm) end |(thm::_)=>(Utils.verbose_msg4ctxt(fn_=>"cachehit:"^Thm.string_of_thmctxtthm);SOMEthm) in fnphi=>fnctxt=>fnct=> ifConfig.getctxtactiveorelse(is_assume_stack_allocct)thenNONEelse let val_=Utils.verbose_msg4ctxt(fn_=>"unchanged_typing_spec_monadinvokedon:\n"^@{make_string}ct) in try_prove(Config.putactivetruectxt)\<^instantiate>\<open>P=ctincterm\<open>TruepropP\<close>forP\<close> |>Option.map(fnthm=>prop_to_meta_eqOF[thm]) end end \<close> declare[[simprocdel:unchanged_typing_spec_monad]]
setup\<open> let val(unchanged_typing_simproc_name,_)= Simplifier.check_simproc@{context}("unchanged_typing_spec_monad",\<^here>) in Context.theory_map(Monad_Cong_Simp.add_simprocunchanged_typing_simproc_name) end \<close>
(* Herethelocalizedversion.
contextheap_typing_state begin
simproc_setupunchanged_typing_spec_monad(\<open>c\<bullet>s?\<lbrace>\<lambda>r.unchanged_typing_on\<S>s\<rbrace>\<close>)=\<open> let valprop_to_meta_eq=@{lemma\<open>P\<Longrightarrow>(P\<equiv>True)\<close>forPbyauto} funtry_provectxtprop=try(Goal.prove_internalctxt[]prop) (fn_=>Unchanged_Typing.unchanged_typing_tacNONEctxt) in fnphi=>fnctxt=>fnct=> let val_=Utils.verbose_msg4ctxt(fn_=>"unchanged_typing_spec_monadinvokedon:\n"^@{make_string}ct) in try_provectxt\<^instantiate>\<open>P=ctincterm\<open>TruepropP\<close>forP\<close> |>Option.map(fnthm=>prop_to_meta_eqOF[thm]) end end \<close> declare[[simprocdel:unchanged_typing_spec_monad]]
declaration\<open> let val(unchanged_typing_simproc_name,_)= Simplifier.check_simproc@{context}("unchanged_typing_spec_monad",\<^here>) valb=Binding.make(Long_Name.base_nameunchanged_typing_simproc_name,\<^here>) in
fnphi=> let valb'=Morphism.bindingphib vallong_name=Long_Name.implode((mapfst(Binding.prefix_ofb'))@[Binding.name_ofb']) in Monad_Cong_Simp.add_simproc(long_name) end
end
\<close> end
*)
simproc_setup spec_monad_simproc (‹f::('a, 'b, 'c) spec_monad›) = ‹fn _ => fn ctxt =>
if Monad_Cong_Simp.monad_simp_active ctxt then K NONE else
Match_Cterm.switch [
@{cterm_match "STOP _"} #> (fn _ => NONE),
fn ct =>
let
val _ = Utils.verbose_msg 7 ctxt (fn _ => ("spec_monad_simproc:\n " ^ string_of_cterm ctxt ct))
val eq = Monad_Cong_Simp.gen_monad_conv {stop=true} ctxt ct
val _ = Utils.verbose_msg 7 ctxt (fn _ => ("spec_monad_simproc eq:\n " ^ Thm.string_of_thm ctxt eq))
in
SOME eq
end]› declare [[simproc del: spec_monad_simproc]]
ML ‹
Monad_Cong_Simp =
open Monad_Cong_Simp
prepare_simpset max_depth ctxt =
let
val {stop_congs, simprocs, ...} = Monad_Cong_Simp.Data.get (Context.Proof ctxt)
val simprocs' = map (snd o Simplifier.check_simproc ctxt o rpair Position.none) simprocs
val visible = Context_Position.is_visible ctxt
val monad_cong_simps = Named_Theorems.get ctxt @{named_theorems monad_simp_simp}
val run_spec_monad = Named_Theorems.get ctxt @{named_theorems run_spec_monad}
val state_fold_congs = Named_Theorems.get ctxt @{named_theorems state_fold_congs}
val recursive_records_fold_congs = Named_Theorems.get ctxt @{named_theorems recursive_records_fold_congs}
context open_types_heap_typing_state begin lemma PRESERVED_FACTS_unchanged_typing_ptr_valid_preserved[monad_simp_simp]: "reaches f s r t ==> ptr_valid (heap_typing s) p ==> f ∙ s ?{λ_ t. unchanged_typing_on UNIV s t}==> ptr_valid (heap_typing t) p" by (rule reaches_unchanged_typing_ptr_valid_preserved)
lemma PRESERVED_FACTS_WHILE_unchanged_typing_ptr_valid_preserved[monad_simp_simp]: assumes reach: "whileLoop_unroll_reachable C B i s r t" assumes valid: "ptr_valid (heap_typing s) p" assumes B: "∧r t. C r t ==> (B r) ∙ t ?{λ_. unchanged_typing_on UNIV t}" shows"ptr_valid (heap_typing t) p" proof - have"unchanged_typing_on UNIV s t" using reach proofinduction case (step b t X c u) with B[of b t] unchanged_typing_on_trans[of UNIV s t u] show ?case by (auto simp add: runs_to_partial_holds_partial_def ) qed simp
with valid show ?thesis by (simp add: unchanged_typing_on_UNIV_iff) qed
end
lemma PRESERVED_FACTS_run_bind_cong[monad_simp_cong split: g and g']: "run f s = run f' s ==> (∧t r. PRESERVED_FACTS f' s (Result r) t ==> run (g r) t = run (g' r) t) ==> (run (bind f g) s) = (run (bind f' g') s)" apply (rule Spec_Monad.run_bind_cong) apply (auto simp add: PRESERVED_FACTS_def runs_to_partial_def_old reaches_def) done
lemma ADD_FACT_run_bind_guard_cong[monad_simp_cong]: "P s = P' s ==> (ADD_FACT P' s ==> run f s = run f' s) ==> (run (bind (guard P) (λ_. f)) s) = (run (bind (guard P') (λ_. f')) s)" apply (simp add: ADD_FACT_def) apply (rule run_bind_cong) apply (simp add: run_guard) apply (auto simp add: run_guard if_split_asm runs_to_partial_def_old) done
lemma PRESERVED_FACTS_WHILE_run_whileLoop_cong[monad_simp_cong split: B and B' and C andC']: assumes i: "i = i'" assumes C_B[unfolded PRESERVED_FACTS_WHILE_def]: "∧t r. PRESERVED_FACTS_WHILE C B i s r t ==> (C r t ≡ C' r t) &&& (C' r t ==> (run (B r) t ≡ run (B' r) t))" shows"run (whileLoop C B i) s = run (whileLoop C' B' i') s" proof - from C_B have C: "∧r s'. whileLoop_unroll_reachable C B i s r s' ==> C r s' = C' r s'"by blast from C_B have B: "∧r s'. whileLoop_unroll_reachable C B i s r s' ==> C' r s' ==> run (B r) s' = run (B' r) s'" by blast with C have"∧r s'. whileLoop_unroll_reachable C B i s r s' ==> C r s' ==> run (B r) s' = run (B' r) s'" by simp from run_whileLoop_unroll_reachable_cong [OF C this] show ?thesis by (simp add: i) qed
lemma whileLoop_condition_only_cong[monad_simp_split_tuple_cong]: "C = C' ==> whileLoop C B I = whileLoop C' B I" by simp
lemma PRESERVED_FACTS_run_bind_exception_or_result_cong[monad_simp_cong split: g andg']: "run f s = run f' s ==> (∧t r. PRESERVED_FACTS f' s r t ==> run (g r) t = run (g' r) t) ==> (run (bind_exception_or_result f g) s) = (run (bind_exception_or_result f' g') s)" apply (rule Spec_Monad.run_bind_exception_or_result_cong) apply (auto simp add: PRESERVED_FACTS_def runs_to_partial_def_old reaches_def) done
lemma PRESERVED_FACTS_run_on_exit'_cong[monad_simp_cong split: g and g']: "run f s = run f' s ==> (∧t r. PRESERVED_FACTS f' s r t ==> run g t = run g' t) ==> (run (on_exit' f g) s) = (run (on_exit' f' g') s)" unfolding on_exit'_def apply (rule PRESERVED_FACTS_run_bind_exception_or_result_cong) apply assumption apply (rule PRESERVED_FACTS_run_bind_cong) apply assumption apply simp done
lemma PRESERVED_FACTS_run_on_exit_cong[monad_simp_cong split: g and g']: "run f s = run f' s ==> (∧t r. PRESERVED_FACTS f' s r t ==> run ((state_select g::('e::default, unit, 's) spec_monad)) t = run (state_select g') t) ==> (run (on_exit f g::('e::default, 'a, 's) spec_monad) s) = (run (on_exit f' g') s)" unfolding on_exit_def apply (rule PRESERVED_FACTS_run_on_exit'_cong) apply assumption apply simp done
lemma ADD_FACT_run_condition_cong [monad_simp_cong]: assumes"c s = c' s" assumes"ADD_FACT c' s ==> run f s = run f' s" assumes"ADD_FACT (λs. ¬ c' s) s ==> run g s = run g' s" shows"run (condition c f g) s = run (condition c' f' g') s" using assms by (auto simp add: ADD_FACT_def run_condition)
lemma ADD_FACT_run_when [monad_simp_cong]: assumes"c = c'" assumes"ADD_FACT (λ_. c') s ==> run f s = run f' s" shows"run (when c f) s = run (when c' f') s" using assms by (auto simp add: ADD_FACT_def when_def run_condition)
lemma PRESERVED_FACTS_run_catch_cong [monad_simp_cong split: g and g']: "run f s = run f' s ==> (∧t e. PRESERVED_FACTS f' s (Exn e) t ==> run (g e) t = run (g' e) t) ==> (run (catch f g) s) = (run (catch f' g') s)" apply (simp add: run_catch PRESERVED_FACTS_def reaches_def) apply (rule bind_post_state_cong) apply (auto split: xval_splits) done
lemma run_finally_cong [monad_simp_cong]: assumes"run f s = run f' s" shows"run (finally f) s = run (finally f') s" using assms by (simp add: run_finally)
lemma run_liftE_cong [monad_simp_cong]: assumes"run f s = run f' s" shows"run (liftE f) s = run (liftE f') s" using assms by (simp add: run_liftE)
lemma run_guard_cong [monad_simp_cong]: assumes"P s = P' s" shows"run (guard P) s = run (guard P') s" using assms by (simp add: run_guard)
lemma run_try_cong [monad_simp_cong]: assumes"run f s = run f' s" shows"run (try f) s = run (try f') s" using assms by (simp add: run_try)
lemma run_case_prod_cong[monad_simp_cong]: "RUN_CASE_PROD f x s f' x' ==> (run (case_prod f x) s) = (run (case_prod f' x') s)" by (cases x) (auto simp add: RUN_CASE_PROD_def)
lemma run_bind_when_throw_cong [monad_simp_cong]: "c = c' ==> e = e' ==> (ADD_FACT (λ_. ¬ c') s ==> run f s = run f' s) ==> run (bind (when c (throw e)) (λ_. f)) s = run (bind (when c' (throw e')) (λ_. f')) s" by (auto simp add: ADD_FACT_def)
ML ‹
.print_rules (Context.Proof @{context}) ›
lemma with_fresh_stack_ptr_stop_cong [monad_simp_global_stop_cong]: "typ_heap_typing.with_fresh_stack_ptr r w heap_typing heap_typing_upd S n init f≡ typ_heap_typing.with_fresh_stack_ptr r w heap_typing heap_typing_upd S n init f" by (simp)
lemma assume_with_fresh_stack_ptr_stop_cong [monad_simp_global_stop_cong]: "typ_heap_typing.assume_with_fresh_stack_ptr r w heap_typing heap_typing_upd S n init f ≡ typ_heap_typing.assume_with_fresh_stack_ptr r w heap_typing heap_typing_upd S n init f" by (simp)
lemma guard_with_fresh_stack_ptr_stop_cong [monad_simp_global_stop_cong]: "typ_heap_typing.guard_with_fresh_stack_ptr r w heap_typing heap_typing_upd S n init f ≡ typ_heap_typing.guard_with_fresh_stack_ptr r w heap_typing heap_typing_upd S n init f" by (simp)
context typ_heap_simulation_open_types_stack begin
lemma PRESERVED_FACTS_assume_stack_alloc_ptr_valid_preserved[monad_simp_simp]: "reaches (assume_stack_alloc n init) s x t ==> ptr_valid (heap_typing s) (p::'b::mem_type ptr) ==> typ_uinfo_t TYPE('b) ≠ typ_uinfo_t TYPE(stack_byte) ==> ptr_valid (heap_typing t) p" apply (clarsimp simp add: stack_ptr_acquire_def heap_typing_fold_upd_write reaches_def
assume_stack_alloc_def) using stack_allocs_ptr_valid_cases2 by blast
lemma PRESERVED_FACTS_with_fresh_stack_ptr_cong[monad_simp_cong split: f and f' (* rename bound variable *)]: fixes f::"'a ptr ==> ('e::default, 'd, 't) spec_monad" assumes"∧t p. PRESERVED_FACTS (assume_stack_alloc n init::('e::default, 'a ptr, 't) spec_monad) s (Result p) t ==> run (f p) t = run (f' p) t" shows"run (with_fresh_stack_ptr n init f) s = run (with_fresh_stack_ptr n init f') s" apply (simp add: with_fresh_stack_ptr_def PRESERVED_FACTS_def ADD_FACT_def) apply (rule run_bind_cong)
subgoal by simp
subgoal apply (clarsimp simp add: runs_to_partial_def_old on_exit_def on_exit'_def) apply (rule run_bind_exception_or_result_cong)
subgoal apply (rule assms) apply (simp add: PRESERVED_FACTS_def ADD_FACT_def) done
subgoal by simp done done
lemma PRESERVED_FACTS_assume_with_fresh_stack_ptr_cong[monad_simp_cong split: f and f' (* rename bound variable *)]: fixes f::"'a ptr ==> ('e::default, 'd, 't) spec_monad" assumes"∧t p. PRESERVED_FACTS (assume_stack_alloc n init::('e::default, 'a ptr, 't) spec_monad) s (Result p) t ==> run (f p) t = run (f' p) t" shows"run (assume_with_fresh_stack_ptr n init f) s = run (assume_with_fresh_stack_ptr n init f') s" apply (simp add: assume_with_fresh_stack_ptr_def PRESERVED_FACTS_def ADD_FACT_def) apply (rule run_bind_cong)
subgoal by simp
subgoal apply (clarsimp simp add: runs_to_partial_def_old on_exit_def on_exit'_def) apply (rule run_bind_exception_or_result_cong)
subgoal apply (rule assms) apply (simp add: PRESERVED_FACTS_def ADD_FACT_def) done
subgoal by simp done done
lemma PRESERVED_FACTS_guard_with_fresh_stack_ptr_cong[monad_simp_cong split: f and f' (* rename bound variable *)]: fixes f::"'a ptr ==> ('e::default, 'd, 't) spec_monad" assumes"∧t p. PRESERVED_FACTS (assume_stack_alloc n init::('e::default, 'a ptr, 't) spec_monad) s (Result p) t ==> run (f p) t = run (f' p) t" shows"run (guard_with_fresh_stack_ptr n init f) s = run (guard_with_fresh_stack_ptr n init f') s" apply (simp add: guard_with_fresh_stack_ptr_def PRESERVED_FACTS_def ADD_FACT_def) apply (rule run_bind_cong)
subgoal by simp
subgoal apply (clarsimp simp add: runs_to_partial_def_old on_exit_def on_exit'_def) apply (rule run_bind_exception_or_result_cong)
subgoal apply (rule assms) apply (simp add: PRESERVED_FACTS_def ADD_FACT_def) done
subgoal by simp done done
lemma ptr_valid_assume_stack_alloc [monad_simp_derive_rule]: "PRESERVED_FACTS (assume_stack_alloc n init::('e::default, 'a ptr, 't) spec_monad) s (Result p) t ==> ADD_FACT (λt. PTR_VALID('a) (heap_typing t) p) t" apply (simp add: PRESERVED_FACTS_def ADD_FACT_def) apply (auto simp add: stack_ptr_acquire_def heap_typing_fold_upd_write reaches_def
assume_stack_alloc_def root_ptr_valid_ptr_valid elim!: stack_allocs_cases) done
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.