Program Definition age1_juicy_mem (j: juicy_mem): option juicy_mem :=
match age1 (m_phi j) with
| Some phi' => Some (mkJuicyMem (m_dry j) phi' _ _ _ _)
| None => None
end.
Next Obligation.  (* contents_cohere *)
assert (necR (m_phi j) phi')
by (constructor 1; symmetry in Heq_anonymous; apply Heq_anonymous).
destruct j; hnf; simpl in *; intros.
case_eq (phi @ loc); intros.
apply (necR_NO _ _ _ _ _ H) in H1. congruence.
generalize (necR_YES _ _ _ _ _ _ _ H H1); intros.
rewrite H0 in H2. inv H2.
destruct (JMcontents sh0 r v loc _ H1). subst; split; auto.
rewrite (necR_PURE _ _ _ _ _ H H1) in H0. inv H0.
Qed.
Next Obligation. (* access_cohere *)
assert (necR (m_phi j) phi')
by (constructor 1; symmetry in Heq_anonymous; apply Heq_anonymous).
destruct j; hnf; simpl in *; intros.
generalize (JMaccess loc); case_eq (phi @ loc); intros.
apply (necR_NO _ _ loc _ _ H) in H0. rewrite H0; auto.
rewrite (necR_YES _ _ _ _ _ _ _ H H0); auto.
rewrite (necR_PURE _ _ _ _ _ H H0); auto.
Qed.
Next Obligation. (* max_access_cohere *)
assert (necR (m_phi j) phi')
by (constructor 1; symmetry in Heq_anonymous; apply Heq_anonymous).
destruct j; hnf; simpl in *; intros.
generalize (JMmax_access loc); case_eq (phi @ loc); intros.
apply (necR_NO _ _ loc _ _ H) in H0. rewrite H0; auto.
rewrite (necR_YES _ _ _ _ _ _ _ H H0); auto.
rewrite (necR_PURE _ _ _ _ _ H H0); auto.
Qed.
Next Obligation. (* alloc_cohere *)
assert (necR (m_phi j) phi')
by (constructor 1; symmetry in Heq_anonymous; apply Heq_anonymous).
destruct j; hnf; simpl in *; intros.
specialize (JMalloc loc H0).
apply (necR_NO _ _ loc _ _ H). auto.
Qed.

(* Specifications: *)
Lemma age1_juicy_mem_unpack: forall j j',
age1_juicy_mem j = Some j' ->
age (m_phi j)  (m_phi j')
/\ m_dry j = m_dry j'.
Lemma age1_juicy_mem_unpack': forall j j',
age (m_phi j)  (m_phi j')  /\ m_dry j = m_dry j' ->
age1_juicy_mem j = Some j'.
Lemma age1_juicy_mem_unpack'': forall j j',
age (m_phi j)  (m_phi j')  -> m_dry j = m_dry j' ->
age1_juicy_mem j = Some j'.
(* TODO: move into rmaps_lemmas *)
Lemma rmap_join_eq_level: forall phi1 phi2: rmap, joins phi1 phi2 -> level phi1 = level phi2.
Lemma rmap_join_sub_eq_level: forall phi1 phi2: rmap,
join_sub phi1 phi2 -> level phi1 = level phi2.
Lemma age1_juicy_mem_None1:
forall j, age1_juicy_mem j = None -> age1 (m_phi j) = None.
Lemma age1_juicy_mem_None2:
forall j, age1 (m_phi j) = None -> age1_juicy_mem j = None.
Lemma age1_juicy_mem_Some:
forall j j', age1_juicy_mem j = Some j' -> age1 (m_phi j) = Some (m_phi j').
Lemma unage_juicy_mem: forall j' : juicy_mem,
exists j : juicy_mem, age1_juicy_mem j = Some j'.
Lemma level1_juicy_mem: forall j: juicy_mem,
age1_juicy_mem j = None <-> level (m_phi j) = 0%nat.
Lemma level2_juicy_mem: forall j1 j2: juicy_mem,
age1_juicy_mem j1 = Some j2 -> level (m_phi j1) = S (level (m_phi j2)).
Lemma juicy_mem_ageable_facts: ageable_facts juicy_mem (fun j => level (m_phi j)) age1_juicy_mem.
Instance juicy_mem_ageable: ageable juicy_mem :=
mkAgeable _ (fun j => level (m_phi j)) age1_juicy_mem juicy_mem_ageable_facts.
Lemma level_juice_level_phi: forall (j: juicy_mem), level j = level (m_phi j).
Lemma unage_writable: forall (phi phi': rmap) loc,
age phi phi' -> writable loc phi' -> writable loc phi.
Lemma unage_readable: forall (phi phi': rmap) loc,
age phi phi' -> readable loc phi' -> readable loc phi.
Lemma readable_inv: forall phi loc, readable loc phi ->
exists rsh, exists sh, exists v, exists pp, phi @ loc = YES rsh sh (VAL v) pp.