(** * Semantics annotated with Owens-style trace*)
Inductive mem_event :=
Write : forall (b : block) (ofs : Z) (bytes : list memval), mem_event
| Read : forall (b:block) (ofs n:Z) (bytes: list memval), mem_event
| Alloc: forall (b:block)(lo hi:Z), mem_event
(*| Lock: drf_event | Unlock: drf_event  -- these events are not generated by core steps*)
| Free: forall (l: list (block * Z * Z)), mem_event.
Fixpoint ev_elim (m:mem) (T: list mem_event) (m':mem):Prop :=
match T with
nil => m'=m
| (Read b ofs n bytes :: R) => Mem.loadbytes m b ofs n = Some bytes /\ ev_elim m R m'
| (Write b ofs bytes :: R) => exists m'', Mem.storebytes m b ofs bytes = Some m'' /\ ev_elim m'' R m'
| (Alloc b lo hi :: R) => exists m'', Mem.alloc m lo hi = (m'',b) /\ ev_elim m'' R m'
| (Free l :: R) => exists m'', Mem.free_list m l = Some m'' /\ ev_elim m'' R m'
end.
Definition pmax (popt qopt: option permission): option permission :=
match popt, qopt with
_, None => popt
| None, _ => qopt
| Some p, Some q => if Mem.perm_order_dec p q then Some p else Some q
end.
Fixpoint cur_perm (l: block * Z) (T: list mem_event): option permission :=
match T with
nil => None
| (mu :: R) =>
let popt := cur_perm l R in
match mu, l with
| (Read b ofs n bytes), (b',ofs') =>
pmax (if eq_block b b' && zle ofs ofs' && zlt ofs' (ofs+n)
then Some Readable else None) popt
| (Write b ofs bytes), (b',ofs') =>
pmax (if eq_block b b' && zle ofs ofs' && zlt ofs' (ofs+ Zlength bytes)
then Some Writable else None) popt
| (Alloc b lo hi), (b',ofs') =>  (*we don't add a constraint relating lo/hi/ofs*)
if eq_block b b' then None else popt
| (Free l), (b',ofs') =>
List.fold_right (fun tr qopt => match tr with (b,lo,hi) =>
if eq_block b b' && zle lo ofs' && zlt ofs' hi
then Some Freeable else qopt
end)
popt l
end
end.
(** Similar to effect semantics, event semantics augment memory semantics with suitable effects, in the form of a set of memory access traces associated with each internal step of the semantics. *)
Record EvSem {C} :=
{ (** [sem] is a memory semantics. *)
msem :> @MemSem C
(** The step relation of the new semantics. *)
; ev_step: C -> mem -> list mem_event -> C -> mem -> Prop
(** The next four fields axiomatize [drfstep] and its relation to the underlying step relation of [msem]. *)
; ev_step_ax1: forall c m T c' m',
ev_step c m T c' m' ->
corestep msem c m c' m'
; ev_step_ax2: forall c m c' m',
corestep msem c m c' m' ->
exists T, ev_step c m T c' m'
(*  ; ev_step_fun: forall c m T' c' m' T'' c'' m'', ev_step c m T' c' m' -> ev_step c m T'' c'' m'' -> T'=T'' *)
(*  ; ev_step_elim: forall g c m T c' m', ev_step g c m T c' m' -> ev_elim m T m'*)
; ev_step_elim: forall c m T c' m' (STEP: ev_step c m T c' m'),
ev_elim m T m' (*/\
(forall mm mm', ev_elim mm T mm' -> exists cc', ev_step c mm T cc' mm')*)
}.
Definition ev_step_fun {C} (sem: @EvSem C) : Prop :=
forall c m T' c' m' T'' c'' m'',
ev_step sem c m T' c' m' -> ev_step sem c m T'' c'' m'' -> T'=T''.

(** If (b, ofs) is in the list of freed addresses then the permission was Freeable and became None or it was not allocated*)
Lemma ev_elim_free_1 b ofs:
forall ev m m',
ev_elim m ev m' ->
in_free_list_trace b ofs ev ->
(Mem.perm m b ofs Cur Freeable \/
~ Mem.valid_block m b) /\
(Mem.mem_access m') !! b ofs Cur = None /\
Mem.valid_block m' b /\
exists e, List.In e ev /\
match e with
| Free _ => True
| _ => False
end.