End LINK_MATCH_PROGRAM.
(** We now wrap this commutation diagram into a class, and provide some common instances. *)
Class TransfLink {A B: Type} {LA: Linker A} {LB: Linker B} (transf: A -> B -> Prop) :=
transf_link:
forall (p1 p2: A) (tp1 tp2: B) (p: A),
link p1 p2 = Some p ->
transf p1 tp1 -> transf p2 tp2 ->
exists tp, link tp1 tp2 = Some tp /\ transf p tp.
Remark link_transf_partial_fundef:
forall (A B: Type) (tr1 tr2: A -> res B) (f1 f2: fundef A) (tf1 tf2: fundef B) (f: fundef A),
link f1 f2 = Some f ->
transf_partial_fundef tr1 f1 = OK tf1 ->
transf_partial_fundef tr2 f2 = OK tf2 ->
exists tf,
link tf1 tf2 = Some tf
/\ (transf_partial_fundef tr1 f = OK tf \/ transf_partial_fundef tr2 f = OK tf).
Instance TransfPartialContextualLink
{A B C V: Type} {LV: Linker V}
(tr_fun: C -> A -> res B)
(ctx_for: program (fundef A) V -> C):
TransfLink (fun (p1: program (fundef A) V) (p2: program (fundef B) V) =>
match_program
(fun cu f tf => AST.transf_partial_fundef (tr_fun (ctx_for cu)) f = OK tf)
eq p1 p2).
Instance TransfPartialLink
{A B V: Type} {LV: Linker V}
(tr_fun: A -> res B):
TransfLink (fun (p1: program (fundef A) V) (p2: program (fundef B) V) =>
match_program
(fun cu f tf => AST.transf_partial_fundef tr_fun f = OK tf)
eq p1 p2).
Instance TransfTotallContextualLink
{A B C V: Type} {LV: Linker V}
(tr_fun: C -> A -> B)
(ctx_for: program (fundef A) V -> C):
TransfLink (fun (p1: program (fundef A) V) (p2: program (fundef B) V) =>
match_program
(fun cu f tf => tf = AST.transf_fundef (tr_fun (ctx_for cu)) f)
eq p1 p2).
Instance TransfTotalLink
{A B V: Type} {LV: Linker V}
(tr_fun: A -> B):
TransfLink (fun (p1: program (fundef A) V) (p2: program (fundef B) V) =>
match_program
(fun cu f tf => tf = AST.transf_fundef tr_fun f)
eq p1 p2).
(** * Linking a set of compilation units *)
(** Here, we take a more general view of linking as taking a nonempty list of compilation units and producing a whole program. *)
Section LINK_LIST.
Context {A: Type} {LA: Linker A}.
Fixpoint link_list (l: nlist A) : option A :=
match l with
| nbase a => Some a
| ncons a l =>
match link_list l with None => None | Some b => link a b end
end.

(* Specifications: *)
Lemma link_list_linkorder:
forall a l b, link_list l = Some b -> nIn a l -> linkorder a b.