(*Inserts the new injection entries into extern component, but not into foreign*)
Definition insert_as_extern (mu: SM_Injection) (j: meminj) (DomJ TgtJ:block->bool)
: SM_Injection:=
match mu with
Build_SM_Injection locBSrc locBTgt pSrc pTgt local extBSrc extBTgt fSrc fTgt extern =>
Build_SM_Injection locBSrc locBTgt pSrc pTgt local
(fun b => orb (extBSrc b) (DomJ b))
(fun b => orb (extBTgt b) (TgtJ b))
fSrc
fTgt
(join extern (fun b => match local b with Some _ => None
| None => j b end))
end.
Definition convertL (nu12: SM_Injection) (j12':meminj) FreshSrc FreshMid:=
insert_as_extern nu12 j12' FreshSrc FreshMid.
Definition convertR (nu23: SM_Injection) (j23':meminj) FreshMid FreshTgt:=
insert_as_extern nu23 j23' FreshMid FreshTgt.
Definition AccessEffProperty nu23 nu12 (j12' :meminj) (m1 m1' m2 : mem)
(AM:ZMap.t (Z -> perm_kind -> option permission)):Prop :=
forall b2,
(Mem.valid_block m2 b2 -> forall k ofs2,
if (locBlocksSrc nu23 b2)
then if (pubBlocksSrc nu23 b2)
then match source (local_of nu12) m1 b2 ofs2 with
Some(b1,ofs1) => if pubBlocksSrc nu12 b1
then PMap.get b2 AM ofs2 k =
PMap.get b1 m1'.(Mem.mem_access) ofs1 k
else PMap.get b2 AM ofs2 k =
PMap.get b2 m2.(Mem.mem_access) ofs2 k
| None =>  PMap.get b2 AM ofs2 k =
PMap.get b2 m2.(Mem.mem_access) ofs2 k
end
else PMap.get b2 AM ofs2 k =
PMap.get b2 m2.(Mem.mem_access) ofs2 k
else match source (as_inj nu12) m1 b2 ofs2 with
Some(b1,ofs1) =>  PMap.get b2 AM ofs2 k =
PMap.get b1 m1'.(Mem.mem_access) ofs1 k
| None => match (*j23*) (as_inj nu23) b2 with
None => PMap.get b2 AM ofs2 k  = PMap.get b2 m2.(Mem.mem_access) ofs2 k
| Some (b3,d3) =>  PMap.get b2 AM ofs2 k = None (* mem_interpolation_II.v has PMap.get b2 m2.(Mem.mem_access) ofs2 k here
-- see the comment in the proof script below to see where None is needed*)
end
end)
/\ (~ Mem.valid_block m2 b2 -> forall k ofs2,
match source j12' m1' b2 ofs2 with
Some(b1,ofs1) => PMap.get b2 AM ofs2 k =
PMap.get b1 m1'.(Mem.mem_access) ofs1 k
| None =>  PMap.get b2 AM ofs2 k = None
end).
Definition ContentEffProperty nu23 nu12 (j12':meminj) (m1 m1' m2:Mem.mem)
(CM:ZMap.t (ZMap.t memval)):=
forall b2,
(Mem.valid_block m2 b2 -> forall ofs2,
if locBlocksSrc nu23 b2
then if (pubBlocksSrc nu23 b2)
then match source (local_of nu12) m1 b2 ofs2 with
Some(b1,ofs1) =>
if pubBlocksSrc nu12 b1
then ZMap.get ofs2 (PMap.get b2 CM) =
inject_memval j12'
(ZMap.get ofs1 (PMap.get b1 m1'.(Mem.mem_contents)))
else ZMap.get ofs2 (PMap.get b2 CM) =
ZMap.get ofs2 (PMap.get b2 m2.(Mem.mem_contents))
| None => ZMap.get ofs2 (PMap.get b2 CM) =
ZMap.get ofs2 (PMap.get b2 m2.(Mem.mem_contents))
end
else ZMap.get ofs2 (PMap.get b2 CM) =
ZMap.get ofs2 (PMap.get b2 m2.(Mem.mem_contents))
else match source (as_inj nu12) m1 b2 ofs2 with
Some(b1,ofs1) => ZMap.get ofs2 (PMap.get b2 CM) =
inject_memval j12'
(ZMap.get ofs1 (PMap.get b1 m1'.(Mem.mem_contents)))
| None => ZMap.get ofs2 (PMap.get b2 CM) =
ZMap.get ofs2 (PMap.get b2 m2.(Mem.mem_contents))
end)
/\ (~ Mem.valid_block m2 b2 -> forall ofs2,
match source j12' m1' b2 ofs2 with
None => ZMap.get ofs2 (PMap.get b2 CM) = Undef
| Some(b1,ofs1) =>
ZMap.get ofs2 (PMap.get b2 CM) =
inject_memval j12'
(ZMap.get ofs1 (PMap.get b1 m1'.(Mem.mem_contents)))
end)
/\ fst CM !! b2 = Undef.

Lemma effect_interp_OK: forall m1 m2 nu12
(MInj12 : Mem.inject (as_inj nu12) m1 m2) m1'
(Fwd1: mem_forward m1 m1') nu23 m3
(MInj23 : Mem.inject (as_inj nu23) m2 m3) m3'
(Fwd3: mem_forward m3 m3')
nu' (WDnu' : SM_wd nu')
(SMvalNu' : sm_valid nu' m1' m3')
(MemInjNu' : Mem.inject (as_inj nu') m1' m3')
(ExtIncr: extern_incr (compose_sm nu12 nu23) nu')
(SMInjSep: sm_inject_separated (compose_sm nu12 nu23) nu' m1 m3)
(SMV12: sm_valid nu12 m1 m2)
(SMV23: sm_valid nu23 m2 m3)
(UnchPrivSrc: Mem.unchanged_on (fun b ofs => locBlocksSrc (compose_sm nu12 nu23) b = true /\
pubBlocksSrc (compose_sm nu12 nu23) b = false) m1 m1')
(UnchLOOR13: Mem.unchanged_on (local_out_of_reach (compose_sm nu12 nu23) m1) m3 m3')
(GlueInvNu: SM_wd nu12 /\ SM_wd nu23 /\
locBlocksTgt nu12 = locBlocksSrc nu23 /\
extBlocksTgt nu12 = extBlocksSrc nu23 /\
(forall b, pubBlocksTgt nu12 b = true ->
pubBlocksSrc nu23 b = true) /\
(forall b, frgnBlocksTgt nu12 b = true ->
frgnBlocksSrc nu23 b = true))
(Norm12: forall b1 b2 d1, extern_of  nu12 b1 = Some(b2,d1) ->
exists b3 d2, extern_of nu23 b2 = Some(b3, d2))
prej12' j23' n1' n2'
(HeqMKI: mkInjections m1 m1' m2 (as_inj nu12) (as_inj nu23) (as_inj nu') =
(prej12', j23', n1', n2'))
j12' (Hj12': j12'= removeUndefs (as_inj nu12) (as_inj nu') prej12')
m2'
(NB: m2'.(Mem.nextblock)=n2')
(CONT:  ContentEffProperty nu23 nu12 j12' m1 m1' m2
(m2'.(Mem.mem_contents)))
(ACCESS: AccessEffProperty nu23 nu12 (*(as_inj nu23)*) j12' m1 m1' m2
(m2'.(Mem.mem_access))),
Mem.unchanged_on (fun b ofs => locBlocksSrc nu23 b = true /\
pubBlocksSrc nu23 b = false) m2 m2' /\
Mem.unchanged_on (local_out_of_reach nu12 m1) m2 m2' /\
exists (nu12' nu23':SM_Injection),
nu12'  = (convertL nu12 (removeUndefs (as_inj nu12) (as_inj nu') prej12')
end
else fun ofs2 k =>
match source j12' m1' b2 ofs2 with
Some(b1,ofs1) => PMap.get b1 m1'.(Mem.mem_access) ofs1 k
| None => None
end.