diff options
| author | Jon French | 2018-06-11 15:25:02 +0100 |
|---|---|---|
| committer | Jon French | 2018-06-11 15:25:02 +0100 |
| commit | 826e94548a86a88d8fefeb1edef177c02bf5d68d (patch) | |
| tree | fc9a5484440e030cc479101c5cab345c1c77468e /lib/isabelle | |
| parent | 5717bb3d0cef5932cb2b33bc66b3b2f0c0552164 (diff) | |
| parent | 4336409f923c10a8c5e4acc91fa7e6ef5551a88f (diff) | |
Merge branch 'sail2' into mappings
(involved some manual tinkering with gitignore, type_check, riscv)
Diffstat (limited to 'lib/isabelle')
| -rw-r--r-- | lib/isabelle/Hoare.thy | 100 | ||||
| -rw-r--r-- | lib/isabelle/Makefile | 5 | ||||
| -rw-r--r-- | lib/isabelle/Prompt_monad_lemmas.thy | 1 | ||||
| -rw-r--r-- | lib/isabelle/State_lemmas.thy | 138 | ||||
| -rw-r--r-- | lib/isabelle/manual/Manual.thy | 19 |
5 files changed, 187 insertions, 76 deletions
diff --git a/lib/isabelle/Hoare.thy b/lib/isabelle/Hoare.thy index ee7a5fa6..9271e2fa 100644 --- a/lib/isabelle/Hoare.thy +++ b/lib/isabelle/Hoare.thy @@ -42,19 +42,20 @@ lemma PrePost_weaken_post: shows "PrePost A f C" using assms by (blast intro: PrePost_consequence) -named_theorems PrePost_intro +named_theorems PrePost_compositeI +named_theorems PrePost_atomI -lemma PrePost_True_post[PrePost_intro, intro, simp]: +lemma PrePost_True_post[PrePost_atomI, intro, simp]: "PrePost P m (\<lambda>_ _. True)" unfolding PrePost_def by auto lemma PrePost_any: "PrePost (\<lambda>s. \<forall>(r, s') \<in> m s. Q r s') m Q" unfolding PrePost_def by auto -lemma PrePost_returnS[intro, PrePost_intro]: "PrePost (P (Value x)) (returnS x) P" +lemma PrePost_returnS[intro, PrePost_atomI]: "PrePost (P (Value x)) (returnS x) P" unfolding PrePost_def returnS_def by auto -lemma PrePost_bindS[intro, PrePost_intro]: +lemma PrePost_bindS[intro, PrePost_compositeI]: assumes f: "\<And>s a s'. (Value a, s') \<in> m s \<Longrightarrow> PrePost (R a) (f a) Q" and m: "PrePost P m (\<lambda>r. case r of Value a \<Rightarrow> R a | Ex e \<Rightarrow> Q (Ex e))" shows "PrePost P (bindS m f) Q" @@ -89,10 +90,10 @@ lemma PrePost_bindS_unit: shows "PrePost P (bindS m f) Q" using assms by auto -lemma PrePost_readS[intro, PrePost_intro]: "PrePost (\<lambda>s. P (Value (f s)) s) (readS f) P" +lemma PrePost_readS[intro, PrePost_atomI]: "PrePost (\<lambda>s. P (Value (f s)) s) (readS f) P" unfolding PrePost_def readS_def returnS_def by auto -lemma PrePost_updateS[intro, PrePost_intro]: "PrePost (\<lambda>s. P (Value ()) (f s)) (updateS f) P" +lemma PrePost_updateS[intro, PrePost_atomI]: "PrePost (\<lambda>s. P (Value ()) (f s)) (updateS f) P" unfolding PrePost_def updateS_def returnS_def by auto lemma PrePost_if: @@ -100,7 +101,7 @@ lemma PrePost_if: shows "PrePost P (if b then f else g) Q" using assms by auto -lemma PrePost_if_branch[PrePost_intro]: +lemma PrePost_if_branch[PrePost_compositeI]: assumes "b \<Longrightarrow> PrePost Pf f Q" and "\<not>b \<Longrightarrow> PrePost Pg g Q" shows "PrePost (if b then Pf else Pg) (if b then f else g) Q" using assms by auto @@ -115,35 +116,65 @@ lemma PrePost_if_else: shows "PrePost P (if b then f else g) Q" using assms by auto -lemma PrePost_prod_cases[PrePost_intro]: +lemma PrePost_prod_cases[PrePost_compositeI]: assumes "PrePost P (f (fst x) (snd x)) Q" shows "PrePost P (case x of (a, b) \<Rightarrow> f a b) Q" using assms by (auto split: prod.splits) -lemma PrePost_option_cases[PrePost_intro]: +lemma PrePost_option_cases[PrePost_compositeI]: assumes "\<And>a. PrePost (PS a) (s a) Q" and "PrePost PN n Q" shows "PrePost (case x of Some a \<Rightarrow> PS a | None \<Rightarrow> PN) (case x of Some a \<Rightarrow> s a | None \<Rightarrow> n) Q" using assms by (auto split: option.splits) -lemma PrePost_let[intro, PrePost_intro]: +lemma PrePost_let[intro, PrePost_compositeI]: assumes "PrePost P (m y) Q" shows "PrePost P (let x = y in m x) Q" using assms by auto -lemma PrePost_assert_expS[intro, PrePost_intro]: "PrePost (if c then P (Value ()) else P (Ex (Failure m))) (assert_expS c m) P" +lemma PrePost_and_boolS[PrePost_compositeI]: + assumes r: "PrePost R r Q" + and l: "PrePost P l (\<lambda>r. case r of Value True \<Rightarrow> R | _ \<Rightarrow> Q r)" + shows "PrePost P (and_boolS l r) Q" + unfolding and_boolS_def +proof (rule PrePost_bindS) + fix s a s' + assume "(Value a, s') \<in> l s" + show "PrePost (if a then R else Q (Value False)) (if a then r else returnS False) Q" + using r by auto +next + show "PrePost P l (\<lambda>r. case r of Value a \<Rightarrow> if a then R else Q (Value False) | Ex e \<Rightarrow> Q (Ex e))" + using l by (elim PrePost_weaken_post) (auto split: result.splits) +qed + +lemma PrePost_or_boolS[PrePost_compositeI]: + assumes r: "PrePost R r Q" + and l: "PrePost P l (\<lambda>r. case r of Value False \<Rightarrow> R | _ \<Rightarrow> Q r)" + shows "PrePost P (or_boolS l r) Q" + unfolding or_boolS_def +proof (rule PrePost_bindS) + fix s a s' + assume "(Value a, s') \<in> l s" + show "PrePost (if a then Q (Value True) else R) (if a then returnS True else r) Q" + using r by auto +next + show "PrePost P l (\<lambda>r. case r of Value a \<Rightarrow> if a then Q (Value True) else R | Ex e \<Rightarrow> Q (Ex e))" + using l by (elim PrePost_weaken_post) (auto split: result.splits) +qed + +lemma PrePost_assert_expS[intro, PrePost_atomI]: "PrePost (if c then P (Value ()) else P (Ex (Failure m))) (assert_expS c m) P" unfolding PrePost_def assert_expS_def by (auto simp: returnS_def failS_def) -lemma PrePost_chooseS[intro, PrePost_intro]: "PrePost (\<lambda>s. \<forall>x \<in> xs. Q (Value x) s) (chooseS xs) Q" +lemma PrePost_chooseS[intro, PrePost_atomI]: "PrePost (\<lambda>s. \<forall>x \<in> xs. Q (Value x) s) (chooseS xs) Q" by (auto simp: PrePost_def chooseS_def) -lemma PrePost_failS[intro, PrePost_intro]: "PrePost (Q (Ex (Failure msg))) (failS msg) Q" +lemma PrePost_failS[intro, PrePost_atomI]: "PrePost (Q (Ex (Failure msg))) (failS msg) Q" by (auto simp: PrePost_def failS_def) lemma case_result_combine[simp]: "(case r of Value a \<Rightarrow> Q (Value a) | Ex e \<Rightarrow> Q (Ex e)) = Q r" by (auto split: result.splits) -lemma PrePost_foreachS_Nil[intro, simp, PrePost_intro]: +lemma PrePost_foreachS_Nil[intro, simp, PrePost_atomI]: "PrePost (Q (Value vars)) (foreachS [] vars body) Q" by auto @@ -219,20 +250,21 @@ lemma PrePostE_weaken_post: shows "PrePostE A f C E" using assms by (blast intro: PrePostE_consequence) -named_theorems PrePostE_intro +named_theorems PrePostE_compositeI +named_theorems PrePostE_atomI -lemma PrePostE_True_post[PrePost_intro, intro, simp]: +lemma PrePostE_True_post[PrePostE_atomI, intro, simp]: "PrePostE P m (\<lambda>_ _. True) (\<lambda>_ _. True)" unfolding PrePost_defs by (auto split: result.splits) lemma PrePostE_any: "PrePostE (\<lambda>s. \<forall>(r, s') \<in> m s. case r of Value a \<Rightarrow> Q a s' | Ex e \<Rightarrow> E e s') m Q E" by (intro PrePostE_I) auto -lemma PrePostE_returnS[PrePostE_intro, intro, simp]: +lemma PrePostE_returnS[PrePostE_atomI, intro, simp]: "PrePostE (P x) (returnS x) P Q" unfolding PrePostE_def by (auto intro: PrePost_strengthen_pre) -lemma PrePostE_bindS[intro, PrePostE_intro]: +lemma PrePostE_bindS[intro, PrePostE_compositeI]: assumes f: "\<And>s a s'. (Value a, s') \<in> m s \<Longrightarrow> PrePostE (R a) (f a) Q E" and m: "PrePostE P m R E" shows "PrePostE P (bindS m f) Q E" @@ -252,13 +284,13 @@ lemma PrePostE_bindS_unit: shows "PrePostE P (bindS m f) Q E" using assms by auto -lemma PrePostE_readS[PrePostE_intro, intro]: "PrePostE (\<lambda>s. Q (f s) s) (readS f) Q E" +lemma PrePostE_readS[PrePostE_atomI, intro]: "PrePostE (\<lambda>s. Q (f s) s) (readS f) Q E" unfolding PrePostE_def by (auto intro: PrePost_strengthen_pre) -lemma PrePostE_updateS[PrePostE_intro, intro]: "PrePostE (\<lambda>s. Q () (f s)) (updateS f) Q E" +lemma PrePostE_updateS[PrePostE_atomI, intro]: "PrePostE (\<lambda>s. Q () (f s)) (updateS f) Q E" unfolding PrePostE_def by (auto intro: PrePost_strengthen_pre) -lemma PrePostE_if_branch[PrePostE_intro]: +lemma PrePostE_if_branch[PrePostE_compositeI]: assumes "b \<Longrightarrow> PrePostE Pf f Q E" and "\<not>b \<Longrightarrow> PrePostE Pg g Q E" shows "PrePostE (if b then Pf else Pg) (if b then f else g) Q E" using assms by (auto) @@ -278,30 +310,44 @@ lemma PrePostE_if_else: shows "PrePostE P (if b then f else g) Q E" using assms by auto -lemma PrePostE_prod_cases[PrePostE_intro]: +lemma PrePostE_prod_cases[PrePostE_compositeI]: assumes "PrePostE P (f (fst x) (snd x)) Q E" shows "PrePostE P (case x of (a, b) \<Rightarrow> f a b) Q E" using assms by (auto split: prod.splits) -lemma PrePostE_option_cases[PrePostE_intro]: +lemma PrePostE_option_cases[PrePostE_compositeI]: assumes "\<And>a. PrePostE (PS a) (s a) Q E" and "PrePostE PN n Q E" 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_let[PrePostE_intro]: +lemma PrePostE_let[PrePostE_compositeI]: assumes "PrePostE P (m y) Q E" shows "PrePostE P (let x = y in m x) Q E" using assms by auto -lemma PrePostE_assert_expS[PrePostE_intro, intro]: +lemma PrePostE_and_boolS[PrePostE_compositeI]: + assumes r: "PrePostE R r Q E" + and l: "PrePostE P l (\<lambda>r. if r then R else Q False) E" + shows "PrePostE P (and_boolS l r) Q E" + using assms unfolding PrePostE_def + by (intro PrePost_and_boolS) (auto elim: PrePost_weaken_post split: if_splits result.splits) + +lemma PrePostE_or_boolS[PrePostE_compositeI]: + assumes r: "PrePostE R r Q E" + and l: "PrePostE P l (\<lambda>r. if r then Q True else R) E" + shows "PrePostE P (or_boolS l r) Q E" + using assms unfolding PrePostE_def + by (intro PrePost_or_boolS) (auto elim: PrePost_weaken_post split: if_splits result.splits) + +lemma PrePostE_assert_expS[PrePostE_atomI, intro]: "PrePostE (if c then P () else Q (Failure m)) (assert_expS c m) P Q" unfolding PrePostE_def by (auto intro: PrePost_strengthen_pre) -lemma PrePostE_failS[PrePost_intro, intro]: +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_chooseS[intro, PrePostE_intro]: +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) diff --git a/lib/isabelle/Makefile b/lib/isabelle/Makefile index f8786321..b10dde78 100644 --- a/lib/isabelle/Makefile +++ b/lib/isabelle/Makefile @@ -1,6 +1,6 @@ THYS = Sail_instr_kinds.thy Sail_values.thy Sail_operators.thy \ Sail_operators_mwords.thy Sail_operators_bitlists.thy \ - State_monad.thy State.thy Prompt_monad.thy Prompt.thy + State_monad.thy State.thy State_lifting.thy Prompt_monad.thy Prompt.thy EXTRA_THYS = State_monad_lemmas.thy State_lemmas.thy Prompt_monad_lemmas.thy \ Sail_operators_mwords_lemmas.thy Hoare.thy @@ -51,5 +51,8 @@ State_monad.thy: ../../src/gen_lib/state_monad.lem Sail_values.thy State.thy: ../../src/gen_lib/state.lem Prompt.thy State_monad.thy State_monad_lemmas.thy lem -isa -outdir . -auxiliary_level none -lib ../../src/lem_interp -lib ../../src/gen_lib $< +State_lifting.thy: ../../src/gen_lib/state_lifting.lem Prompt.thy State.thy + lem -isa -outdir . -auxiliary_level none -lib ../../src/lem_interp -lib ../../src/gen_lib $< + clean: -rm $(THYS) diff --git a/lib/isabelle/Prompt_monad_lemmas.thy b/lib/isabelle/Prompt_monad_lemmas.thy index e883c2a0..7a3a108d 100644 --- a/lib/isabelle/Prompt_monad_lemmas.thy +++ b/lib/isabelle/Prompt_monad_lemmas.thy @@ -17,6 +17,7 @@ lemmas bind_induct[case_names Done Read_mem Write_memv Read_reg Excl_res Write_e lemma bind_return[simp]: "bind (return a) f = f a" by (auto simp: return_def) +lemma bind_return_right[simp]: "bind x return = x" by (induction x) (auto simp: return_def) lemma bind_assoc[simp]: "bind (bind m f) g = bind m (\<lambda>x. bind (f x) g)" by (induction m f arbitrary: g rule: bind.induct) auto diff --git a/lib/isabelle/State_lemmas.thy b/lib/isabelle/State_lemmas.thy index 84b08e6c..cf5e4dbf 100644 --- a/lib/isabelle/State_lemmas.thy +++ b/lib/isabelle/State_lemmas.thy @@ -1,16 +1,18 @@ theory State_lemmas - imports State + imports State State_lifting begin lemma All_liftState_dom: "liftState_dom (r, m)" by (induction m) (auto intro: liftState.domintros) termination liftState using All_liftState_dom by auto -lemma liftState_bind[simp]: +named_theorems liftState_simp + +lemma liftState_bind[liftState_simp]: "liftState r (bind m f) = bindS (liftState r m) (liftState r \<circ> f)" by (induction m f rule: bind.induct) auto -lemma liftState_return[simp]: "liftState r (return a) = returnS a" by (auto simp: return_def) +lemma liftState_return[liftState_simp]: "liftState r (return a) = returnS a" by (auto simp: return_def) lemma Value_liftState_Run: assumes "(Value a, s') \<in> liftState r m s" @@ -19,45 +21,58 @@ lemma Value_liftState_Run: auto simp add: failS_def throwS_def returnS_def simp del: read_regvalS.simps; blast elim: Value_bindS_elim) -lemmas liftState_if_distrib[simp] = if_distrib[where f = "liftState ra" for ra] - -lemma liftState_throw[simp]: "liftState r (throw e) = throwS e" by (auto simp: throw_def) -lemma liftState_assert[simp]: "liftState r (assert_exp c msg) = assert_expS c msg" by (auto simp: assert_exp_def assert_expS_def) -lemma liftState_exit[simp]: "liftState r (exit0 ()) = exitS ()" by (auto simp: exit0_def exitS_def) -lemma liftState_exclResult[simp]: "liftState r (excl_result ()) = excl_resultS ()" by (auto simp: excl_result_def) -lemma liftState_barrier[simp]: "liftState r (barrier bk) = returnS ()" by (auto simp: barrier_def) -lemma liftState_footprint[simp]: "liftState r (footprint ()) = returnS ()" by (auto simp: footprint_def) -lemma liftState_undefined[simp]: "liftState r (undefined_bool ()) = undefined_boolS ()" by (auto simp: undefined_bool_def) -lemma liftState_maybe_fail[simp]: "liftState r (maybe_fail msg x) = maybe_failS msg x" - by (auto simp: maybe_fail_def maybe_failS_def split: option.splits) - -lemma liftState_try_catch[simp]: +lemmas liftState_if_distrib[liftState_simp] = if_distrib[where f = "liftState ra" for ra] + +lemma liftState_throw[liftState_simp]: "liftState r (throw e) = throwS e" + by (auto simp: throw_def) +lemma liftState_assert[liftState_simp]: "liftState r (assert_exp c msg) = assert_expS c msg" + by (auto simp: assert_exp_def assert_expS_def) +lemma liftState_exit[liftState_simp]: "liftState r (exit0 ()) = exitS ()" + by (auto simp: exit0_def exitS_def) +lemma liftState_exclResult[liftState_simp]: "liftState r (excl_result ()) = excl_resultS ()" + by (auto simp: excl_result_def liftState_simp) +lemma liftState_barrier[liftState_simp]: "liftState r (barrier bk) = returnS ()" + by (auto simp: barrier_def) +lemma liftState_footprint[liftState_simp]: "liftState r (footprint ()) = returnS ()" + by (auto simp: footprint_def) +lemma liftState_undefined[liftState_simp]: "liftState r (undefined_bool ()) = undefined_boolS ()" + by (auto simp: undefined_bool_def liftState_simp) +lemma liftState_maybe_fail[liftState_simp]: "liftState r (maybe_fail msg x) = maybe_failS msg x" + by (auto simp: maybe_fail_def maybe_failS_def liftState_simp split: option.splits) +lemma liftState_and_boolM[liftState_simp]: + "liftState r (and_boolM x y) = and_boolS (liftState r x) (liftState r y)" + by (auto simp: and_boolM_def and_boolS_def liftState_simp cong: bindS_cong if_cong) +lemma liftState_or_boolM[liftState_simp]: + "liftState r (or_boolM x y) = or_boolS (liftState r x) (liftState r y)" + by (auto simp: or_boolM_def or_boolS_def liftState_simp cong: bindS_cong if_cong) + +lemma liftState_try_catch[liftState_simp]: "liftState r (try_catch m h) = try_catchS (liftState r m) (liftState r \<circ> h)" by (induction m h rule: try_catch_induct) (auto simp: try_catchS_bindS_no_throw) -lemma liftState_early_return[simp]: +lemma liftState_early_return[liftState_simp]: "liftState r (early_return r) = early_returnS r" - by (auto simp: early_return_def early_returnS_def) + by (auto simp: early_return_def early_returnS_def liftState_simp) -lemma liftState_catch_early_return[simp]: +lemma liftState_catch_early_return[liftState_simp]: "liftState r (catch_early_return m) = catch_early_returnS (liftState r m)" - by (auto simp: catch_early_return_def catch_early_returnS_def sum.case_distrib cong: sum.case_cong) + by (auto simp: catch_early_return_def catch_early_returnS_def sum.case_distrib liftState_simp cong: sum.case_cong) -lemma liftState_liftR[simp]: - "liftState r (liftR m) = liftSR (liftState r m)" - by (auto simp: liftR_def liftSR_def) +lemma liftState_liftR[liftState_simp]: + "liftState r (liftR m) = liftRS (liftState r m)" + by (auto simp: liftR_def liftRS_def liftState_simp) -lemma liftState_try_catchR[simp]: - "liftState r (try_catchR m h) = try_catchSR (liftState r m) (liftState r \<circ> h)" - by (auto simp: try_catchR_def try_catchSR_def sum.case_distrib cong: sum.case_cong) +lemma liftState_try_catchR[liftState_simp]: + "liftState r (try_catchR m h) = try_catchRS (liftState r m) (liftState r \<circ> h)" + by (auto simp: try_catchR_def try_catchRS_def sum.case_distrib liftState_simp cong: sum.case_cong) lemma liftState_read_mem_BC: assumes "unsigned_method BC_bitU_list (bits_of_method BCa a) = unsigned_method BCa a" shows "liftState r (read_mem BCa BCb rk a sz) = read_memS BCa BCb rk a sz" using assms - by (auto simp: read_mem_def read_mem_bytes_def read_memS_def read_mem_bytesS_def maybe_failS_def split: option.splits) + by (auto simp: read_mem_def read_mem_bytes_def read_memS_def read_mem_bytesS_def maybe_failS_def liftState_simp split: option.splits) -lemma liftState_read_mem[simp]: +lemma liftState_read_mem[liftState_simp]: "\<And>a. liftState r (read_mem BC_mword BC_mword rk a sz) = read_memS BC_mword BC_mword rk a sz" "\<And>a. liftState r (read_mem BC_bitU_list BC_bitU_list rk a sz) = read_memS BC_bitU_list BC_bitU_list rk a sz" by (auto simp: liftState_read_mem_BC) @@ -67,14 +82,14 @@ lemma liftState_write_mem_ea_BC: shows "liftState r (write_mem_ea BCa rk a sz) = write_mem_eaS BCa rk a (nat sz)" using assms by (auto simp: write_mem_ea_def write_mem_eaS_def) -lemma liftState_write_mem_ea[simp]: +lemma liftState_write_mem_ea[liftState_simp]: "\<And>a. liftState r (write_mem_ea BC_mword rk a sz) = write_mem_eaS BC_mword rk a (nat sz)" "\<And>a. liftState r (write_mem_ea BC_bitU_list rk a sz) = write_mem_eaS BC_bitU_list rk a (nat sz)" by (auto simp: liftState_write_mem_ea_BC) lemma liftState_write_mem_val: "liftState r (write_mem_val BC v) = write_mem_valS BC v" - by (auto simp: write_mem_val_def write_mem_valS_def split: option.splits) + by (auto simp: write_mem_val_def write_mem_valS_def liftState_simp split: option.splits) lemma liftState_read_reg_readS: assumes "\<And>s. Option.bind (get_regval' (name reg) s) (of_regval reg) = Some (read_from reg s)" @@ -93,22 +108,23 @@ lemma liftState_write_reg_updateS: shows "liftState (get_regval', set_regval') (write_reg reg v) = updateS (regstate_update (write_to reg v))" using assms by (auto simp: write_reg_def updateS_def returnS_def bindS_readS) -lemma liftState_iter_aux[simp]: +lemma liftState_iter_aux[liftState_simp]: shows "liftState r (iter_aux i f xs) = iterS_aux i (\<lambda>i x. liftState r (f i x)) xs" - by (induction i "\<lambda>i x. liftState r (f i x)" xs rule: iterS_aux.induct) (auto cong: bindS_cong) + by (induction i "\<lambda>i x. liftState r (f i x)" xs rule: iterS_aux.induct) + (auto simp: liftState_simp cong: bindS_cong) -lemma liftState_iteri[simp]: +lemma liftState_iteri[liftState_simp]: "liftState r (iteri f xs) = iteriS (\<lambda>i x. liftState r (f i x)) xs" - by (auto simp: iteri_def iteriS_def) + by (auto simp: iteri_def iteriS_def liftState_simp) -lemma liftState_iter[simp]: +lemma liftState_iter[liftState_simp]: "liftState r (iter f xs) = iterS (liftState r \<circ> f) xs" - by (auto simp: iter_def iterS_def) + by (auto simp: iter_def iterS_def liftState_simp) -lemma liftState_foreachM[simp]: +lemma liftState_foreachM[liftState_simp]: "liftState r (foreachM xs vars body) = foreachS xs vars (\<lambda>x vars. liftState r (body x vars))" by (induction xs vars "\<lambda>x vars. liftState r (body x vars)" rule: foreachS.induct) - (auto cong: bindS_cong) + (auto simp: liftState_simp cong: bindS_cong) lemma whileS_dom_step: assumes "whileS_dom (vars, cond, body, s)" @@ -156,7 +172,7 @@ proof (use assms in \<open>induction vars "liftState r \<circ> cond" "liftState qed then show ?case using while while' that IH by auto qed auto - then show ?case by auto + then show ?case by (auto simp: liftState_simp) qed auto qed @@ -194,9 +210,51 @@ proof (use assms in \<open>induction vars "liftState r \<circ> cond" "liftState show "\<exists>t. Run (body vars) t vars'" using k by (auto elim: Value_liftState_Run) show "\<exists>t'. Run (cond vars') t' False" using until that by (auto elim: Value_liftState_Run) qed - then show ?case using k until IH by (auto simp: comp_def) + then show ?case using k until IH by (auto simp: comp_def liftState_simp) qed auto qed auto qed +(* Simplification rules for monadic Boolean connectives *) + +lemma if_return_return[simp]: "(if a then return True else return False) = return a" by auto + +lemma and_boolM_simps[simp]: + "and_boolM (return b) y = (if b then y else return False)" + "and_boolM x (return True) = x" + "and_boolM x (return False) = x \<bind> (\<lambda>_. return False)" + "\<And>x y z. and_boolM (x \<bind> y) z = (x \<bind> (\<lambda>r. and_boolM (y r) z))" + by (auto simp: and_boolM_def) + +lemmas and_boolM_if_distrib[simp] = if_distrib[where f = "\<lambda>x. and_boolM x y" for y] + +lemma or_boolM_simps[simp]: + "or_boolM (return b) y = (if b then return True else y)" + "or_boolM x (return True) = x \<bind> (\<lambda>_. return True)" + "or_boolM x (return False) = x" + "\<And>x y z. or_boolM (x \<bind> y) z = (x \<bind> (\<lambda>r. or_boolM (y r) z))" + by (auto simp: or_boolM_def) + +lemmas or_boolM_if_distrib[simp] = if_distrib[where f = "\<lambda>x. or_boolM x y" for y] + +lemma if_returnS_returnS[simp]: "(if a then returnS True else returnS False) = returnS a" by auto + +lemma and_boolS_simps[simp]: + "and_boolS (returnS b) y = (if b then y else returnS False)" + "and_boolS x (returnS True) = x" + "and_boolS x (returnS False) = bindS x (\<lambda>_. returnS False)" + "\<And>x y z. and_boolS (bindS x y) z = (bindS x (\<lambda>r. and_boolS (y r) z))" + by (auto simp: and_boolS_def) + +lemmas and_boolS_if_distrib[simp] = if_distrib[where f = "\<lambda>x. and_boolS x y" for y] + +lemma or_boolS_simps[simp]: + "or_boolS (returnS b) y = (if b then returnS True else y)" + "or_boolS x (returnS True) = bindS x (\<lambda>_. returnS True)" + "or_boolS x (returnS False) = x" + "\<And>x y z. or_boolS (bindS x y) z = (bindS x (\<lambda>r. or_boolS (y r) z))" + by (auto simp: or_boolS_def) + +lemmas or_boolS_if_distrib[simp] = if_distrib[where f = "\<lambda>x. or_boolS x y" for y] + end diff --git a/lib/isabelle/manual/Manual.thy b/lib/isabelle/manual/Manual.thy index 6cdfbfa1..0c83ebea 100644 --- a/lib/isabelle/manual/Manual.thy +++ b/lib/isabelle/manual/Manual.thy @@ -288,7 +288,7 @@ exception handler as arguments. The exception mechanism is also used to implement early returns by throwing and catching return values: A function body with one or more early returns of type @{typ 'a} (and exception type @{typ 'e}) is lifted to a monadic expression with exception type @{typ "('a + 'e)"} using -@{term liftSR}, such that an early return of the value @{term a} throws @{term "Inl a"}, and a +@{term liftRS}, such that an early return of the value @{term a} throws @{term "Inl a"}, and a regular exception @{term e} is thrown as @{term "Inr e"}. The function body is then wrapped in @{term catch_early_returnS} to lower it back to the default monad and exception type. These liftings and lowerings are automatically inserted by Sail for functions with early returns.\<^footnote>\<open>To be @@ -412,7 +412,9 @@ case, defined as @{thm [display, names_short] PrePostE_def} The theory includes standard proof rules for both of these variants, in particular rules giving weakest preconditions of the predefined primitives of the monad, collected under the names -@{attribute PrePost_intro} and @{attribute PrePostE_intro}, respectively. +@{attribute PrePost_atomI} for atoms such as @{term return} and @{attribute PrePost_compositeI} +for composites such as @{term bind} (or @{attribute PrePostE_atomI} and +@{attribute PrePostE_compositeI}, respectively, for the quadruple variant). The instruction we are considering is defined as @{thm [display] execute_ITYPE.simps[of _ rs for rs]} @@ -448,16 +450,17 @@ lemma shows "PrePostE pre (liftS instr) post (\<lambda>_ _. False)" unfolding pre_def instr_def post_def - by (simp add: rX_def wX_def cong: bindS_cong if_cong split del: if_split) - (rule PrePostE_strengthen_pre, (rule PrePostE_intro)+, auto simp: uint_0_iff) + by (simp add: rX_def wX_def liftState_simp cong: bindS_cong if_cong split del: if_split) + (rule PrePostE_strengthen_pre, (rule PrePostE_atomI PrePostE_compositeI)+, auto simp: uint_0_iff) text \<open>The proof begins with a simplification step, which not only unfolds the definitions of the auxiliary functions @{term rX} and @{term wX}, but also performs the lifting from the free monad to the state monad. We apply the rule @{thm [source] PrePostE_strengthen_pre} (in a -backward manner) to allow a weaker precondition, then use the rules in @{attribute PrePostE_intro} -to derive a weakest precondition, and then use @{method auto} to show that it is implied by -the given precondition. For more serious proofs, one will want to set up specialised proof -tactics. This example uses only basic proof methods, to make the reasoning steps more explicit.\<close> +backward manner) to allow a weaker precondition, then use the rules in +@{attribute PrePostE_compositeI} and @{attribute PrePostE_atomI} to derive a weakest precondition, +and then use @{method auto} to show that it is implied by the given precondition. For more serious +proofs, one will want to set up specialised proof tactics. This example uses only basic proof +methods, to make the reasoning steps more explicit.\<close> (*<*) end |
