Section correctness.
(* We assume each instruction in P is compiled in Q according to the individual instruction compiler combined with what the linker says for branching. This is a *syntactic correctness criterion* for the whole compiled program Q *)
Variables (linker : nat -> nat) (P : nat * list X) (Q : nat * list Y)
(HPQ : forall i I, (i,I::nil) <sc P -> (linker i, icomp linker i I) <sc Q
/\ linker (1+i) = ilen I + linker i).
(* From semantic correctness of individually compiled instructions and syntactic correctness of the whole compiled program, we derive soundness and completeness of the compiled program Q wrt the source program P *)
(* When still inside of P, the computation in Q simulates a computation in P *)
Local Lemma compiler_complete_step p st1 w1 w3 :
snd st1 ⋈ snd w1
-> linker (fst st1) = fst w1
-> in_code (fst st1) P
-> out_code (fst w3) Q
-> Q /Y/ w1 -[p]-> w3
-> exists q st2 w2, snd st2 ⋈ snd w2
/\ linker (fst st2) = fst w2
/\ P /X/ st1 ->> st2
/\ Q /Y/ w2 -[q]-> w3
/\ q < p.
(* Termination in Q simulates termination in P *)

Theorem compiler_complete i1 v1 w1 :
v1 ⋈ w1 -> Q /Y/ (linker i1,w1) ↓ -> P /X/ (i1,v1) ↓.