case nil
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
⊢ Reaches₁ (TM2.step tr)
    { l := some (head stack q), var := s, stk := elim (trList L₁) [] [] (trList [] ++ Γ'.consₗ :: L₃) }
    { l := some q, var := none, stk := elim (trList (List.headI [] :: L₁)) [] [] L₃ }

case cons
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
a : ℕ
L₂ : List ℕ
⊢ Reaches₁ (TM2.step tr)
    { l := some (head stack q), var := s, stk := elim (trList L₁) [] [] (trList (a :: L₂) ++ Γ'.consₗ :: L₃) }
    { l := some q, var := none, stk := elim (trList (List.headI (a :: L₂) :: L₁)) [] [] L₃ }
q : Λ'
s : Option Γ'
L₁ L₂ : List ℕ
L₃ : List Γ'
⊢ Reaches₁ (TM2.step tr)
    { l := some (head stack q), var := s, stk := elim (trList L₁) [] [] (trList L₂ ++ Γ'.consₗ :: L₃) }
    { l := some q, var := none, stk := elim (trList (List.headI L₂ :: L₁)) [] [] L₃ }
cases' L₂ with a L₂
case nil
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
⊢ TransGen (fun a b => b ∈ TM2.step tr a)
    (TM2.stepAux
      (tr
        ((fun x =>
            Λ'.read fun s => ite (s = some Γ'.consₗ) id (Λ'.clear (fun x => decide (x = Γ'.consₗ)) stack) (unrev q))
          (some Γ'.consₗ)))
      (some Γ'.consₗ)
      (update
        (update (update (elim (trList L₁) [] [] (trList [] ++ Γ'.consₗ :: L₃)) stack L₃) rev
          (List.reverseAux [] (elim (trList L₁) [] [] (trList [] ++ Γ'.consₗ :: L₃) rev)))
        rev
        ((fun s => Option.iget ((fun x => some Γ'.cons) s)) (some Γ'.consₗ) ::
          update (update (elim (trList L₁) [] [] (trList [] ++ Γ'.consₗ :: L₃)) stack L₃) rev
            (List.reverseAux [] (elim (trList L₁) [] [] (trList [] ++ Γ'.consₗ :: L₃) rev)) rev)))
    { l := some q, var := none, stk := elim (trList (List.headI [] :: L₁)) [] [] L₃ }
case nil
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
⊢ Reaches₁ (TM2.step tr)
    { l := some (head stack q), var := s, stk := elim (trList L₁) [] [] (trList [] ++ Γ'.consₗ :: L₃) }
    { l := some q, var := none, stk := elim (trList (List.headI [] :: L₁)) [] [] L₃ }
refine'
  TransGen.trans
    (move_ok (by decide)
      (splitAtPred_eq _ _ [] (some Γ'.consₗ) L₃ (by rintro _ ⟨⟩) ⟨rfl, rfl⟩))
    (TransGen.head rfl (TransGen.head rfl _))
case nil
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
⊢ TransGen
    (fun a b =>
      (match a with
        | { l := none, var := var, stk := stk } => none
        | { l := some l, var := v, stk := S } => some (TM2.stepAux (tr l) v S)) =
        some b)
    { l := some (unrev q), var := some Γ'.consₗ, stk := elim (trList L₁) [Option.iget (some Γ'.cons)] [] L₃ }
    { l := some q, var := none, stk := elim (Γ'.cons :: trList L₁) [] [] L₃ }
case nil
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
⊢ TransGen (fun a b => b ∈ TM2.step tr a)
    (TM2.stepAux
      (tr
        ((fun x =>
            Λ'.read fun s => ite (s = some Γ'.consₗ) id (Λ'.clear (fun x => decide (x = Γ'.consₗ)) stack) (unrev q))
          (some Γ'.consₗ)))
      (some Γ'.consₗ)
      (update
        (update (update (elim (trList L₁) [] [] (trList [] ++ Γ'.consₗ :: L₃)) stack L₃) rev
          (List.reverseAux [] (elim (trList L₁) [] [] (trList [] ++ Γ'.consₗ :: L₃) rev)))
        rev
        ((fun s => Option.iget ((fun x => some Γ'.cons) s)) (some Γ'.consₗ) ::
          update (update (elim (trList L₁) [] [] (trList [] ++ Γ'.consₗ :: L₃)) stack L₃) rev
            (List.reverseAux [] (elim (trList L₁) [] [] (trList [] ++ Γ'.consₗ :: L₃) rev)) rev)))
    { l := some q, var := none, stk := elim (trList (List.headI [] :: L₁)) [] [] L₃ }
simp
case h.e'_2.h.e'_7
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
⊢ elim (Γ'.cons :: trList L₁) [] [] L₃ =
    update (update (elim (trList L₁) [Option.iget (some Γ'.cons)] [] L₃) rev []) main
      (List.reverseAux (elim (trList L₁) [Option.iget (some Γ'.cons)] [] L₃ rev)
        (elim (trList L₁) [Option.iget (some Γ'.cons)] [] L₃ main))
case nil
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
⊢ TransGen
    (fun a b =>
      (match a with
        | { l := none, var := var, stk := stk } => none
        | { l := some l, var := v, stk := S } => some (TM2.stepAux (tr l) v S)) =
        some b)
    { l := some (unrev q), var := some Γ'.consₗ, stk := elim (trList L₁) [Option.iget (some Γ'.cons)] [] L₃ }
    { l := some q, var := none, stk := elim (Γ'.cons :: trList L₁) [] [] L₃ }
convert unrev_ok using 2
no goals
case h.e'_2.h.e'_7
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
⊢ elim (Γ'.cons :: trList L₁) [] [] L₃ =
    update (update (elim (trList L₁) [Option.iget (some Γ'.cons)] [] L₃) rev []) main
      (List.reverseAux (elim (trList L₁) [Option.iget (some Γ'.cons)] [] L₃ rev)
        (elim (trList L₁) [Option.iget (some Γ'.cons)] [] L₃ main))
simp
no goals
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
⊢ stack ≠ rev
decide
no goals
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
⊢ ∀ (x : Γ'), x ∈ [] → natEnd x = false
rintro _ ⟨⟩
case cons
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
a : ℕ
L₂ : List ℕ
⊢ TransGen (fun a b => b ∈ TM2.step tr a)
    (TM2.stepAux
      (tr
        ((fun x =>
            Λ'.read fun s => ite (s = some Γ'.consₗ) id (Λ'.clear (fun x => decide (x = Γ'.consₗ)) stack) (unrev q))
          (some Γ'.cons)))
      (some Γ'.cons)
      (update
        (update
          (update (elim (trList L₁) [] [] (trList (a :: L₂) ++ Γ'.consₗ :: L₃)) stack (trList L₂ ++ Γ'.consₗ :: L₃)) rev
          (List.reverseAux (trNat a) (elim (trList L₁) [] [] (trList (a :: L₂) ++ Γ'.consₗ :: L₃) rev)))
        rev
        ((fun s => Option.iget ((fun x => some Γ'.cons) s)) (some Γ'.cons) ::
          update
            (update (elim (trList L₁) [] [] (trList (a :: L₂) ++ Γ'.consₗ :: L₃)) stack (trList L₂ ++ Γ'.consₗ :: L₃))
            rev (List.reverseAux (trNat a) (elim (trList L₁) [] [] (trList (a :: L₂) ++ Γ'.consₗ :: L₃) rev)) rev)))
    { l := some q, var := none, stk := elim (trList (List.headI (a :: L₂) :: L₁)) [] [] L₃ }
case cons
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
a : ℕ
L₂ : List ℕ
⊢ Reaches₁ (TM2.step tr)
    { l := some (head stack q), var := s, stk := elim (trList L₁) [] [] (trList (a :: L₂) ++ Γ'.consₗ :: L₃) }
    { l := some q, var := none, stk := elim (trList (List.headI (a :: L₂) :: L₁)) [] [] L₃ }
refine'
  TransGen.trans
    (move_ok (by decide)
      (splitAtPred_eq _ _ (trNat a) (some Γ'.cons) (trList L₂ ++ Γ'.consₗ :: L₃)
        (trNat_natEnd _) ⟨rfl, by simp⟩))
    (TransGen.head rfl (TransGen.head rfl _))
case cons
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
a : ℕ
L₂ : List ℕ
⊢ TransGen
    (fun a b =>
      (match a with
        | { l := none, var := var, stk := stk } => none
        | { l := some l, var := v, stk := S } => some (TM2.stepAux (tr l) v S)) =
        some b)
    { l := some (Λ'.clear (fun x => decide (x = Γ'.consₗ)) stack (unrev q)), var := some Γ'.cons,
      stk :=
        elim (trList L₁) (Option.iget (some Γ'.cons) :: List.reverseAux (trNat a) []) [] (trList L₂ ++ Γ'.consₗ :: L₃) }
    { l := some q, var := none, stk := elim (trNat a ++ Γ'.cons :: trList L₁) [] [] L₃ }
case cons
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
a : ℕ
L₂ : List ℕ
⊢ TransGen (fun a b => b ∈ TM2.step tr a)
    (TM2.stepAux
      (tr
        ((fun x =>
            Λ'.read fun s => ite (s = some Γ'.consₗ) id (Λ'.clear (fun x => decide (x = Γ'.consₗ)) stack) (unrev q))
          (some Γ'.cons)))
      (some Γ'.cons)
      (update
        (update
          (update (elim (trList L₁) [] [] (trList (a :: L₂) ++ Γ'.consₗ :: L₃)) stack (trList L₂ ++ Γ'.consₗ :: L₃)) rev
          (List.reverseAux (trNat a) (elim (trList L₁) [] [] (trList (a :: L₂) ++ Γ'.consₗ :: L₃) rev)))
        rev
        ((fun s => Option.iget ((fun x => some Γ'.cons) s)) (some Γ'.cons) ::
          update
            (update (elim (trList L₁) [] [] (trList (a :: L₂) ++ Γ'.consₗ :: L₃)) stack (trList L₂ ++ Γ'.consₗ :: L₃))
            rev (List.reverseAux (trNat a) (elim (trList L₁) [] [] (trList (a :: L₂) ++ Γ'.consₗ :: L₃) rev)) rev)))
    { l := some q, var := none, stk := elim (trList (List.headI (a :: L₂) :: L₁)) [] [] L₃ }
simp
case cons
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
a : ℕ
L₂ : List ℕ
⊢ TransGen
    (fun a b =>
      (match a with
        | { l := none, var := var, stk := stk } => none
        | { l := some l, var := v, stk := S } => some (TM2.stepAux (tr l) v S)) =
        some b)
    { l := some (unrev q), var := some Γ'.consₗ,
      stk :=
        update
          (elim (trList L₁) (Option.iget (some Γ'.cons) :: List.reverseAux (trNat a) []) []
            (trList L₂ ++ Γ'.consₗ :: L₃))
          stack L₃ }
    { l := some q, var := none, stk := elim (trNat a ++ Γ'.cons :: trList L₁) [] [] L₃ }
case cons
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
a : ℕ
L₂ : List ℕ
⊢ TransGen
    (fun a b =>
      (match a with
        | { l := none, var := var, stk := stk } => none
        | { l := some l, var := v, stk := S } => some (TM2.stepAux (tr l) v S)) =
        some b)
    { l := some (Λ'.clear (fun x => decide (x = Γ'.consₗ)) stack (unrev q)), var := some Γ'.cons,
      stk :=
        elim (trList L₁) (Option.iget (some Γ'.cons) :: List.reverseAux (trNat a) []) [] (trList L₂ ++ Γ'.consₗ :: L₃) }
    { l := some q, var := none, stk := elim (trNat a ++ Γ'.cons :: trList L₁) [] [] L₃ }
refine'
  TransGen.trans
    (clear_ok
      (splitAtPred_eq _ _ (trList L₂) (some Γ'.consₗ) L₃
        (fun x h => Bool.decide_false (trList_ne_consₗ _ _ h)) ⟨rfl, by simp⟩))
    _
case h.e'_2.h.e'_7
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
a : ℕ
L₂ : List ℕ
⊢ elim (trNat a ++ Γ'.cons :: trList L₁) [] [] L₃ =
    update
      (update
        (update
          (elim (trList L₁) (Option.iget (some Γ'.cons) :: List.reverseAux (trNat a) []) []
            (trList L₂ ++ Γ'.consₗ :: L₃))
          stack L₃)
        rev [])
      main
      (List.reverseAux
        (update
          (elim (trList L₁) (Option.iget (some Γ'.cons) :: List.reverseAux (trNat a) []) []
            (trList L₂ ++ Γ'.consₗ :: L₃))
          stack L₃ rev)
        (update
          (elim (trList L₁) (Option.iget (some Γ'.cons) :: List.reverseAux (trNat a) []) []
            (trList L₂ ++ Γ'.consₗ :: L₃))
          stack L₃ main))
case cons
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
a : ℕ
L₂ : List ℕ
⊢ TransGen
    (fun a b =>
      (match a with
        | { l := none, var := var, stk := stk } => none
        | { l := some l, var := v, stk := S } => some (TM2.stepAux (tr l) v S)) =
        some b)
    { l := some (unrev q), var := some Γ'.consₗ,
      stk :=
        update
          (elim (trList L₁) (Option.iget (some Γ'.cons) :: List.reverseAux (trNat a) []) []
            (trList L₂ ++ Γ'.consₗ :: L₃))
          stack L₃ }
    { l := some q, var := none, stk := elim (trNat a ++ Γ'.cons :: trList L₁) [] [] L₃ }
convert unrev_ok using 2
no goals
case h.e'_2.h.e'_7
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
a : ℕ
L₂ : List ℕ
⊢ elim (trNat a ++ Γ'.cons :: trList L₁) [] [] L₃ =
    update
      (update
        (update
          (elim (trList L₁) (Option.iget (some Γ'.cons) :: List.reverseAux (trNat a) []) []
            (trList L₂ ++ Γ'.consₗ :: L₃))
          stack L₃)
        rev [])
      main
      (List.reverseAux
        (update
          (elim (trList L₁) (Option.iget (some Γ'.cons) :: List.reverseAux (trNat a) []) []
            (trList L₂ ++ Γ'.consₗ :: L₃))
          stack L₃ rev)
        (update
          (elim (trList L₁) (Option.iget (some Γ'.cons) :: List.reverseAux (trNat a) []) []
            (trList L₂ ++ Γ'.consₗ :: L₃))
          stack L₃ main))
simp [List.reverseAux_eq]
no goals
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
a : ℕ
L₂ : List ℕ
⊢ stack ≠ rev
decide
no goals
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
a : ℕ
L₂ : List ℕ
⊢ elim (trList L₁) [] [] (trList (a :: L₂) ++ Γ'.consₗ :: L₃) stack =
    trNat a ++ Γ'.cons :: (trList L₂ ++ Γ'.consₗ :: L₃)
simp
no goals
q : Λ'
s : Option Γ'
L₁ : List ℕ
L₃ : List Γ'
a : ℕ
L₂ : List ℕ
⊢ elim (trList L₁) (Option.iget (some Γ'.cons) :: List.reverseAux (trNat a) []) [] (trList L₂ ++ Γ'.consₗ :: L₃) stack =
    trList L₂ ++ Γ'.consₗ :: L₃
simp