Theorem: Regex.VM.stepChar_mem_done_iff
Proof state before:
nfa : NFA
c : Char
pos : String.Pos
next : SparseSet nfa.nodes.size
saveSlots : Data.Vec (Array (Option String.Pos)) nfa.nodes.size
target : Fin nfa.nodes.size
matched' : Option (Array (Option String.Pos))
next' : SparseSet nfa.nodes.size
saveSlots' : Data.Vec (Array (Option String.Pos)) nfa.nodes.size
h :
  (match hn : nfa[target] with
    | Node.char c' target' =>
      if c = c' then
        let_fun isLt := ⋯;
        let currentSave := saveSlots.get ↑target ⋯;
        exploreεClosure nfa pos next currentSave none saveSlots ⟨target', isLt⟩ #[]
      else (none, next, saveSlots)
    | Node.sparse cs target' =>
      if c ∈ cs then
        let_fun isLt := ⋯;
        let currentSave := saveSlots.get ↑target ⋯;
        exploreεClosure nfa pos next currentSave none saveSlots ⟨target', isLt⟩ #[]
      else (none, next, saveSlots)
    | x => (none, next, saveSlots)) =
    (matched', next', saveSlots')
hnotDone : ∀ i ∈ next, nfa[i] ≠ Node.done
⊢ (∃ i ∈ next', nfa[i] = Node.done) ↔ matched'.isSome = true
Tactic:
split at h
Proof state after:
case h_1
nfa : NFA
c : Char
pos : String.Pos
next : SparseSet nfa.nodes.size
saveSlots : Data.Vec (Array (Option String.Pos)) nfa.nodes.size
target : Fin nfa.nodes.size
matched' : Option (Array (Option String.Pos))
next' : SparseSet nfa.nodes.size
saveSlots' : Data.Vec (Array (Option String.Pos)) nfa.nodes.size
hnotDone : ∀ i ∈ next, nfa[i] ≠ Node.done
c'✝ : Char
target'✝ : ℕ
heq✝ : nfa[target] = Node.char c'✝ target'✝
h :
  (if c = c'✝ then
      let_fun isLt := ⋯;
      let currentSave := saveSlots.get ↑target ⋯;
      exploreεClosure nfa pos next currentSave none saveSlots ⟨target'✝, isLt⟩ #[]
    else (none, next, saveSlots)) =
    (matched', next', saveSlots')
⊢ (∃ i ∈ next', nfa[i] = Node.done) ↔ matched'.isSome = true

case h_2
nfa : NFA
c : Char
pos : String.Pos
next : SparseSet nfa.nodes.size
saveSlots : Data.Vec (Array (Option String.Pos)) nfa.nodes.size
target : Fin nfa.nodes.size
matched' : Option (Array (Option String.Pos))
next' : SparseSet nfa.nodes.size
saveSlots' : Data.Vec (Array (Option String.Pos)) nfa.nodes.size
hnotDone : ∀ i ∈ next, nfa[i] ≠ Node.done
cs✝ : Data.Classes
target'✝ : ℕ
heq✝ : nfa[target] = Node.sparse cs✝ target'✝
h :
  (if c ∈ cs✝ then
      let_fun isLt := ⋯;
      let currentSave := saveSlots.get ↑target ⋯;
      exploreεClosure nfa pos next currentSave none saveSlots ⟨target'✝, isLt⟩ #[]
    else (none, next, saveSlots)) =
    (matched', next', saveSlots')
⊢ (∃ i ∈ next', nfa[i] = Node.done) ↔ matched'.isSome = true

case h_3
nfa : NFA
c : Char
pos : String.Pos
next : SparseSet nfa.nodes.size
saveSlots : Data.Vec (Array (Option String.Pos)) nfa.nodes.size
target : Fin nfa.nodes.size
matched' : Option (Array (Option String.Pos))
next' : SparseSet nfa.nodes.size
saveSlots' : Data.Vec (Array (Option String.Pos)) nfa.nodes.size
hnotDone : ∀ i ∈ next, nfa[i] ≠ Node.done
x✝¹ : ∀ (c' : Char) (target' : ℕ), nfa[target] = Node.char c' target' → False
x✝ : ∀ (cs : Data.Classes) (target' : ℕ), nfa[target] = Node.sparse cs target' → False
h : (none, next, saveSlots) = (matched', next', saveSlots')
⊢ (∃ i ∈ next', nfa[i] = Node.done) ↔ matched'.isSome = true