From Undecidability.L Require Import Prelim.MoreBase Util.L_facts AbstractMachines.LargestVar.
Require Export Undecidability.L.AbstractMachines.FlatPro.ProgramsDef.
(* * Abstract L machines *)
(* *** Program size *)
Definition sizeT t :=
match t with
varT n => 1 + n
|  _ => 1
end.
Definition sizeP (P:Pro) := sumn (map sizeT P) + 1.
Hint Unfold sizeP : core.
(* *** Programm Decomposition *)
Fixpoint jumpTarget (l:nat) (res:Pro) (P:Pro) : option (Pro*Pro) :=
match P with
| retT :: P => match l with
| 0 => Some (res,P)
| S l => jumpTarget l (res++[retT]) P
end
| lamT :: P => jumpTarget (S l) (res++[lamT])P
| t :: P    => jumpTarget l (res++[t]) P
| []        => None
end.
(* *** Program Substitution *)
Fixpoint substP (P:Pro) k Q : Pro :=
match P with
[] => []
| lamT::P => lamT::substP P (S k) Q
| retT::P => retT::match k with
S k => substP P k Q
| 0 => [(* doesnt matter *)]
end
| varT k'::P => (if k' =? k then Q else [varT k'])++substP P k Q
| appT::P => appT::substP P k Q
end.

Lemma substP_correct s k t:
substP (compile s) k (compile t) = compile (subst s k t).