Definition join (j k:meminj):meminj := fun b =>
match j b with
Some (b1, delta) => Some (b1,delta)
| None => k b
end.
Definition disjoint (j k:meminj):Prop :=
forall b, j b = None \/ k b = None.
Definition shared_of (mu: SM_Injection) : meminj :=
join (foreign_of mu) (pub_of mu).
Record SM_wd (mu:SM_Injection):Prop := {
disjoint_extern_local_Src: forall b, locBlocksSrc mu b = false \/ extBlocksSrc mu b = false;
disjoint_extern_local_Tgt: forall b, locBlocksTgt mu b = false \/ extBlocksTgt mu b = false;
local_DomRng: forall b1 b2 z, local_of mu b1 = Some(b2,z) ->
(locBlocksSrc mu b1 = true /\ locBlocksTgt mu b2 = true);
extern_DomRng: forall b1 b2 z, extern_of mu b1 = Some(b2,z) ->
(extBlocksSrc mu b1 = true /\ extBlocksTgt mu b2 = true);
pubSrcAx: forall b1, pubBlocksSrc mu b1 = true ->
exists b2 z, local_of mu b1 = Some(b2,z) /\
pubBlocksTgt mu b2 = true;
frgnSrcAx: forall b1, frgnBlocksSrc mu b1 = true ->
exists b2 z, extern_of mu b1 = Some(b2,z) /\
frgnBlocksTgt mu b2 = true;
pubBlocksLocalTgt: forall b, pubBlocksTgt mu b = true ->
locBlocksTgt mu b = true;
frgnBlocksExternTgt: forall b, frgnBlocksTgt mu b = true ->
extBlocksTgt mu b = true
}.
(*DOM/RNG: all blocks mentioned by a SM_Injection. Used for stating match_validblocks etc*)
Definition DomSrc (mu: SM_Injection) (b1: block): bool :=
locBlocksSrc mu b1 || extBlocksSrc mu b1.
Definition DOM (mu: SM_Injection) (b1: block): Prop := DomSrc mu b1 = true.
Definition DomTgt (mu: SM_Injection) (b2: block): bool :=
locBlocksTgt mu b2 || extBlocksTgt mu b2.
Definition RNG (mu: SM_Injection) (b2:block): Prop := DomTgt mu b2 = true.
(*we enforce pub_of mu = pub_of mu', via pubBlocksSrc/Tgt mu = pubBlocksSrc/Tgt mu': it suffices to reclassify leakage at at/afterExternal. This enables the proof of effect_corediagram_trans.diagram_injinj etc*)
Definition intern_incr (mu mu': SM_Injection): Prop :=
inject_incr (local_of mu) (local_of mu') /\
(extern_of mu = extern_of mu') /\
(forall b, locBlocksSrc mu b = true -> locBlocksSrc mu' b = true) /\
(forall b, locBlocksTgt mu b = true -> locBlocksTgt mu' b = true) /\
(pubBlocksSrc mu = pubBlocksSrc mu') /\
(pubBlocksTgt mu = pubBlocksTgt mu') /\
(frgnBlocksSrc mu = frgnBlocksSrc mu') /\
(frgnBlocksTgt mu = frgnBlocksTgt mu') /\
(extBlocksSrc mu = extBlocksSrc mu') /\
(extBlocksTgt mu = extBlocksTgt mu').
Definition extern_incr (mu mu': SM_Injection): Prop :=
inject_incr (extern_of mu) (extern_of mu') /\
(local_of mu = local_of mu') /\
(forall b, extBlocksSrc mu b = true -> extBlocksSrc mu' b = true) /\
(forall b, extBlocksTgt mu b = true -> extBlocksTgt mu' b = true) /\
(locBlocksSrc mu = locBlocksSrc mu') /\
(locBlocksTgt mu = locBlocksTgt mu') /\
(pubBlocksSrc mu = pubBlocksSrc mu') /\
(pubBlocksTgt mu = pubBlocksTgt mu') /\
(frgnBlocksSrc mu = frgnBlocksSrc mu') /\
(frgnBlocksTgt mu = frgnBlocksTgt mu').
(*The join of all four components - useful for stating match_state conditions*)
Definition as_inj (mu: SM_Injection) : meminj :=
join (extern_of mu) (local_of mu).
Definition locvisible_of mu := join (foreign_of mu) (local_of mu) .
Definition extvisible_of mu := join (extern_of mu) (pub_of mu).
(*an inject_separated-like property wrt DOM/RNG instead of wrt validity in suitable memories*)
Definition sm_inject_separated (mu mu' : SM_Injection) (m1 m2:mem):Prop :=
(forall b1 b2 d, as_inj mu b1 = None -> as_inj mu' b1 = Some(b2,d) ->
(DomSrc mu b1 = false /\ DomTgt mu b2 = false)) /\
(forall b1, DomSrc mu b1 = false -> DomSrc mu' b1 = true -> ~Mem.valid_block m1 b1) /\
(forall b2, DomTgt mu b2 = false -> DomTgt mu' b2 = true -> ~Mem.valid_block m2 b2).
Definition freshloc m m' b := andb (valid_block_dec m' b) (negb (valid_block_dec m b)).

Lemma freshloc_irrefl: forall m b, freshloc m m b = false.
Lemma freshloc_trans: forall m m'' m' b
(FWD: mem_forward m m'') (FWD': mem_forward m'' m'),
(orb (freshloc m m'' b) (freshloc m'' m' b)) = freshloc m m' b.