summaryrefslogtreecommitdiff
path: root/lib/isabelle/Hoare.thy
diff options
context:
space:
mode:
Diffstat (limited to 'lib/isabelle/Hoare.thy')
-rw-r--r--lib/isabelle/Hoare.thy131
1 files changed, 131 insertions, 0 deletions
diff --git a/lib/isabelle/Hoare.thy b/lib/isabelle/Hoare.thy
index 88807c7c..76750117 100644
--- a/lib/isabelle/Hoare.thy
+++ b/lib/isabelle/Hoare.thy
@@ -253,6 +253,27 @@ lemma PrePostE_weaken_post:
named_theorems PrePostE_compositeI
named_theorems PrePostE_atomI
+lemma PrePostE_conj_conds:
+ assumes "PrePostE P1 m Q1 E1"
+ and "PrePostE P2 m Q2 E2"
+ shows "PrePostE (\<lambda>s. P1 s \<and> P2 s) m (\<lambda>r s. Q1 r s \<and> Q2 r s) (\<lambda>e s. E1 e s \<and> E2 e s)"
+ using assms by (auto intro: PrePostE_I elim: PrePostE_elim)
+
+lemmas PrePostE_conj_conds_consequence = PrePostE_conj_conds[THEN PrePostE_consequence]
+
+lemma PrePostE_post_mp:
+ assumes "PrePostE P m Q' E"
+ and "PrePostE P m (\<lambda>r s. Q' r s \<longrightarrow> Q r s) E"
+ shows "PrePostE P m Q E"
+ using PrePostE_conj_conds[OF assms] by (auto intro: PrePostE_weaken_post)
+
+lemma PrePostE_cong:
+ assumes "\<And>s. P1 s \<longleftrightarrow> P2 s" and "\<And>s. P1 s \<Longrightarrow> m1 s = m2 s" and "\<And>r s. Q1 r s \<longleftrightarrow> Q2 r s"
+ and "\<And>e s. E1 e s \<longleftrightarrow> E2 e s"
+ shows "PrePostE P1 m1 Q1 E1 \<longleftrightarrow> PrePostE P2 m2 Q2 E2"
+ using assms unfolding PrePostE_def PrePost_def
+ by (auto split: result.splits)
+
lemma PrePostE_True_post[PrePostE_atomI, intro, simp]:
"PrePostE P m (\<lambda>_ _. True) (\<lambda>_ _. True)"
unfolding PrePost_defs by (auto split: result.splits)
@@ -320,6 +341,11 @@ lemma PrePostE_option_cases[PrePostE_compositeI]:
shows "PrePostE (case x of Some a \<Rightarrow> PS a | None \<Rightarrow> PN) (case x of Some a \<Rightarrow> s a | None \<Rightarrow> n) Q E"
using assms by (auto split: option.splits)
+lemma PrePostE_sum_cases[PrePostE_compositeI]:
+ assumes "\<And>a. PrePostE (Pl a) (l a) Q E" and "\<And>b. PrePostE (Pr b) (r b) Q E"
+ shows "PrePostE (case x of Inl a \<Rightarrow> Pl a | Inr b \<Rightarrow> Pr b) (case x of Inl a \<Rightarrow> l a | Inr b \<Rightarrow> r b) Q E"
+ using assms by (auto split: sum.splits)
+
lemma PrePostE_let[PrePostE_compositeI]:
assumes "PrePostE P (m y) Q E"
shows "PrePostE P (let x = y in m x) Q E"
@@ -347,10 +373,51 @@ lemma PrePostE_failS[PrePostE_atomI, intro]:
"PrePostE (E (Failure msg)) (failS msg) Q E"
unfolding PrePostE_def by (auto intro: PrePost_strengthen_pre)
+lemma PrePostE_maybe_failS[PrePostE_atomI]:
+ "PrePostE (\<lambda>s. case v of Some v \<Rightarrow> Q v s | None \<Rightarrow> E (Failure msg) s) (maybe_failS msg v) Q E"
+ by (auto simp: maybe_failS_def split: option.splits)
+
+lemma PrePostE_exitS[PrePostE_atomI, intro]: "PrePostE (E (Failure ''exit'')) (exitS msg) Q E"
+ unfolding exitS_def PrePostE_def PrePost_def failS_def by auto
+
lemma PrePostE_chooseS[intro, PrePostE_atomI]:
"PrePostE (\<lambda>s. \<forall>x \<in> xs. Q x s) (chooseS xs) Q E"
unfolding PrePostE_def by (auto intro: PrePost_strengthen_pre)
+lemma PrePostE_throwS[PrePostE_atomI]: "PrePostE (E (Throw e)) (throwS e) Q E"
+ by (intro PrePostE_I) (auto simp: throwS_def)
+
+lemma PrePostE_try_catchS[PrePostE_compositeI]:
+ assumes Ph: "\<And>s e s'. (Ex (Throw e), s') \<in> m s \<Longrightarrow> PrePostE (Ph e) (h e) Q E"
+ and m: "PrePostE P m Q (\<lambda>ex. case ex of Throw e \<Rightarrow> Ph e | Failure msg \<Rightarrow> E (Failure msg))"
+ shows "PrePostE P (try_catchS m h) Q E"
+ unfolding PrePostE_def
+proof (intro PrePostI)
+ fix s r s'
+ assume "(r, s') \<in> try_catchS m h s" and P: "P s"
+ then show "(case r of Value a \<Rightarrow> Q a | result.Ex e \<Rightarrow> E e) s'" using m
+ proof (cases rule: try_catchS_cases)
+ case (h e s'')
+ then have "Ph e s''" using P m by (auto elim!: PrePostE_elim)
+ then show ?thesis using Ph[OF h(1)] h(2) by (auto elim!: PrePostE_elim)
+ qed (auto elim!: PrePostE_elim)
+qed
+
+lemma PrePostE_catch_early_returnS[PrePostE_compositeI]:
+ assumes "PrePostE P m Q (\<lambda>ex. case ex of Throw (Inl a) \<Rightarrow> Q a | Throw (Inr e) \<Rightarrow> E (Throw e) | Failure msg \<Rightarrow> E (Failure msg))"
+ shows "PrePostE P (catch_early_returnS m) Q E"
+ unfolding catch_early_returnS_def
+ by (rule PrePostE_try_catchS, rule PrePostE_sum_cases[OF PrePostE_returnS PrePostE_throwS])
+ (auto intro: assms)
+
+lemma PrePostE_early_returnS[PrePostE_atomI]: "PrePostE (E (Throw (Inl r))) (early_returnS r) Q E"
+ by (auto simp: early_returnS_def intro: PrePostE_throwS)
+
+lemma PrePostE_liftRS[PrePostE_compositeI]:
+ assumes "PrePostE P m Q (\<lambda>ex. case ex of Throw e \<Rightarrow> E (Throw (Inr e)) | Failure msg \<Rightarrow> E (Failure msg))"
+ shows "PrePostE P (liftRS m) Q E"
+ using assms unfolding liftRS_def by (intro PrePostE_try_catchS[OF PrePostE_throwS])
+
lemma PrePostE_foreachS_Cons:
assumes "\<And>s vars' s'. (Value vars', s') \<in> body x vars s \<Longrightarrow> PrePostE (Q vars') (foreachS xs vars' body) Q E"
and "PrePostE (Q vars) (body x vars) Q E"
@@ -363,6 +430,70 @@ lemma PrePostE_foreachS_invariant:
using assms unfolding PrePostE_def
by (intro PrePost_foreachS_invariant[THEN PrePost_strengthen_pre]) auto
+lemma PrePostE_untilS:
+ assumes dom: "\<And>s. Inv Q vars s \<Longrightarrow> untilS_dom (vars, cond, body, s)"
+ and cond: "\<And>vars. PrePostE (Inv' Q vars) (cond vars) (\<lambda>c s'. Inv Q vars s' \<and> (c \<longrightarrow> Q vars s')) E"
+ and body: "\<And>vars. PrePostE (Inv Q vars) (body vars) (Inv' Q) E"
+ shows "PrePostE (Inv Q vars) (untilS vars cond body) Q E"
+proof (unfold PrePostE_def, rule PrePostI)
+ fix s r s'
+ assume Inv_s: "Inv Q vars s" and r: "(r, s') \<in> untilS vars cond body s"
+ with dom[OF Inv_s] cond body
+ show "(case r of Value a \<Rightarrow> Q a | result.Ex e \<Rightarrow> E e) s'"
+ proof (induction vars cond body s rule: untilS.pinduct[case_names Step])
+ case (Step vars cond body s)
+ consider
+ (Value) vars' c sb sc where "(Value vars', sb) \<in> body vars s" and "(Value c, sc) \<in> cond vars' sb"
+ and "if c then r = Value vars' \<and> s' = sc else (r, s') \<in> untilS vars' cond body sc"
+ | (Ex) e where "(Ex e, s') \<in> bindS (body vars) cond s" and "r = Ex e"
+ using Step(1,6)
+ by (auto simp: untilS.psimps returnS_def Ex_bindS_iff elim!: bindS_cases split: if_splits; fastforce)
+ then show ?case
+ proof cases
+ case Value
+ then show ?thesis using Step.IH[OF Value(1,2) _ Step(3,4)] Step(3,4,5)
+ by (auto split: if_splits elim: PrePostE_elim)
+ next
+ case Ex
+ then show ?thesis using Step(3,4,5) by (auto elim!: bindS_cases PrePostE_elim)
+ qed
+ qed
+qed
+
+lemma PrePostE_untilS_pure_cond:
+ assumes dom: "\<And>s. Inv Q vars s \<Longrightarrow> untilS_dom (vars, returnS \<circ> cond, body, s)"
+ and body: "\<And>vars. PrePostE (Inv Q vars) (body vars) (\<lambda>vars' s'. Inv Q vars' s' \<and> (cond vars' \<longrightarrow> Q vars' s')) E"
+ shows "PrePostE (Inv Q vars) (untilS vars (returnS \<circ> cond) body) Q E"
+ using assms by (intro PrePostE_untilS) (auto simp: comp_def)
+
+lemma PrePostE_liftState_untilM:
+ assumes dom: "\<And>s. Inv Q vars s \<Longrightarrow> untilM_dom (vars, cond, body)"
+ and cond: "\<And>vars. PrePostE (Inv' Q vars) (liftState r (cond vars)) (\<lambda>c s'. Inv Q vars s' \<and> (c \<longrightarrow> Q vars s')) E"
+ and body: "\<And>vars. PrePostE (Inv Q vars) (liftState r (body vars)) (Inv' Q) E"
+ shows "PrePostE (Inv Q vars) (liftState r (untilM vars cond body)) Q E"
+proof -
+ have domS: "untilS_dom (vars, liftState r \<circ> cond, liftState r \<circ> body, s)" if "Inv Q vars s" for s
+ using dom that by (intro untilM_dom_untilS_dom)
+ then have "PrePostE (Inv Q vars) (untilS vars (liftState r \<circ> cond) (liftState r \<circ> body)) Q E"
+ using cond body by (auto intro: PrePostE_untilS simp: comp_def)
+ moreover have "liftState r (untilM vars cond body) s = untilS vars (liftState r \<circ> cond) (liftState r \<circ> body) s"
+ if "Inv Q vars s" for s
+ unfolding liftState_untilM[OF domS[OF that] dom[OF that]] ..
+ ultimately show ?thesis by (auto cong: PrePostE_cong)
+qed
+
+lemma PrePostE_liftState_untilM_pure_cond:
+ assumes dom: "\<And>s. Inv Q vars s \<Longrightarrow> untilM_dom (vars, return \<circ> cond, body)"
+ and body: "\<And>vars. PrePostE (Inv Q vars) (liftState r (body vars)) (\<lambda>vars' s'. Inv Q vars' s' \<and> (cond vars' \<longrightarrow> Q vars' s')) E"
+ shows "PrePostE (Inv Q vars) (liftState r (untilM vars (return \<circ> cond) body)) Q E"
+ using assms by (intro PrePostE_liftState_untilM) (auto simp: comp_def liftState_simp)
+
+lemma PrePostE_undefined_boolS[PrePostE_atomI]:
+ "PrePostE (\<lambda>s. \<forall>b. Q b s)
+ (undefined_boolS unit) Q E"
+ unfolding undefined_boolS_def seqS_def
+ by (auto intro: PrePostE_strengthen_pre PrePostE_chooseS)
+
lemma PrePostE_bool_of_bitU_nondetS_any:
"PrePostE (\<lambda>s. \<forall>b. Q b s) (bool_of_bitU_nondetS b) Q E"
unfolding bool_of_bitU_nondetS_def undefined_boolS_def