Theorem: Regex.NFA.matches_of_path.group (RegexCorrectness/NFA/Transition/Path/Equivalence/MatchOfPath.lean)

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq : nfa.pushRegex next (Expr.group i r) = result
path : (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
⊢ Expr.matches cs (Expr.group i r)
Tactic:
apply pushRegex.group eq
State after:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq : nfa.pushRegex next (Expr.group i r) = result
path : (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
⊢ ∀ (nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }) (nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size })
    (nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }) (property : nfa.nodes.size < (↑nfa''').nodes.size)
    (inBounds' : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1))
    (inBounds''' : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)),
    nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds' →
      nfa'' = (↑nfa').pushRegex (↑nfa').start r →
        nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds''' →
          result = ⟨↑nfa''', property⟩ → Expr.matches cs (Expr.group i r)

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq : nfa.pushRegex next (Expr.group i r) = result
path : (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
⊢ ∀ (nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }) (nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size })
    (nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }) (property : nfa.nodes.size < (↑nfa''').nodes.size)
    (inBounds' : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1))
    (inBounds''' : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)),
    nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds' →
      nfa'' = (↑nfa').pushRegex (↑nfa').start r →
        nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds''' →
          result = ⟨↑nfa''', property⟩ → Expr.matches cs (Expr.group i r)
Tactic:
intro nfa' nfa'' nfa''' property _ _ eq₁ eq₂ eq₃ eq
State after:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
path : (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
⊢ Expr.matches cs (Expr.group i r)

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
path : (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
⊢ Expr.matches cs (Expr.group i r)
Tactic:
suffices pathToNext nfa'' nfa'.val.start nfa'.val.nodes.size nfa''.val.start cs from
  .group (ih eq₂.symm this)
State after:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
path : (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
path : (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs
Tactic:
rw [eq] at path
State after:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
path : (↑⟨↑nfa''', property⟩).pathToNext (↑next) nfa.nodes.size (↑(↑⟨↑nfa''', property⟩).start) cs
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
path : (↑⟨↑nfa''', property⟩).pathToNext (↑next) nfa.nodes.size (↑(↑⟨↑nfa''', property⟩).start) cs
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs
Tactic:
simp at path
State after:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
path : (↑nfa''').pathToNext (↑next) nfa.nodes.size (↑(↑nfa''').start) cs
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
path : (↑nfa''').pathToNext (↑next) nfa.nodes.size (↑(↑nfa''').start) cs
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs
Tactic:
obtain ⟨i', cs₁, cs₂, eqs, path, step⟩ := path
State after:
case intro.intro.intro.intro.intro
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs

State before:
case intro.intro.intro.intro.intro
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs
Tactic:
have heq : i' = nfa.nodes.size ∧ cs₂ = [] := by
  cases Nat.eq_or_lt_of_le (le_of_pathIn_right path) with
  | inl eq =>
    have eqStart : nfa'''.val[nfa.nodes.size] = .save (2 * i + 1) next := by
      simp [eq₃]
      rw [pushNode_get_lt _ (Nat.lt_trans nfa'.property nfa''.property)]
      rw [pushRegex_get_lt eq₂.symm _ nfa'.property]
      simp [eq₁]
    rw [←eq] at step
    cases step with
    | charStep _ _ step =>
      rw [eqStart] at step
      simp [Node.charStep] at step
    | εStep _ _ eqs => exact ⟨eq.symm, rfl⟩
  | inr gt =>
    apply False.elim
    cases Nat.lt_or_ge i' nfa''.val.nodes.size with
    | inl lt =>
      have h₁ : nfa'.val.nodes.size ≤ i' := by
        simp [eq₁]
        exact gt
      have : i' < nfa'''.val.nodes.size := Nat.lt_trans lt nfa'''.property
      have : nfa'''.val[i'] = nfa''.val[i'] := by
        simp [eq₃]
        rw [pushNode_get_lt _ lt]
      have := eq_or_ge_of_step_pushRegex eq₂.symm h₁ lt (step.cast lt this).step
      cases this with
      | inl eq =>
        rw [eq₁] at eq
        simp at eq
        exact Nat.lt_irrefl _ (eq ▸ next.isLt)
      | inr ge => exact Nat.lt_irrefl _ (Nat.lt_of_lt_of_le (Nat.lt_trans next.isLt nfa'.property) ge)
    | inr ge =>
      have eqStart : nfa'''.val[nfa''.val.nodes.size]'nfa'''.property = .save (2 * i) nfa''.val.start := by
        simp [eq₃]
      have h₂ := step.h₂
      simp [eq₃] at h₂
      have : i' = nfa''.val.nodes.size := Nat.eq_of_le_of_lt_succ ge h₂
      have step := step.step
      simp [this, eqStart, Node.charStep, Node.εStep] at step
      have : nfa.nodes.size < nfa''.val.start := Nat.lt_of_lt_of_le nfa'.property (ge_pushRegex_start eq₂.symm)
      exact Nat.lt_irrefl _ (Nat.lt_trans (step ▸ this) next.isLt)
State after:
case intro.intro.intro.intro.intro
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
heq : i' = nfa.nodes.size ∧ cs₂ = []
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs

State before:
case intro.intro.intro.intro.intro
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
heq : i' = nfa.nodes.size ∧ cs₂ = []
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs
Tactic:
cases path with
| base _ =>
  rw [eq₃] at heq
  simp at heq
  have : nfa.nodes.size < nfa''.val.nodes.size := Nat.lt_trans nfa'.property nfa''.property
  exact (Nat.lt_irrefl _ (heq.left ▸ this)).elim
| @step _ j _ cs₁ cs₂ step' rest =>
  simp [eqs, heq.right]
  have eqStart : nfa'''.val[nfa'''.val.start.val] = .save (2 * i) nfa''.val.start := by
    rw [eq₃]
    simp
  cases step' with
  | charStep _ _ step => simp [eqStart, Node.charStep] at step
  | εStep _ _ step =>
    simp [eqStart, Node.εStep] at step
    subst step
    simp
    have : pathIn nfa'' nfa.nodes.size nfa''.val.start i' cs₂ := by
      apply rest.cast' (nfa''.val.start.isLt) (Nat.le_of_lt nfa'''.property)
      intro i _ h₂
      rw [eq₃, pushNode_get_lt _ h₂]
    have ⟨cs₃, cs₄, eqs, path', path''⟩ :=
      pathIn_split eq₂.symm (heq.left ▸ nfa'.property) (ge_pushRegex_start eq₂.symm) this
    cases path'' with
    | base _ =>
      simp at eqs
      exact eqs ▸ path'
    | step step rest =>
      have : nfa'.val.start.val < nfa''.val.nodes.size :=
        Nat.lt_trans nfa'.val.start.isLt nfa''.property
      have eqStart : nfa''.val[nfa'.val.start.val] = .save (2 * i + 1) next := by
        rw [pushRegex_get_lt eq₂.symm _ nfa'.val.start.isLt]
        rw [eq₁]
        simp
      have step := step.step
      simp [eqStart, Node.charStep, Node.εStep] at step
      subst step
      have := le_of_pathIn_left rest
      exact (Nat.lt_irrefl _ (Nat.lt_of_le_of_lt this next.isLt)).elim
State after:
no goals

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
⊢ i' = nfa.nodes.size ∧ cs₂ = []
Tactic:
cases Nat.eq_or_lt_of_le (le_of_pathIn_right path) with
| inl eq =>
  have eqStart : nfa'''.val[nfa.nodes.size] = .save (2 * i + 1) next := by
    simp [eq₃]
    rw [pushNode_get_lt _ (Nat.lt_trans nfa'.property nfa''.property)]
    rw [pushRegex_get_lt eq₂.symm _ nfa'.property]
    simp [eq₁]
  rw [←eq] at step
  cases step with
  | charStep _ _ step =>
    rw [eqStart] at step
    simp [Node.charStep] at step
  | εStep _ _ eqs => exact ⟨eq.symm, rfl⟩
| inr gt =>
  apply False.elim
  cases Nat.lt_or_ge i' nfa''.val.nodes.size with
  | inl lt =>
    have h₁ : nfa'.val.nodes.size ≤ i' := by
      simp [eq₁]
      exact gt
    have : i' < nfa'''.val.nodes.size := Nat.lt_trans lt nfa'''.property
    have : nfa'''.val[i'] = nfa''.val[i'] := by
      simp [eq₃]
      rw [pushNode_get_lt _ lt]
    have := eq_or_ge_of_step_pushRegex eq₂.symm h₁ lt (step.cast lt this).step
    cases this with
    | inl eq =>
      rw [eq₁] at eq
      simp at eq
      exact Nat.lt_irrefl _ (eq ▸ next.isLt)
    | inr ge => exact Nat.lt_irrefl _ (Nat.lt_of_lt_of_le (Nat.lt_trans next.isLt nfa'.property) ge)
  | inr ge =>
    have eqStart : nfa'''.val[nfa''.val.nodes.size]'nfa'''.property = .save (2 * i) nfa''.val.start := by
      simp [eq₃]
    have h₂ := step.h₂
    simp [eq₃] at h₂
    have : i' = nfa''.val.nodes.size := Nat.eq_of_le_of_lt_succ ge h₂
    have step := step.step
    simp [this, eqStart, Node.charStep, Node.εStep] at step
    have : nfa.nodes.size < nfa''.val.start := Nat.lt_of_lt_of_le nfa'.property (ge_pushRegex_start eq₂.symm)
    exact Nat.lt_irrefl _ (Nat.lt_trans (step ▸ this) next.isLt)
State after:
no goals

State before:
case inl
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
eq : nfa.nodes.size = i'
⊢ i' = nfa.nodes.size ∧ cs₂ = []
Tactic:
have eqStart : nfa'''.val[nfa.nodes.size] = .save (2 * i + 1) next := by
  simp [eq₃]
  rw [pushNode_get_lt _ (Nat.lt_trans nfa'.property nfa''.property)]
  rw [pushRegex_get_lt eq₂.symm _ nfa'.property]
  simp [eq₁]
State after:
case inl
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
eq : nfa.nodes.size = i'
eqStart : (↑nfa''')[nfa.nodes.size] = Node.save (2 * i + 1) ↑next
⊢ i' = nfa.nodes.size ∧ cs₂ = []

State before:
case inl
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
eq : nfa.nodes.size = i'
eqStart : (↑nfa''')[nfa.nodes.size] = Node.save (2 * i + 1) ↑next
⊢ i' = nfa.nodes.size ∧ cs₂ = []
Tactic:
rw [←eq] at step
State after:
case inl
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size nfa.nodes.size (↑next) cs₂
eq : nfa.nodes.size = i'
eqStart : (↑nfa''')[nfa.nodes.size] = Node.save (2 * i + 1) ↑next
⊢ i' = nfa.nodes.size ∧ cs₂ = []

State before:
case inl
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size nfa.nodes.size (↑next) cs₂
eq : nfa.nodes.size = i'
eqStart : (↑nfa''')[nfa.nodes.size] = Node.save (2 * i + 1) ↑next
⊢ i' = nfa.nodes.size ∧ cs₂ = []
Tactic:
cases step with
| charStep _ _ step =>
  rw [eqStart] at step
  simp [Node.charStep] at step
| εStep _ _ eqs => exact ⟨eq.symm, rfl⟩
State after:
no goals

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
eq : nfa.nodes.size = i'
⊢ (↑nfa''')[nfa.nodes.size] = Node.save (2 * i + 1) ↑next
Tactic:
simp [eq₃]
State after:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
eq : nfa.nodes.size = i'
⊢ (↑((↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝))[nfa.nodes.size] = Node.save (2 * i + 1) ↑next

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
eq : nfa.nodes.size = i'
⊢ (↑((↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝))[nfa.nodes.size] = Node.save (2 * i + 1) ↑next
Tactic:
rw [pushNode_get_lt _ (Nat.lt_trans nfa'.property nfa''.property)]
State after:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
eq : nfa.nodes.size = i'
⊢ (↑nfa'')[nfa.nodes.size] = Node.save (2 * i + 1) ↑next

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
eq : nfa.nodes.size = i'
⊢ (↑nfa'')[nfa.nodes.size] = Node.save (2 * i + 1) ↑next
Tactic:
rw [pushRegex_get_lt eq₂.symm _ nfa'.property]
State after:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
eq : nfa.nodes.size = i'
⊢ (↑nfa')[nfa.nodes.size] = Node.save (2 * i + 1) ↑next

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
eq : nfa.nodes.size = i'
⊢ (↑nfa')[nfa.nodes.size] = Node.save (2 * i + 1) ↑next
Tactic:
simp [eq₁]
State after:
no goals

State before:
case inl.charStep
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ : List Char
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
eq : nfa.nodes.size = i'
eqStart : (↑nfa''')[nfa.nodes.size] = Node.save (2 * i + 1) ↑next
c✝ : Char
h₁✝ : nfa.nodes.size ≤ nfa.nodes.size
h₂✝ : nfa.nodes.size < (↑nfa''').nodes.size
step : ↑next ∈ (↑nfa''')[nfa.nodes.size].charStep c✝
eqs : cs = cs₁ ++ [c✝]
⊢ i' = nfa.nodes.size ∧ [c✝] = []
Tactic:
rw [eqStart] at step
State after:
case inl.charStep
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ : List Char
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
eq : nfa.nodes.size = i'
eqStart : (↑nfa''')[nfa.nodes.size] = Node.save (2 * i + 1) ↑next
c✝ : Char
h₁✝ : nfa.nodes.size ≤ nfa.nodes.size
h₂✝ : nfa.nodes.size < (↑nfa''').nodes.size
step : ↑next ∈ (Node.save (2 * i + 1) ↑next).charStep c✝
eqs : cs = cs₁ ++ [c✝]
⊢ i' = nfa.nodes.size ∧ [c✝] = []

State before:
case inl.charStep
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ : List Char
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
eq : nfa.nodes.size = i'
eqStart : (↑nfa''')[nfa.nodes.size] = Node.save (2 * i + 1) ↑next
c✝ : Char
h₁✝ : nfa.nodes.size ≤ nfa.nodes.size
h₂✝ : nfa.nodes.size < (↑nfa''').nodes.size
step : ↑next ∈ (Node.save (2 * i + 1) ↑next).charStep c✝
eqs : cs = cs₁ ++ [c✝]
⊢ i' = nfa.nodes.size ∧ [c✝] = []
Tactic:
simp [Node.charStep] at step
State after:
no goals

State before:
case inl.εStep
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ : List Char
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
eq : nfa.nodes.size = i'
eqStart : (↑nfa''')[nfa.nodes.size] = Node.save (2 * i + 1) ↑next
h₁✝ : nfa.nodes.size ≤ nfa.nodes.size
h₂✝ : nfa.nodes.size < (↑nfa''').nodes.size
eqs✝ : ↑next ∈ (↑nfa''')[nfa.nodes.size].εStep
eqs : cs = cs₁ ++ []
⊢ i' = nfa.nodes.size ∧ [] = []
Tactic:
exact ⟨eq.symm, rfl⟩
State after:
no goals

State before:
case inr
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
⊢ i' = nfa.nodes.size ∧ cs₂ = []
Tactic:
apply False.elim
State after:
case inr.h
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
⊢ False

State before:
case inr.h
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
⊢ False
Tactic:
cases Nat.lt_or_ge i' nfa''.val.nodes.size with
| inl lt =>
  have h₁ : nfa'.val.nodes.size ≤ i' := by
    simp [eq₁]
    exact gt
  have : i' < nfa'''.val.nodes.size := Nat.lt_trans lt nfa'''.property
  have : nfa'''.val[i'] = nfa''.val[i'] := by
    simp [eq₃]
    rw [pushNode_get_lt _ lt]
  have := eq_or_ge_of_step_pushRegex eq₂.symm h₁ lt (step.cast lt this).step
  cases this with
  | inl eq =>
    rw [eq₁] at eq
    simp at eq
    exact Nat.lt_irrefl _ (eq ▸ next.isLt)
  | inr ge => exact Nat.lt_irrefl _ (Nat.lt_of_lt_of_le (Nat.lt_trans next.isLt nfa'.property) ge)
| inr ge =>
  have eqStart : nfa'''.val[nfa''.val.nodes.size]'nfa'''.property = .save (2 * i) nfa''.val.start := by
    simp [eq₃]
  have h₂ := step.h₂
  simp [eq₃] at h₂
  have : i' = nfa''.val.nodes.size := Nat.eq_of_le_of_lt_succ ge h₂
  have step := step.step
  simp [this, eqStart, Node.charStep, Node.εStep] at step
  have : nfa.nodes.size < nfa''.val.start := Nat.lt_of_lt_of_le nfa'.property (ge_pushRegex_start eq₂.symm)
  exact Nat.lt_irrefl _ (Nat.lt_trans (step ▸ this) next.isLt)
State after:
no goals

State before:
case inr.h.inl
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
⊢ False
Tactic:
have h₁ : nfa'.val.nodes.size ≤ i' := by
  simp [eq₁]
  exact gt
State after:
case inr.h.inl
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
h₁ : (↑nfa').nodes.size ≤ i'
⊢ False

State before:
case inr.h.inl
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
h₁ : (↑nfa').nodes.size ≤ i'
⊢ False
Tactic:
have : i' < nfa'''.val.nodes.size := Nat.lt_trans lt nfa'''.property
State after:
case inr.h.inl
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
h₁ : (↑nfa').nodes.size ≤ i'
this : i' < (↑nfa''').nodes.size
⊢ False

State before:
case inr.h.inl
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
h₁ : (↑nfa').nodes.size ≤ i'
this : i' < (↑nfa''').nodes.size
⊢ False
Tactic:
have : nfa'''.val[i'] = nfa''.val[i'] := by
  simp [eq₃]
  rw [pushNode_get_lt _ lt]
State after:
case inr.h.inl
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
h₁ : (↑nfa').nodes.size ≤ i'
this✝ : i' < (↑nfa''').nodes.size
this : (↑nfa''')[i'] = (↑nfa'')[i']
⊢ False

State before:
case inr.h.inl
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
h₁ : (↑nfa').nodes.size ≤ i'
this✝ : i' < (↑nfa''').nodes.size
this : (↑nfa''')[i'] = (↑nfa'')[i']
⊢ False
Tactic:
have := eq_or_ge_of_step_pushRegex eq₂.symm h₁ lt (step.cast lt this).step
State after:
case inr.h.inl
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
h₁ : (↑nfa').nodes.size ≤ i'
this✝¹ : i' < (↑nfa''').nodes.size
this✝ : (↑nfa''')[i'] = (↑nfa'')[i']
this : ↑next = ↑(↑nfa').start ∨ (↑nfa').nodes.size ≤ ↑next
⊢ False

State before:
case inr.h.inl
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
h₁ : (↑nfa').nodes.size ≤ i'
this✝¹ : i' < (↑nfa''').nodes.size
this✝ : (↑nfa''')[i'] = (↑nfa'')[i']
this : ↑next = ↑(↑nfa').start ∨ (↑nfa').nodes.size ≤ ↑next
⊢ False
Tactic:
cases this with
| inl eq =>
  rw [eq₁] at eq
  simp at eq
  exact Nat.lt_irrefl _ (eq ▸ next.isLt)
| inr ge => exact Nat.lt_irrefl _ (Nat.lt_of_lt_of_le (Nat.lt_trans next.isLt nfa'.property) ge)
State after:
no goals

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
⊢ (↑nfa').nodes.size ≤ i'
Tactic:
simp [eq₁]
State after:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
⊢ nfa.nodes.size + 1 ≤ i'

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
⊢ nfa.nodes.size + 1 ≤ i'
Tactic:
exact gt
State after:
no goals

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
h₁ : (↑nfa').nodes.size ≤ i'
this : i' < (↑nfa''').nodes.size
⊢ (↑nfa''')[i'] = (↑nfa'')[i']
Tactic:
simp [eq₃]
State after:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
h₁ : (↑nfa').nodes.size ≤ i'
this : i' < (↑nfa''').nodes.size
⊢ (↑((↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝))[i'] = (↑nfa'')[i']

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
h₁ : (↑nfa').nodes.size ≤ i'
this : i' < (↑nfa''').nodes.size
⊢ (↑((↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝))[i'] = (↑nfa'')[i']
Tactic:
rw [pushNode_get_lt _ lt]
State after:
no goals

State before:
case inr.h.inl.inl
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
h₁ : (↑nfa').nodes.size ≤ i'
this✝ : i' < (↑nfa''').nodes.size
this : (↑nfa''')[i'] = (↑nfa'')[i']
eq : ↑next = ↑(↑nfa').start
⊢ False
Tactic:
rw [eq₁] at eq
State after:
case inr.h.inl.inl
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
h₁ : (↑nfa').nodes.size ≤ i'
this✝ : i' < (↑nfa''').nodes.size
this : (↑nfa''')[i'] = (↑nfa'')[i']
eq : ↑next = ↑(↑(nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝)).start
⊢ False

State before:
case inr.h.inl.inl
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
h₁ : (↑nfa').nodes.size ≤ i'
this✝ : i' < (↑nfa''').nodes.size
this : (↑nfa''')[i'] = (↑nfa'')[i']
eq : ↑next = ↑(↑(nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝)).start
⊢ False
Tactic:
simp at eq
State after:
case inr.h.inl.inl
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
h₁ : (↑nfa').nodes.size ≤ i'
this✝ : i' < (↑nfa''').nodes.size
this : (↑nfa''')[i'] = (↑nfa'')[i']
eq : ↑next = nfa.nodes.size
⊢ False

State before:
case inr.h.inl.inl
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝¹ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq✝ : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
h₁ : (↑nfa').nodes.size ≤ i'
this✝ : i' < (↑nfa''').nodes.size
this : (↑nfa''')[i'] = (↑nfa'')[i']
eq : ↑next = nfa.nodes.size
⊢ False
Tactic:
exact Nat.lt_irrefl _ (eq ▸ next.isLt)
State after:
no goals

State before:
case inr.h.inl.inr
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
lt : i' < (↑nfa'').nodes.size
h₁ : (↑nfa').nodes.size ≤ i'
this✝ : i' < (↑nfa''').nodes.size
this : (↑nfa''')[i'] = (↑nfa'')[i']
ge : (↑nfa').nodes.size ≤ ↑next
⊢ False
Tactic:
exact Nat.lt_irrefl _ (Nat.lt_of_lt_of_le (Nat.lt_trans next.isLt nfa'.property) ge)
State after:
no goals

State before:
case inr.h.inr
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
ge : i' ≥ (↑nfa'').nodes.size
⊢ False
Tactic:
have eqStart : nfa'''.val[nfa''.val.nodes.size]'nfa'''.property = .save (2 * i) nfa''.val.start := by
  simp [eq₃]
State after:
case inr.h.inr
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
ge : i' ≥ (↑nfa'').nodes.size
eqStart : (↑nfa''')[(↑nfa'').nodes.size] = Node.save (2 * i) ↑(↑nfa'').start
⊢ False

State before:
case inr.h.inr
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
ge : i' ≥ (↑nfa'').nodes.size
eqStart : (↑nfa''')[(↑nfa'').nodes.size] = Node.save (2 * i) ↑(↑nfa'').start
⊢ False
Tactic:
have h₂ := step.h₂
State after:
case inr.h.inr
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
ge : i' ≥ (↑nfa'').nodes.size
eqStart : (↑nfa''')[(↑nfa'').nodes.size] = Node.save (2 * i) ↑(↑nfa'').start
h₂ : i' < (↑nfa''').nodes.size
⊢ False

State before:
case inr.h.inr
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
ge : i' ≥ (↑nfa'').nodes.size
eqStart : (↑nfa''')[(↑nfa'').nodes.size] = Node.save (2 * i) ↑(↑nfa'').start
h₂ : i' < (↑nfa''').nodes.size
⊢ False
Tactic:
simp [eq₃] at h₂
State after:
case inr.h.inr
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
ge : i' ≥ (↑nfa'').nodes.size
eqStart : (↑nfa''')[(↑nfa'').nodes.size] = Node.save (2 * i) ↑(↑nfa'').start
h₂ : i' < (↑nfa'').nodes.size + 1
⊢ False

State before:
case inr.h.inr
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
ge : i' ≥ (↑nfa'').nodes.size
eqStart : (↑nfa''')[(↑nfa'').nodes.size] = Node.save (2 * i) ↑(↑nfa'').start
h₂ : i' < (↑nfa'').nodes.size + 1
⊢ False
Tactic:
have : i' = nfa''.val.nodes.size := Nat.eq_of_le_of_lt_succ ge h₂
State after:
case inr.h.inr
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
ge : i' ≥ (↑nfa'').nodes.size
eqStart : (↑nfa''')[(↑nfa'').nodes.size] = Node.save (2 * i) ↑(↑nfa'').start
h₂ : i' < (↑nfa'').nodes.size + 1
this : i' = (↑nfa'').nodes.size
⊢ False

State before:
case inr.h.inr
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
ge : i' ≥ (↑nfa'').nodes.size
eqStart : (↑nfa''')[(↑nfa'').nodes.size] = Node.save (2 * i) ↑(↑nfa'').start
h₂ : i' < (↑nfa'').nodes.size + 1
this : i' = (↑nfa'').nodes.size
⊢ False
Tactic:
have step := step.step
State after:
case inr.h.inr
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
ge : i' ≥ (↑nfa'').nodes.size
eqStart : (↑nfa''')[(↑nfa'').nodes.size] = Node.save (2 * i) ↑(↑nfa'').start
h₂ : i' < (↑nfa'').nodes.size + 1
this : i' = (↑nfa'').nodes.size
step : (∃ c, ↑next ∈ (↑nfa''')[i'].charStep c) ∨ ↑next ∈ (↑nfa''')[i'].εStep
⊢ False

State before:
case inr.h.inr
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
ge : i' ≥ (↑nfa'').nodes.size
eqStart : (↑nfa''')[(↑nfa'').nodes.size] = Node.save (2 * i) ↑(↑nfa'').start
h₂ : i' < (↑nfa'').nodes.size + 1
this : i' = (↑nfa'').nodes.size
step : (∃ c, ↑next ∈ (↑nfa''')[i'].charStep c) ∨ ↑next ∈ (↑nfa''')[i'].εStep
⊢ False
Tactic:
simp [this, eqStart, Node.charStep, Node.εStep] at step
State after:
case inr.h.inr
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
ge : i' ≥ (↑nfa'').nodes.size
eqStart : (↑nfa''')[(↑nfa'').nodes.size] = Node.save (2 * i) ↑(↑nfa'').start
h₂ : i' < (↑nfa'').nodes.size + 1
this : i' = (↑nfa'').nodes.size
step : ↑next = ↑(↑nfa'').start
⊢ False

State before:
case inr.h.inr
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
ge : i' ≥ (↑nfa'').nodes.size
eqStart : (↑nfa''')[(↑nfa'').nodes.size] = Node.save (2 * i) ↑(↑nfa'').start
h₂ : i' < (↑nfa'').nodes.size + 1
this : i' = (↑nfa'').nodes.size
step : ↑next = ↑(↑nfa'').start
⊢ False
Tactic:
have : nfa.nodes.size < nfa''.val.start := Nat.lt_of_lt_of_le nfa'.property (ge_pushRegex_start eq₂.symm)
State after:
case inr.h.inr
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
ge : i' ≥ (↑nfa'').nodes.size
eqStart : (↑nfa''')[(↑nfa'').nodes.size] = Node.save (2 * i) ↑(↑nfa'').start
h₂ : i' < (↑nfa'').nodes.size + 1
this✝ : i' = (↑nfa'').nodes.size
step : ↑next = ↑(↑nfa'').start
this : nfa.nodes.size < ↑(↑nfa'').start
⊢ False

State before:
case inr.h.inr
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
ge : i' ≥ (↑nfa'').nodes.size
eqStart : (↑nfa''')[(↑nfa'').nodes.size] = Node.save (2 * i) ↑(↑nfa'').start
h₂ : i' < (↑nfa'').nodes.size + 1
this✝ : i' = (↑nfa'').nodes.size
step : ↑next = ↑(↑nfa'').start
this : nfa.nodes.size < ↑(↑nfa'').start
⊢ False
Tactic:
exact Nat.lt_irrefl _ (Nat.lt_trans (step ▸ this) next.isLt)
State after:
no goals

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₁ cs₂ : List Char
eqs : cs = cs₁ ++ cs₂
path : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa''').start) i' cs₁
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂
gt : nfa.nodes.size < i'
ge : i' ≥ (↑nfa'').nodes.size
⊢ (↑nfa''')[(↑nfa'').nodes.size] = Node.save (2 * i) ↑(↑nfa'').start
Tactic:
simp [eq₃]
State after:
no goals

State before:
case intro.intro.intro.intro.intro.base
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
cs₂ : List Char
h✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
step : (↑nfa''').stepIn nfa.nodes.size (↑(↑nfa''').start) (↑next) cs₂
heq : ↑(↑nfa''').start = nfa.nodes.size ∧ cs₂ = []
eqs : cs = [] ++ cs₂
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs
Tactic:
rw [eq₃] at heq
State after:
case intro.intro.intro.intro.intro.base
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
cs₂ : List Char
h✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
step : (↑nfa''').stepIn nfa.nodes.size (↑(↑nfa''').start) (↑next) cs₂
heq : ↑(↑((↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝)).start = nfa.nodes.size ∧ cs₂ = []
eqs : cs = [] ++ cs₂
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs

State before:
case intro.intro.intro.intro.intro.base
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
cs₂ : List Char
h✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
step : (↑nfa''').stepIn nfa.nodes.size (↑(↑nfa''').start) (↑next) cs₂
heq : ↑(↑((↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝)).start = nfa.nodes.size ∧ cs₂ = []
eqs : cs = [] ++ cs₂
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs
Tactic:
simp at heq
State after:
case intro.intro.intro.intro.intro.base
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
cs₂ : List Char
h✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
step : (↑nfa''').stepIn nfa.nodes.size (↑(↑nfa''').start) (↑next) cs₂
heq : (↑nfa'').nodes.size = nfa.nodes.size ∧ cs₂ = []
eqs : cs = [] ++ cs₂
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs

State before:
case intro.intro.intro.intro.intro.base
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
cs₂ : List Char
h✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
step : (↑nfa''').stepIn nfa.nodes.size (↑(↑nfa''').start) (↑next) cs₂
heq : (↑nfa'').nodes.size = nfa.nodes.size ∧ cs₂ = []
eqs : cs = [] ++ cs₂
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs
Tactic:
have : nfa.nodes.size < nfa''.val.nodes.size := Nat.lt_trans nfa'.property nfa''.property
State after:
case intro.intro.intro.intro.intro.base
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
cs₂ : List Char
h✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
step : (↑nfa''').stepIn nfa.nodes.size (↑(↑nfa''').start) (↑next) cs₂
heq : (↑nfa'').nodes.size = nfa.nodes.size ∧ cs₂ = []
eqs : cs = [] ++ cs₂
this : nfa.nodes.size < (↑nfa'').nodes.size
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs

State before:
case intro.intro.intro.intro.intro.base
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
cs₂ : List Char
h✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
step : (↑nfa''').stepIn nfa.nodes.size (↑(↑nfa''').start) (↑next) cs₂
heq : (↑nfa'').nodes.size = nfa.nodes.size ∧ cs₂ = []
eqs : cs = [] ++ cs₂
this : nfa.nodes.size < (↑nfa'').nodes.size
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs
Tactic:
exact (Nat.lt_irrefl _ (heq.left ▸ this)).elim
State after:
no goals

State before:
case intro.intro.intro.intro.intro.step
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
j : ℕ
cs₁ cs₂ : List Char
step' : (↑nfa''').stepIn nfa.nodes.size (↑(↑nfa''').start) j cs₁
rest : (↑nfa''').pathIn nfa.nodes.size j i' cs₂
eqs : cs = cs₁ ++ cs₂ ++ cs₂✝
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs
Tactic:
simp [eqs, heq.right]
State after:
case intro.intro.intro.intro.intro.step
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
j : ℕ
cs₁ cs₂ : List Char
step' : (↑nfa''').stepIn nfa.nodes.size (↑(↑nfa''').start) j cs₁
rest : (↑nfa''').pathIn nfa.nodes.size j i' cs₂
eqs : cs = cs₁ ++ cs₂ ++ cs₂✝
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) (cs₁ ++ cs₂)

State before:
case intro.intro.intro.intro.intro.step
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
j : ℕ
cs₁ cs₂ : List Char
step' : (↑nfa''').stepIn nfa.nodes.size (↑(↑nfa''').start) j cs₁
rest : (↑nfa''').pathIn nfa.nodes.size j i' cs₂
eqs : cs = cs₁ ++ cs₂ ++ cs₂✝
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) (cs₁ ++ cs₂)
Tactic:
have eqStart : nfa'''.val[nfa'''.val.start.val] = .save (2 * i) nfa''.val.start := by
  rw [eq₃]
  simp
State after:
case intro.intro.intro.intro.intro.step
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
j : ℕ
cs₁ cs₂ : List Char
step' : (↑nfa''').stepIn nfa.nodes.size (↑(↑nfa''').start) j cs₁
rest : (↑nfa''').pathIn nfa.nodes.size j i' cs₂
eqs : cs = cs₁ ++ cs₂ ++ cs₂✝
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) (cs₁ ++ cs₂)

State before:
case intro.intro.intro.intro.intro.step
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
j : ℕ
cs₁ cs₂ : List Char
step' : (↑nfa''').stepIn nfa.nodes.size (↑(↑nfa''').start) j cs₁
rest : (↑nfa''').pathIn nfa.nodes.size j i' cs₂
eqs : cs = cs₁ ++ cs₂ ++ cs₂✝
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) (cs₁ ++ cs₂)
Tactic:
cases step' with
| charStep _ _ step => simp [eqStart, Node.charStep] at step
| εStep _ _ step =>
  simp [eqStart, Node.εStep] at step
  subst step
  simp
  have : pathIn nfa'' nfa.nodes.size nfa''.val.start i' cs₂ := by
    apply rest.cast' (nfa''.val.start.isLt) (Nat.le_of_lt nfa'''.property)
    intro i _ h₂
    rw [eq₃, pushNode_get_lt _ h₂]
  have ⟨cs₃, cs₄, eqs, path', path''⟩ :=
    pathIn_split eq₂.symm (heq.left ▸ nfa'.property) (ge_pushRegex_start eq₂.symm) this
  cases path'' with
  | base _ =>
    simp at eqs
    exact eqs ▸ path'
  | step step rest =>
    have : nfa'.val.start.val < nfa''.val.nodes.size :=
      Nat.lt_trans nfa'.val.start.isLt nfa''.property
    have eqStart : nfa''.val[nfa'.val.start.val] = .save (2 * i + 1) next := by
      rw [pushRegex_get_lt eq₂.symm _ nfa'.val.start.isLt]
      rw [eq₁]
      simp
    have step := step.step
    simp [eqStart, Node.charStep, Node.εStep] at step
    subst step
    have := le_of_pathIn_left rest
    exact (Nat.lt_irrefl _ (Nat.lt_of_le_of_lt this next.isLt)).elim
State after:
no goals

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
j : ℕ
cs₁ cs₂ : List Char
step' : (↑nfa''').stepIn nfa.nodes.size (↑(↑nfa''').start) j cs₁
rest : (↑nfa''').pathIn nfa.nodes.size j i' cs₂
eqs : cs = cs₁ ++ cs₂ ++ cs₂✝
⊢ (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
Tactic:
rw [eq₃]
State after:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
j : ℕ
cs₁ cs₂ : List Char
step' : (↑nfa''').stepIn nfa.nodes.size (↑(↑nfa''').start) j cs₁
rest : (↑nfa''').pathIn nfa.nodes.size j i' cs₂
eqs : cs = cs₁ ++ cs₂ ++ cs₂✝
⊢ (↑((↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start)
          inBounds'''✝))[↑(↑((↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝)).start] =
    Node.save (2 * i) ↑(↑nfa'').start

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
j : ℕ
cs₁ cs₂ : List Char
step' : (↑nfa''').stepIn nfa.nodes.size (↑(↑nfa''').start) j cs₁
rest : (↑nfa''').pathIn nfa.nodes.size j i' cs₂
eqs : cs = cs₁ ++ cs₂ ++ cs₂✝
⊢ (↑((↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start)
          inBounds'''✝))[↑(↑((↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝)).start] =
    Node.save (2 * i) ↑(↑nfa'').start
Tactic:
simp
State after:
no goals

State before:
case intro.intro.intro.intro.intro.step.charStep
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
j : ℕ
cs₂ : List Char
rest : (↑nfa''').pathIn nfa.nodes.size j i' cs₂
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
c✝ : Char
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
step : j ∈ (↑nfa''')[↑(↑nfa''').start].charStep c✝
eqs : cs = [c✝] ++ cs₂ ++ cs₂✝
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) ([c✝] ++ cs₂)
Tactic:
simp [eqStart, Node.charStep] at step
State after:
no goals

State before:
case intro.intro.intro.intro.intro.step.εStep
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
j : ℕ
cs₂ : List Char
rest : (↑nfa''').pathIn nfa.nodes.size j i' cs₂
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
step : j ∈ (↑nfa''')[↑(↑nfa''').start].εStep
eqs : cs = [] ++ cs₂ ++ cs₂✝
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) ([] ++ cs₂)
Tactic:
simp [eqStart, Node.εStep] at step
State after:
case intro.intro.intro.intro.intro.step.εStep
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
j : ℕ
cs₂ : List Char
rest : (↑nfa''').pathIn nfa.nodes.size j i' cs₂
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs : cs = [] ++ cs₂ ++ cs₂✝
step : j = ↑(↑nfa'').start
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) ([] ++ cs₂)

State before:
case intro.intro.intro.intro.intro.step.εStep
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
j : ℕ
cs₂ : List Char
rest : (↑nfa''').pathIn nfa.nodes.size j i' cs₂
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs : cs = [] ++ cs₂ ++ cs₂✝
step : j = ↑(↑nfa'').start
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) ([] ++ cs₂)
Tactic:
subst step
State after:
case intro.intro.intro.intro.intro.step.εStep
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs : cs = [] ++ cs₂ ++ cs₂✝
rest : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) ([] ++ cs₂)

State before:
case intro.intro.intro.intro.intro.step.εStep
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs : cs = [] ++ cs₂ ++ cs₂✝
rest : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) ([] ++ cs₂)
Tactic:
simp
State after:
case intro.intro.intro.intro.intro.step.εStep
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs : cs = [] ++ cs₂ ++ cs₂✝
rest : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂

State before:
case intro.intro.intro.intro.intro.step.εStep
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs : cs = [] ++ cs₂ ++ cs₂✝
rest : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂
Tactic:
have : pathIn nfa'' nfa.nodes.size nfa''.val.start i' cs₂ := by
  apply rest.cast' (nfa''.val.start.isLt) (Nat.le_of_lt nfa'''.property)
  intro i _ h₂
  rw [eq₃, pushNode_get_lt _ h₂]
State after:
case intro.intro.intro.intro.intro.step.εStep
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs : cs = [] ++ cs₂ ++ cs₂✝
rest : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂

State before:
case intro.intro.intro.intro.intro.step.εStep
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs : cs = [] ++ cs₂ ++ cs₂✝
rest : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂
Tactic:
have ⟨cs₃, cs₄, eqs, path', path''⟩ :=
  pathIn_split eq₂.symm (heq.left ▸ nfa'.property) (ge_pushRegex_start eq₂.symm) this
State after:
case intro.intro.intro.intro.intro.step.εStep
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝
rest : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ cs₄ : List Char
eqs : cs₂ = cs₃ ++ cs₄
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
path'' : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa').start) i' cs₄
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂

State before:
case intro.intro.intro.intro.intro.step.εStep
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝
rest : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ cs₄ : List Char
eqs : cs₂ = cs₃ ++ cs₄
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
path'' : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa').start) i' cs₄
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂
Tactic:
cases path'' with
| base _ =>
  simp at eqs
  exact eqs ▸ path'
| step step rest =>
  have : nfa'.val.start.val < nfa''.val.nodes.size :=
    Nat.lt_trans nfa'.val.start.isLt nfa''.property
  have eqStart : nfa''.val[nfa'.val.start.val] = .save (2 * i + 1) next := by
    rw [pushRegex_get_lt eq₂.symm _ nfa'.val.start.isLt]
    rw [eq₁]
    simp
  have step := step.step
  simp [eqStart, Node.charStep, Node.εStep] at step
  subst step
  have := le_of_pathIn_left rest
  exact (Nat.lt_irrefl _ (Nat.lt_of_le_of_lt this next.isLt)).elim
State after:
no goals

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs : cs = [] ++ cs₂ ++ cs₂✝
rest : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
⊢ (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
Tactic:
apply rest.cast' (nfa''.val.start.isLt) (Nat.le_of_lt nfa'''.property)
State after:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs : cs = [] ++ cs₂ ++ cs₂✝
rest : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
⊢ ∀ (i : ℕ), nfa.nodes.size ≤ i → ∀ (h₂ : i < (↑nfa'').nodes.size), (↑nfa'')[i] = (↑nfa''')[i]

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs : cs = [] ++ cs₂ ++ cs₂✝
rest : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
⊢ ∀ (i : ℕ), nfa.nodes.size ≤ i → ∀ (h₂ : i < (↑nfa'').nodes.size), (↑nfa'')[i] = (↑nfa''')[i]
Tactic:
intro i _ h₂
State after:
nfa : NFA
next : Fin nfa.nodes.size
i✝ : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i✝ r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i✝ + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i✝) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i✝ + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i✝) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i✝) ↑(↑nfa'').start
h₁✝¹ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs : cs = [] ++ cs₂ ++ cs₂✝
rest : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
i : ℕ
h₁✝ : nfa.nodes.size ≤ i
h₂ : i < (↑nfa'').nodes.size
⊢ (↑nfa'')[i] = (↑nfa''')[i]

State before:
nfa : NFA
next : Fin nfa.nodes.size
i✝ : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i✝ r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i✝ + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i✝) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i✝ + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i✝) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝ : List Char
step : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝
heq : i' = nfa.nodes.size ∧ cs₂✝ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i✝) ↑(↑nfa'').start
h₁✝¹ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs : cs = [] ++ cs₂ ++ cs₂✝
rest : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
i : ℕ
h₁✝ : nfa.nodes.size ≤ i
h₂ : i < (↑nfa'').nodes.size
⊢ (↑nfa'')[i] = (↑nfa''')[i]
Tactic:
rw [eq₃, pushNode_get_lt _ h₂]
State after:
no goals

State before:
case intro.intro.intro.intro.intro.step.εStep.base
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
cs₂✝ cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
h✝ : nfa.nodes.size ≤ ↑(↑nfa').start
step : (↑nfa''').stepIn nfa.nodes.size (↑(↑nfa').start) (↑next) cs₂✝
heq : ↑(↑nfa').start = nfa.nodes.size ∧ cs₂✝ = []
rest : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) (↑(↑nfa').start) cs₂
this : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) (↑(↑nfa').start) cs₂
eqs : cs₂ = cs₃ ++ []
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂
Tactic:
simp at eqs
State after:
case intro.intro.intro.intro.intro.step.εStep.base
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
cs₂✝ cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
h✝ : nfa.nodes.size ≤ ↑(↑nfa').start
step : (↑nfa''').stepIn nfa.nodes.size (↑(↑nfa').start) (↑next) cs₂✝
heq : ↑(↑nfa').start = nfa.nodes.size ∧ cs₂✝ = []
rest : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) (↑(↑nfa').start) cs₂
this : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) (↑(↑nfa').start) cs₂
eqs : cs₂ = cs₃
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂

State before:
case intro.intro.intro.intro.intro.step.εStep.base
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
cs₂✝ cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
h✝ : nfa.nodes.size ≤ ↑(↑nfa').start
step : (↑nfa''').stepIn nfa.nodes.size (↑(↑nfa').start) (↑next) cs₂✝
heq : ↑(↑nfa').start = nfa.nodes.size ∧ cs₂✝ = []
rest : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) (↑(↑nfa').start) cs₂
this : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) (↑(↑nfa').start) cs₂
eqs : cs₂ = cs₃
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂
Tactic:
exact eqs ▸ path'
State after:
no goals

State before:
case intro.intro.intro.intro.intro.step.εStep.step
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝¹ : List Char
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝¹
heq : i' = nfa.nodes.size ∧ cs₂✝¹ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝¹
rest✝ : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
j✝ : ℕ
cs₁✝ cs₂✝ : List Char
step : (↑nfa'').stepIn nfa.nodes.size (↑(↑nfa').start) j✝ cs₁✝
rest : (↑nfa'').pathIn nfa.nodes.size j✝ i' cs₂✝
eqs : cs₂ = cs₃ ++ (cs₁✝ ++ cs₂✝)
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂
Tactic:
have : nfa'.val.start.val < nfa''.val.nodes.size :=
  Nat.lt_trans nfa'.val.start.isLt nfa''.property
State after:
case intro.intro.intro.intro.intro.step.εStep.step
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝¹ : List Char
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝¹
heq : i' = nfa.nodes.size ∧ cs₂✝¹ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝¹
rest✝ : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this✝ : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
j✝ : ℕ
cs₁✝ cs₂✝ : List Char
step : (↑nfa'').stepIn nfa.nodes.size (↑(↑nfa').start) j✝ cs₁✝
rest : (↑nfa'').pathIn nfa.nodes.size j✝ i' cs₂✝
eqs : cs₂ = cs₃ ++ (cs₁✝ ++ cs₂✝)
this : ↑(↑nfa').start < (↑nfa'').nodes.size
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂

State before:
case intro.intro.intro.intro.intro.step.εStep.step
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝¹ : List Char
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝¹
heq : i' = nfa.nodes.size ∧ cs₂✝¹ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝¹
rest✝ : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this✝ : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
j✝ : ℕ
cs₁✝ cs₂✝ : List Char
step : (↑nfa'').stepIn nfa.nodes.size (↑(↑nfa').start) j✝ cs₁✝
rest : (↑nfa'').pathIn nfa.nodes.size j✝ i' cs₂✝
eqs : cs₂ = cs₃ ++ (cs₁✝ ++ cs₂✝)
this : ↑(↑nfa').start < (↑nfa'').nodes.size
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂
Tactic:
have eqStart : nfa''.val[nfa'.val.start.val] = .save (2 * i + 1) next := by
  rw [pushRegex_get_lt eq₂.symm _ nfa'.val.start.isLt]
  rw [eq₁]
  simp
State after:
case intro.intro.intro.intro.intro.step.εStep.step
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝¹ : List Char
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝¹
heq : i' = nfa.nodes.size ∧ cs₂✝¹ = []
cs₂ : List Char
eqStart✝ : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝¹
rest✝ : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this✝ : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
j✝ : ℕ
cs₁✝ cs₂✝ : List Char
step : (↑nfa'').stepIn nfa.nodes.size (↑(↑nfa').start) j✝ cs₁✝
rest : (↑nfa'').pathIn nfa.nodes.size j✝ i' cs₂✝
eqs : cs₂ = cs₃ ++ (cs₁✝ ++ cs₂✝)
this : ↑(↑nfa').start < (↑nfa'').nodes.size
eqStart : (↑nfa'')[↑(↑nfa').start] = Node.save (2 * i + 1) ↑next
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂

State before:
case intro.intro.intro.intro.intro.step.εStep.step
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝¹ : List Char
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝¹
heq : i' = nfa.nodes.size ∧ cs₂✝¹ = []
cs₂ : List Char
eqStart✝ : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝¹
rest✝ : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this✝ : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
j✝ : ℕ
cs₁✝ cs₂✝ : List Char
step : (↑nfa'').stepIn nfa.nodes.size (↑(↑nfa').start) j✝ cs₁✝
rest : (↑nfa'').pathIn nfa.nodes.size j✝ i' cs₂✝
eqs : cs₂ = cs₃ ++ (cs₁✝ ++ cs₂✝)
this : ↑(↑nfa').start < (↑nfa'').nodes.size
eqStart : (↑nfa'')[↑(↑nfa').start] = Node.save (2 * i + 1) ↑next
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂
Tactic:
have step := step.step
State after:
case intro.intro.intro.intro.intro.step.εStep.step
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝¹ : List Char
step✝¹ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝¹
heq : i' = nfa.nodes.size ∧ cs₂✝¹ = []
cs₂ : List Char
eqStart✝ : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝¹
rest✝ : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this✝ : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
j✝ : ℕ
cs₁✝ cs₂✝ : List Char
step✝ : (↑nfa'').stepIn nfa.nodes.size (↑(↑nfa').start) j✝ cs₁✝
rest : (↑nfa'').pathIn nfa.nodes.size j✝ i' cs₂✝
eqs : cs₂ = cs₃ ++ (cs₁✝ ++ cs₂✝)
this : ↑(↑nfa').start < (↑nfa'').nodes.size
eqStart : (↑nfa'')[↑(↑nfa').start] = Node.save (2 * i + 1) ↑next
step : (∃ c, j✝ ∈ (↑nfa'')[↑(↑nfa').start].charStep c) ∨ j✝ ∈ (↑nfa'')[↑(↑nfa').start].εStep
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂

State before:
case intro.intro.intro.intro.intro.step.εStep.step
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝¹ : List Char
step✝¹ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝¹
heq : i' = nfa.nodes.size ∧ cs₂✝¹ = []
cs₂ : List Char
eqStart✝ : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝¹
rest✝ : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this✝ : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
j✝ : ℕ
cs₁✝ cs₂✝ : List Char
step✝ : (↑nfa'').stepIn nfa.nodes.size (↑(↑nfa').start) j✝ cs₁✝
rest : (↑nfa'').pathIn nfa.nodes.size j✝ i' cs₂✝
eqs : cs₂ = cs₃ ++ (cs₁✝ ++ cs₂✝)
this : ↑(↑nfa').start < (↑nfa'').nodes.size
eqStart : (↑nfa'')[↑(↑nfa').start] = Node.save (2 * i + 1) ↑next
step : (∃ c, j✝ ∈ (↑nfa'')[↑(↑nfa').start].charStep c) ∨ j✝ ∈ (↑nfa'')[↑(↑nfa').start].εStep
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂
Tactic:
simp [eqStart, Node.charStep, Node.εStep] at step
State after:
case intro.intro.intro.intro.intro.step.εStep.step
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝¹ : List Char
step✝¹ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝¹
heq : i' = nfa.nodes.size ∧ cs₂✝¹ = []
cs₂ : List Char
eqStart✝ : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝¹
rest✝ : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this✝ : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
j✝ : ℕ
cs₁✝ cs₂✝ : List Char
step✝ : (↑nfa'').stepIn nfa.nodes.size (↑(↑nfa').start) j✝ cs₁✝
rest : (↑nfa'').pathIn nfa.nodes.size j✝ i' cs₂✝
eqs : cs₂ = cs₃ ++ (cs₁✝ ++ cs₂✝)
this : ↑(↑nfa').start < (↑nfa'').nodes.size
eqStart : (↑nfa'')[↑(↑nfa').start] = Node.save (2 * i + 1) ↑next
step : j✝ = ↑next
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂

State before:
case intro.intro.intro.intro.intro.step.εStep.step
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝¹ : List Char
step✝¹ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝¹
heq : i' = nfa.nodes.size ∧ cs₂✝¹ = []
cs₂ : List Char
eqStart✝ : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝¹
rest✝ : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this✝ : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
j✝ : ℕ
cs₁✝ cs₂✝ : List Char
step✝ : (↑nfa'').stepIn nfa.nodes.size (↑(↑nfa').start) j✝ cs₁✝
rest : (↑nfa'').pathIn nfa.nodes.size j✝ i' cs₂✝
eqs : cs₂ = cs₃ ++ (cs₁✝ ++ cs₂✝)
this : ↑(↑nfa').start < (↑nfa'').nodes.size
eqStart : (↑nfa'')[↑(↑nfa').start] = Node.save (2 * i + 1) ↑next
step : j✝ = ↑next
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂
Tactic:
subst step
State after:
case intro.intro.intro.intro.intro.step.εStep.step
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝¹ : List Char
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝¹
heq : i' = nfa.nodes.size ∧ cs₂✝¹ = []
cs₂ : List Char
eqStart✝ : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝¹
rest✝ : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this✝ : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
cs₁✝ cs₂✝ : List Char
eqs : cs₂ = cs₃ ++ (cs₁✝ ++ cs₂✝)
this : ↑(↑nfa').start < (↑nfa'').nodes.size
eqStart : (↑nfa'')[↑(↑nfa').start] = Node.save (2 * i + 1) ↑next
step : (↑nfa'').stepIn nfa.nodes.size (↑(↑nfa').start) (↑next) cs₁✝
rest : (↑nfa'').pathIn nfa.nodes.size (↑next) i' cs₂✝
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂

State before:
case intro.intro.intro.intro.intro.step.εStep.step
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝¹ : List Char
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝¹
heq : i' = nfa.nodes.size ∧ cs₂✝¹ = []
cs₂ : List Char
eqStart✝ : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝¹
rest✝ : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this✝ : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
cs₁✝ cs₂✝ : List Char
eqs : cs₂ = cs₃ ++ (cs₁✝ ++ cs₂✝)
this : ↑(↑nfa').start < (↑nfa'').nodes.size
eqStart : (↑nfa'')[↑(↑nfa').start] = Node.save (2 * i + 1) ↑next
step : (↑nfa'').stepIn nfa.nodes.size (↑(↑nfa').start) (↑next) cs₁✝
rest : (↑nfa'').pathIn nfa.nodes.size (↑next) i' cs₂✝
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂
Tactic:
have := le_of_pathIn_left rest
State after:
case intro.intro.intro.intro.intro.step.εStep.step
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝¹ : List Char
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝¹
heq : i' = nfa.nodes.size ∧ cs₂✝¹ = []
cs₂ : List Char
eqStart✝ : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝¹
rest✝ : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this✝¹ : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
cs₁✝ cs₂✝ : List Char
eqs : cs₂ = cs₃ ++ (cs₁✝ ++ cs₂✝)
this✝ : ↑(↑nfa').start < (↑nfa'').nodes.size
eqStart : (↑nfa'')[↑(↑nfa').start] = Node.save (2 * i + 1) ↑next
step : (↑nfa'').stepIn nfa.nodes.size (↑(↑nfa').start) (↑next) cs₁✝
rest : (↑nfa'').pathIn nfa.nodes.size (↑next) i' cs₂✝
this : nfa.nodes.size ≤ ↑next
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂

State before:
case intro.intro.intro.intro.intro.step.εStep.step
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝¹ : List Char
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝¹
heq : i' = nfa.nodes.size ∧ cs₂✝¹ = []
cs₂ : List Char
eqStart✝ : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝¹
rest✝ : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this✝¹ : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
cs₁✝ cs₂✝ : List Char
eqs : cs₂ = cs₃ ++ (cs₁✝ ++ cs₂✝)
this✝ : ↑(↑nfa').start < (↑nfa'').nodes.size
eqStart : (↑nfa'')[↑(↑nfa').start] = Node.save (2 * i + 1) ↑next
step : (↑nfa'').stepIn nfa.nodes.size (↑(↑nfa').start) (↑next) cs₁✝
rest : (↑nfa'').pathIn nfa.nodes.size (↑next) i' cs₂✝
this : nfa.nodes.size ≤ ↑next
⊢ (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₂
Tactic:
exact (Nat.lt_irrefl _ (Nat.lt_of_le_of_lt this next.isLt)).elim
State after:
no goals

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝¹ : List Char
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝¹
heq : i' = nfa.nodes.size ∧ cs₂✝¹ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝¹
rest✝ : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this✝ : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
j✝ : ℕ
cs₁✝ cs₂✝ : List Char
step : (↑nfa'').stepIn nfa.nodes.size (↑(↑nfa').start) j✝ cs₁✝
rest : (↑nfa'').pathIn nfa.nodes.size j✝ i' cs₂✝
eqs : cs₂ = cs₃ ++ (cs₁✝ ++ cs₂✝)
this : ↑(↑nfa').start < (↑nfa'').nodes.size
⊢ (↑nfa'')[↑(↑nfa').start] = Node.save (2 * i + 1) ↑next
Tactic:
rw [pushRegex_get_lt eq₂.symm _ nfa'.val.start.isLt]
State after:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝¹ : List Char
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝¹
heq : i' = nfa.nodes.size ∧ cs₂✝¹ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝¹
rest✝ : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this✝ : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
j✝ : ℕ
cs₁✝ cs₂✝ : List Char
step : (↑nfa'').stepIn nfa.nodes.size (↑(↑nfa').start) j✝ cs₁✝
rest : (↑nfa'').pathIn nfa.nodes.size j✝ i' cs₂✝
eqs : cs₂ = cs₃ ++ (cs₁✝ ++ cs₂✝)
this : ↑(↑nfa').start < (↑nfa'').nodes.size
⊢ (↑nfa')[↑(↑nfa').start] = Node.save (2 * i + 1) ↑next

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝¹ : List Char
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝¹
heq : i' = nfa.nodes.size ∧ cs₂✝¹ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝¹
rest✝ : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this✝ : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
j✝ : ℕ
cs₁✝ cs₂✝ : List Char
step : (↑nfa'').stepIn nfa.nodes.size (↑(↑nfa').start) j✝ cs₁✝
rest : (↑nfa'').pathIn nfa.nodes.size j✝ i' cs₂✝
eqs : cs₂ = cs₃ ++ (cs₁✝ ++ cs₂✝)
this : ↑(↑nfa').start < (↑nfa'').nodes.size
⊢ (↑nfa')[↑(↑nfa').start] = Node.save (2 * i + 1) ↑next
Tactic:
rw [eq₁]
State after:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝¹ : List Char
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝¹
heq : i' = nfa.nodes.size ∧ cs₂✝¹ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝¹
rest✝ : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this✝ : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
j✝ : ℕ
cs₁✝ cs₂✝ : List Char
step : (↑nfa'').stepIn nfa.nodes.size (↑(↑nfa').start) j✝ cs₁✝
rest : (↑nfa'').pathIn nfa.nodes.size j✝ i' cs₂✝
eqs : cs₂ = cs₃ ++ (cs₁✝ ++ cs₂✝)
this : ↑(↑nfa').start < (↑nfa'').nodes.size
⊢ (↑(nfa.pushNode (Node.save (2 * i + 1) ↑next)
          inBounds'✝))[↑(↑(nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝)).start] =
    Node.save (2 * i + 1) ↑next

State before:
nfa : NFA
next : Fin nfa.nodes.size
i : ℕ
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
cs : List Char
eq✝ : nfa.pushRegex next (Expr.group i r) = result
ih :
  ∀ {nfa : NFA} {next : Fin nfa.nodes.size} {result : { nfa' // nfa.nodes.size < nfa'.nodes.size }} {cs : List Char},
    nfa.pushRegex next r = result →
      (↑result).pathToNext (↑next) nfa.nodes.size (↑(↑result).start) cs → Expr.matches cs r
nfa' : { nfa' // nfa.nodes.size < nfa'.nodes.size }
nfa'' : { nfa'_1 // (↑nfa').nodes.size < nfa'_1.nodes.size }
nfa''' : { nfa'_1 // (↑nfa'').nodes.size < nfa'_1.nodes.size }
property : nfa.nodes.size < (↑nfa''').nodes.size
inBounds'✝ : (Node.save (2 * i + 1) ↑next).inBounds (nfa.nodes.size + 1)
inBounds'''✝ : (Node.save (2 * i) ↑(↑nfa'').start).inBounds ((↑nfa'').nodes.size + 1)
eq₁ : nfa' = nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝
eq₂ : nfa'' = (↑nfa').pushRegex (↑nfa').start r
eq₃ : nfa''' = (↑nfa'').pushNode (Node.save (2 * i) ↑(↑nfa'').start) inBounds'''✝
eq : result = ⟨↑nfa''', property⟩
i' : ℕ
cs₂✝¹ : List Char
step✝ : (↑nfa''').stepIn nfa.nodes.size i' (↑next) cs₂✝¹
heq : i' = nfa.nodes.size ∧ cs₂✝¹ = []
cs₂ : List Char
eqStart : (↑nfa''')[↑(↑nfa''').start] = Node.save (2 * i) ↑(↑nfa'').start
h₁✝ : nfa.nodes.size ≤ ↑(↑nfa''').start
h₂✝ : ↑(↑nfa''').start < (↑nfa''').nodes.size
eqs✝ : cs = [] ++ cs₂ ++ cs₂✝¹
rest✝ : (↑nfa''').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
this✝ : (↑nfa'').pathIn nfa.nodes.size (↑(↑nfa'').start) i' cs₂
cs₃ : List Char
path' : (↑nfa'').pathToNext (↑(↑nfa').start) (↑nfa').nodes.size (↑(↑nfa'').start) cs₃
j✝ : ℕ
cs₁✝ cs₂✝ : List Char
step : (↑nfa'').stepIn nfa.nodes.size (↑(↑nfa').start) j✝ cs₁✝
rest : (↑nfa'').pathIn nfa.nodes.size j✝ i' cs₂✝
eqs : cs₂ = cs₃ ++ (cs₁✝ ++ cs₂✝)
this : ↑(↑nfa').start < (↑nfa'').nodes.size
⊢ (↑(nfa.pushNode (Node.save (2 * i + 1) ↑next)
          inBounds'✝))[↑(↑(nfa.pushNode (Node.save (2 * i + 1) ↑next) inBounds'✝)).start] =
    Node.save (2 * i + 1) ↑next
Tactic:
simp
State after:
no goals