(* Autor(s): Andrej Dudenhefner (1) Affiliation(s): (1) Saarland University, Saarbrücken, Germany *)
From Undecidability.SystemF.Util Require Import Facts poly_type_facts pure_term_facts.
Fact head_form_ren_term {ζ ξ P} :
head_form P -> head_form (ren_term ζ ξ P).
(* type annotation erasure *)
Fixpoint erase (P: term) : pure_term :=
match P with
| var x => pure_var x
| app P Q => pure_app (erase P) (erase Q)
| abs _ P => pure_abs (erase P)
| ty_app P _ => erase P
| ty_abs P => erase P
end.
Fact erase_subst_term_var {P σ} : erase (subst_term σ var P) = erase P.
(* COMPOUND term CONSTRUCTION *)
(* many_app P [Q1 .. Qn] = P Q1 .. Qn *)
Definition many_app (P: term) (Qs: list term) :=
fold_left app Qs P.
(* many_app P [t1 .. tn] = P t1 .. tn *)
Definition many_ty_app (P: term) (ts: list poly_type) :=
fold_left ty_app ts P.
(* many_ty_abs n P = Λ .. Λ t *)
Definition many_ty_abs (n: nat) (P: term) :=
Nat.iter n ty_abs P.
Fact many_app_app {P Qs Qs'} : many_app P (Qs ++ Qs') = many_app (many_app P Qs) Qs'.
Fact erase_many_ty_abs {n P} : erase (many_ty_abs n P) = erase P.
Fixpoint term_size (P: term) :=
match P with
| var _ => 1
| app P Q => 1 + term_size P + term_size Q
| abs _ P => 1 + term_size P
| ty_app P _ => 1 + term_size P
| ty_abs P => 1 + term_size P
end.
(* evaluates propositional predicate P on all free variables *)
Fixpoint allfv_term (p: nat -> Prop) (P: term) :=
match P with
| var x => p x
| app P Q => allfv_term p P /\ allfv_term p Q
| abs _ P => allfv_term (scons True p) P
| ty_app P _ => allfv_term p P
| ty_abs P => allfv_term p P
end.

Lemma allfv_term_impl {p1 p2: nat -> Prop} {P}:
(forall x, p1 x -> p2 x) -> allfv_term p1 P -> allfv_term p2 P.