Section PredicativeNotationRecursion.
Variable sl : nat. (* sl = |x| *)
Hypothesis sl_not_zero : sl <> 0.
Definition comp2n h ln ls := comp 2 0 h ln ls.
Definition comp2s h ln ls := comp 2 sl h ln ls.
Definition comp2Ss h ln ls := comp 2 (S sl) h ln ls.
Definition comp2SSs h ln ls := comp 2 (S (S sl)) h ln ls.
Definition proj2n i := proj 2 0 i.
Definition proj2s i := proj 2 sl i.
Definition proj2Ss i := proj 2 (S sl) i.
Definition proj2SSs i := proj 2 (S (S sl)) i.
Definition f'_cond := comp2Ss Y_e
[comp2n (succ true) nil [proj2n 0];
proj2n 1]
[proj2Ss 3].
Opaque f'_cond.
Variables g : BC.
Hypothesis g_inf  : arities g = ok_arities 1 (sl - 1).
Definition f'_nil := BC_dummies 1 1 2 (sl - 1) g.
Opaque f'_nil.
Variable h0 h1 : BC.
Hypothesis h0_inf : arities h0 = ok_arities 1 (S sl).
Hypothesis h1_inf : arities h1 = ok_arities 1 (S sl).
Definition f'_then :=
comp2Ss h1 [proj2n 1]
([comp2Ss Y_e [proj2n 0; proj2n 1] [proj2Ss 3];
proj2Ss 2 ] ++ (map (proj 2 (S sl)) (seq 4 (sl - 1)))).
Transparent P_e Y_e.
Opaque f'_then.
Definition f'_else :=
comp2Ss h0 [proj2n 1]
([comp2Ss Y_e [proj2n 0; proj2n 1] [proj2Ss 3];
proj2Ss 2 ] ++ (map (proj 2 (S sl)) (seq 4 (sl - 1)))).
Opaque f'_else.
Definition f' : BC :=
rec2 (BC_dummies 0 1 1 (sl - 1) g)
(comp2Ss cond nil [f'_cond; f'_nil; f'_then; f'_else] ).
Definition f : BC :=
comp 1 sl f' [proj 1 0 0; proj 1 0 0]
(map (proj 1 sl) (seq 1 sl)).
Opaque f'.
Variables g' h0' h1' cj : Cobham.
Hypothesis g'_inf : arity g' = ok_arity (sl - 1).
Hypothesis h0'_inf : arity h0' = ok_arity (S sl).
Hypothesis h1'_inf : arity h1' = ok_arity (S sl).
Hypothesis cj'_inf : arity cj = ok_arity sl.
Hypothesis g_correct  : forall w xl,
length xl = (sl - 1) ->
peval (rec_simulation (sl - 1) g') (map (@length _) xl) <= length w ->
Sem g' xl  = sem g [w] xl.
Hypothesis h0_correct : forall w xl,
length xl = (S sl) ->
peval (rec_simulation (S sl) h0') (map (@length _) xl) <= length w ->
Sem h0' xl = sem h0 [w] xl.
Hypothesis h1_correct : forall w xl,
length xl = (S sl) ->
peval (rec_simulation (S sl) h1') (map (@length _) xl) <= length w ->
Sem h1' xl = sem h1 [w] xl.
Transparent f'_then f'_else f'_cond f' .
Opaque f'.
End PredicativeNotationRecursion.
Definition f_smash' :=
f 2 (proj 1 1 1)
(comp 1 3 (succ false) nil [proj 1 3 2])
(comp 1 3 (succ false) nil [proj 1 3 2]).
Opaque f_smash'.
Fixpoint Cobham_to_BC' sl (e : Cobham) : BC :=
match e with
| Zero => comp 1 sl zero nil nil
| Proj n i => proj 1 sl (S i)
| Succ b => comp 1 sl (succ b) nil [proj 1 sl 1]
| Smash => f sl (one_e 1 1)
(BC_dummies 0 1 1 2 (comp 1 2 f_smash' [proj 1 0 0] [proj 1 2 2; proj 1 2 1]))
(BC_dummies 0 1 1 2 (comp 1 2 f_smash' [proj 1 0 0] [proj 1 2 2; proj 1 2 1]))
| Rec g' h0' h1' _ =>
let g  := Cobham_to_BC' (sl - 1) g' in
let h0 := Cobham_to_BC' (S sl) h0' in
let h1 := Cobham_to_BC' (S sl) h1' in
f sl g h0 h1
| Comp n h l => comp 1 sl (Cobham_to_BC' (length l) h)
[proj 1 0 0] (map (Cobham_to_BC' sl) l)
end.
Opaque f.
Opaque f'.
Definition smash'_e : BC :=
rec2 (proj 0 1 0) (comp 1 2 (succ false) nil [proj 1 2 1]).
(* Eval vm_compute in arities smash'_e. *)
Opaque smash'_e.
Definition smash_e : BC :=
rec2 (comp 1 0 (succ true) nil [zero_e 1 0])
(comp 2 1 smash'_e [proj 2 0 1] [proj 2 1 2]).
(* Eval vm_compute in arities smash_e. *)
Transparent f.
Opaque Mult_e.
Opaque Plus_e.
Opaque App_e.
Definition concat := smash'_e.
Definition poly_BC_pow (ar:nat)(xn:pow) : BC :=
multl_e ar (repeat (snd xn) (proj ar 0 (fst xn))).
Opaque poly_BC_pow.
Definition poly_BC_mon (ar:nat)(m:mon) : BC :=
multl_e ar (nat2BC ar 0 (fst m) :: map (poly_BC_pow ar) (snd m)).
Definition poly_BC (p : pol) : BC :=
plusl_e (fst p) (map (poly_BC_mon (fst p)) (snd p)).
Definition Cobham_to_BC'' n e :=
comp n n (Cobham_to_BC' n e) [poly_BC (rec_simulation n e)]
(map (proj n n) (seq n n)).

Lemma Cobham_to_BC''_correct : forall e xl n,
rec_bounded e ->
arity e = ok_arity n ->
length xl = n ->
Sem e xl = sem (Cobham_to_BC'' n e) xl xl.