(** * Effect Semantics *)
(** Effect semantics augment memory semantics with effects, in the form of a set of locations [block -> Z -> bool] associated with each internal step of the semantics. *)
Record EffectSem {C} :=
{ (** [sem] is a memory semantics. *)
sem :> @MemSem C
(** The step relation of the new semantics. *)
; effstep: (block -> Z -> bool) -> C -> mem -> C -> mem -> Prop
(** The next three fields axiomatize [effstep] and its relation to the underlying step relation of [sem]. *)
; effax1: forall M c m c' m',
effstep M c m c' m' ->
corestep sem c m c' m'
/\ Mem.unchanged_on (fun b ofs => M b ofs = false) m m'
; effax2: forall c m c' m',
corestep sem c m c' m' ->
exists M, effstep M c m c' m'
; effstep_perm: forall M c m c' m',
effstep M c m c' m' ->
forall b z, M b z = true -> Mem.perm m b z Cur Writable
}.
(* Arguments EffectSem []. *)
(** * Lemmas and auxiliary definitions *)
Section effsemlemmas.
Context {C:Type} (Sem: @EffectSem C).

(* Specifications: *)
Lemma effstep_valid: forall M c m c' m',
effstep Sem M c m c' m' ->
forall b z, M b z = true -> Mem.valid_block m b.
Lemma effstep_fwd U c m c' m' (EF: effstep Sem U c m c' m'): mem_forward m m'.
Fixpoint effstepN (n:nat) : (block -> Z -> bool) -> C -> mem -> C -> mem -> Prop :=
match n with
| O => fun U c m c' m' => (c,m) = (c',m') /\ U = (fun b z => false)
| S k => fun U c1 m1 c3 m3 => exists c2, exists m2, exists U1, exists U2,
effstep Sem U1 c1 m1 c2 m2 /\
effstepN k U2 c2 m2 c3 m3 /\
U = (fun b z => U1 b z || (U2 b z && valid_block_dec m1 b))
end.
Lemma effstepN_perm: forall n U c1 m1 c2 m2, effstepN n U c1 m1 c2 m2 ->
forall b z, U b z = true -> Mem.perm m1 b z Cur Writable.
Lemma effstepN_valid n U c1 m1 c2 m2  (Step:effstepN n U c1 m1 c2 m2)
b z (EFF:U b z = true): Mem.valid_block m1 b.
Lemma effstepN_fwd n U c m c' m' (EF:effstepN n U c m c' m'): mem_forward m m'.
Lemma effstepN_corestepN: forall n E c m c' m',
effstepN n E c m c' m' -> corestepN Sem n c m c' m'.
Lemma effstepN_unchanged: forall n U c1 m1 c2 m2,
effstepN n U c1 m1 c2 m2 ->
Mem.unchanged_on (fun b z => U b z = false) m1 m2.
Lemma effstepN_trans: forall n1 n2 U1 st1 m1 st2 m2 U2 st3 m3,
effstepN n1 U1 st1 m1 st2 m2 ->
effstepN n2 U2 st2 m2 st3 m3 ->
effstepN (n1+n2)
(fun b z => U1 b z || (U2 b z && valid_block_dec m1 b)) st1 m1 st3 m3.
Lemma effstepN_trans': forall n1 n2 U U1 st1 m1 st2 m2 U2 st3 m3,
effstepN n1 U1 st1 m1 st2 m2 ->
effstepN n2 U2 st2 m2 st3 m3 ->
U = (fun b z => U1 b z || (U2 b z && valid_block_dec m1 b)) ->
effstepN (n1+n2) U st1 m1 st3 m3.
Lemma effstep_plus_trans' : forall U U1 c1 c2 c3 U2 m1 m2 m3,
effstep_plus U1 c1 m1 c2 m2 -> effstep_plus U2 c2 m2 c3 m3 ->
U = (fun b z => U1 b z || (U2 b z && valid_block_dec m1 b)) ->
effstep_plus U c1 m1 c3 m3.
Lemma effstep_star_plus_trans' : forall U U1 c1 c2 c3 U2 m1 m2 m3,
effstep_star U1 c1 m1 c2 m2 -> effstep_plus U2 c2 m2 c3 m3 ->
U = (fun b z => U1 b z || (U2 b z && valid_block_dec m1 b)) ->
effstep_plus U c1 m1 c3 m3.
Lemma effstep_plus_star_trans': forall U U1 c1 c2 c3 U2 m1 m2 m3,
effstep_plus U1 c1 m1 c2 m2 -> effstep_star U2 c2 m2 c3 m3 ->
U = (fun b z => U1 b z || (U2 b z && valid_block_dec m1 b)) ->
effstep_plus U c1 m1 c3 m3.
Lemma effstep_star_trans': forall U U1 c1 c2 c3 U2 m1 m2 m3,
effstep_star U1 c1 m1 c2 m2 -> effstep_star U2 c2 m2 c3 m3 ->
U = (fun b z => U1 b z || (U2 b z && valid_block_dec m1 b)) ->
effstep_star U c1 m1 c3 m3.
Lemma effstep_plus_two: forall U1 c m c' m' U2 c'' m'',
effstep  Sem U1 c m c' m' -> effstep Sem U2 c' m' c'' m'' ->
effstep_plus (fun b z => U1 b z || (U2 b z && valid_block_dec m b)) c m c'' m''.
Lemma effstep_star_zero: forall c m, effstep_star (fun b z =>false) c m c m.
Lemma effstep_plus_split: forall U c m c' m',
effstep_plus U c m c' m' ->
exists c'', exists m'', exists U1, exists U2,
effstep Sem U1 c m c'' m'' /\
effstep_star U2 c'' m'' c' m' /\
U = (fun b z => U1 b z || (U2 b z && valid_block_dec m b)).
Lemma effstep_plus_perm U c1 m1 c2 m2 (Step: effstep_plus U c1 m1 c2 m2):
forall b z, U b z = true -> Mem.perm m1 b z Cur Writable.
Lemma effstep_plus_mem U c m c' m' (EF: effstep_plus U c m c' m'): mem_step m m'.
Lemma effstep_plus_fwd U c m c' m' (EF: effstep_plus U c m c' m'): mem_forward m m'.
Lemma effstep_star_fwd U c m c' m' (EF: effstep_star U c m c' m'): mem_forward m m'.
End effsemlemmas.