Section SubAllVars.
Variable L : Language.
Notation Formula := (Formula L) (only parsing).
Notation Formulas := (Formulas L) (only parsing).
Notation System := (System L) (only parsing).
Notation Term := (Term L) (only parsing).
Notation Terms := (Terms L) (only parsing).
Notation var := (var L) (only parsing).
Notation apply := (apply L) (only parsing).
Notation equal := (equal L) (only parsing).
Notation atomic := (atomic L) (only parsing).
Notation impH := (impH L) (only parsing).
Notation notH := (notH L) (only parsing).
Notation forallH := (forallH L) (only parsing).
Notation iffH := (iffH L) (only parsing).
Notation SysPrf := (SysPrf L) (only parsing).
Fixpoint subAllTerm (t : fol.Term L) : (nat -> fol.Term L) -> fol.Term L :=
match t return ((nat -> fol.Term L) -> fol.Term L) with
| fol.var x => fun m => m x
| fol.apply f ts => fun m => fol.apply L f (subAllTerms _ ts m)
end
with subAllTerms (n : nat) (ts : fol.Terms L n) {struct ts} :
(nat -> fol.Term L) -> fol.Terms L n :=
match
ts in (fol.Terms _ n) return ((nat -> fol.Term L) -> fol.Terms L n)
with
| Tnil => fun _ => Tnil L
| Tcons n' t ss =>
fun m => Tcons L n' (subAllTerm t m) (subAllTerms _ ss m)
end.
Fixpoint freeVarMap (l : list nat) : (nat -> fol.Term L) -> list nat :=
match l with
| nil => fun _ => nil
| a :: l' => fun m => freeVarTerm L (m a) ++ freeVarMap l' m
end.
Fixpoint subAllFormula (f : Formula) (m : (nat -> Term)) {struct f} : Formula :=
match f with
| fol.equal t s => equal (subAllTerm t m) (subAllTerm s m)
| fol.atomic r ts => atomic r (subAllTerms _ ts m)
| fol.impH f g =>
impH (subAllFormula f m) (subAllFormula g m)
| fol.notH f => notH (subAllFormula f m)
| fol.forallH n f =>
let nv :=
newVar
(freeVarFormula L f ++
freeVarMap (freeVarFormula L (forallH n f)) m) in
forallH nv
(subAllFormula f
(fun v : nat =>
match eq_nat_dec v n with
| left _ => var nv
| right _ => m v
end))
end.

Lemma subAllSubAllFormula :
forall (T : fol.System L) (f : fol.Formula L) (m1 m2 : nat -> fol.Term L),
folProof.SysPrf L T
(fol.iffH L (subAllFormula (subAllFormula f m1) m2)
(subAllFormula f (fun n : nat => subAllTerm (m1 n) m2))).