(*Trace has form ((v,s, formula_input), formula_output, [subTrace1], [subTrace2])*)
Definition codeNewVar (l : nat) : nat :=
evalStrongRec 0
(fun n Hrecs : nat =>
switchPR n
(max (S (cPairPi1 (pred n)))
(codeNth (n - S (cPairPi2 (pred n))) Hrecs)) 0) l.

(* Specifications: *)
Lemma codeNewVarCorrect :
forall l : list nat, codeNewVar (codeList l) = newVar l.
Lemma codeNewVarIsPR : isPR 1 codeNewVar.
Definition checkSubFormulaTrace : nat -> nat :=
evalStrongRec 0
(fun trace recs : nat =>
let v := cTriplePi1 (cTriplePi1 trace) in
let s := cTriplePi2 (cTriplePi1 trace) in
let input := cTriplePi3 (cTriplePi1 trace) in
let output := cTriplePi2 trace in
let rest := cTriplePi3 trace in
let type := cPairPi1 input in
switchPR type
(switchPR (pred type)
(switchPR (pred (pred type))
(switchPR (pred (pred (pred type)))
(charFunction 2 beq_nat output
(cPair type (codeSubTerms (cPairPi2 input) v s)))
(switchPR
(charFunction 2 beq_nat v (cPairPi1 (cPairPi2 input)))
(charFunction 2 beq_nat input output)
(switchPR
(codeIn (cPairPi1 (cPairPi2 input)) (codeFreeVarTerm s))
(let nv :=
codeNewVar
(S
(cPair v
(codeApp (codeFreeVarTerm s)
(codeFreeVarFormula
(cPairPi2 (cPairPi2 input)))))) in
charFunction 0
(beq_nat output
(cPair 3 (cPair nv (cTriplePi2 (cPairPi2 rest)))) &&
(beq_nat (cTriple v s (cTriplePi2 (cPairPi1 rest)))
(cTriplePi1 (cPairPi2 rest)) &&
beq_nat
(cTriple (cPairPi1 (cPairPi2 input))
(cPair 0 nv) (cPairPi2 (cPairPi2 input)))
(cTriplePi1 (cPairPi1 rest)))) *
(codeNth (trace - S (cPairPi1 rest)) recs *
codeNth (trace - S (cPairPi2 rest)) recs))
(charFunction 0
(beq_nat output
(cPair 3
(cPair (cPairPi1 (cPairPi2 input))
(cTriplePi2 rest))) &&
beq_nat (cTriple v s (cPairPi2 (cPairPi2 input)))
(cTriplePi1 rest)) *
codeNth (trace - S rest) recs))))
(charFunction 0
(beq_nat output (cPair 2 (cTriplePi2 rest)) &&
beq_nat (cTriple v s (cPairPi2 input)) (cTriplePi1 rest)) *
codeNth (trace - S rest) recs))
(charFunction 0
(beq_nat output
(cPair 1
(cPair (cTriplePi2 (cPairPi1 rest))
(cTriplePi2 (cPairPi2 rest)))) &&
(beq_nat (cTriple v s (cPairPi1 (cPairPi2 input)))
(cTriplePi1 (cPairPi1 rest)) &&
beq_nat (cTriple v s (cPairPi2 (cPairPi2 input)))
(cTriplePi1 (cPairPi2 rest)))) *
(codeNth (trace - S (cPairPi1 rest)) recs *
codeNth (trace - S (cPairPi2 rest)) recs)))
(charFunction 2 beq_nat output
(cPair 0
(cPair (codeSubTerm (cPairPi1 (cPairPi2 input)) v s)
(codeSubTerm (cPairPi2 (cPairPi2 input)) v s))))).