Module ListTape.
Record ListES := {
l: list Σ;
r: list Σ;
m: Σ;
s: St;
}.
Definition ListES_toES(x:ListES):ExecState Σ :=
let (l0,r0,m0,s0):=x in
(s0,
fun x =>
match x with
| Zpos x0 => nth (Pos.to_nat x0) (m0::r0) Σ0
| Zneg x0 => nth (Pos.to_nat x0) (m0::l0) Σ0
| Z0 => m0
end).
Definition ListES_step(tm:TM Σ)(x:ListES):option ListES :=
let (l0,r0,m0,s0):=x in
match tm s0 m0 with
| None => None
| Some tr =>
let (s1,d,o) := tr in
Some
match d with
| Dpos =>
match r0 with
| m1::r1 => {| l:=o::l0; r:=r1; m:=m1; s:=s1 |}
| nil => {| l:=o::l0; r:=nil; m:=Σ0; s:=s1 |}
end
| Dneg =>
match l0 with
| m1::l1 => {| l:=l1; r:=o::r0; m:=m1; s:=s1 |}
| nil => {| l:=nil; r:=o::r0; m:=Σ0; s:=s1 |}
end
end
end.
Definition app_halftape(h:list Σ)(t:nat->Σ):nat->Σ :=
fun n =>
match nth_error h n with
| None => t (n-(length h))
| Some c => c
end.
Definition make_tape(l0:nat->Σ)(m0:Σ)(r0:nat->Σ):Z->Σ :=
fun x =>
match x with
| Z0 => m0
| Zpos x0 => r0 (Nat.pred (Pos.to_nat x0))
| Zneg x0 => l0 (Nat.pred (Pos.to_nat x0))
end.
Definition make_tape'(l1:nat->Σ)(l0:list Σ)(m0:Σ)(r0:list Σ)(r1:nat->Σ):Z->Σ :=
make_tape (app_halftape l0 l1) m0 (app_halftape r0 r1).
Definition makeES(st:ListES)(l1 r1:nat->Σ):ExecState Σ :=
let (l0,r0,m0,s0):=st in
(s0, make_tape' l1 l0 m0 r0 r1).
Definition addmul(x:Z)(d:Dir)(n:nat):Z := x+(Dir_to_Z d)*(Z.of_nat n).
Definition half_tape(f:Z->Σ)(x:Z)(d:Dir):nat->Σ :=
fun n =>
f (addmul x d n).
Definition tape_rev(f:Z->Σ):Z->Σ := fun x => f (-x)%Z.
Definition half_tape_cdr(f:nat->Σ):nat->Σ :=
fun n => f (S n).

Lemma app_halftape_eq_cons {h a b h' a' b'}:
app_halftape (h::a) b = app_halftape (h'::a') b' ->
(h=h'/\app_halftape a b = app_halftape a' b').