Require Import Sail.State_monad. (*Require Import Sail.Values_lemmas.*) Require Export Setoid. Require Export Morphisms Equivalence. (* Basic results for reasoning about definitions which use the state monad. Note that rewriting results are put into both a rewriting hint database and a normal automation one. The former can be used with autorewrite and friends, but the latter can be used with the rewriting under congruence tactics, such as statecong in Sail.State_lemmas, and PrePostE_rewrite in Hoare. *) (* Ensure that pointwise equality on states is the preferred notion of equivalence for the state monad. *) Local Open Scope equiv_scope. Instance monadS_equivalence {Regs A E} : Equivalence (pointwise_relation (sequential_state Regs) (@eq (list (result A E * sequential_state Regs)))) | 9. split; apply _. Qed. Global Instance refl_eq_subrelation {A : Type} {R : A -> A -> Prop} `{Reflexive A R} : subrelation eq R. intros x y EQ. subst. reflexivity. Qed. Hint Extern 4 (_ === _) => reflexivity : core. Hint Extern 4 (_ === _) => symmetry : core. Lemma bindS_ext_cong (*[fundef_cong]:*) {Regs A B E} {m1 m2 : monadS Regs A E} {f1 f2 : A -> monadS Regs B E} s : m1 s = m2 s -> (forall a s', List.In (Value a, s') (m2 s) -> f1 a s' = f2 a s') -> bindS m1 f1 s = bindS m2 f2 s. intros. unfold bindS. rewrite H. rewrite !List.flat_map_concat_map. f_equal. apply List.map_ext_in. intros [[a|a] s'] H_in; auto. Qed. (* Weaker than the Isabelle version, but avoids talking about individual states *) Lemma bindS_cong (*[fundef_cong]:*) Regs A B E m1 m2 (f1 f2 : A -> monadS Regs B E) : m1 === m2 -> (forall a, f1 a === f2 a) -> bindS m1 f1 === bindS m2 f2. intros M F s. apply bindS_ext_cong; intros; auto. apply F. Qed. Add Parametric Morphism {Regs A B E : Type} : (@bindS Regs A B E) with signature equiv ==> equiv ==> equiv as bindS_morphism. auto using bindS_cong. Qed. Lemma bindS_returnS_left Regs A B E {x : A} {f : A -> monadS Regs B E} : bindS (returnS x) f === f x. intro s. unfold returnS, bindS. simpl. auto using List.app_nil_r. Qed. Hint Rewrite bindS_returnS_left : state. Hint Resolve bindS_returnS_left : state. Lemma bindS_returnS_right Regs A E {m : monadS Regs A E} : bindS m returnS === m. intro s. unfold returnS, bindS. induction (m s) as [|[[a|a] s'] t]; auto; simpl; rewrite IHt; reflexivity. Qed. Hint Rewrite bindS_returnS_right : state. Hint Resolve bindS_returnS_right : state. Lemma bindS_readS {Regs A E} {f} {m : A -> monadS Regs A E} {s} : bindS (readS f) m s = m (f s) s. unfold readS, bindS. simpl. rewrite List.app_nil_r. reflexivity. Qed. Lemma bindS_updateS {Regs A E} {f : sequential_state Regs -> sequential_state Regs} {m : unit -> monadS Regs A E} {s} : bindS (updateS f) m s = m tt (f s). unfold updateS, bindS. simpl. auto using List.app_nil_r. Qed. Lemma bindS_assertS_true Regs A E msg {f : unit -> monadS Regs A E} : bindS (assert_expS true msg) f === f tt. intro s. unfold assert_expS, bindS. simpl. auto using List.app_nil_r. Qed. Hint Rewrite bindS_assertS_true : state. Hint Resolve bindS_assertS_true : state. Lemma bindS_chooseS_returnS (*[simp]:*) Regs A B E {xs : list A} {f : A -> B} : bindS (Regs := Regs) (E := E) (chooseS xs) (fun x => returnS (f x)) === chooseS (List.map f xs). intro s. unfold chooseS, bindS, returnS. induction xs; auto. simpl. rewrite IHxs. reflexivity. Qed. Hint Rewrite bindS_chooseS_returnS : state. Hint Resolve bindS_chooseS_returnS : state. Lemma result_cases : forall (A E : Type) (P : result A E -> Prop), (forall a, P (Value a)) -> (forall e, P (Ex (Throw e))) -> (forall msg, P (Ex (Failure msg))) -> forall r, P r. intros. destruct r; auto. destruct e; auto. Qed. Lemma result_state_cases {A E S} {P : result A E * S -> Prop} : (forall a s, P (Value a, s)) -> (forall e s, P (Ex (Throw e), s)) -> (forall msg s, P (Ex (Failure msg), s)) -> forall rs, P rs. intros. destruct rs as [[a|[e|msg]] s]; auto. Qed. (* TODO: needs sets, not lists Lemma monadS_ext_eqI {Regs A E} {m m' : monadS Regs A E} s : (forall a s', List.In (Value a, s') (m s) <-> List.In (Value a, s') (m' s)) -> (forall e s', List.In (Ex (Throw e), s') (m s) <-> List.In (Ex (Throw e), s') (m' s)) -> (forall msg s', List.In (Ex (Failure msg), s') (m s) <-> List.In (Ex (Failure msg), s') (m' s)) -> m s = m' s. proof (intro set_eqI) fix x show "x \ m s \ x \ m' s" using assms by (cases x rule: result_state_cases) auto qed lemma monadS_eqI: fixes m m' :: "('regs, 'a, 'e) monadS" assumes "\s a s'. (Value a, s') \ m s \ (Value a, s') \ m' s" and "\s e s'. (Ex (Throw e), s') \ m s \ (Ex (Throw e), s') \ m' s" and "\s msg s'. (Ex (Failure msg), s') \ m s \ (Ex (Failure msg), s') \ m' s" shows "m = m'" using assms by (intro ext monadS_ext_eqI) *) Lemma bindS_cases {Regs A B E} {m} {f : A -> monadS Regs B E} {r s s'} : List.In (r, s') (bindS m f s) -> (exists a a' s'', r = Value a /\ List.In (Value a', s'') (m s) /\ List.In (Value a, s') (f a' s'')) \/ (exists e, r = Ex e /\ List.In (Ex e, s') (m s)) \/ (exists e a s'', r = Ex e /\ List.In (Value a, s'') (m s) /\ List.In (Ex e, s') (f a s'')). unfold bindS. intro IN. apply List.in_flat_map in IN. destruct IN as [[r' s''] [INr' INr]]. destruct r' as [a'|e']. * destruct r as [a|e]. + left. eauto 10. + right; right. eauto 10. * right; left. simpl in INr. destruct INr as [|[]]. inversion H. subst. eauto 10. Qed. Lemma bindS_intro_Value {Regs A B E} {m} {f : A -> monadS Regs B E} {s a s' a' s''} : List.In (Value a', s'') (m s) -> List.In (Value a, s') (f a' s'') -> List.In (Value a, s') (bindS m f s). intros; unfold bindS. apply List.in_flat_map. eauto. Qed. Lemma bindS_intro_Ex_left {Regs A B E} {m} {f : A -> monadS Regs B E} {s e s'} : List.In (Ex e, s') (m s) -> List.In (Ex e, s') (bindS m f s). intros; unfold bindS. apply List.in_flat_map. exists (Ex e, s'). auto with datatypes. Qed. Lemma bindS_intro_Ex_right {Regs A B E} {m} {f : A -> monadS Regs B E} {s e s' a s''} : List.In (Ex e, s') (f a s'') -> List.In (Value a, s'') (m s) -> List.In (Ex e, s') (bindS m f s). intros; unfold bindS. apply List.in_flat_map. eauto. Qed. Hint Resolve bindS_intro_Value bindS_intro_Ex_left bindS_intro_Ex_right : bindS_intros. Lemma bindS_assoc Regs A B C E {m} {f : A -> monadS Regs B E} {g : B -> monadS Regs C E} : bindS (bindS m f) g === bindS m (fun x => bindS (f x) g). intro s. unfold bindS. induction (m s) as [ | [[a | e] t]]. * reflexivity. * simpl. rewrite <- IHl. rewrite !List.flat_map_concat_map. rewrite List.map_app. rewrite List.concat_app. reflexivity. * simpl. rewrite IHl. reflexivity. Qed. Hint Rewrite bindS_assoc : state. Hint Resolve bindS_assoc : state. Lemma bindS_failS Regs A B E {msg} {f : A -> monadS Regs B E} : bindS (failS msg) f = failS msg. reflexivity. Qed. Hint Rewrite bindS_failS : state. Hint Resolve bindS_failS : state. Lemma bindS_throwS Regs A B E {e} {f : A -> monadS Regs B E} : bindS (throwS e) f = throwS e. reflexivity. Qed. Hint Rewrite bindS_throwS : state. Hint Resolve bindS_throwS : state. (*declare seqS_def[simp]*) Lemma seqS_def Regs A E m (m' : monadS Regs A E) : m >>$ m' = m >>$= (fun _ => m'). reflexivity. Qed. Hint Rewrite seqS_def : state. Hint Resolve seqS_def : state. Lemma Value_bindS_elim {Regs A B E} {a m} {f : A -> monadS Regs B E} {s s'} : List.In (Value a, s') (bindS m f s) -> exists s'' a', List.In (Value a', s'') (m s) /\ List.In (Value a, s') (f a' s''). intro H. apply bindS_cases in H. destruct H as [(a0 & a' & s'' & [= <-] & [*]) | [(e & [= ] & _) | (_ & _ & _ & [= ] & _)]]. eauto. Qed. Lemma Ex_bindS_elim {Regs A B E} {e m s s'} {f : A -> monadS Regs B E} : List.In (Ex e, s') (bindS m f s) -> List.In (Ex e, s') (m s) \/ exists s'' a', List.In (Value a', s'') (m s) /\ List.In (Ex e, s') (f a' s''). intro H. apply bindS_cases in H. destruct H as [(? & ? & ? & [= ] & _) | [(? & [= <-] & X) | (? & ? & ? & [= <-] & X)]]; eauto. Qed. Lemma try_catchS_returnS Regs A E1 E2 {a} {h : E1 -> monadS Regs A E2}: try_catchS (returnS a) h = returnS a. reflexivity. Qed. Hint Rewrite try_catchS_returnS : state. Hint Resolve try_catchS_returnS : state. Lemma try_catchS_failS Regs A E1 E2 {msg} {h : E1 -> monadS Regs A E2}: try_catchS (failS msg) h = failS msg. reflexivity. Qed. Hint Rewrite try_catchS_failS : state. Hint Resolve try_catchS_failS : state. Lemma try_catchS_throwS Regs A E1 E2 {e} {h : E1 -> monadS Regs A E2}: try_catchS (throwS e) h === h e. intro s. unfold try_catchS, throwS. simpl. auto using List.app_nil_r. Qed. Hint Rewrite try_catchS_throwS : state. Hint Resolve try_catchS_throwS : state. Lemma try_catchS_cong (*[cong]:*) {Regs A E1 E2 m1 m2} {h1 h2 : E1 -> monadS Regs A E2} : m1 === m2 -> (forall e, h1 e === h2 e) -> try_catchS m1 h1 === try_catchS m2 h2. intros H1 H2 s. unfold try_catchS. rewrite H1. rewrite !List.flat_map_concat_map. f_equal. apply List.map_ext_in. intros [[a|[e|msg]] s'] H_in; auto. apply H2. Qed. Add Parametric Morphism {Regs A E1 E2 : Type} : (@try_catchS Regs A E1 E2) with signature equiv ==> equiv ==> equiv as try_catchS_morphism. intros. auto using try_catchS_cong. Qed. Add Parametric Morphism {Regs A E : Type} : (@catch_early_returnS Regs A E) with signature equiv ==> equiv as catch_early_returnS_morphism. intros. unfold catch_early_returnS. rewrite H. reflexivity. Qed. Lemma try_catchS_cases {Regs A E1 E2 m} {h : E1 -> monadS Regs A E2} {r s s'} : List.In (r, s') (try_catchS m h s) -> (exists a, r = Value a /\ List.In (Value a, s') (m s)) \/ (exists msg, r = Ex (Failure msg) /\ List.In (Ex (Failure msg), s') (m s)) \/ (exists e s'', List.In (Ex (Throw e), s'') (m s) /\ List.In (r, s') (h e s'')). unfold try_catchS. intro IN. apply List.in_flat_map in IN. destruct IN as [[r' s''] [INr' INr]]. destruct r' as [a'|[e'|msg]]. * left. simpl in INr. destruct INr as [[= <- <-] | []]. eauto 10. * simpl in INr. destruct INr as [[= <- <-] | []]. eauto 10. * eauto 10. Qed. Lemma try_catchS_intros {Regs A E1 E2} {m} {h : E1 -> monadS Regs A E2} : (forall s a s', List.In (Value a, s') (m s) -> List.In (Value a, s') (try_catchS m h s)) /\ (forall s msg s', List.In (Ex (Failure msg), s') (m s) -> List.In (Ex (Failure msg), s') (try_catchS m h s)) /\ (forall s e s'' r s', List.In (Ex (Throw e), s'') (m s) -> List.In (r, s') (h e s'') -> List.In (r, s') (try_catchS m h s)). repeat split; unfold try_catchS; intros; apply List.in_flat_map. * eexists; split; [ apply H | ]. simpl. auto. * eexists; split; [ apply H | ]. simpl. auto. * eexists; split; [ apply H | ]. simpl. auto. Qed. Lemma no_Ex_basic_builtins (*[simp]:*) {Regs E} {s s' : sequential_state Regs} {e : ex E} : (forall A (a:A), ~ List.In (Ex e, s') (returnS a s)) /\ (forall A (f : _ -> A), ~ List.In (Ex e, s') (readS f s)) /\ (forall f, ~ List.In (Ex e, s') (updateS f s)) /\ (forall A (xs : list A), ~ List.In (Ex e, s') (chooseS xs s)). repeat split; intros; unfold returnS, readS, updateS, chooseS; simpl; try intuition congruence. * intro H. apply List.in_map_iff in H. destruct H as [x [X _]]. congruence. Qed. Import List.ListNotations. Definition ignore_throw_aux {A E1 E2 S} (rs : result A E1 * S) : list (result A E2 * S) := match rs with | (Value a, s') => [(Value a, s')] | (Ex (Throw e), s') => [] | (Ex (Failure msg), s') => [(Ex (Failure msg), s')] end. Definition ignore_throw {A E1 E2 S} (m : S -> list (result A E1 * S)) s : list (result A E2 * S) := List.flat_map ignore_throw_aux (m s). Lemma ignore_throw_cong {Regs A E1 E2} {m1 m2 : monadS Regs A E1} : m1 === m2 -> ignore_throw (E2 := E2) m1 === ignore_throw m2. intros H s. unfold ignore_throw. rewrite H. reflexivity. Qed. Lemma ignore_throw_aux_member_simps (*[simp]:*) {A E1 E2 S} {s' : S} {ms} : (forall a:A, List.In (Value a, s') (ignore_throw_aux (E1 := E1) (E2 := E2) ms) <-> ms = (Value a, s')) /\ (forall e, ~ List.In (Ex (E := E2) (Throw e), s') (ignore_throw_aux ms)) /\ (forall msg, List.In (Ex (E := E2) (Failure msg), s') (ignore_throw_aux ms) <-> ms = (Ex (Failure msg), s')). destruct ms as [[a' | [e' | msg']] s]; simpl; intuition congruence. Qed. Lemma ignore_throw_member_simps (*[simp]:*) {A E1 E2 S} {s s' : S} {m} : (forall {a:A}, List.In (Value (E := E2) a, s') (ignore_throw m s) <-> List.In (Value (E := E1) a, s') (m s)) /\ (forall {a:A}, List.In (Value (E := E2) a, s') (ignore_throw m s) <-> List.In (Value a, s') (m s)) /\ (forall e, ~ List.In (Ex (E := E2) (Throw e), s') (ignore_throw m s)) /\ (forall {msg}, List.In (Ex (E := E2) (Failure msg), s') (ignore_throw m s) <-> List.In (Ex (Failure msg), s') (m s)). unfold ignore_throw. repeat apply conj; intros; try apply conj; rewrite ?List.in_flat_map; solve [ intros [x [H1 H2]]; apply ignore_throw_aux_member_simps in H2; congruence | intro H; eexists; split; [ apply H | apply ignore_throw_aux_member_simps; reflexivity] ]. Qed. Lemma ignore_throw_cases {A E S} {m : S -> list (result A E * S)} {r s s'} : ignore_throw m s = m s -> List.In (r, s') (m s) -> (exists a, r = Value a) \/ (exists msg, r = Ex (Failure msg)). destruct r as [a | [e | msg]]; eauto. * intros H1 H2. rewrite <- H1 in H2. apply ignore_throw_member_simps in H2. destruct H2. Qed. (* *** *) Lemma flat_map_app {A B} {f : A -> list B} {l1 l2} : List.flat_map f (l1 ++ l2) = (List.flat_map f l1 ++ List.flat_map f l2)%list. rewrite !List.flat_map_concat_map. rewrite List.map_app, List.concat_app. reflexivity. Qed. Lemma ignore_throw_bindS (*[simp]:*) Regs A B E E2 {m} {f : A -> monadS Regs B E} : ignore_throw (E2 := E2) (bindS m f) === bindS (ignore_throw m) (fun s => ignore_throw (f s)). intro s. unfold bindS, ignore_throw. induction (m s) as [ | [[a | [e | msg]] t]]. * reflexivity. * simpl. rewrite <- IHl. rewrite flat_map_app. reflexivity. * simpl. rewrite <- IHl. reflexivity. * simpl. apply IHl. Qed. Hint Rewrite ignore_throw_bindS : ignore_throw. Hint Resolve ignore_throw_bindS : ignore_throw. Lemma try_catchS_bindS_no_throw {Regs A B E1 E2} {m1 : monadS Regs A E1} {m2 : monadS Regs A E2} {f : A -> monadS Regs B _} {h} : ignore_throw m1 === m1 -> ignore_throw m1 === m2 -> try_catchS (bindS m1 f) h === bindS m2 (fun a => try_catchS (f a) h). intros Ignore1 Ignore2. transitivity ((ignore_throw m1 >>$= (fun a => try_catchS (f a) h))). * intro s. unfold bindS, try_catchS, ignore_throw. specialize (Ignore1 s). revert Ignore1. unfold ignore_throw. induction (m1 s) as [ | [[a | [e | msg]] t]]; auto. + intro Ig. simpl. rewrite flat_map_app. rewrite IHl. auto. injection Ig. auto. + intro Ig. simpl. rewrite IHl. reflexivity. injection Ig. auto. + intro Ig. exfalso. clear -Ig. assert (List.In (Ex (Throw msg), t) (List.flat_map ignore_throw_aux l)). simpl in Ig. rewrite Ig. simpl. auto. apply List.in_flat_map in H. destruct H as [x [H1 H2]]. apply ignore_throw_aux_member_simps in H2. assumption. * apply bindS_cong; auto. Qed. Lemma concat_map_singleton {A B} {f : A -> B} {a : list A} : List.concat (List.map (fun x => [f x]%list) a) = List.map f a. induction a; simpl; try rewrite IHa; auto with datatypes. Qed. (*lemma no_throw_basic_builtins[simp]:*) Lemma no_throw_basic_builtins_1 Regs A E E2 {a : A} : ignore_throw (E1 := E2) (returnS a) = @returnS Regs A E a. reflexivity. Qed. Lemma no_throw_basic_builtins_2 Regs A E E2 {f : sequential_state Regs -> A} : ignore_throw (E1 := E) (E2 := E2) (readS f) = readS f. reflexivity. Qed. Lemma no_throw_basic_builtins_3 Regs E E2 {f : sequential_state Regs -> sequential_state Regs} : ignore_throw (E1 := E) (E2 := E2) (updateS f) = updateS f. reflexivity. Qed. Lemma no_throw_basic_builtins_4 Regs A E1 E2 {xs : list A} : ignore_throw (E1 := E1) (chooseS xs) === @chooseS Regs A E2 xs. intro s. unfold ignore_throw, chooseS. rewrite List.flat_map_concat_map, List.map_map. simpl. rewrite concat_map_singleton. reflexivity. Qed. Lemma no_throw_basic_builtins_5 Regs E1 E2 : ignore_throw (E1 := E1) (choose_boolS tt) = @choose_boolS Regs E2 tt. reflexivity. Qed. Lemma no_throw_basic_builtins_6 Regs A E1 E2 msg : ignore_throw (E1 := E1) (failS msg) = @failS Regs A E2 msg. reflexivity. Qed. Lemma no_throw_basic_builtins_7 Regs A E1 E2 msg x : ignore_throw (E1 := E1) (maybe_failS msg x) = @maybe_failS Regs A E2 msg x. destruct x; reflexivity. Qed. Hint Rewrite no_throw_basic_builtins_1 no_throw_basic_builtins_2 no_throw_basic_builtins_3 no_throw_basic_builtins_4 no_throw_basic_builtins_5 no_throw_basic_builtins_6 no_throw_basic_builtins_7 : ignore_throw. Hint Resolve no_throw_basic_builtins_1 no_throw_basic_builtins_2 no_throw_basic_builtins_3 no_throw_basic_builtins_4 no_throw_basic_builtins_5 no_throw_basic_builtins_6 no_throw_basic_builtins_7 : ignore_throw. Lemma ignore_throw_option_case_distrib_1 Regs B C E1 E2 (c : sequential_state Regs -> option B) s (n : monadS Regs C E1) (f : B -> monadS Regs C E1) : ignore_throw (E2 := E2) (match c s with None => n | Some b => f b end) s = match c s with None => ignore_throw n s | Some b => ignore_throw (f b) s end. destruct (c s); auto. Qed. Lemma ignore_throw_option_case_distrib_2 Regs B C E1 E2 (c : option B) (n : monadS Regs C E1) (f : B -> monadS Regs C E1) : ignore_throw (E2 := E2) (match c with None => n | Some b => f b end) = match c with None => ignore_throw n | Some b => ignore_throw (f b) end. destruct c; auto. Qed. Lemma ignore_throw_let_distrib Regs A B E1 E2 (y : A) (f : A -> monadS Regs B E1) : ignore_throw (E2 := E2) (let x := y in f x) = (let x := y in ignore_throw (f x)). reflexivity. Qed. Lemma no_throw_mem_builtins_1 Regs E1 E2 rk a sz : ignore_throw (E2 := E2) (@read_memt_bytesS Regs E1 rk a sz) === read_memt_bytesS rk a sz. unfold read_memt_bytesS. autorewrite with ignore_throw. apply bindS_cong; auto. intros. autorewrite with ignore_throw. reflexivity. Qed. Hint Rewrite no_throw_mem_builtins_1 : ignore_throw. Hint Resolve no_throw_mem_builtins_1 : ignore_throw. Lemma no_throw_mem_builtins_2 Regs E1 E2 rk a sz : ignore_throw (E2 := E2) (@read_mem_bytesS Regs E1 rk a sz) === read_mem_bytesS rk a sz. unfold read_mem_bytesS. autorewrite with ignore_throw. apply bindS_cong; intros; autorewrite with ignore_throw; auto. destruct a0; reflexivity. Qed. Hint Rewrite no_throw_mem_builtins_2 : ignore_throw. Hint Resolve no_throw_mem_builtins_2 : ignore_throw. Lemma no_throw_mem_builtins_3 Regs A E1 E2 a : ignore_throw (E2 := E2) (@read_tagS Regs A E1 a) === read_tagS a. reflexivity. Qed. Hint Rewrite no_throw_mem_builtins_3 : ignore_throw. Hint Resolve no_throw_mem_builtins_3 : ignore_throw. Lemma no_throw_mem_builtins_4 Regs A V E1 E2 rk a sz H : ignore_throw (E2 := E2) (@read_memtS Regs E1 A V rk a sz H) === read_memtS rk a sz. unfold read_memtS. autorewrite with ignore_throw. apply bindS_cong; intros; autorewrite with ignore_throw. reflexivity. destruct a0; simpl. autorewrite with ignore_throw. reflexivity. Qed. Hint Rewrite no_throw_mem_builtins_4 : ignore_throw. Hint Resolve no_throw_mem_builtins_4 : ignore_throw. Lemma no_throw_mem_builtins_5 Regs A V E1 E2 rk a sz H : ignore_throw (E2 := E2) (@read_memS Regs E1 A V rk a sz H) === read_memS rk a sz. unfold read_memS. autorewrite with ignore_throw. apply bindS_cong; intros; autorewrite with ignore_throw; auto. destruct a0; auto. Qed. Hint Rewrite no_throw_mem_builtins_5 : ignore_throw. Hint Resolve no_throw_mem_builtins_5 : ignore_throw. Lemma no_throw_mem_builtins_6 Regs E1 E2 wk addr sz v t : ignore_throw (E2 := E2) (@write_memt_bytesS Regs E1 wk addr sz v t) === write_memt_bytesS wk addr sz v t. unfold write_memt_bytesS. unfold seqS. autorewrite with ignore_throw. reflexivity. Qed. Hint Rewrite no_throw_mem_builtins_6 : ignore_throw. Hint Resolve no_throw_mem_builtins_6 : ignore_throw. Lemma no_throw_mem_builtins_7 Regs E1 E2 wk addr sz v : ignore_throw (E2 := E2) (@write_mem_bytesS Regs E1 wk addr sz v) === write_mem_bytesS wk addr sz v. unfold write_mem_bytesS. autorewrite with ignore_throw. reflexivity. Qed. Hint Rewrite no_throw_mem_builtins_7 : ignore_throw. Hint Resolve no_throw_mem_builtins_7 : ignore_throw. Lemma no_throw_mem_builtins_8 Regs E1 E2 A B wk addr sz v t : ignore_throw (E2 := E2) (@write_memtS Regs E1 A B wk addr sz v t) === write_memtS wk addr sz v t. unfold write_memtS. rewrite ignore_throw_option_case_distrib_2. destruct (Sail.Values.mem_bytes_of_bits v); autorewrite with ignore_throw; auto. Qed. Hint Rewrite no_throw_mem_builtins_8 : ignore_throw. Hint Resolve no_throw_mem_builtins_8 : ignore_throw. Lemma no_throw_mem_builtins_9 Regs E1 E2 A B wk addr sz v : ignore_throw (E2 := E2) (@write_memS Regs E1 A B wk addr sz v) === write_memS wk addr sz v. unfold write_memS. autorewrite with ignore_throw; auto. Qed. Hint Rewrite no_throw_mem_builtins_9 : ignore_throw. Hint Resolve no_throw_mem_builtins_9 : ignore_throw. Lemma no_throw_mem_builtins_10 Regs E1 E2 : ignore_throw (E2 := E2) (@excl_resultS Regs E1 tt) === excl_resultS tt. reflexivity. Qed. Hint Rewrite no_throw_mem_builtins_10 : ignore_throw. Hint Resolve no_throw_mem_builtins_10 : ignore_throw. Lemma no_throw_mem_builtins_11 Regs E1 E2 : ignore_throw (E2 := E2) (@undefined_boolS Regs E1 tt) === undefined_boolS tt. reflexivity. Qed. Hint Rewrite no_throw_mem_builtins_11 : ignore_throw. Hint Resolve no_throw_mem_builtins_11 : ignore_throw. Lemma no_throw_read_regvalS Regs RV E1 E2 r reg_name : ignore_throw (E2 := E2) (@read_regvalS Regs RV E1 r reg_name) === read_regvalS r reg_name. destruct r; simpl. autorewrite with ignore_throw. apply bindS_cong; intros; auto. rewrite ignore_throw_option_case_distrib_2. autorewrite with ignore_throw. reflexivity. Qed. Hint Rewrite no_throw_read_regvalS : ignore_throw. Hint Resolve no_throw_read_regvalS : ignore_throw. Lemma no_throw_write_regvalS Regs RV E1 E2 r reg_name v : ignore_throw (E2 := E2) (@write_regvalS Regs RV E1 r reg_name v) === write_regvalS r reg_name v. destruct r; simpl. autorewrite with ignore_throw. apply bindS_cong; intros; auto. rewrite ignore_throw_option_case_distrib_2. autorewrite with ignore_throw. reflexivity. Qed. Hint Rewrite no_throw_write_regvalS : ignore_throw. Hint Resolve no_throw_write_regvalS : ignore_throw.