Section Rev.
(* Reversing is just consing and deconsing. We don't save the original list. *)
Variable (sig sigX : finType) (X : Type) (cX : codable sigX X).
Definition Rev_Step : pTM (sigList sigX)^+ (option unit) 3 :=
If (CaseList _ @[|Fin0;Fin2|])
(Return (Constr_cons _ @[|Fin1; Fin2|];; Reset _ @[|Fin2|]) None)
(Return (ResetEmpty1 _ @[|Fin0|]) (Some tt)).
Definition Rev_Step_size (xs : list X) :=
match xs with
| nil => [| ResetEmpty1_size; id; id |]
| x :: xs' => [| CaseList_size0 x; Constr_cons_size x; CaseList_size1 x >> Reset_size x |]
end.
Definition Rev_Step_Rel : pRel (sigList sigX)^+ (option unit) 3 :=
fun tin '(yout, tout) =>
forall (xs ys : list X) (sx sy sz : nat),
let size := Rev_Step_size xs in
tin[@Fin0] ≃(;sx) xs ->
tin[@Fin1] ≃(;sy) ys ->
isVoid_size tin[@Fin2] sz ->
match yout, xs with
| (Some tt), nil =>
isVoid_size tout[@Fin0] (size@>Fin0 sx) /\
tout[@Fin1] ≃(;size@>Fin1 sy) ys /\
isVoid_size tout[@Fin2] (size@>Fin2 sz)
| None, x :: xs' =>
tout[@Fin0] ≃(;size@>Fin0 sx) xs' /\
tout[@Fin1] ≃(;size@>Fin1 sy) x :: ys /\
isVoid_size tout[@Fin2] (size@>Fin2 sz)
| _, _ => False
end.
Definition Rev_Step_steps (xs : list X) : nat :=
match xs with
| nil => 1 + CaseList_steps xs + ResetEmpty1_steps
| x :: xs' => 2 + CaseList_steps xs + Constr_cons_steps x + Reset_steps x
end.
Definition Rev_Step_T : tRel (sigList sigX)^+ 3 :=
fun tin k => exists (xs ys : list X),
tin[@Fin0] ≃ xs /\ tin[@Fin1] ≃ ys /\ isVoid tin[@Fin2] /\ Rev_Step_steps xs <= k.

Lemma Rev_Step_Terminates : projT1 Rev_Step ↓ Rev_Step_T.