Definition AccessMap_EE_Property  (m1 m1' m2:Mem.mem)
(AM:ZMap.t (Z -> perm_kind -> option permission)):Prop :=
forall b,
(Mem.valid_block m2 b -> forall k ofs,
(Mem.perm m1 b ofs Max Nonempty ->
PMap.get b AM ofs k = PMap.get b m1'.(Mem.mem_access) ofs k) /\
(~Mem.perm m1 b ofs Max Nonempty ->
PMap.get b AM ofs k = PMap.get b m2.(Mem.mem_access) ofs k))
/\ (~ Mem.valid_block m2 b -> forall k ofs,
PMap.get b AM ofs k = PMap.get b m1'.(Mem.mem_access) ofs k).
Definition Content_EE_Property
(m1 m1' m2:Mem.mem) (CM:ZMap.t (ZMap.t memval)):=
forall b,
(Mem.valid_block m2 b -> forall ofs,
(Mem.perm m1 b ofs Max Nonempty ->
ZMap.get ofs (PMap.get b CM) =
ZMap.get ofs (PMap.get b m1'.(Mem.mem_contents))) /\
(~Mem.perm m1 b ofs Max Nonempty ->
ZMap.get ofs (PMap.get b CM) =
ZMap.get ofs (PMap.get b m2.(Mem.mem_contents))))
/\ (~ Mem.valid_block m2 b -> forall (HM1': Mem.valid_block m1' b) ofs,
ZMap.get ofs (PMap.get b CM) =
ZMap.get ofs (PMap.get b m1'.(Mem.mem_contents)))
/\ fst CM !! b = Undef.
Definition AccessMap_EE_FUN'  (m1 m1' m2:Mem.mem) (b:block):
Z -> perm_kind -> option permission :=
if plt b (Mem.nextblock m1')
then
if plt b (Mem.nextblock m2)
then (fun ofs k =>
if Mem.perm_dec m1 b ofs Max Nonempty
then PMap.get b m1'.(Mem.mem_access) ofs k
else PMap.get b m2.(Mem.mem_access) ofs k)
else PMap.get b m1'.(Mem.mem_access)
else (fun ofs k => None).
Definition AccessMap_EE_FUN  (m1 m1' m2:Mem.mem) (b:block):
Z -> perm_kind -> option permission :=
if plt b (Mem.nextblock m2)
then (fun ofs k =>
if Mem.perm_dec m1 b ofs Max Nonempty
then PMap.get b m1'.(Mem.mem_access) ofs k
else PMap.get b m2.(Mem.mem_access) ofs k)
else PMap.get b m1'.(Mem.mem_access).
Definition ContentMap_EE_ValidBlock_FUN m1 m1' m2 b ofs: memval :=
if Mem.perm_dec m1 b ofs Max Nonempty
then ZMap.get ofs (PMap.get b m1'.(Mem.mem_contents))
else ZMap.get ofs (PMap.get b m2.(Mem.mem_contents)).
Definition ContentMap_EE_InvalidBlock_FUN m1' b ofs: memval:=
ZMap.get ofs (PMap.get b m1'.(Mem.mem_contents)).
Definition ContentMap_EE_Block_FUN m1 m1' m2 b ofs : memval:=
if plt b (Mem.nextblock m2)
then ContentMap_EE_ValidBlock_FUN m1 m1' m2 b ofs
else ContentMap_EE_InvalidBlock_FUN m1' b ofs.
Definition ContentsMap_EE_FUN  (m1 m1' m2:Mem.mem) (b:block):
ZMap.t memval.
destruct (plt b (Mem.nextblock m1')).
apply(CM_block_EE_existsT m1 m1' m2 b).
apply (ZMap.init Undef).
Defined.
Definition mkEE (m1 m1' m2 m3 m3':Mem.mem) (Ext12: Mem.extends m1 m2)
(Fwd1: mem_forward m1 m1')
(Ext23: Mem.extends m2 m3) (Fwd3: mem_forward m3 m3')
(Ext13' : Mem.extends m1' m3')
(UnchOn3: Mem.unchanged_on (loc_out_of_bounds m1) m3 m3')
: Mem.mem'.
destruct (mkAccessMap_EE_existsT m1 m1' m2) as [AM [ADefault PAM]].
destruct (ContentsMap_EE_existsT m1 m1' m2) as [CM [CDefault PCM]].
eapply Mem.mkmem with (nextblock:=m3'.(Mem.nextblock))
(mem_access:=AM)
(mem_contents:=CM).
(* (NB: forall b, Mem.valid_block m2 b -> Mem.valid_block m3' b)*)
(*  apply (mkContentsMap_EE_exists m1 m1' m2).*)
(*eapply Mem.mkmem with (nextblock:=m3'.(Mem.nextblock)) (mem_access:=(Mem.mem_access m2')).*)
(*  apply m3'.*)
(*access_max*)
intros. rewrite PAM. unfold AccessMap_EE_FUN'.
destruct (plt b (Mem.nextblock m1')).
remember (plt b m2.(Mem.nextblock)) as z.
destruct z as [z|z]; clear Heqz.
(*Case valid*) (*clear Inval. specialize (Val z). destruct (Val Max ofs) as [MaxA MaxB]. destruct (Val Cur ofs) as [CurA CurB]. clear Val.*)
remember (Mem.perm_dec m1 b ofs Max Nonempty) as zz.
destruct zz; clear Heqzz. apply m1'. apply m2.
(*Case invalid*) apply m1'. reflexivity. (*nextblock_noaccess*)
intros. rewrite PAM.
unfold AccessMap_EE_FUN'.
destruct (plt b (Mem.nextblock m1')).
exfalso. apply H; clear - Ext13' p.
destruct Ext13'. rewrite <- mext_next. apply p.
trivial.
(*Default*)
intros. simpl. rewrite PCM.
unfold ContentsMap_EE_FUN.
destruct (plt b (Mem.nextblock m1')).
remember (CM_block_EE_existsT m1 m1' m2 b).
destruct s. apply a.
reflexivity.
Defined.

Lemma interpolate_EE: forall m1 m2 (Ext12: Mem.extends m1 m2) m1'
(Fwd1: mem_forward m1 m1') m3 (Ext23: Mem.extends m2 m3) m3'
(Fwd3: mem_forward m3 m3') (Ext13' : Mem.extends m1' m3')
(UnchOn3: Mem.unchanged_on (loc_out_of_bounds m1) m3 m3'),
exists m2', mem_forward m2 m2' /\ Mem.extends m1' m2' /\
Mem.extends m2' m3' /\
Mem.unchanged_on (loc_out_of_bounds m1) m2 m2'.