Definition FreshDom (j j': meminj) b :=
  match j' b with
     None => false
   | Some(b',z) => match j b with
                     None => true
                   | Some _ => false
                   end
  end.(*So FreshDom in src language is FreshDom j12 j12', equaling
        (not quite, due to unmapped!) DomSrc nu' - DomSrc nu (take DomSrc nu' - DomSrc nu, since
          that has all the unmapped ones, too, to satisfy nu' = sm_compose nu12' nu23'
     FreshDom in mid langauge is FreshDom j23 j23', and
     FreshDom in tgt language is DomTgt nu' - DomTgt nu*)

(*And frgnMid b = (match j23' b with
                        None => false
                      | Some (b',z) => frgnBlocksTgt nu' b' end)*)

Goal forall mu (WD: SM_wd mu) M,
          (forall b ofs, locBlocksSrc mu b = true -> loc_unmapped (pub_of mu) b ofs -> ~M b ofs)
          <-> (forall b, locBlocksSrc mu b = true -> forall ofs, M b ofs -> pubBlocksSrc mu b = true).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).

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' /\ (* Mem.unchanged_on (local_out_of_reach nu23 m2) m3 m3' /\*) exists (nu12' nu23':SM_Injection), nu12' = (convertL nu12 (removeUndefs (as_inj nu12) (as_inj nu') prej12') (*FreshSrc:*) (fun b => andb (DomSrc nu' b) (negb (DomSrc nu12 b))) (*FreshMid:*) (FreshDom (as_inj nu23) j23')) /\ nu23' = (convertR nu23 j23' (*FreshMid:*) (FreshDom (as_inj nu23) j23') (*FreshTgt:*) (fun b => andb (DomTgt nu' b) (negb (DomTgt nu23 b)))) /\ nu'=compose_sm nu12' nu23' /\ extern_incr nu12 nu12' /\ extern_incr nu23 nu23' /\ sm_inject_separated nu12 nu12' m1 m2 /\ sm_inject_separated nu23 nu23' m2 m3 /\ sm_valid nu12' m1' m2' /\ sm_valid nu23' m2' m3' /\ (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)) /\ (forall b1 b2 d1, extern_of nu12' b1 = Some(b2,d1) -> exists b3 d2, extern_of nu23' b2 = Some(b3, d2)) /\ mem_forward m2 m2' /\ Mem.inject (as_inj nu12') m1' m2' /\ Mem.inject (as_inj nu23') m2' m3'.