Set Bullet Behavior "Strict Subproofs".
Instance CompSpecs : compspecs. make_compspecs prog. Defined.
Definition Vprog : varspecs. mk_varspecs prog. Defined.
Definition load_acq_spec := DECLARE _load_acq load_acq_spec.
Definition store_rel_spec := DECLARE _store_rel store_rel_spec.
Definition surely_malloc_spec :=
DECLARE _surely_malloc
WITH n:Z
PRE [ _n OF tuint ]
PROP (0 <= n <= Int.max_unsigned)
LOCAL (temp _n (Vint (Int.repr n)))
SEP ()
POST [ tptr tvoid ] EX p:_,
PROP ()
LOCAL (temp ret_temp p)
SEP (malloc_token Tsh n p * memory_block Tsh n p).
Definition tnode := Tstruct _node noattr.
Definition has_size : {x : Z | x = 8}.
Definition size := proj1_sig has_size.
(* Lexicographic ordering doesn't lead to a PCM (it's not associative), so we keep a full log of values. *)
(* In this example, all the resources held in the protocols are snapshots, so the full and read interpretations are equal. *)
(* This is a bit messy to allow the mutually recursive protocol interpretations. *)
Definition data_T' version version_T s (v : Z) := EX ver : Z, !!(Z.even ver = true /\ log_latest s ver v) &&
protocol_R version (ver - 1) Z.le (version_T, version_T).
Definition version_T_fun version locs g : (Z * Z -> mpred) -> (Z * Z -> mpred) :=
fun R '(s, v) => !!(v = s) && EX L : _,
!!(exists vs, Zlength vs = size /\ log_latest L (if Z.even v then v else v - 1) vs) &&
(if eq_dec v 0 then emp
else fold_right sepcon emp (map (fun i => protocol_R (Znth i locs Vundef) (map_Znth i L 0) map_incl
(data_T' version (fun s v => |>R (s, v)), data_T' version (fun s v => |>R (s, v)))) (upto (Z.to_nat size)))) *
ghost_snap L g.
Definition version_T' version locs g := HORec (version_T_fun version locs g).
Definition version_T version locs g s v := version_T' version locs g (s, v).
Definition data_T version locs g := data_T' version (|>version_T version locs g).

Lemma version_T_eq version locs g s v : version_T version locs g s v = !!(v = s) && EX L : _,
!!(exists vs, Zlength vs = size /\ log_latest L (if Z.even v then v else v - 1) vs) &&
(if eq_dec v 0 then emp
else fold_right sepcon emp (map (fun i => protocol_R (Znth i locs Vundef) (map_Znth i L 0) map_incl
(data_T version locs g, data_T version locs g)) (upto (Z.to_nat size)))) * ghost_snap L g.