Inductive add_events h : list hist_el -> hist -> Prop :=
| add_events_nil : add_events h [] h
| add_events_snoc : forall le h' t e (Hh' : add_events h le h') (Ht : newer h' t),
add_events h (le ++ [e]) (h' ++ [(t, e)]).
Hint Resolve add_events_nil.

(* Specifications: *)
Lemma add_events_1 : forall h t e (Ht : newer h t), add_events h [e] (h ++ [(t, e)]).
Lemma add_events_trans : forall h le h' le' h'' (H1 : add_events h le h') (H2 : add_events h' le' h''),
add_events h (le ++ le') h''.
Lemma add_events_add : forall h le h', add_events h le h' -> exists h2, h' = h ++ h2 /\ map snd h2 = le.
Corollary add_events_snd : forall h le h', add_events h le h' -> map snd h' = map snd h ++ le.
Corollary add_events_incl : forall h le h', add_events h le h' -> incl h h'.
Corollary add_events_newer : forall h le h' t, add_events h le h' -> newer h' t -> newer h t.
Lemma add_events_in : forall h le h' e, add_events h le h' -> In e le -> exists t, newer h t /\ In (t, e) h'.
Lemma add_events_ordered : forall h le h', add_events h le h' -> ordered_hist h -> ordered_hist h'.
Lemma add_events_last : forall h le h', add_events h le h' -> le <> [] ->
value_of_hist h' = value_of (last le (Store (vint 0))).
Lemma add_events_NoDup : forall h le h', add_events h le h' -> NoDup (map fst h) -> NoDup (map fst h').
Notation AL_witness sh p g R h P Q :=
(sh%logic, p%logic, (ghost_hist sh h g * P)%logic, hist_R g%logic R,
EX h' : hist, fun v => !!(add_events h [Load v] h') && ghost_hist sh h' g * Q v).
(* FCSL takes the approach that h is always empty, and the previous history is framed out and then combined with the new event by hist join. We can do that, but whether it's preferable might be a matter of taste. *)
Lemma AL_hist_spec : forall sh g R h P Q
(HPQR : forall h' v (Hhist : hist_incl h h'), apply_hist (vint 0) h' = Some v ->
view_shift (valid (R h') v * P) (valid (R (h' ++ [Load v])) v * Q v)) (Hsh : sh <> Share.bot),
AL_spec (ghost_hist sh h g * P) (hist_R g R)
(EX h' : hist, fun v => !!(add_events h [Load v] h') && ghost_hist sh h' g * Q v).
Lemma add_events_1 : forall h t e (Ht : newer h t), add_events h [e] (h ++ [(t, e)]).
Lemma add_events_trans : forall h le h' le' h'' (H1 : add_events h le h') (H2 : add_events h' le' h''),
add_events h (le ++ le') h''.
Lemma add_events_add : forall h le h', add_events h le h' -> exists h2, h' = h ++ h2 /\ map snd h2 = le.
Corollary add_events_snd : forall h le h', add_events h le h' -> map snd h' = map snd h ++ le.
Corollary add_events_incl : forall h le h', add_events h le h' -> incl h h'.
Corollary add_events_newer : forall h le h' t, add_events h le h' -> newer h' t -> newer h t.
Lemma add_events_in : forall h le h' e, add_events h le h' -> In e le -> exists t, newer h t /\ In (t, e) h'.
Lemma add_events_ordered : forall h le h', add_events h le h' -> ordered_hist h -> ordered_hist h'.
Lemma add_events_last : forall h le h', add_events h le h' -> le <> [] ->
value_of_hist h' = value_of (last le (Store (vint 0))).
Lemma add_events_NoDup : forall h le h', add_events h le h' -> NoDup (map fst h) -> NoDup (map fst h').
Notation AL_witness sh p g i R h P Q :=
(sh%logic, p%logic, (ghost_hist sh h g * P)%logic, hist_R g%logic i R,
EX h' : hist, fun v => !!(add_events h [Load (vint v)] h') && ghost_hist sh h' g * Q v).
(* FCSL takes the approach that h is always empty, and the previous history is framed out and then combined with the new event by hist join. We can do that, but whether it's preferable might be a matter of taste. *)
Lemma AL_hist_spec : forall sh g i R h P Q
(HPQR : forall h' v (Hhist : hist_incl h h'), apply_hist (vint i) h' = Some (vint v) -> repable_signed v ->
view_shift (R h' v * P) (R (h' ++ [Load (vint v)]) v * Q v)) (Hsh : sh <> Share.bot),
AL_spec (ghost_hist sh h g * P) (hist_R g i R)
(EX h' : hist, fun v => !!(add_events h [Load (vint v)] h') && ghost_hist sh h' g * Q v).