l3lab/ntp-mathlib huggingface dataset:
theorem cont_eval_fix {f k v} (fok : Code.Ok f) :
    Turing.eval step (stepNormal f (Cont.fix f k) v) =
      f.fix.eval v >>= fun v => Turing.eval step (Cfg.ret k v) := by
  refine' Part.ext fun x => _
  simp only [Part.bind_eq_bind, Part.mem_bind_iff]
  constructor
  · suffices ∀ c, x ∈ eval step c → ∀ v c', c = Cfg.then c' (Cont.fix f k) →
      Reaches step (stepNormal f Cont.halt v) c' →
        ∃ v₁ ∈ f.eval v, ∃ v₂ ∈ if List.headI v₁ = 0 then pure v₁.tail else f.fix.eval v₁.tail,
          x ∈ eval step (Cfg.ret k v₂) by
      intro h
      obtain ⟨v₁, hv₁, v₂, hv₂, h₃⟩ :=
        this _ h _ _ (stepNormal_then _ Cont.halt _ _) ReflTransGen.refl
      refine' ⟨v₂, PFun.mem_fix_iff.2 _, h₃⟩
      simp only [Part.eq_some_iff.2 hv₁, Part.map_some]
      split_ifs at hv₂ ⊢
      · rw [Part.mem_some_iff.1 hv₂]
        exact Or.inl (Part.mem_some _)
      · 

Proof state:
case neg
f : Code
k : Cont
v : List ℕ
fok : Code.Ok f
x : Cfg
this :
  ∀ (c : Cfg),
    x ∈ eval step c →
      ∀ (v : List ℕ) (c' : Cfg),
        c = Cfg.then c' (Cont.fix f k) →
          Reaches step (stepNormal f Cont.halt v) c' →
            ∃ v₁ ∈ Code.eval f v,
              ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
                x ∈ eval step (Cfg.ret k v₂)
h : x ∈ eval step (stepNormal f (Cont.fix f k) v)
v₁ : List ℕ
hv₁ : v₁ ∈ Code.eval f v
v₂ : List ℕ
h₃ : x ∈ eval step (Cfg.ret k v₂)
h✝ : ¬List.headI v₁ = 0
hv₂ : v₂ ∈ Code.eval (Code.fix f) (List.tail v₁)
⊢ Sum.inl v₂ ∈ Part.some (Sum.inr (List.tail v₁)) ∨
    ∃ a',
      Sum.inr a' ∈ Part.some (Sum.inr (List.tail v₁)) ∧
        v₂ ∈
          PFun.fix
            (fun v =>
              Part.map (fun v => if List.headI v = 0 then Sum.inl (List.tail v) else Sum.inr (List.tail v))
                (Code.eval f v))
            a'

Next tactic:
exact Or.inr ⟨_, Part.mem_some _, hv₂⟩
theorem cont_eval_fix {f k v} (fok : Code.Ok f) :
    Turing.eval step (stepNormal f (Cont.fix f k) v) =
      f.fix.eval v >>= fun v => Turing.eval step (Cfg.ret k v) := by
  refine' Part.ext fun x => _
  simp only [Part.bind_eq_bind, Part.mem_bind_iff]
  constructor
  · suffices ∀ c, x ∈ eval step c → ∀ v c', c = Cfg.then c' (Cont.fix f k) →
      Reaches step (stepNormal f Cont.halt v) c' →
        ∃ v₁ ∈ f.eval v, ∃ v₂ ∈ if List.headI v₁ = 0 then pure v₁.tail else f.fix.eval v₁.tail,
          x ∈ eval step (Cfg.ret k v₂) by
      intro h
      obtain ⟨v₁, hv₁, v₂, hv₂, h₃⟩ :=
        this _ h _ _ (stepNormal_then _ Cont.halt _ _) ReflTransGen.refl
      refine' ⟨v₂, PFun.mem_fix_iff.2 _, h₃⟩
      simp only [Part.eq_some_iff.2 hv₁, Part.map_some]
      split_ifs at hv₂ ⊢
      · rw [Part.mem_some_iff.1 hv₂]
        exact Or.inl (Part.mem_some _)
      · exact Or.inr ⟨_, Part.mem_some _, hv₂⟩
    

Proof state:
case mp
f : Code
k : Cont
v : List ℕ
fok : Code.Ok f
x : Cfg
⊢ ∀ (c : Cfg),
    x ∈ eval step c →
      ∀ (v : List ℕ) (c' : Cfg),
        c = Cfg.then c' (Cont.fix f k) →
          Reaches step (stepNormal f Cont.halt v) c' →
            ∃ v₁ ∈ Code.eval f v,
              ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
                x ∈ eval step (Cfg.ret k v₂)

Next tactic:
refine' fun c he => evalInduction he fun y h IH => _
theorem cont_eval_fix {f k v} (fok : Code.Ok f) :
    Turing.eval step (stepNormal f (Cont.fix f k) v) =
      f.fix.eval v >>= fun v => Turing.eval step (Cfg.ret k v) := by
  refine' Part.ext fun x => _
  simp only [Part.bind_eq_bind, Part.mem_bind_iff]
  constructor
  · suffices ∀ c, x ∈ eval step c → ∀ v c', c = Cfg.then c' (Cont.fix f k) →
      Reaches step (stepNormal f Cont.halt v) c' →
        ∃ v₁ ∈ f.eval v, ∃ v₂ ∈ if List.headI v₁ = 0 then pure v₁.tail else f.fix.eval v₁.tail,
          x ∈ eval step (Cfg.ret k v₂) by
      intro h
      obtain ⟨v₁, hv₁, v₂, hv₂, h₃⟩ :=
        this _ h _ _ (stepNormal_then _ Cont.halt _ _) ReflTransGen.refl
      refine' ⟨v₂, PFun.mem_fix_iff.2 _, h₃⟩
      simp only [Part.eq_some_iff.2 hv₁, Part.map_some]
      split_ifs at hv₂ ⊢
      · rw [Part.mem_some_iff.1 hv₂]
        exact Or.inl (Part.mem_some _)
      · exact Or.inr ⟨_, Part.mem_some _, hv₂⟩
    refine' fun c he => evalInduction he fun y h IH => _
    

Proof state:
case mp
f : Code
k : Cont
v : List ℕ
fok : Code.Ok f
x c : Cfg
he : x ∈ eval step c
y : Cfg
h : x ∈ eval step y
IH :
  ∀ (a' : Cfg),
    step y = some a' →
      ∀ (v : List ℕ) (c' : Cfg),
        a' = Cfg.then c' (Cont.fix f k) →
          Reaches step (stepNormal f Cont.halt v) c' →
            ∃ v₁ ∈ Code.eval f v,
              ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
                x ∈ eval step (Cfg.ret k v₂)
⊢ ∀ (v : List ℕ) (c' : Cfg),
    y = Cfg.then c' (Cont.fix f k) →
      Reaches step (stepNormal f Cont.halt v) c' →
        ∃ v₁ ∈ Code.eval f v,
          ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
            x ∈ eval step (Cfg.ret k v₂)

Next tactic:
rintro v (⟨v'⟩ | ⟨k', v'⟩) rfl hr
theorem cont_eval_fix {f k v} (fok : Code.Ok f) :
    Turing.eval step (stepNormal f (Cont.fix f k) v) =
      f.fix.eval v >>= fun v => Turing.eval step (Cfg.ret k v) := by
  refine' Part.ext fun x => _
  simp only [Part.bind_eq_bind, Part.mem_bind_iff]
  constructor
  · suffices ∀ c, x ∈ eval step c → ∀ v c', c = Cfg.then c' (Cont.fix f k) →
      Reaches step (stepNormal f Cont.halt v) c' →
        ∃ v₁ ∈ f.eval v, ∃ v₂ ∈ if List.headI v₁ = 0 then pure v₁.tail else f.fix.eval v₁.tail,
          x ∈ eval step (Cfg.ret k v₂) by
      intro h
      obtain ⟨v₁, hv₁, v₂, hv₂, h₃⟩ :=
        this _ h _ _ (stepNormal_then _ Cont.halt _ _) ReflTransGen.refl
      refine' ⟨v₂, PFun.mem_fix_iff.2 _, h₃⟩
      simp only [Part.eq_some_iff.2 hv₁, Part.map_some]
      split_ifs at hv₂ ⊢
      · rw [Part.mem_some_iff.1 hv₂]
        exact Or.inl (Part.mem_some _)
      · exact Or.inr ⟨_, Part.mem_some _, hv₂⟩
    refine' fun c he => evalInduction he fun y h IH => _
    rintro v (⟨v'⟩ | ⟨k', v'⟩) rfl hr <;> 

Proof state:
case mp.halt
f : Code
k : Cont
v✝ : List ℕ
fok : Code.Ok f
x c : Cfg
he : x ∈ eval step c
v v' : List ℕ
h : x ∈ eval step (Cfg.then (Cfg.halt v') (Cont.fix f k))
IH :
  ∀ (a' : Cfg),
    step (Cfg.then (Cfg.halt v') (Cont.fix f k)) = some a' →
      ∀ (v : List ℕ) (c' : Cfg),
        a' = Cfg.then c' (Cont.fix f k) →
          Reaches step (stepNormal f Cont.halt v) c' →
            ∃ v₁ ∈ Code.eval f v,
              ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
                x ∈ eval step (Cfg.ret k v₂)
hr : Reaches step (stepNormal f Cont.halt v) (Cfg.halt v')
⊢ ∃ v₁ ∈ Code.eval f v,
    ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
      x ∈ eval step (Cfg.ret k v₂)

Next tactic:
rw [Cfg.then] at h IH
theorem cont_eval_fix {f k v} (fok : Code.Ok f) :
    Turing.eval step (stepNormal f (Cont.fix f k) v) =
      f.fix.eval v >>= fun v => Turing.eval step (Cfg.ret k v) := by
  refine' Part.ext fun x => _
  simp only [Part.bind_eq_bind, Part.mem_bind_iff]
  constructor
  · suffices ∀ c, x ∈ eval step c → ∀ v c', c = Cfg.then c' (Cont.fix f k) →
      Reaches step (stepNormal f Cont.halt v) c' →
        ∃ v₁ ∈ f.eval v, ∃ v₂ ∈ if List.headI v₁ = 0 then pure v₁.tail else f.fix.eval v₁.tail,
          x ∈ eval step (Cfg.ret k v₂) by
      intro h
      obtain ⟨v₁, hv₁, v₂, hv₂, h₃⟩ :=
        this _ h _ _ (stepNormal_then _ Cont.halt _ _) ReflTransGen.refl
      refine' ⟨v₂, PFun.mem_fix_iff.2 _, h₃⟩
      simp only [Part.eq_some_iff.2 hv₁, Part.map_some]
      split_ifs at hv₂ ⊢
      · rw [Part.mem_some_iff.1 hv₂]
        exact Or.inl (Part.mem_some _)
      · exact Or.inr ⟨_, Part.mem_some _, hv₂⟩
    refine' fun c he => evalInduction he fun y h IH => _
    rintro v (⟨v'⟩ | ⟨k', v'⟩) rfl hr <;> 

Proof state:
case mp.ret
f : Code
k : Cont
v✝ : List ℕ
fok : Code.Ok f
x c : Cfg
he : x ∈ eval step c
v : List ℕ
k' : Cont
v' : List ℕ
h : x ∈ eval step (Cfg.then (Cfg.ret k' v') (Cont.fix f k))
IH :
  ∀ (a' : Cfg),
    step (Cfg.then (Cfg.ret k' v') (Cont.fix f k)) = some a' →
      ∀ (v : List ℕ) (c' : Cfg),
        a' = Cfg.then c' (Cont.fix f k) →
          Reaches step (stepNormal f Cont.halt v) c' →
            ∃ v₁ ∈ Code.eval f v,
              ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
                x ∈ eval step (Cfg.ret k v₂)
hr : Reaches step (stepNormal f Cont.halt v) (Cfg.ret k' v')
⊢ ∃ v₁ ∈ Code.eval f v,
    ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
      x ∈ eval step (Cfg.ret k v₂)

Next tactic:
rw [Cfg.then] at h IH
theorem cont_eval_fix {f k v} (fok : Code.Ok f) :
    Turing.eval step (stepNormal f (Cont.fix f k) v) =
      f.fix.eval v >>= fun v => Turing.eval step (Cfg.ret k v) := by
  refine' Part.ext fun x => _
  simp only [Part.bind_eq_bind, Part.mem_bind_iff]
  constructor
  · suffices ∀ c, x ∈ eval step c → ∀ v c', c = Cfg.then c' (Cont.fix f k) →
      Reaches step (stepNormal f Cont.halt v) c' →
        ∃ v₁ ∈ f.eval v, ∃ v₂ ∈ if List.headI v₁ = 0 then pure v₁.tail else f.fix.eval v₁.tail,
          x ∈ eval step (Cfg.ret k v₂) by
      intro h
      obtain ⟨v₁, hv₁, v₂, hv₂, h₃⟩ :=
        this _ h _ _ (stepNormal_then _ Cont.halt _ _) ReflTransGen.refl
      refine' ⟨v₂, PFun.mem_fix_iff.2 _, h₃⟩
      simp only [Part.eq_some_iff.2 hv₁, Part.map_some]
      split_ifs at hv₂ ⊢
      · rw [Part.mem_some_iff.1 hv₂]
        exact Or.inl (Part.mem_some _)
      · exact Or.inr ⟨_, Part.mem_some _, hv₂⟩
    refine' fun c he => evalInduction he fun y h IH => _
    rintro v (⟨v'⟩ | ⟨k', v'⟩) rfl hr <;> rw [Cfg.then] at h IH <;> 

Proof state:
case mp.halt
f : Code
k : Cont
v✝ : List ℕ
fok : Code.Ok f
x c : Cfg
he : x ∈ eval step c
v v' : List ℕ
h :
  x ∈
    eval step
      ((match (motive := Cfg → Cont → Cfg) Cfg.halt v' with
        | Cfg.halt v => fun k' => stepRet k' v
        | Cfg.ret k v => fun k' => Cfg.ret (Cont.then k k') v)
        (Cont.fix f k))
IH :
  ∀ (a' : Cfg),
    step
          ((match (motive := Cfg → Cont → Cfg) Cfg.halt v' with
            | Cfg.halt v => fun k' => stepRet k' v
            | Cfg.ret k v => fun k' => Cfg.ret (Cont.then k k') v)
            (Cont.fix f k)) =
        some a' →
      ∀ (v : List ℕ) (c' : Cfg),
        a' = Cfg.then c' (Cont.fix f k) →
          Reaches step (stepNormal f Cont.halt v) c' →
            ∃ v₁ ∈ Code.eval f v,
              ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
                x ∈ eval step (Cfg.ret k v₂)
hr : Reaches step (stepNormal f Cont.halt v) (Cfg.halt v')
⊢ ∃ v₁ ∈ Code.eval f v,
    ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
      x ∈ eval step (Cfg.ret k v₂)

Next tactic:
simp only [] at h IH
theorem cont_eval_fix {f k v} (fok : Code.Ok f) :
    Turing.eval step (stepNormal f (Cont.fix f k) v) =
      f.fix.eval v >>= fun v => Turing.eval step (Cfg.ret k v) := by
  refine' Part.ext fun x => _
  simp only [Part.bind_eq_bind, Part.mem_bind_iff]
  constructor
  · suffices ∀ c, x ∈ eval step c → ∀ v c', c = Cfg.then c' (Cont.fix f k) →
      Reaches step (stepNormal f Cont.halt v) c' →
        ∃ v₁ ∈ f.eval v, ∃ v₂ ∈ if List.headI v₁ = 0 then pure v₁.tail else f.fix.eval v₁.tail,
          x ∈ eval step (Cfg.ret k v₂) by
      intro h
      obtain ⟨v₁, hv₁, v₂, hv₂, h₃⟩ :=
        this _ h _ _ (stepNormal_then _ Cont.halt _ _) ReflTransGen.refl
      refine' ⟨v₂, PFun.mem_fix_iff.2 _, h₃⟩
      simp only [Part.eq_some_iff.2 hv₁, Part.map_some]
      split_ifs at hv₂ ⊢
      · rw [Part.mem_some_iff.1 hv₂]
        exact Or.inl (Part.mem_some _)
      · exact Or.inr ⟨_, Part.mem_some _, hv₂⟩
    refine' fun c he => evalInduction he fun y h IH => _
    rintro v (⟨v'⟩ | ⟨k', v'⟩) rfl hr <;> rw [Cfg.then] at h IH <;> 

Proof state:
case mp.ret
f : Code
k : Cont
v✝ : List ℕ
fok : Code.Ok f
x c : Cfg
he : x ∈ eval step c
v : List ℕ
k' : Cont
v' : List ℕ
h :
  x ∈
    eval step
      ((match (motive := Cfg → Cont → Cfg) Cfg.ret k' v' with
        | Cfg.halt v => fun k' => stepRet k' v
        | Cfg.ret k v => fun k' => Cfg.ret (Cont.then k k') v)
        (Cont.fix f k))
IH :
  ∀ (a' : Cfg),
    step
          ((match (motive := Cfg → Cont → Cfg) Cfg.ret k' v' with
            | Cfg.halt v => fun k' => stepRet k' v
            | Cfg.ret k v => fun k' => Cfg.ret (Cont.then k k') v)
            (Cont.fix f k)) =
        some a' →
      ∀ (v : List ℕ) (c' : Cfg),
        a' = Cfg.then c' (Cont.fix f k) →
          Reaches step (stepNormal f Cont.halt v) c' →
            ∃ v₁ ∈ Code.eval f v,
              ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
                x ∈ eval step (Cfg.ret k v₂)
hr : Reaches step (stepNormal f Cont.halt v) (Cfg.ret k' v')
⊢ ∃ v₁ ∈ Code.eval f v,
    ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
      x ∈ eval step (Cfg.ret k v₂)

Next tactic:
simp only [] at h IH
theorem cont_eval_fix {f k v} (fok : Code.Ok f) :
    Turing.eval step (stepNormal f (Cont.fix f k) v) =
      f.fix.eval v >>= fun v => Turing.eval step (Cfg.ret k v) := by
  refine' Part.ext fun x => _
  simp only [Part.bind_eq_bind, Part.mem_bind_iff]
  constructor
  · suffices ∀ c, x ∈ eval step c → ∀ v c', c = Cfg.then c' (Cont.fix f k) →
      Reaches step (stepNormal f Cont.halt v) c' →
        ∃ v₁ ∈ f.eval v, ∃ v₂ ∈ if List.headI v₁ = 0 then pure v₁.tail else f.fix.eval v₁.tail,
          x ∈ eval step (Cfg.ret k v₂) by
      intro h
      obtain ⟨v₁, hv₁, v₂, hv₂, h₃⟩ :=
        this _ h _ _ (stepNormal_then _ Cont.halt _ _) ReflTransGen.refl
      refine' ⟨v₂, PFun.mem_fix_iff.2 _, h₃⟩
      simp only [Part.eq_some_iff.2 hv₁, Part.map_some]
      split_ifs at hv₂ ⊢
      · rw [Part.mem_some_iff.1 hv₂]
        exact Or.inl (Part.mem_some _)
      · exact Or.inr ⟨_, Part.mem_some _, hv₂⟩
    refine' fun c he => evalInduction he fun y h IH => _
    rintro v (⟨v'⟩ | ⟨k', v'⟩) rfl hr <;> rw [Cfg.then] at h IH <;> simp only [] at h IH
    · 

Proof state:
case mp.halt
f : Code
k : Cont
v✝ : List ℕ
fok : Code.Ok f
x c : Cfg
he : x ∈ eval step c
v v' : List ℕ
h : x ∈ eval step (stepRet (Cont.fix f k) v')
IH :
  ∀ (a' : Cfg),
    step (stepRet (Cont.fix f k) v') = some a' →
      ∀ (v : List ℕ) (c' : Cfg),
        a' = Cfg.then c' (Cont.fix f k) →
          Reaches step (stepNormal f Cont.halt v) c' →
            ∃ v₁ ∈ Code.eval f v,
              ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
                x ∈ eval step (Cfg.ret k v₂)
hr : Reaches step (stepNormal f Cont.halt v) (Cfg.halt v')
⊢ ∃ v₁ ∈ Code.eval f v,
    ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
      x ∈ eval step (Cfg.ret k v₂)

Next tactic:
have := mem_eval.2 ⟨hr, rfl⟩
theorem cont_eval_fix {f k v} (fok : Code.Ok f) :
    Turing.eval step (stepNormal f (Cont.fix f k) v) =
      f.fix.eval v >>= fun v => Turing.eval step (Cfg.ret k v) := by
  refine' Part.ext fun x => _
  simp only [Part.bind_eq_bind, Part.mem_bind_iff]
  constructor
  · suffices ∀ c, x ∈ eval step c → ∀ v c', c = Cfg.then c' (Cont.fix f k) →
      Reaches step (stepNormal f Cont.halt v) c' →
        ∃ v₁ ∈ f.eval v, ∃ v₂ ∈ if List.headI v₁ = 0 then pure v₁.tail else f.fix.eval v₁.tail,
          x ∈ eval step (Cfg.ret k v₂) by
      intro h
      obtain ⟨v₁, hv₁, v₂, hv₂, h₃⟩ :=
        this _ h _ _ (stepNormal_then _ Cont.halt _ _) ReflTransGen.refl
      refine' ⟨v₂, PFun.mem_fix_iff.2 _, h₃⟩
      simp only [Part.eq_some_iff.2 hv₁, Part.map_some]
      split_ifs at hv₂ ⊢
      · rw [Part.mem_some_iff.1 hv₂]
        exact Or.inl (Part.mem_some _)
      · exact Or.inr ⟨_, Part.mem_some _, hv₂⟩
    refine' fun c he => evalInduction he fun y h IH => _
    rintro v (⟨v'⟩ | ⟨k', v'⟩) rfl hr <;> rw [Cfg.then] at h IH <;> simp only [] at h IH
    · have := mem_eval.2 ⟨hr, rfl⟩
      

Proof state:
case mp.halt
f : Code
k : Cont
v✝ : List ℕ
fok : Code.Ok f
x c : Cfg
he : x ∈ eval step c
v v' : List ℕ
h : x ∈ eval step (stepRet (Cont.fix f k) v')
IH :
  ∀ (a' : Cfg),
    step (stepRet (Cont.fix f k) v') = some a' →
      ∀ (v : List ℕ) (c' : Cfg),
        a' = Cfg.then c' (Cont.fix f k) →
          Reaches step (stepNormal f Cont.halt v) c' →
            ∃ v₁ ∈ Code.eval f v,
              ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
                x ∈ eval step (Cfg.ret k v₂)
hr : Reaches step (stepNormal f Cont.halt v) (Cfg.halt v')
this : Cfg.halt v' ∈ eval step (stepNormal f Cont.halt v)
⊢ ∃ v₁ ∈ Code.eval f v,
    ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
      x ∈ eval step (Cfg.ret k v₂)

Next tactic:
rw [fok, Part.bind_eq_bind, Part.mem_bind_iff] at this
theorem cont_eval_fix {f k v} (fok : Code.Ok f) :
    Turing.eval step (stepNormal f (Cont.fix f k) v) =
      f.fix.eval v >>= fun v => Turing.eval step (Cfg.ret k v) := by
  refine' Part.ext fun x => _
  simp only [Part.bind_eq_bind, Part.mem_bind_iff]
  constructor
  · suffices ∀ c, x ∈ eval step c → ∀ v c', c = Cfg.then c' (Cont.fix f k) →
      Reaches step (stepNormal f Cont.halt v) c' →
        ∃ v₁ ∈ f.eval v, ∃ v₂ ∈ if List.headI v₁ = 0 then pure v₁.tail else f.fix.eval v₁.tail,
          x ∈ eval step (Cfg.ret k v₂) by
      intro h
      obtain ⟨v₁, hv₁, v₂, hv₂, h₃⟩ :=
        this _ h _ _ (stepNormal_then _ Cont.halt _ _) ReflTransGen.refl
      refine' ⟨v₂, PFun.mem_fix_iff.2 _, h₃⟩
      simp only [Part.eq_some_iff.2 hv₁, Part.map_some]
      split_ifs at hv₂ ⊢
      · rw [Part.mem_some_iff.1 hv₂]
        exact Or.inl (Part.mem_some _)
      · exact Or.inr ⟨_, Part.mem_some _, hv₂⟩
    refine' fun c he => evalInduction he fun y h IH => _
    rintro v (⟨v'⟩ | ⟨k', v'⟩) rfl hr <;> rw [Cfg.then] at h IH <;> simp only [] at h IH
    · have := mem_eval.2 ⟨hr, rfl⟩
      rw [fok, Part.bind_eq_bind, Part.mem_bind_iff] at this
      

Proof state:
case mp.halt
f : Code
k : Cont
v✝ : List ℕ
fok : Code.Ok f
x c : Cfg
he : x ∈ eval step c
v v' : List ℕ
h : x ∈ eval step (stepRet (Cont.fix f k) v')
IH :
  ∀ (a' : Cfg),
    step (stepRet (Cont.fix f k) v') = some a' →
      ∀ (v : List ℕ) (c' : Cfg),
        a' = Cfg.then c' (Cont.fix f k) →
          Reaches step (stepNormal f Cont.halt v) c' →
            ∃ v₁ ∈ Code.eval f v,
              ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
                x ∈ eval step (Cfg.ret k v₂)
hr : Reaches step (stepNormal f Cont.halt v) (Cfg.halt v')
this : ∃ a ∈ Code.eval f v, Cfg.halt v' ∈ eval step (Cfg.ret Cont.halt a)
⊢ ∃ v₁ ∈ Code.eval f v,
    ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
      x ∈ eval step (Cfg.ret k v₂)

Next tactic:
obtain ⟨v'', h₁, h₂⟩ := this
theorem cont_eval_fix {f k v} (fok : Code.Ok f) :
    Turing.eval step (stepNormal f (Cont.fix f k) v) =
      f.fix.eval v >>= fun v => Turing.eval step (Cfg.ret k v) := by
  refine' Part.ext fun x => _
  simp only [Part.bind_eq_bind, Part.mem_bind_iff]
  constructor
  · suffices ∀ c, x ∈ eval step c → ∀ v c', c = Cfg.then c' (Cont.fix f k) →
      Reaches step (stepNormal f Cont.halt v) c' →
        ∃ v₁ ∈ f.eval v, ∃ v₂ ∈ if List.headI v₁ = 0 then pure v₁.tail else f.fix.eval v₁.tail,
          x ∈ eval step (Cfg.ret k v₂) by
      intro h
      obtain ⟨v₁, hv₁, v₂, hv₂, h₃⟩ :=
        this _ h _ _ (stepNormal_then _ Cont.halt _ _) ReflTransGen.refl
      refine' ⟨v₂, PFun.mem_fix_iff.2 _, h₃⟩
      simp only [Part.eq_some_iff.2 hv₁, Part.map_some]
      split_ifs at hv₂ ⊢
      · rw [Part.mem_some_iff.1 hv₂]
        exact Or.inl (Part.mem_some _)
      · exact Or.inr ⟨_, Part.mem_some _, hv₂⟩
    refine' fun c he => evalInduction he fun y h IH => _
    rintro v (⟨v'⟩ | ⟨k', v'⟩) rfl hr <;> rw [Cfg.then] at h IH <;> simp only [] at h IH
    · have := mem_eval.2 ⟨hr, rfl⟩
      rw [fok, Part.bind_eq_bind, Part.mem_bind_iff] at this
      obtain ⟨v'', h₁, h₂⟩ := this
      

Proof state:
case mp.halt.intro.intro
f : Code
k : Cont
v✝ : List ℕ
fok : Code.Ok f
x c : Cfg
he : x ∈ eval step c
v v' : List ℕ
h : x ∈ eval step (stepRet (Cont.fix f k) v')
IH :
  ∀ (a' : Cfg),
    step (stepRet (Cont.fix f k) v') = some a' →
      ∀ (v : List ℕ) (c' : Cfg),
        a' = Cfg.then c' (Cont.fix f k) →
          Reaches step (stepNormal f Cont.halt v) c' →
            ∃ v₁ ∈ Code.eval f v,
              ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
                x ∈ eval step (Cfg.ret k v₂)
hr : Reaches step (stepNormal f Cont.halt v) (Cfg.halt v')
v'' : List ℕ
h₁ : v'' ∈ Code.eval f v
h₂ : Cfg.halt v' ∈ eval step (Cfg.ret Cont.halt v'')
⊢ ∃ v₁ ∈ Code.eval f v,
    ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
      x ∈ eval step (Cfg.ret k v₂)

Next tactic:
rw [reaches_eval] at h₂
theorem cont_eval_fix {f k v} (fok : Code.Ok f) :
    Turing.eval step (stepNormal f (Cont.fix f k) v) =
      f.fix.eval v >>= fun v => Turing.eval step (Cfg.ret k v) := by
  refine' Part.ext fun x => _
  simp only [Part.bind_eq_bind, Part.mem_bind_iff]
  constructor
  · suffices ∀ c, x ∈ eval step c → ∀ v c', c = Cfg.then c' (Cont.fix f k) →
      Reaches step (stepNormal f Cont.halt v) c' →
        ∃ v₁ ∈ f.eval v, ∃ v₂ ∈ if List.headI v₁ = 0 then pure v₁.tail else f.fix.eval v₁.tail,
          x ∈ eval step (Cfg.ret k v₂) by
      intro h
      obtain ⟨v₁, hv₁, v₂, hv₂, h₃⟩ :=
        this _ h _ _ (stepNormal_then _ Cont.halt _ _) ReflTransGen.refl
      refine' ⟨v₂, PFun.mem_fix_iff.2 _, h₃⟩
      simp only [Part.eq_some_iff.2 hv₁, Part.map_some]
      split_ifs at hv₂ ⊢
      · rw [Part.mem_some_iff.1 hv₂]
        exact Or.inl (Part.mem_some _)
      · exact Or.inr ⟨_, Part.mem_some _, hv₂⟩
    refine' fun c he => evalInduction he fun y h IH => _
    rintro v (⟨v'⟩ | ⟨k', v'⟩) rfl hr <;> rw [Cfg.then] at h IH <;> simp only [] at h IH
    · have := mem_eval.2 ⟨hr, rfl⟩
      rw [fok, Part.bind_eq_bind, Part.mem_bind_iff] at this
      obtain ⟨v'', h₁, h₂⟩ := this
      rw [reaches_eval] at h₂
      swap
      exact ReflTransGen.single rfl
      

Proof state:
case mp.halt.intro.intro
f : Code
k : Cont
v✝ : List ℕ
fok : Code.Ok f
x c : Cfg
he : x ∈ eval step c
v v' : List ℕ
h : x ∈ eval step (stepRet (Cont.fix f k) v')
IH :
  ∀ (a' : Cfg),
    step (stepRet (Cont.fix f k) v') = some a' →
      ∀ (v : List ℕ) (c' : Cfg),
        a' = Cfg.then c' (Cont.fix f k) →
          Reaches step (stepNormal f Cont.halt v) c' →
            ∃ v₁ ∈ Code.eval f v,
              ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
                x ∈ eval step (Cfg.ret k v₂)
hr : Reaches step (stepNormal f Cont.halt v) (Cfg.halt v')
v'' : List ℕ
h₁ : v'' ∈ Code.eval f v
h₂✝ : Cfg.halt v' ∈ eval step (Cfg.ret Cont.halt v'')
h₂ : Cfg.halt v' ∈ eval step (stepRet Cont.halt v'')
⊢ ∃ v₁ ∈ Code.eval f v,
    ∃ v₂ ∈ if List.headI v₁ = 0 then pure (List.tail v₁) else Code.eval (Code.fix f) (List.tail v₁),
      x ∈ eval step (Cfg.ret k v₂)

Next tactic:
cases Part.mem_unique h₂ (mem_eval.2 ⟨ReflTransGen.refl, rfl⟩)