(* * Copyright 2014, NICTA * * This software may be distributed and modified according to the terms of * the BSD 2-Clause license. Note that NO WARRANTY is provided. * See "LICENSE_BSD2.txt" for details. * * @TAG(NICTA_BSD) *) theory L2Defs imports CorresXF L1Defs L1Peephole MonadMono begin type_synonym ('s, 'a, 'e) L2_monad = "('s, 'e + 'a) nondet_monad" definition "L2_unknown (name :: string list) \ liftE (select UNIV) :: ('s, 'a, 'e) L2_monad" definition "L2_seq (A :: ('s, 'a, 'e) L2_monad) (B :: 'a \ ('s, 'b, 'e) L2_monad) \ (A >>=E B) :: ('s, 'b, 'e) L2_monad" definition "L2_modify m \ liftE (modify m) :: ('s, unit, 'e) L2_monad" definition "L2_gets f (names :: string list) \ liftE (gets f) :: ('s, 'a, 'e) L2_monad" definition "L2_condition c (A :: ('s, 'a, 'e) L2_monad) (B :: ('s, 'a, 'e) L2_monad) \ condition c A B" definition "L2_catch (A :: ('s, 'a, 'e) L2_monad) (B :: 'e \ ('s, 'a, 'ee) L2_monad) \ (A B)" definition "L2_while c (A :: 'a \ ('s, 'a, 'e) L2_monad) i (name :: string list) \ whileLoopE c A i :: ('s, 'a, 'e) L2_monad" definition "L2_throw x (name :: string list) \ throwError x :: ('s, 'a, 'e) L2_monad" definition "L2_spec r \ liftE (spec r >>= (\_. select UNIV)) :: ('s, 'a, 'e) L2_monad" definition "L2_guard c \ (liftE (guard c)) :: ('s, unit, 'e) L2_monad" definition "L2_fail \ fail :: ('s, 'a, 'e) L2_monad" definition "L2_call x \ x (\_. fail) :: ('s, 'a, 'e) L2_monad" definition "L2_recguard n b \ (condition (\s. (n :: nat) = 0) fail b) :: ('s, 'a, 'e) L2_monad" abbreviation "L2_skip \ L2_gets (\_. ()) []" (* * Temporary constructions, used internally but not emitted. * * "L2_folded_gets" is like "L2_gets", but the peephole optimiser will * try to eliminate the call to where it is used, eliminating it where * possible. It is used for automatically generated "L2_gets" calls * which the user really doesn't need to know about. * * The various "call" defintions are to help generate proofs for the * different ways of making function calls, which are hard to unify. *) definition "L2_folded_gets f names \ L2_gets f names :: ('s, 'a, 'e) L2_monad" definition "L2_voidcall x \ L2_seq (L2_call x) (\ret. L2_skip) :: ('s, unit, 'e) L2_monad" definition "L2_modifycall x m \ L2_seq (L2_call x) (\ret. L2_modify (m ret)) :: ('s, unit, 'e) L2_monad" definition "L2_returncall x f \ L2_seq (L2_call x) (\ret. L2_folded_gets (f ret) [''retval'']) :: ('s, 'a, 'e) L2_monad" lemma L2_folded_gets_bind: "L2_seq (L2_folded_gets (\_. x) name) f = f x" apply (rule ext) apply (monad_eq simp: L2_folded_gets_def L2_seq_def L2_gets_def) done (* FIXME: we can merge these *) lemmas L2_remove_scaffolding_1 = L2_folded_gets_bind [THEN eq_reflection] L2_returncall_def L2_modifycall_def L2_voidcall_def lemmas L2_remove_scaffolding_2 = L2_remove_scaffolding_1 L2_folded_gets_def abbreviation (input) "L2_guarded_while G C B i n \ L2_seq (L2_guard (G i)) (\_. L2_while C (\i. L2_seq (B i) (\r. L2_seq (L2_guard (G r)) (\_. L2_gets (\_. r) n))) i n)" lemmas L2_defs = L2_unknown_def L2_seq_def L2_modify_def L2_gets_def L2_condition_def L2_catch_def L2_while_def L2_throw_def L2_spec_def L2_guard_def L2_fail_def L2_folded_gets_def L2_voidcall_def L2_modifycall_def L2_returncall_def L2_recguard_def (* Alternate definitions. *) lemma L2_defs': "L2_unknown n \ unknownE" "L2_seq A' B' \ A' >>=E B'" "L2_modify m \ modifyE m" "L2_gets f n \ getsE f" "L2_condition c L R \ condition c L R" "L2_catch A B \ (A B)" "L2_while c' B'' i n \ whileLoopE c' B'' i" "L2_throw x n \ throwError x" "L2_spec r \ (specE r >>=E (\_. selectE UNIV))" "L2_guard c \ guardE c" "L2_fail \ fail" by (auto simp: monad_defs L2_defs bind_liftE_distrib) definition L2corres :: "('s \ 't) \ ('s \ 'r) \ ('s \ 'e) \ ('s \ bool) \ ('t, 'e + 'r) nondet_monad \ ('s, unit + unit) nondet_monad \ bool" where "L2corres st ret_xf ex_xf P A C \ corresXF st (\_. ret_xf) (\_. ex_xf) P A C" (* Wrapper for calling un-translated functions. *) definition "L2_call_L1 arg_xf gs ret_xf l1body = do cur_gs \ get; s \ select {s. gs s = cur_gs \ arg_xf s}; (rv, s') \ select_f (l1body s); put (gs s'); case rv of Inl _ \ fail | Inr _ \ return (Inr (ret_xf s') :: (unit + _)) od" lemma L2corres_L2_call_L1: "L2corres gs ret_xf ex_xf arg_xf (L2_call_L1 arg_xf gs ret_xf f) f" apply (clarsimp simp: L2corres_def corresXF_def L2_call_L1_def split: sum.split) apply (clarsimp simp: snd_bind in_monad exec_get select_def) apply (clarsimp simp: select_f_def snd_bind put_def split: sum.split_asm) apply (fastforce simp: return_def) done lemma L2corres_L2_call_simpl: "l1_f \ simpl_f \ L2corres gs ret_xf ex_xf arg_xf (L2_call_L1 arg_xf gs ret_xf simpl_f) l1_f" by (simp add: L2corres_L2_call_L1) (* shouldn't be needed lemma empty_set_exists: "(\a. a \ {}) = False" apply blast done *) lemma L2corres_modify_global: "\ \s. P s \ M (st s) = st (M' s) \ \ L2corres st ret ex P (L2_modify M) (L1_modify M')" apply (clarsimp simp: L2corres_def L2_defs L1_defs) apply (fold modifyE_def) apply (auto intro: corresXF_modify_global) done lemma L2corres_modify_unknown: "\ \s. P s \ st s = st (M s) \ \ L2corres st ret ex P (L2_unknown name) (L1_modify M)" apply (clarsimp simp: L2corres_def L2_defs L1_defs) apply (fold selectE_def modifyE_def) apply (auto intro: corresXF_select_modify) done lemma L2corres_spec_unknown: "\ \s a. st s = st (M (a::('a \ ('a::{type}))) s) \ \ L2corres st ret ex P (L2_unknown name) (L1_init M)" apply (monad_eq simp: L2corres_def corresXF_def L1_defs L2_defs) done lemma L2corres_modify_gets: "\ \s. P s \ st s = st (M s); \s. P s \ ret (M s) = f (st s) \ \ L2corres st ret ex P (L2_gets (\s. f s) n) (L1_modify M)" apply (monad_eq simp: L2corres_def corresXF_def L1_defs L2_defs) done lemma L2corres_gets_skip: "L2corres st ret ex P L2_skip L1_skip" by (monad_eq simp: L2corres_def corresXF_def L1_defs L2_defs) lemma L2corres_guard: "\ \s. P s \ G' s = G (st s) \ \ L2corres st return_xf exception_xf P (L2_guard G) (L1_guard G')" apply (monad_eq simp: L2corres_def corresXF_def L1_defs L2_defs) done lemma L2corres_fail: "L2corres st return_xf exception_xf P L2_fail X" apply (monad_eq simp: L2corres_def corresXF_def L1_defs L2_defs) done lemma spec_alt_def: "spec r = (\s. (Pair () ` {s'. (s, s') \ r}, \ (\s'. (s, s') \ r)))" apply (clarsimp simp: spec_def) done lemma L2corres_spec: "\ \s s'. ((s, s') \ A') = ((st s, st s') \ A); surj st \ \ L2corres st return_xf exception_xf P (L2_spec A) (L1_spec A')" apply (clarsimp simp: L2corres_def L2_defs L1_spec_def corresXF_def liftE_def spec_alt_def return_def bind_def select_def) apply (clarsimp simp: image_def) apply (subst (asm) set_eq_UNIV) apply metis done lemma L2corres_seq: "\ L2corres st return_xf exception_xf P A A'; \x. L2corres st return_xf' exception_xf (P' x) (B x) B'; \R\ A' \\_ s. P' (return_xf s) s\, \\_. \\; \s. R s \ P s \ \ L2corres st return_xf' exception_xf R (L2_seq A B) (L1_seq A' B')" apply (unfold L2corres_def L2_seq_def L1_seq_def) apply (rule corresXF_guard_imp) apply (rule corresXF_join, assumption+) done lemma L2corres_catch: "\ L2corres st V E P L L'; \x. L2corres st V E' (P' x) (R x) R'; \Q\ L' \\_ _. True\, \\_ s. P' (E s) s\; \s. Q s \ P s \ \ L2corres st V E' Q (L2_catch L R) (L1_catch L' R')" apply (clarsimp simp: L2corres_def L2_catch_def L1_catch_def) apply (unfold handleE_def) apply (erule corresXF_except) apply assumption apply assumption apply simp done lemma L2corres_throw: "\ \s. P s \ E s = A \ \ L2corres st V E P (L2_throw A n) (L1_throw)" apply (clarsimp simp: L2corres_def L2_throw_def L1_throw_def) apply (clarsimp simp: throwError_def return_def) apply (clarsimp simp: corresXF_def) done lemma L2corres_cond: "\ L2corres st return_xf exception_xf P A A'; L2corres st return_xf exception_xf P' B B'; \s. R s \ P s; \s. R s \ P' s; \s. R s \ c' s = c (st s) \ \ L2corres st return_xf exception_xf R (L2_condition c A B) (L1_condition c' A' B')" apply (unfold L2corres_def L2_condition_def L1_condition_def) apply (rule corresXF_cond) apply (erule corresXF_guard_imp, fastforce) apply (erule corresXF_guard_imp, fastforce) apply (clarsimp) done lemma L2corres_inject_return: "\ L2corres st V E P L R; \P'\ R \\_ s. W (V s) = V' s\, \ \_. \ \; \s. P' s \ P s\ \ L2corres st V' E P' (L2_seq L (\x. L2_gets (\_. W x) n)) R" apply (clarsimp simp: L2corres_def) apply (drule corresXF_guard_imp [where P=P'], simp) apply (unfold L2_seq_def L2_gets_def) apply (fold getsE_def) apply (rule corresXF_guard_imp) apply (erule corresXF_append_gets_abs) apply (erule hoare_weaken_preE) apply simp apply simp done lemma L2corres_skip: "L2corres st return_xf exception_xf P L2_skip L1_skip" apply (monad_eq simp: L2corres_def corresXF_def L1_defs L2_defs) done lemma L2corres_while: assumes body_corres: "\x. L2corres st ret ex (P' x) (A x) B" and inv_holds: "\\s. P (ret s) s \ B \\_ s. P (ret s) s \, \\_ _. True\" and cond_match: "\s. P (ret s) s \ c' s = c (ret s) (st s)" and pred_imply: "\s x. P x s \ P' x s" and pred_extract: "\s. P x s \ ret s = x" and pred_imply2: "\s. Q x s \ P x s" shows "L2corres st ret ex (Q x) (L2_while c A x n) (L1_while c' B)" apply (clarsimp simp: L2corres_def L2_while_def L1_while_def) apply (rule corresXF_guard_imp) apply (rule corresXF_while [ where P="\r s. P (ret s) s" and C'=c and C="\_. c'" and A=A and B="\_. B" and ret="\r s. ret s" and ex="\r s. ex s" and st=st and y=x and x="()" and P'="\r s. Q x s"]) apply (rule corresXF_guard_imp) apply (rule body_corres [unfolded L2corres_def]) apply (clarsimp simp: pred_imply) apply (clarsimp simp: cond_match) apply (rule validE_weaken [OF inv_holds], (clarsimp simp: pred_imply2)+)[1] apply (metis pred_extract pred_imply2) apply (metis pred_extract pred_imply2) apply simp done lemma corresXF_E: fixes st :: "'state \ 'state2" shows "\ corresXF st ret_xf ex_xf P A C; P s; \ \ snd (A (st s)); \ snd (C s) \ \ (r, t) \ fst (C s); \ \ snd (A (st s)); \ snd (C s); \x. r = Inl x \ (Inl (ex_xf x t), st t) \ fst (A (st s)) \ \ R; \ \ snd (A (st s)); \ snd (C s); \x. r = Inr x \ (Inr (ret_xf x t), st t) \ fst (A (st s)) \ \ R; \ snd (A (st s)) \ \ R \ \ R" apply atomize_elim apply (unfold corresXF_def) apply clarsimp apply (erule allE, erule impE, fastforce) apply clarsimp apply (erule (1) my_BallE) apply (clarsimp split: sum.splits) done declare Ball_def [monad_eq] declare Bex_def [monad_eq] lemma corresXF_measure_call: "\ monad_mono C; \m. corresXF st rx ex P (A m) (C m) \ \ corresXF st rx ex P (measure_call A) (measure_call C)" apply (unfold measure_call_def corresXF_def) apply (clarsimp split: prod.splits sum.splits) apply (fastforce dest: monad_mono_incl) done lemma L2corres_returncall: "\ monad_mono dest_fn; \m. L2corres st ret' ex' P' (Z m) (dest_fn m); \s. P s \ P' (scope_setup s); \t s. st (return_xf t (scope_teardown s t)) = st t; \s. st (scope_setup s) = st s; \t s. P s \ ret (return_xf t (scope_teardown s t)) = F (ret' t) (st t) \ \ L2corres st ret ex P (L2_returncall (measure_call Z) F) (L1_call scope_setup (measure_call dest_fn) scope_teardown return_xf)" unfolding L1_call_def L2_returncall_def L2_call_def L2corres_def L2_defs apply (drule_tac A = Z and C = dest_fn in corresXF_measure_call, assumption) apply (rule corresXF_I) apply monad_eq apply (erule allE) apply (erule_tac s="scope_setup s'" in corresXF_E) apply simp apply blast apply clarsimp apply clarsimp apply blast apply clarsimp apply monad_eq apply monad_eq apply (rule conjI) apply (metis (lifting, mono_tags) corresXF_exec_fail) apply (metis (lifting, mono_tags) corresXF_exec_except sum.distinct(2)) done lemma L2corres_recursive_returncall: "\ L2corres st ret' ex' P' (Z m) (dest_fn m); \s. P s \ P' (scope_setup s); \t s. st (return_xf t (scope_teardown s t)) = st t; \s. st (scope_setup s) = st s; \t s. P s \ ret (return_xf t (scope_teardown s t)) = F (ret' t) (st t) \ \ L2corres st ret ex P (L2_returncall (Z m) F) (L1_call scope_setup (dest_fn m) scope_teardown return_xf)" apply atomize unfolding L1_call_def L2_returncall_def L2_call_def L2_defs L2corres_def apply (rule corresXF_I) apply monad_eq apply (erule_tac s="scope_setup s'" in corresXF_E) apply simp apply assumption apply simp apply monad_eq apply blast apply simp apply monad_eq apply monad_eq apply (rule conjI) apply (simp add: corresXF_def) apply clarsimp apply (drule (1) corresXF_exec_except) apply force apply clarsimp apply clarsimp apply force done lemma handleE_fail: "(A (\_. fail)) = (liftE (A (\_. fail)))" apply (monad_eq) apply force done lemma handleE'_fail: "(A (\_. fail)) = (liftE (A (\_. fail)))" apply (monad_eq) apply force done lemma L2corres_modifycall: "\ monad_mono dest_fn; \m. L2corres st ret' ex' P' (Z m) (dest_fn m); \s. P s \ P' (scope_setup s); \s r. P r \ F (ret' s) (st s) = st (return_xf s (scope_teardown r s)); \s. st (scope_setup s) = st s \ \ L2corres st ret ex P (L2_modifycall (measure_call Z) F) (L1_call scope_setup (measure_call dest_fn) scope_teardown return_xf)" apply (clarsimp simp: L1_call_def L2_call_def L2_defs L2corres_def) apply (clarsimp simp: liftE_bindE_handle liftE_bindE handleE'_fail handleE_fail) apply (drule_tac A = Z and C = dest_fn in corresXF_measure_call, assumption) apply (rule corresXF_I) apply monad_eq apply (erule allE) apply (drule (1) corresXF_exec_normal) apply clarsimp apply clarsimp apply clarsimp apply metis apply monad_eq apply monad_eq apply (rule conjI) apply (fastforce dest!: corresXF_exec_fail) apply (fastforce dest!: corresXF_exec_except) done lemma L2corres_recursive_modifycall: "\ L2corres st ret' ex' P' (Z m) (dest_fn (m :: nat)); \s. P s \ P' (scope_setup s); \s r. P r \ F (ret' s) (st s) = st (return_xf s (scope_teardown r s)); \s. st (scope_setup s) = st s \ \ L2corres st ret ex P (L2_modifycall (Z m) F) (L1_call scope_setup (dest_fn m) scope_teardown return_xf)" apply atomize apply (clarsimp simp: L1_call_def L2_call_def L2_defs L2corres_def) apply (clarsimp simp: liftE_bindE_handle liftE_bindE handleE'_fail handleE_fail) apply (rule corresXF_I) apply monad_eq apply (erule_tac s="scope_setup s'" in corresXF_E) apply simp apply assumption apply simp apply metis apply simp apply monad_eq apply monad_eq apply (rule conjI) apply (simp add: corresXF_def) apply (fastforce dest!: corresXF_exec_except) done lemma L2corres_voidcall: "\ monad_mono dest_fn; \m. L2corres st ret' ex' P' (Z m) (dest_fn m); \s. P s \ P' (scope_setup s); \s r. st (return_xf s (scope_teardown r s)) = st s; \s. st (scope_setup s) = st s \ \ L2corres st ret ex P (L2_voidcall (measure_call Z)) (L1_call scope_setup (measure_call dest_fn) scope_teardown return_xf)" apply (unfold L2_voidcall_def) apply (frule corresXF_measure_call) apply (subst (asm) L2corres_def, assumption) apply (rule_tac t = "L2_skip" and s = "L2_modify (\s. s)" in subst) apply (monad_eq simp: L2_defs) apply (fold L2_modifycall_def L2corres_def) apply (fastforce elim!: L2corres_modifycall) done lemma L2corres_recursive_voidcall: "\ L2corres st ret' ex' P' (Z m) (dest_fn m); \s. P s \ P' (scope_setup s); \s r. st (return_xf s (scope_teardown r s)) = st s; \s. st (scope_setup s) = st s \ \ L2corres st ret ex P (L2_voidcall (Z m)) (L1_call scope_setup (dest_fn m) scope_teardown return_xf)" apply (unfold L2_voidcall_def) apply (subgoal_tac "L2_skip = L2_modify (\s. s)") apply (erule ssubst) apply (fold L2_modifycall_def) apply (erule L2corres_recursive_modifycall, simp_all)[1] apply (monad_eq simp: L2_defs) done lemma L2corres_call: "\ monad_mono dest_fn; \m. L2corres st ret' ex' P' (Z m) (dest_fn m); \s. P s \ P' (scope_setup s); \s r. st (return_xf s (scope_teardown r s)) = st s; \s r. ret (return_xf s (scope_teardown r s)) = ret' s; \s. st (scope_setup s) = st s \ \ L2corres st ret ex P (L2_call (measure_call Z)) (L1_call scope_setup (measure_call dest_fn) scope_teardown return_xf)" apply (clarsimp simp: L2corres_def L2_call_def L1_call_def L2_defs) apply (drule corresXF_measure_call, assumption) apply (clarsimp simp: liftE_bindE_handle liftE_bindE handleE'_fail handleE_fail) apply (rule corresXF_I) apply monad_eq apply (fastforce dest!: corresXF_exec_normal) apply monad_eq apply monad_eq apply (rule conjI) apply (fastforce dest!: corresXF_exec_fail) apply (fastforce dest!: corresXF_exec_except) done lemma L2corres_recursive_call: "\ L2corres st ret' ex' P' (Z m) (dest_fn m); \s. P s \ P' (scope_setup s); \s r. st (return_xf s (scope_teardown r s)) = st s; \s r. ret (return_xf s (scope_teardown r s)) = ret' s; \s. st (scope_setup s) = st s \ \ L2corres st ret ex P (L2_call (Z m)) (L1_call scope_setup (dest_fn m) scope_teardown return_xf)" apply (clarsimp simp: L2corres_def L2_call_def L1_call_def L2_defs) apply (clarsimp simp: liftE_bindE_handle liftE_bindE handleE'_fail handleE_fail) apply (rule corresXF_I) apply monad_eq apply (fastforce dest!: corresXF_exec_normal) apply monad_eq apply monad_eq apply (rule conjI) apply (fastforce dest!: corresXF_exec_fail) apply (fastforce dest!: corresXF_exec_except) done lemma L2corres_recguard: "\ L2corres st ret ex P' B B'; \s. P s \ P' s \ \ L2corres st ret ex P (L2_recguard x B) (L1_recguard x B')" apply (clarsimp simp: L2_recguard_def L1_defs) apply (rule L2corres_cond [unfolded L2_condition_def L1_condition_def]) apply (rule L2corres_fail [unfolded L2_fail_def L1_fail_def]) apply assumption apply assumption apply simp apply simp done lemma L2_gets_bind: "\ \s s'. V s = V s' \ \ L2_seq (L2_gets V n) f = f (V undefined)" apply (rule ext) apply (clarsimp simp: L2_seq_def L2_gets_def gets_def get_def return_def bindE_def) apply (clarsimp simp: liftE_def2 bind_def lift_def) apply atomize apply (erule_tac x=x and y=undefined in allE2) apply simp done (* TODO: remove internal var if it is not user-visible *) lemma L2corres_folded_gets: "\ \a. L2corres st ret ex (P and (\s. a = c (st s))) (X a) Y \ \ L2corres st ret ex P (L2_seq (L2_folded_gets c name) X) Y" apply atomize apply (clarsimp simp: L2_seq_def L2_folded_gets_def L2_gets_def bindE_def bind_def gets_def liftE_def return_def) apply (clarsimp simp: split_def image_def lift_def get_def pred_conj_def) apply (clarsimp simp: L2corres_def corresXF_def) done lemma L2corres_guard_imp: "\ L2corres st ret_state ex_state Q M M'; \s. P s \ Q s \ \ L2corres st ret_state ex_state P M M'" apply (monad_eq simp: L2corres_def corresXF_def L1_defs L2_defs) done lemma L2_recguard_cong [fundef_cong, cong]: "\ n = n'; n \ 0 \ b = b' \ \ L2_recguard n b = L2_recguard n' b'" apply (clarsimp simp: L2_recguard_def) done lemma L2_call_cong [fundef_cong, cong]: "f = f' \ L2_call f = L2_call f'" by simp lemma L2corres_recguard_0: "L2corres sr ret ex P (L2_recguard 0 X) Y" apply (clarsimp simp: L2_recguard_def) apply (rule L2corres_fail [unfolded L2_fail_def]) done lemma L2_call_liftE [simp]: "L2_call (liftE x) \ liftE x" by (monad_eq simp: L2_defs L2_call_def liftE_left liftE_liftE) lemma L2_recguard_0 [simp]: "L2_recguard 0 x = fail" apply (clarsimp simp: L2_recguard_def) done lemma L2_call_fail [simp]: "L2_call fail = fail" apply (monad_eq simp: L2_call_def) done lemma L2_call_L2_gets [simp]: "L2_call (L2_gets x n) = L2_gets x n" apply (monad_eq simp: L2_call_def L2_gets_def) done (* * Rules for adjusting case_prod statements after transformations. * * c.f. fix_L2_while_loop_splits_conv *) lemma L2_split_fixup_1: "(L2_seq A (\x. case y of (a, b) \ B a b x)) = (case y of (a, b) \ L2_seq A (\x. B a b x))" by (auto simp: split_def) lemma L2_split_fixup_2: "(L2_seq (case y of (a, b) \ B a b) A) = (case y of (a, b) \ L2_seq (B a b) A)" by (auto simp: split_def) lemma L2_split_fixup_3: "(case (x, y) of (a, b) \ P a b) = P x y" by (auto simp: split_def) lemma L2_split_fixup_4: "case_prod (\a (b :: 'a \ 'b). P a ) = case_prod (\a. case_prod (\(x :: 'a) (y :: 'b). P a ))" by (auto simp: split_def) lemma L2_split_fixup_f: "(f (case y of (a, b) \ G a b) = (case y of (a, b) \ f (G a b)))" by (auto simp: split_def) lemma L2_split_fixup_g: "case_prod (\a (b :: 'a \ 'b). P a b) = case_prod (\a. case_prod (\(x :: 'a) (y :: 'b). P a (x, y)))" by (auto simp: split_def) lemmas L2_split_fixups = L2_split_fixup_1 L2_split_fixup_2 L2_split_fixup_3 L2_split_fixup_4 L2_split_fixup_f [where f=L2_guard] L2_split_fixup_f [where f=L2_gets] L2_split_fixup_f [where f=L2_modify] L2_split_fixup_g [where P="\a b. L2_gets (P a b) n" for P n] L2_split_fixup_g [where P="\a b. L2_guard (P a b)" for P] L2_split_fixup_g [where P="\a b. L2_modify (P a b)" for P] L2_split_fixup_g [where P="\a b. L2_spec (P a b)" for P] L2_split_fixup_g [where P="\a b. L2_throw (P a b) n" for P n] L2_split_fixup_g [where P="\a b. L2_seq (L a b) (R a b)" for L R] L2_split_fixup_g [where P="\a b. L2_while (C a b) (B a b) (I a b) n" for C B I n] L2_split_fixup_g [where P="\a b. L2_unknown n" for n] L2_split_fixup_g [where P="\a b. L2_catch (L a b) (R a b)" for L R] L2_split_fixup_g [where P="\a b. L2_condition (C a b) (L a b) (R a b)" for C L R] L2_split_fixup_g [where P="\a b. L2_call (M a b)" for M] lemmas L2_split_fixups_congs = prod.case_cong (* Peephole simplification rules for L2 programs (including HeapLift and WordAbstract). *) named_theorems L2opt (* L2 monad_mono rules *) lemma L2_seq_monad_mono_step: "\ monad_mono_step f m; \x. monad_mono_step (\m. g m x) m \ \ monad_mono_step (\m. L2_seq (f m) (g m)) m" by (simp add: L2_seq_def monad_mono_step_bindE) lemma L2_condition_monad_mono_step: "\ monad_mono_step f m; monad_mono_step g m \ \ monad_mono_step (\m. L2_condition C (f m) (g m)) m" by (simp add: L2_condition_def monad_mono_step_condition) lemma L2_catch_monad_mono_step: "\ monad_mono_step f m; \x. monad_mono_step (\m. g m x) m \ \ monad_mono_step (\m. L2_catch (f m) (g m)) m" by (simp add: L2_catch_def monad_mono_step_handleE') lemma L2_while_monad_mono_step: "(\x. monad_mono_step (\m. B m x) m) \ monad_mono_step (\m. L2_while C (B m) i n) m" by (simp add: L2_while_def monad_mono_step_whileLoopE) lemma L2_recguard_monad_mono_step: "monad_mono_step f m \ monad_mono_step (\m. L2_recguard m (f m)) m" by (simp add: L2_recguard_def monad_mono_step_def condition_def fail_def) lemma L2_reccall_monad_mono_step: "monad_mono_step f m \ monad_mono_step (\m. L2_call (f m)) m" apply (simp add: L2_call_def) apply (force intro: monad_mono_step_bindE monad_mono_step_const monad_mono_step_handleE') done lemmas L2_monad_mono_step_rules = monad_mono_step_const L2_while_monad_mono_step L2_recguard_monad_mono_step L2_catch_monad_mono_step L2_seq_monad_mono_step L2_condition_monad_mono_step L2_reccall_monad_mono_step monad_mono_step_recguard_dec_Suc (* Base case *) lemma monad_mono_step_L2_recguard_0: "monad_mono_step (\m. L2_recguard m (x m)) 0" by (monad_eq simp: monad_mono_step_def L2_recguard_def) end