Definition access_cohere (m: mem)  (phi: rmap) :=
forall loc,  access_at m loc Cur = perm_of_res (phi @ loc).
Definition max_access_at m loc := access_at m loc Max.
Definition max_access_cohere (m: mem) (phi: rmap)  :=
forall loc,
perm_order'' (max_access_at m loc) (perm_of_res' (phi @ loc)).
(* Definition max_access_cohere (m: mem) (phi: rmap)  := forall loc, match phi @ loc with | YES rsh sh _ _ => perm_order'' (max_access_at m loc) (perm_of_sh rsh (pshare_sh sh)) | NO rsh => perm_order'' (max_access_at m loc) (perm_of_sh rsh Share.bot ) | PURE _ _ => (fst loc < nextblock m)%positive end. *)
Definition alloc_cohere (m: mem) (phi: rmap) :=
forall loc,  (fst loc >= nextblock m)%positive -> phi @ loc = NO Share.bot bot_unreadable.
Inductive juicy_mem: Type :=
mkJuicyMem: forall (m: mem) (phi: rmap)
(JMcontents: contents_cohere m phi)
(JMaccess: access_cohere m phi)
(JMmax_access: max_access_cohere m phi)
(JMalloc: alloc_cohere m phi),
juicy_mem.
Section selectors.
Variable (j: juicy_mem).
Definition m_dry := match j with mkJuicyMem m _ _ _ _ _ => m end.
Definition m_phi := match j with mkJuicyMem _ phi _ _ _ _ => phi end.

(* Specifications: *)
Lemma juicy_mem_contents: contents_cohere m_dry m_phi.
Lemma writable_join_sub: forall loc phi1 phi2,
join_sub phi1 phi2 -> writable loc phi1 -> writable loc phi2.
Lemma writable_inv: forall phi loc, writable loc phi ->
exists sh, exists rsh, exists k, exists pp,
phi @ loc = YES sh rsh k pp /\
writable0_share sh /\
isVAL k.
Lemma nreadable_inv: forall phi loc, ~readable loc phi
-> (exists sh, exists nsh, phi @ loc = NO sh nsh)
\/ (exists sh, exists rsh, exists k, exists pp, phi @ loc = YES sh rsh k pp /\ ~isVAL k)
\/ (exists k, exists pp, phi @ loc = PURE k pp).
Lemma age1_joinx {A}  {JA: Join A}{PA: Perm_alg A}{agA: ageable A}{AgeA: Age_alg A} : forall phi1 phi2 phi3 phi1' phi2' phi3',
age phi1 phi1' -> age phi2 phi2' -> age phi3 phi3' ->
join phi1 phi2 phi3 -> join phi1' phi2' phi3'.
Lemma constructive_age1_join  {A}  {JA: Join A}{PA: Perm_alg A}{agA: ageable A}{AgeA: Age_alg A} : forall x y z x' : A,
join x y z ->
age x x' ->
{ yz' : A*A | join x' (fst yz') (snd yz') /\ age y (fst yz') /\ age z (snd yz')}.
Lemma age1_constructive_joins_eq : forall {A}  {JA: Join A}{PA: Perm_alg A}{agA: ageable A}{AgeA: Age_alg A}  {phi1 phi2},
constructive_joins phi1 phi2
-> forall {phi1'}, age1 phi1 = Some phi1'
-> forall {phi2'}, age1 phi2 = Some phi2'
-> constructive_joins phi1' phi2'.