End LINKER_PROG.
Instance Linker_prog (F V: Type) {LF: Linker F} {LV: Linker V} : Linker (program F V) := {
link := link_prog;
linkorder := fun p1 p2 =>
p1.(prog_main) = p2.(prog_main)
/\ incl p1.(prog_public) p2.(prog_public)
/\ forall id gd1,
(prog_defmap p1)!id = Some gd1 ->
exists gd2,
(prog_defmap p2)!id = Some gd2
/\ linkorder gd1 gd2
/\ (~In id p2.(prog_public) -> gd2 = gd1)
}.
Global Opaque Linker_prog.
(** * Matching between two programs *)
(** The following is a relational presentation of program transformations, e.g. [transf_partial_program] from module [AST].  *)
(** To capture the possibility of separate compilation, we parameterize the [match_fundef] relation between function definitions with a context, e.g. the compilation unit from which the function definition comes. This unit is characterized as any program that is in the [linkorder] relation with the final, whole program. *)
Section MATCH_PROGRAM_GENERIC.
Context {C F1 V1 F2 V2: Type} {LC: Linker C} {LF: Linker F1} {LV: Linker V1}.
Variable match_fundef: C -> F1 -> F2 -> Prop.
Variable match_varinfo: V1 -> V2 -> Prop.
Inductive match_globvar: globvar V1 -> globvar V2 -> Prop :=
| match_globvar_intro: forall i1 i2 init ro vo,
match_varinfo i1 i2 ->
match_globvar (mkglobvar i1 init ro vo) (mkglobvar i2 init ro vo).
Inductive match_globdef (ctx: C): globdef F1 V1 -> globdef F2 V2 -> Prop :=
| match_globdef_fun: forall ctx' f1 f2,
linkorder ctx' ctx ->
match_fundef ctx' f1 f2 ->
match_globdef ctx (Gfun f1) (Gfun f2)
| match_globdef_var: forall v1 v2,
match_globvar v1 v2 ->
match_globdef ctx (Gvar v1) (Gvar v2).
Definition match_ident_globdef
(ctx: C) (ig1: ident * globdef F1 V1) (ig2: ident * globdef F2 V2) : Prop :=
fst ig1 = fst ig2 /\ match_globdef ctx (snd ig1) (snd ig2).
Definition match_program_gen (ctx: C) (p1: program F1 V1) (p2: program F2 V2) : Prop :=
list_forall2 (match_ident_globdef ctx) p1.(prog_defs) p2.(prog_defs)
/\ p2.(prog_main) = p1.(prog_main)
/\ p2.(prog_public) = p1.(prog_public).

Lemma match_program_gen_len_defs:
forall ctx p1 p2,
match_program_gen ctx p1 p2 ->
length (AST.prog_defs p1) =length (AST.prog_defs p2) .