(* * 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 HaskellLemmaBucket imports HaskellLib_H NonDetMonadLemmaBucket begin lemma map_bits_to_bl: "map ((!!) x) [0.. orList ls \ ls = replicate (length ls) False" proof (induct ls rule: rev_induct) case Nil thus ?case unfolding orList_def by simp next case (snoc l ls) from snoc.prems have ol: "\ orList ls" and nl: "\ l" unfolding orList_def by auto have "ls = replicate (length ls) False" by (rule snoc.hyps [OF ol]) thus ?case by (rule ssubst) (simp add: nl replicate_app_Cons_same [where xs = "[]", simplified]) qed lemma andList_Cons: assumes al: "andList $ map P (y # ys)" shows "P y" using al unfolding andList_def by simp (induct rule: rev_induct, simp+) lemma andList_mapE: assumes al: "andList $ map P xs" and xv: "x \ set xs" shows "P x" using al xv proof (induct xs arbitrary: x rule: rev_induct) case Nil thus ?case by simp next case (snoc y ys) show ?case proof (cases "x = y") case True with snoc.prems show ?thesis by (simp add: andList_def) next case False with snoc.prems show ?thesis by (auto simp: andList_def intro!: snoc.hyps) qed qed lemma andList_to_aligned: assumes al: "andList $ map (\x. x && mask pageBits = 0) xs" and xv: "x \ set xs" shows "is_aligned x pageBits" proof (subst is_aligned_mask) from al show "x && mask pageBits = 0" by (rule andList_mapE) fact qed (* minimum/maximum *) lemma maximum_ge: "x \ set b \ x \ maximum b" unfolding maximum_def by (auto intro: Max_ge) lemma less_minimum_not_in: "\ ls \ []; x < minimum ls \ \ x \ set ls" unfolding minimum_def by auto lemma minimum_le_member: "\ x \ set ls; ls \ []\ \ minimum ls \ x" unfolding minimum_def apply (rule Min_le) apply simp apply simp done lemma minimum_map_distrib: fixes f :: "('a :: linorder) \ 'a" and ls :: "'a list" assumes minf: "\x y. \x \ set ls; y \ set ls\ \ min (f x) (f y) = f (min x y)" and lsn: "ls \ []" shows "minimum (map f ls) = f (minimum ls)" unfolding minimum_def apply simp apply (rule Min_image_distrib) apply (erule (1) minf) apply simp apply (simp add: lsn) done lemma minimum_enum_upto: fixes x :: "'a::len word" assumes le: "x \ y" shows "minimum [x .e. y] = x" unfolding minimum_def using le by (auto intro!: MinI) lemma break_subsetsD: "break f xs = (ys, zs) \ set ys \ set xs \ set zs \ set xs" apply (induct xs arbitrary: ys zs) apply simp apply (case_tac "break f xs") apply (elim meta_allE, drule(1) meta_mp) apply (fastforce simp: split_def split: if_split_asm) done lemma distinct_prop_breakD: "\ distinct_prop P xs; break f xs = (ys, zs) \ \ \y \ set ys. \z \ set zs. P y z" apply (induct xs arbitrary: ys zs) apply simp apply (simp add: split_def split: if_split_asm) apply (case_tac "break f xs") apply (elim meta_allE, drule(1) meta_mp) apply (frule break_subsetsD) apply fastforce done lemma stateAssert_wp: "\\s. P s \ Q () s\ stateAssert P e \Q\" by (clarsimp simp: stateAssert_def) wp lemma haskell_assert_wp: "\\s. Q \ P s\ haskell_assert Q xs \\_. P\" by simp wp lemma init_append_last: "xs \ [] \ init xs @ [last xs] = xs" apply (induct xs rule: rev_induct) apply simp apply (simp add: init_def) done lemma init_Snoc[simp]: "init (xs @ [x]) = xs" by (induct xs) (auto simp: init_def) lemma init_upto_enum_upt[simp]: "init [0.e.n] = [0..\\ haskell_fail x \P\" by simp lemma no_fail_haskell_fail [simp, wp]: "no_fail \ (haskell_fail xs)" by simp lemma in_assocs_is_fun: "(x \ set (assocs f)) = (f (fst x) = snd x)" by (cases x) (auto simp add: assocs_def) lemma fun_is_in_assocs: "(f x = y) = ((x,y) \ set (assocs f))" by (simp add: in_assocs_is_fun) lemma empty_set_is_null: "(set xs = {}) = null xs" by (clarsimp simp: null_def) lemma assert_into_when: "(assert P) = (when (\ P) (haskell_fail []))" by (simp add: assert_def when_def) lemma const_apply: "const x y = x" by (simp add: const_def) lemma const_None_empty: "const None = Map.empty" by (rule ext, simp add: const_apply) lemma headM_tailM_Cons: "headM (x # xs) = return x" "tailM (x # xs) = return xs" by (simp add: headM_def tailM_def)+ lemma replicateM_mapM: "replicateM n f = mapM (\x. f) (replicate n ())" by (simp add: replicateM_def mapM_def) lemma orList_False: "(\ orList bs) = (set bs \ {False})" apply (induct bs) apply (simp_all add: orList_def foldl_True) apply (case_tac a) apply (simp_all add: orList_def foldl_True) done lemma Cons_eq_tails: "((xs # xxs) = tails ys) = (ys = xs \ xxs = tl (tails ys))" by (case_tac ys, auto) lemma findM_on_outcome': assumes x: "\x xs. \\s. Q None s \ x \ fn s \ set xs \ fn s\ f x \\rv s. (rv \ Q (Some x) s) \ (\ rv \ Q None s \ set xs \ fn s)\" shows "\\s. Q None s \ set xs \ fn s\ findM f xs \Q\" apply (induct xs) apply (simp, wp) apply (simp, wp) apply (rule x) apply simp done lemma findM_on_outcome: assumes x: "\x ys. x \ set xs \ \Q None and I\ f x \\rv s. (rv \ Q (Some x) s) \ (\ rv \ Q None s \ I s)\" shows "\Q None and I\ findM f xs \Q\" apply (rule hoare_vcg_precond_imp) apply (rule findM_on_outcome' [where fn="\s. if I s then set xs else {}"]) apply (case_tac "x \ set xs") apply simp apply (simp cong: rev_conj_cong) apply (case_tac "\ set xsa \ set xs") apply simp apply simp apply (rule hoare_vcg_precond_imp) apply (rule hoare_post_imp [OF _ x]) apply clarsimp apply assumption apply simp apply simp done lemma in_set_tailsD: "xs \ set (tails ys) \ set xs \ set ys" apply (induct ys) apply simp apply simp apply (erule disjE) apply simp apply simp apply blast done lemma notin_set_tails_set: "x \ set xs \ \xs' \ set (tails xs). \x' \ set xs'. x \ x'" by (fastforce dest!: in_set_tailsD) lemma set_tails_set: "(set (tails v) \ {x. set x \ S}) = (set v \ S)" apply (induct v, simp_all) done lemma filter_assocs_Cons: fixes v :: "('a :: len) word" shows "\ f (v, g v); \x < v. \ f (x, g x) \ \ filter f (assocs g) = (v, g v) # tl (filter f (assocs g))" apply (simp add: assocs_def) apply (cut_tac v=v in enum_word_div) apply clarsimp apply (subst map_cong [OF _ refl], assumption)+ apply (simp(no_asm)) apply simp done lemma snd_stateAssert_after: "\ snd ((do _ \ f; stateAssert R vs od) s) \ \snd (f s) \ (\(rv, s') \ fst (f s). R s')" apply (clarsimp simp: bind_def stateAssert_def get_def assert_def return_def fail_def split_def split: if_split_asm) done lemma oblivious_stateAssert [simp]: "oblivious f (stateAssert g xs) = (\s. g (f s) = g s)" apply (simp add: oblivious_def stateAssert_def exec_get assert_def return_def fail_def split: if_split) apply auto done lemma stateAssert_def2: "stateAssert f xs = do v \ gets f; if v then return () else fail od" by (simp add: stateAssert_def gets_def assert_def) lemma findM_is_mapME: "(findM f xs >>= g) = liftM (\_. ()) (doE ys \ mapME_x (\x. do v \ f x; if v then do g (Some x); throwError () od else returnOk () od) xs; liftE (g None) odE)" apply (induct xs) apply (simp add: mapME_x_def sequenceE_x_def liftM_def returnOk_bind) apply (simp add: liftE_def) apply (simp add: mapME_x_Cons bindE_assoc liftE_bindE[symmetric] liftM_def cong: if_cong) apply (simp add: liftE_bindE bind_assoc) apply (rule bind_cong[OF refl]) apply (simp add: bindE_assoc split: if_split) apply (simp add: liftE_bindE bind_assoc throwError_bind) done text {* Some word equalities can be solved by considering the problem bitwise. This is proven for all n < len_of TYPE ('a), which is different to running word_bitwise and expanding into an explicit list of bits. *} lemmas word_eqI_solve_simps = word_and_le1 word_or_zero le_word_or2 shiftL_nat word_FF_is_mask word_1FF_is_mask neg_mask_bang nth_ucast linorder_not_less word_size minus_one_norm word_ops_nth_size is_aligned_nth nth_w2p nth_shiftl nth_shiftr conj_comms less_2p_is_upper_bits_unset method word_eqI_solve = solves \rule word_eqI; clarsimp simp: word_eqI_solve_simps; (eval_int_nat; clarsimp simp: word_eqI_solve_simps)?; fastforce simp: mask_def \ add_try_method word_eqI_solve end