-- Mathlib/Computability/TMToPartrec.lean
theorem pred_ok (q₁ q₂ s v) (c d : List Γ') : ∃ s',
    Reaches₁ (TM2.step tr) ⟨some (Λ'.pred q₁ q₂), s, K'.elim (trList v) [] c d⟩
      (v.headI.rec ⟨some q₁, s', K'.elim (trList v.tail) [] c d⟩ fun n _ =>
        ⟨some q₂, s', K'.elim (trList (n::v.tail)) [] c d⟩)

Proof state:
case cons.succ.pos.one
q₁ q₂ : Λ'
c d : List Γ'
v : List ℕ
n : ℕ
s : Option Γ'
l₁ : List Γ'
⊢ ∃ l₁' l₂' s',
    l₁.reverseAux (trPosNum PosNum.one) = l₁'.reverseAux l₂' ∧
      Reaches₁ (TM2.step tr)
        { l := some (q₁.pred q₂), var := s, stk := elim (trPosNum PosNum.one.succ ++ Γ'.cons :: trList v) l₁ c d }
        { l := some (unrev q₂), var := s', stk := elim (l₂' ++ Γ'.cons :: trList v) l₁' c d }

Tactic:
refine ⟨Γ'.bit1::l₁, [], some Γ'.cons, rfl, TransGen.head rfl (TransGen.single ?_)⟩

Result:
case cons.succ.pos.one
q₁ q₂ : Λ'
c d : List Γ'
v : List ℕ
n : ℕ
s : Option Γ'
l₁ : List Γ'
⊢ { l := some (unrev q₂), var := some Γ'.cons, stk := elim ([] ++ Γ'.cons :: trList v) (Γ'.bit1 :: l₁) c d } ∈
    TM2.step tr (TM2.stepAux (tr (q₁.pred q₂)) s (elim (trPosNum PosNum.one.succ ++ Γ'.cons :: trList v) l₁ c d))

Proof state:
q₁ q₂ : Λ'
c d : List Γ'
v : List ℕ
n : ℕ
m : PosNum
IH :
  ∀ (s : Option Γ') (l₁ : List Γ'),
    ∃ l₁' l₂' s',
      l₁.reverseAux (trPosNum m) = l₁'.reverseAux l₂' ∧
        Reaches₁ (TM2.step tr)
          { l := some (q₁.pred q₂), var := s, stk := elim (trPosNum m.succ ++ Γ'.cons :: trList v) l₁ c d }
          { l := some (unrev q₂), var := s', stk := elim (l₂' ++ Γ'.cons :: trList v) l₁' c d }
s : Option Γ'
l₁ : List Γ'
a : Γ'
l : List Γ'
e : trPosNum m = a :: l
h : natEnd a = false
⊢ some Γ'.bit1 ≠ some Γ'.bit0

Tactic:
decide

Result:
no goals

Proof state:
case cons.succ
q₁ q₂ : Λ'
s : Option Γ'
c d : List Γ'
v : List ℕ
n : ℕ
⊢ Reaches₁ (TM2.step tr) { l := some (q₁.pred q₂), var := s, stk := elim (trList ((n + 1) :: v)) [] c d }
    (Nat.rec { l := some q₁, var := none, stk := elim (trList ((n + 1) :: v).tail) [] c d }
      (fun n_1 x => { l := some q₂, var := none, stk := elim (trList (n_1 :: ((n + 1) :: v).tail)) [] c d })
      ((n + 1) :: v).headI)

Tactic:
simp only [TM2.step, trList, trNat.eq_1, trNum, Nat.cast_succ, Num.add_one, Num.succ,
  List.tail_cons, List.headI_cons]

Result:
case cons.succ
q₁ q₂ : Λ'
s : Option Γ'
c d : List Γ'
v : List ℕ
n : ℕ
⊢ Reaches₁ (TM2.step tr)
    { l := some (q₁.pred q₂), var := s, stk := elim (trPosNum (↑n).succ' ++ Γ'.cons :: trList v) [] c d }
    { l := some q₂, var := none,
      stk :=
        elim
          ((match ↑n with
            | Num.zero => []
            | Num.pos n => trPosNum n) ++
            Γ'.cons :: trList v)
          [] c d }

Proof state:
case cons.succ.pos
q₁ q₂ : Λ'
s : Option Γ'
c d : List Γ'
v : List ℕ
n : ℕ
a : PosNum
⊢ Reaches₁ (TM2.step tr)
    { l := some (q₁.pred q₂), var := s, stk := elim (trPosNum (Num.pos a).succ' ++ Γ'.cons :: trList v) [] c d }
    { l := some q₂, var := none,
      stk :=
        elim
          ((match Num.pos a with
            | Num.zero => []
            | Num.pos n => trPosNum n) ++
            Γ'.cons :: trList v)
          [] c d }

Tactic:
simp only [Num.succ']

Result:
case cons.succ.pos
q₁ q₂ : Λ'
s : Option Γ'
c d : List Γ'
v : List ℕ
n : ℕ
a : PosNum
⊢ Reaches₁ (TM2.step tr)
    { l := some (q₁.pred q₂), var := s, stk := elim (trPosNum a.succ ++ Γ'.cons :: trList v) [] c d }
    { l := some q₂, var := none, stk := elim (trPosNum a ++ Γ'.cons :: trList v) [] c d }

Proof state:
case cons.succ.pos.bit1.intro.intro.intro.intro
q₁ q₂ : Λ'
c d : List Γ'
v : List ℕ
n : ℕ
m : PosNum
IH :
  ∀ (s : Option Γ') (l₁ : List Γ'),
    ∃ l₁' l₂' s',
      l₁.reverseAux (trPosNum m) = l₁'.reverseAux l₂' ∧
        Reaches₁ (TM2.step tr)
          { l := some (q₁.pred q₂), var := s, stk := elim (trPosNum m.succ ++ Γ'.cons :: trList v) l₁ c d }
          { l := some (unrev q₂), var := s', stk := elim (l₂' ++ Γ'.cons :: trList v) l₁' c d }
s : Option Γ'
l₁ l₁' l₂' : List Γ'
s' : Option Γ'
e : (Γ'.bit1 :: l₁).reverseAux (trPosNum m) = l₁'.reverseAux l₂'
h :
  Reaches₁ (TM2.step tr)
    { l := some (q₁.pred q₂), var := some Γ'.bit0,
      stk := elim (trPosNum m.succ ++ Γ'.cons :: trList v) (Γ'.bit1 :: l₁) c d }
    { l := some (unrev q₂), var := s', stk := elim (l₂' ++ Γ'.cons :: trList v) l₁' c d }
⊢ (bif decide ((trPosNum m.bit1.succ).head?.getD Γ'.cons = Γ'.bit0) then
      { l := some (q₁.pred q₂), var := some ((trPosNum m.bit1.succ).head?.getD Γ'.cons),
        stk := elim (trPosNum m.bit1.succ ++ Γ'.cons :: trList v).tail (Γ'.bit1 :: l₁) c d }
    else
      bif
          match (some ((trPosNum m.bit1.succ).head?.getD Γ'.cons)).iget with
          | Γ'.consₗ => true
          | Γ'.cons => true
          | x => false then
        { l := some q₁, var := some ((trPosNum m.bit1.succ).head?.getD Γ'.cons),
          stk := elim (trPosNum m.bit1.succ ++ Γ'.cons :: trList v).tail l₁ c d }
      else
        bif
            match (trPosNum m.bit1.succ ++ Γ'.cons :: trList v)[1]?.iget with
            | Γ'.consₗ => true
            | Γ'.cons => true
            | x => false then
          { l := some (unrev q₂), var := (trPosNum m.bit1.succ ++ Γ'.cons :: trList v)[1]?,
            stk := elim (trPosNum m.bit1.succ ++ Γ'.cons :: trList v).tail l₁ c d }
        else
          { l := some (unrev q₂), var := (trPosNum m.bit1.succ ++ Γ'.cons :: trList v)[1]?,
            stk := elim (trPosNum m.bit1.succ ++ Γ'.cons :: trList v).tail (Γ'.bit0 :: l₁) c d }) =
    { l := some (q₁.pred q₂), var := some Γ'.bit0,
      stk := elim (trPosNum m.succ ++ Γ'.cons :: trList v) (Γ'.bit1 :: l₁) c d }

Tactic:
rfl

Result:
no goals

Proof state:
case cons.succ.pos
q₁ q₂ : Λ'
s : Option Γ'
c d : List Γ'
v : List ℕ
n : ℕ
a : PosNum
⊢ Reaches₁ (TM2.step tr)
    { l := some (q₁.pred q₂), var := s, stk := elim (trPosNum a.succ ++ Γ'.cons :: trList v) [] c d }
    { l := some q₂, var := none, stk := elim (trPosNum a ++ Γ'.cons :: trList v) [] c d }

Tactic:
suffices ∀ l₁, ∃ l₁' l₂' s',
  List.reverseAux l₁ (trPosNum a) = List.reverseAux l₁' l₂' ∧
    Reaches₁ (TM2.step tr)
      ⟨some (q₁.pred q₂), s, K'.elim (trPosNum a.succ ++ Γ'.cons :: trList v) l₁ c d⟩
      ⟨some (unrev q₂), s', K'.elim (l₂' ++ Γ'.cons :: trList v) l₁' c d⟩ by
  obtain ⟨l₁', l₂', s', e, h⟩ := this []
  simp only [List.reverseAux] at e
  refine h.trans ?_
  convert unrev_ok using 2
  simp [e, List.reverseAux_eq]

Result:
case cons.succ.pos
q₁ q₂ : Λ'
s : Option Γ'
c d : List Γ'
v : List ℕ
n : ℕ
a : PosNum
⊢ ∀ (l₁ : List Γ'),
    ∃ l₁' l₂' s',
      l₁.reverseAux (trPosNum a) = l₁'.reverseAux l₂' ∧
        Reaches₁ (TM2.step tr)
          { l := some (q₁.pred q₂), var := s, stk := elim (trPosNum a.succ ++ Γ'.cons :: trList v) l₁ c d }
          { l := some (unrev q₂), var := s', stk := elim (l₂' ++ Γ'.cons :: trList v) l₁' c d }