(*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).

(* Specifications: *)
Lemma local_in_all: forall j (PR:SM_wd j), inject_incr (local_of j) (as_inj j).
Lemma priv_in_all: forall j (PR:SM_wd j), inject_incr (priv_of j) (as_inj j).
Lemma extern_in_all: forall mu, inject_incr (extern_of mu) (as_inj mu).
Lemma unknown_in_all: forall mu, inject_incr (unknown_of mu) (as_inj mu).
Lemma shared_in_all: forall j (PR:SM_wd j), inject_incr (shared_of j) (as_inj j).
Lemma as_injD_None: forall mu b1, as_inj mu b1 = None ->
extern_of mu b1 = None /\
local_of mu b1 = None.
Lemma extern_ofD_None: forall mu b1, extern_of mu b1 = None ->
foreign_of mu b1 = None /\
unknown_of mu b1 = None.
Lemma disjoint_foreign_priv: forall mu (WD: SM_wd mu),
disjoint (foreign_of mu) (priv_of mu).
Lemma disjoint_foreign_local: forall mu (WD: SM_wd mu),
disjoint (foreign_of mu) (local_of mu).
Lemma disjoint_unknown_local: forall mu (WD: SM_wd mu),
disjoint (unknown_of mu) (local_of mu).
Lemma disjoint_unknown_pub: forall mu (WD: SM_wd mu),
disjoint (unknown_of mu) (pub_of mu).
Lemma disjoint_unknown_priv: forall mu (WD: SM_wd mu),
disjoint (unknown_of mu) (priv_of mu).
Lemma disjoint_shared_priv: forall mu (WD: SM_wd mu),
disjoint (shared_of mu) (priv_of mu).
Lemma disjoint_shared_unknown: forall mu (WD: SM_wd mu),
disjoint (shared_of mu) (unknown_of mu).
Lemma as_inj_DomRng: forall mu b1 b2 d, as_inj mu b1 = Some(b2, d) -> SM_wd mu ->
DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma local_locBlocks: forall mu (WD:SM_wd mu)
b1 b2 z (L: local_of mu b1 = Some(b2,z)),
locBlocksSrc mu b1  = true /\ locBlocksTgt mu b2  = true /\
extBlocksSrc mu b1 = false /\ extBlocksTgt mu b2 = false /\
frgnBlocksSrc mu b1 = false /\ frgnBlocksTgt mu b2 = false /\
DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma pub_locBlocks: forall mu (WD:SM_wd mu)
b1 b2 z (L: pub_of mu b1 = Some(b2,z)),
pubBlocksSrc mu b1 = true /\ pubBlocksTgt mu b2 = true /\
locBlocksSrc mu b1 = true /\ locBlocksTgt mu b2 = true /\
extBlocksSrc mu b1 = false /\ extBlocksTgt mu b2 = false /\
frgnBlocksSrc mu b1 = false /\ frgnBlocksTgt mu b2 = false /\
DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma priv_locBlocks: forall mu (WD:SM_wd mu)
b1 b2 z (L: priv_of mu b1 = Some(b2,z)),
pubBlocksSrc mu b1 = false /\
locBlocksSrc mu b1 = true /\ locBlocksTgt mu b2 = true /\
extBlocksSrc mu b1 = false /\ extBlocksTgt mu b2 = false /\
frgnBlocksSrc mu b1 = false /\ frgnBlocksTgt mu b2 = false /\
DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma extern_DomRng': forall mu (WD:SM_wd mu) b1 b2 d
(L:extern_of mu b1 = Some(b2,d)),
pubBlocksSrc mu b1 = false /\ pubBlocksTgt mu b2 = false /\
locBlocksSrc mu b1 = false /\ locBlocksTgt mu b2 = false /\
extBlocksSrc mu b1 = true /\ extBlocksTgt mu b2 = true /\
DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma foreign_DomRng: forall mu (WD:SM_wd mu) b1 b2 d
(L:foreign_of mu b1 = Some(b2,d)),
pubBlocksSrc mu b1 = false /\ pubBlocksTgt mu b2 = false /\
locBlocksSrc mu b1 = false /\ locBlocksTgt mu b2 = false /\
frgnBlocksSrc mu b1 = true /\ frgnBlocksTgt mu b2 = true /\
extBlocksSrc mu b1 = true /\ extBlocksTgt mu b2 = true /\
DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma unknown_DomRng: forall mu (WD:SM_wd mu) b1 b2 d
(L: unknown_of mu b1 = Some(b2,d)),
pubBlocksSrc mu b1 = false /\ pubBlocksTgt mu b2 = false /\
locBlocksSrc mu b1 = false /\ locBlocksTgt mu b2 = false /\
extBlocksSrc mu b1 = true /\ extBlocksTgt mu b2 = true /\
frgnBlocksSrc mu b1 = false /\
DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma local_in_all: forall j (PR:SM_wd j), inject_incr (local_of j) (as_inj j).
Lemma priv_in_all: forall j (PR:SM_wd j), inject_incr (priv_of j) (as_inj j).
Lemma extern_in_all: forall mu, inject_incr (extern_of mu) (as_inj mu).
Lemma unknown_in_all: forall mu, inject_incr (unknown_of mu) (as_inj mu).
Lemma shared_in_all: forall j (PR:SM_wd j), inject_incr (shared_of j) (as_inj j).
Lemma as_injD_None: forall mu b1, as_inj mu b1 = None ->
extern_of mu b1 = None /\
local_of mu b1 = None.
Lemma extern_ofD_None: forall mu b1, extern_of mu b1 = None ->
foreign_of mu b1 = None /\
unknown_of mu b1 = None.
Lemma disjoint_foreign_priv: forall mu (WD: SM_wd mu),
disjoint (foreign_of mu) (priv_of mu).
Lemma disjoint_foreign_local: forall mu (WD: SM_wd mu),
disjoint (foreign_of mu) (local_of mu).
Lemma disjoint_unknown_local: forall mu (WD: SM_wd mu),
disjoint (unknown_of mu) (local_of mu).
Lemma disjoint_unknown_pub: forall mu (WD: SM_wd mu),
disjoint (unknown_of mu) (pub_of mu).
Lemma disjoint_unknown_priv: forall mu (WD: SM_wd mu),
disjoint (unknown_of mu) (priv_of mu).
Lemma disjoint_shared_priv: forall mu (WD: SM_wd mu),
disjoint (shared_of mu) (priv_of mu).
Lemma disjoint_shared_unknown: forall mu (WD: SM_wd mu),
disjoint (shared_of mu) (unknown_of mu).
Lemma as_inj_DomRng: forall mu b1 b2 d, as_inj mu b1 = Some(b2, d) -> SM_wd mu ->
DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma local_locBlocks: forall mu (WD:SM_wd mu)
b1 b2 z (L: local_of mu b1 = Some(b2,z)),
locBlocksSrc mu b1  = true /\ locBlocksTgt mu b2  = true /\
extBlocksSrc mu b1 = false /\ extBlocksTgt mu b2 = false /\
frgnBlocksSrc mu b1 = false /\ frgnBlocksTgt mu b2 = false /\
DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma pub_locBlocks: forall mu (WD:SM_wd mu)
b1 b2 z (L: pub_of mu b1 = Some(b2,z)),
pubBlocksSrc mu b1 = true /\ pubBlocksTgt mu b2 = true /\
locBlocksSrc mu b1 = true /\ locBlocksTgt mu b2 = true /\
extBlocksSrc mu b1 = false /\ extBlocksTgt mu b2 = false /\
frgnBlocksSrc mu b1 = false /\ frgnBlocksTgt mu b2 = false /\
DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma priv_locBlocks: forall mu (WD:SM_wd mu)
b1 b2 z (L: priv_of mu b1 = Some(b2,z)),
pubBlocksSrc mu b1 = false /\
locBlocksSrc mu b1 = true /\ locBlocksTgt mu b2 = true /\
extBlocksSrc mu b1 = false /\ extBlocksTgt mu b2 = false /\
frgnBlocksSrc mu b1 = false /\ frgnBlocksTgt mu b2 = false /\
DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma extern_DomRng': forall mu (WD:SM_wd mu) b1 b2 d
(L:extern_of mu b1 = Some(b2,d)),
pubBlocksSrc mu b1 = false /\ pubBlocksTgt mu b2 = false /\
locBlocksSrc mu b1 = false /\ locBlocksTgt mu b2 = false /\
extBlocksSrc mu b1 = true /\ extBlocksTgt mu b2 = true /\
DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma foreign_DomRng: forall mu (WD:SM_wd mu) b1 b2 d
(L:foreign_of mu b1 = Some(b2,d)),
pubBlocksSrc mu b1 = false /\ pubBlocksTgt mu b2 = false /\
locBlocksSrc mu b1 = false /\ locBlocksTgt mu b2 = false /\
frgnBlocksSrc mu b1 = true /\ frgnBlocksTgt mu b2 = true /\
extBlocksSrc mu b1 = true /\ extBlocksTgt mu b2 = true /\
DomSrc mu b1 = true /\ DomTgt mu b2 = true.
Lemma unknown_DomRng: forall mu (WD:SM_wd mu) b1 b2 d
(L: unknown_of mu b1 = Some(b2,d)),
pubBlocksSrc mu b1 = false /\ pubBlocksTgt mu b2 = false /\
locBlocksSrc mu b1 = false /\ locBlocksTgt mu b2 = false /\
extBlocksSrc mu b1 = true /\ extBlocksTgt mu b2 = true /\
frgnBlocksSrc mu b1 = false /\
DomSrc mu b1 = true /\ DomTgt mu b2 = true.