End GENV.
(** * Commutation with program transformations *)
Section MATCH_GENVS.
Context {A B V W: Type} (R: globdef A V -> globdef B W -> Prop).
Record match_genvs (ge1: t A V) (ge2: t B W): Prop := {
mge_next:
genv_next ge2 = genv_next ge1;
mge_symb:
forall id, PTree.get id (genv_symb ge2) = PTree.get id (genv_symb ge1);
mge_defs:
forall b, option_rel R (PTree.get b (genv_defs ge1)) (PTree.get b (genv_defs ge2))
}.

(* Specifications: *)
Lemma add_global_match:
forall ge1 ge2 id g1 g2,
match_genvs ge1 ge2 ->
R g1 g2 ->
match_genvs (add_global ge1 (id, g1)) (add_global ge2 (id, g2)).
Lemma add_globals_match:
forall gl1 gl2,
list_forall2 (fun idg1 idg2 => fst idg1 = fst idg2 /\ R (snd idg1) (snd idg2)) gl1 gl2 ->
forall ge1 ge2, match_genvs ge1 ge2 ->
match_genvs (add_globals ge1 gl1) (add_globals ge2 gl2).
Lemma add_global_match:
forall ge1 ge2 id g1 g2,
match_genvs ge1 ge2 ->
R g1 g2 ->
match_genvs (add_global ge1 (id, g1)) (add_global ge2 (id, g2)).
Lemma add_globals_match:
forall gl1 gl2,
list_forall2 (fun idg1 idg2 => fst idg1 = fst idg2 /\ R (snd idg1) (snd idg2)) gl1 gl2 ->
forall ge1 ge2, match_genvs ge1 ge2 ->
match_genvs (add_globals ge1 gl1) (add_globals ge2 gl2).