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.

(* Specifications: *)
Lemma join_assoc: forall f g h, join f (join g h) = join (join f g) h.
Lemma join_com: forall f g, disjoint f g -> join f g = join g f.
Lemma disjoint_com: forall f g, disjoint f g <-> disjoint g f.
Lemma disjoint_sub: forall j k (D: disjoint j k) j' k'
(J: inject_incr j' j) (K:inject_incr k' k),
disjoint j' k'.
Lemma joinI: forall f g b p
(Hp: f b = Some p \/ (f b = None /\ g b = Some p)),
join f g b = Some p.
Lemma joinD: forall j k (D: disjoint j k) b,
match join j k b with
Some(b1,delta) => (j b = Some(b1,delta) /\ k b = None) \/
(k b = Some(b1,delta) /\ j b = None)
| None => j b = None /\ k b = None
end.
Lemma joinD_Some:
forall j k b b' delta (J: join j k b = Some(b',delta)),
j b = Some(b',delta) \/ (j b = None /\ k b = Some(b',delta)).
Lemma joinD_None:
forall j k b (J: join j k b = None),
j b = None /\ k b = None.
Lemma joinI_None: forall j k b (J:j b = None) (K:k b = None),
join j k b = None.
Lemma inject_incr_join: forall j j' k k'
(J: inject_incr j j') (K: inject_incr k k')
(D: disjoint j' k'),
inject_incr (join j k) (join j' k').
Lemma join_incr_left: forall j k, inject_incr j (join j k).
Lemma join_incr_right: forall j k (D:disjoint j k),
inject_incr k (join j k).
Lemma disjointD_left:
forall j k b b' delta (J: j b = Some (b',delta))
(D:disjoint j k), k b = None.
Lemma disjointD_right:
forall j k b b' delta (K: k b = Some (b',delta))
(D:disjoint j k), j b = None.
Lemma join_left_agree:
forall j k b b1 d1 (JK: join j k b = Some(b1,d1))
b2 d2 (J: j b = Some(b2,d2)),
b1=b2 /\ d1=d2.
Lemma join_right_agree:
forall j k b b1 d1 (JK: join j k b = Some(b1,d1))
b2 d2 (K: k b = Some(b2,d2)) (D:disjoint j k),
b1=b2 /\ d1=d2.
Lemma join_disjoint: forall f g h (FH: disjoint f h) (GH: disjoint g h),
disjoint (join f g) h.
Lemma join_None_rightneutral: forall j, join j (fun b => None) = j.
Lemma join_None_leftneutral: forall j, join (fun b => None) j = j.
Definition shared_of (mu: SM_Injection) : meminj :=
join (foreign_of mu) (pub_of mu).
Lemma unknown_in_extern: forall mu,
inject_incr (unknown_of mu) (extern_of mu).
Lemma foreign_in_extern: forall mu,
inject_incr (foreign_of mu) (extern_of mu).
Lemma foreign_in_shared: forall mu,
inject_incr (foreign_of mu) (shared_of mu).
Lemma priv_in_local: forall mu,
inject_incr (priv_of mu) (local_of mu).
Lemma disjoint_pub_priv: forall mu, disjoint (pub_of mu) (priv_of mu).
Lemma disjoint_frgn_unknown: forall mu, disjoint (foreign_of mu) (unknown_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
}.
Lemma pubSrc: forall mu (WD: SM_wd mu) b1, pubBlocksSrc mu b1 = true ->
exists b2 z, pub_of mu b1 = Some(b2,z) /\
pubBlocksTgt mu b2 = true.
Lemma frgnSrc: forall mu (WD: SM_wd mu) b1, frgnBlocksSrc mu b1 = true ->
exists b2 z, foreign_of mu b1 = Some(b2,z) /\
frgnBlocksTgt mu b2 = true.
Lemma extBlocksSrc_locBlocksSrc: forall mu (WD: SM_wd mu) b,
extBlocksSrc mu b = true -> locBlocksSrc mu b = false.
Lemma extBlocksTgt_locBlocksTgt: forall mu (WD: SM_wd mu) b,
extBlocksTgt mu b = true -> locBlocksTgt mu b = false.
Lemma locBlocksSrc_extBlocksSrc: forall mu (WD: SM_wd mu) b,
locBlocksSrc mu b = true -> extBlocksSrc mu b = false.
Lemma locBlocksTgt_extBlocksTgt: forall mu (WD: SM_wd mu) b,
locBlocksTgt mu b = true -> extBlocksTgt mu b = false.
Lemma pubBlocksLocalSrc: forall mu (WD: SM_wd mu) b,
pubBlocksSrc mu b = true -> locBlocksSrc mu b = true.
Lemma frgnBlocksSrc_extBlocksSrc: forall mu (WD: SM_wd mu) b,
frgnBlocksSrc mu b = true -> extBlocksSrc mu b = true.
Lemma locBlocksSrc_externNone: forall mu (WD:SM_wd mu) b
(MB: locBlocksSrc mu b = true), extern_of mu b = None.
Lemma locBlocksSrc_foreignNone: forall mu (WD:SM_wd mu) b
(MB: locBlocksSrc mu b = true), foreign_of mu b = None.
Lemma frgnBlocksSrc_locBlocksSrc: forall mu (WD:SM_wd mu) b
(FB: frgnBlocksSrc mu b = true), locBlocksSrc mu b = false.
Lemma locBlocksSrc_frgnBlocksSrc: forall mu (WD:SM_wd mu) b
(MB: locBlocksSrc mu b = true), frgnBlocksSrc mu b = false.
Lemma locBlocksTgt_frgnBlocksTgt: forall mu (WD:SM_wd mu) b
(MB: locBlocksTgt mu b = true), frgnBlocksTgt mu b = false.
Lemma frgnBlocksTgt_locBlocksTgt: forall mu (WD:SM_wd mu) b
(FB: frgnBlocksTgt mu b = true), locBlocksTgt mu b = false.
Lemma locBlocksTgt_frgnBlocksTgt_D: forall mu (WD:SM_wd mu) b
(MB: locBlocksTgt mu b = true) (FB: frgnBlocksTgt mu b = true),
False.
Lemma locBlocksSrc_unknownNone: forall mu (WD:SM_wd mu) b
(MB: locBlocksSrc mu b = true), unknown_of mu b = None.
Lemma extern_foreignunknown: forall mu (WD: SM_wd mu),
extern_of mu = join (foreign_of mu) (unknown_of mu).
Lemma pubChar: forall mu (WD: SM_wd mu) b1 b2 z, pub_of mu b1 = Some(b2,z) ->
pubBlocksSrc mu b1 = true /\ pubBlocksTgt mu b2 = true.
Lemma privChar: forall mu b1 b2 z, priv_of mu b1 = Some(b2,z) ->
pubBlocksSrc mu b1 = false.
Lemma pubSrcContra: forall mu b1,
pubBlocksSrc mu b1 = false -> pub_of mu b1 = None.
Lemma pubTgtContra: forall mu (WD: SM_wd mu) b2, pubBlocksTgt mu b2 = false ->
~ exists b1 d, pub_of mu b1 = Some(b2,d).
Lemma disjoint_extern_local: forall mu (WD: SM_wd mu),
disjoint (extern_of mu) (local_of mu).
Lemma disjoint_foreign_pub: forall mu (WD: SM_wd mu),
disjoint (foreign_of mu) (pub_of mu).
Lemma pub_in_shared: forall mu (WD: SM_wd mu),
inject_incr (pub_of mu) (shared_of mu).
Lemma join_assoc: forall f g h, join f (join g h) = join (join f g) h.
Lemma join_com: forall f g, disjoint f g -> join f g = join g f.
Lemma disjoint_com: forall f g, disjoint f g <-> disjoint g f.
Lemma disjoint_sub: forall j k (D: disjoint j k) j' k'
(J: inject_incr j' j) (K:inject_incr k' k),
disjoint j' k'.
Lemma joinI: forall f g b p
(Hp: f b = Some p \/ (f b = None /\ g b = Some p)),
join f g b = Some p.
Lemma joinD: forall j k (D: disjoint j k) b,
match join j k b with
Some(b1,delta) => (j b = Some(b1,delta) /\ k b = None) \/
(k b = Some(b1,delta) /\ j b = None)
| None => j b = None /\ k b = None
end.
Lemma joinD_Some:
forall j k b b' delta (J: join j k b = Some(b',delta)),
j b = Some(b',delta) \/ (j b = None /\ k b = Some(b',delta)).
Lemma joinD_None:
forall j k b (J: join j k b = None),
j b = None /\ k b = None.
Lemma joinI_None: forall j k b (J:j b = None) (K:k b = None),
join j k b = None.
Lemma inject_incr_join: forall j j' k k'
(J: inject_incr j j') (K: inject_incr k k')
(D: disjoint j' k'),
inject_incr (join j k) (join j' k').
Lemma join_incr_left: forall j k, inject_incr j (join j k).
Lemma join_incr_right: forall j k (D:disjoint j k),
inject_incr k (join j k).
Lemma disjointD_left:
forall j k b b' delta (J: j b = Some (b',delta))
(D:disjoint j k), k b = None.
Lemma disjointD_right:
forall j k b b' delta (K: k b = Some (b',delta))
(D:disjoint j k), j b = None.
Lemma join_left_agree:
forall j k b b1 d1 (JK: join j k b = Some(b1,d1))
b2 d2 (J: j b = Some(b2,d2)),
b1=b2 /\ d1=d2.
Lemma join_right_agree:
forall j k b b1 d1 (JK: join j k b = Some(b1,d1))
b2 d2 (K: k b = Some(b2,d2)) (D:disjoint j k),
b1=b2 /\ d1=d2.
Lemma join_disjoint: forall f g h (FH: disjoint f h) (GH: disjoint g h),
disjoint (join f g) h.
Lemma join_None_rightneutral: forall j, join j (fun b => None) = j.
Lemma join_None_leftneutral: forall j, join (fun b => None) j = j.
Definition shared_of (mu: SM_Injection) : meminj :=
join (foreign_of mu) (pub_of mu).
Lemma unknown_in_extern: forall mu,
inject_incr (unknown_of mu) (extern_of mu).
Lemma foreign_in_extern: forall mu,
inject_incr (foreign_of mu) (extern_of mu).
Lemma foreign_in_shared: forall mu,
inject_incr (foreign_of mu) (shared_of mu).
Lemma priv_in_local: forall mu,
inject_incr (priv_of mu) (local_of mu).
Lemma disjoint_pub_priv: forall mu, disjoint (pub_of mu) (priv_of mu).
Lemma disjoint_frgn_unknown: forall mu, disjoint (foreign_of mu) (unknown_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
}.
Lemma pubSrc: forall mu (WD: SM_wd mu) b1, pubBlocksSrc mu b1 = true ->
exists b2 z, pub_of mu b1 = Some(b2,z) /\
pubBlocksTgt mu b2 = true.
Lemma frgnSrc: forall mu (WD: SM_wd mu) b1, frgnBlocksSrc mu b1 = true ->
exists b2 z, foreign_of mu b1 = Some(b2,z) /\
frgnBlocksTgt mu b2 = true.
Lemma extBlocksSrc_locBlocksSrc: forall mu (WD: SM_wd mu) b,
extBlocksSrc mu b = true -> locBlocksSrc mu b = false.
Lemma extBlocksTgt_locBlocksTgt: forall mu (WD: SM_wd mu) b,
extBlocksTgt mu b = true -> locBlocksTgt mu b = false.
Lemma locBlocksSrc_extBlocksSrc: forall mu (WD: SM_wd mu) b,
locBlocksSrc mu b = true -> extBlocksSrc mu b = false.
Lemma locBlocksTgt_extBlocksTgt: forall mu (WD: SM_wd mu) b,
locBlocksTgt mu b = true -> extBlocksTgt mu b = false.
Lemma pubBlocksLocalSrc: forall mu (WD: SM_wd mu) b,
pubBlocksSrc mu b = true -> locBlocksSrc mu b = true.
Lemma frgnBlocksSrc_extBlocksSrc: forall mu (WD: SM_wd mu) b,
frgnBlocksSrc mu b = true -> extBlocksSrc mu b = true.
Lemma locBlocksSrc_externNone: forall mu (WD:SM_wd mu) b
(MB: locBlocksSrc mu b = true), extern_of mu b = None.
Lemma locBlocksSrc_foreignNone: forall mu (WD:SM_wd mu) b
(MB: locBlocksSrc mu b = true), foreign_of mu b = None.
Lemma frgnBlocksSrc_locBlocksSrc: forall mu (WD:SM_wd mu) b
(FB: frgnBlocksSrc mu b = true), locBlocksSrc mu b = false.
Lemma locBlocksSrc_frgnBlocksSrc: forall mu (WD:SM_wd mu) b
(MB: locBlocksSrc mu b = true), frgnBlocksSrc mu b = false.
Lemma locBlocksTgt_frgnBlocksTgt: forall mu (WD:SM_wd mu) b
(MB: locBlocksTgt mu b = true), frgnBlocksTgt mu b = false.
Lemma frgnBlocksTgt_locBlocksTgt: forall mu (WD:SM_wd mu) b
(FB: frgnBlocksTgt mu b = true), locBlocksTgt mu b = false.
Lemma locBlocksTgt_frgnBlocksTgt_D: forall mu (WD:SM_wd mu) b
(MB: locBlocksTgt mu b = true) (FB: frgnBlocksTgt mu b = true),
False.
Lemma locBlocksSrc_unknownNone: forall mu (WD:SM_wd mu) b
(MB: locBlocksSrc mu b = true), unknown_of mu b = None.
Lemma extern_foreignunknown: forall mu (WD: SM_wd mu),
extern_of mu = join (foreign_of mu) (unknown_of mu).
Lemma pubChar: forall mu (WD: SM_wd mu) b1 b2 z, pub_of mu b1 = Some(b2,z) ->
pubBlocksSrc mu b1 = true /\ pubBlocksTgt mu b2 = true.
Lemma privChar: forall mu b1 b2 z, priv_of mu b1 = Some(b2,z) ->
pubBlocksSrc mu b1 = false.
Lemma pubSrcContra: forall mu b1,
pubBlocksSrc mu b1 = false -> pub_of mu b1 = None.
Lemma pubTgtContra: forall mu (WD: SM_wd mu) b2, pubBlocksTgt mu b2 = false ->
~ exists b1 d, pub_of mu b1 = Some(b2,d).
Lemma disjoint_extern_local: forall mu (WD: SM_wd mu),
disjoint (extern_of mu) (local_of mu).
Lemma disjoint_foreign_pub: forall mu (WD: SM_wd mu),
disjoint (foreign_of mu) (pub_of mu).
Lemma pub_in_shared: forall mu (WD: SM_wd mu),
inject_incr (pub_of mu) (shared_of mu).