Theorem: Regex.NFA.starLoop.intro' (RegexCorrectness/NFA/Transition/Path/Equivalence/MatchOfPath.lean)

State before:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
assm₁ : i < (↑result).nodes.size
assm₂ : loopStart = nfa.nodes.size
ev : (↑result).pathIn nfa.nodes.size i loopStart cs
⊢ if i = nfa.nodes.size then
    cs = [] ∨
      ∃ cs₁ cs₂,
        cs = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂
Tactic:
induction ev with
| base h =>
  subst assm₂
  simp
| @step i j k cs cs' step path ih =>
  have ih := ih step.lt_right assm₂
  split
  case inl eqi =>
    subst eqi
    have ⟨ge, node⟩ := rStart_of_spec eq
    simp [node]
    cases step with
    | charStep _ _ step => simp [node, NFA.Node.charStep] at step
    | εStep h₁ h₂ step =>
      apply Or.inr
      have : j = rStart_of eq := by
        simp [node, NFA.Node.εStep] at step
        cases step with
        | inl eq => exact eq
        | inr eq =>
          have : nfa.nodes.size ≤ j := le_of_pathIn_left path
          exact absurd next.isLt (Nat.not_lt_of_le (eq ▸ this))
      subst this
      simp [NFA.Node.εStep]
      have : rStart_of eq ≠ nfa.nodes.size := Nat.ne_of_gt ge
      simp [this] at ih
      exact ih
  case inr nei =>
    have gti : nfa.nodes.size < i := Nat.lt_of_le_of_ne step.h₁ (Ne.symm nei)
    split at ih
    case inl eqj =>
      have toNext : pathToNext result nfa.nodes.size (nfa.nodes.size + 1) i cs :=
        ⟨i, [], cs, rfl, .base gti, (eqj ▸ step).castStart' gti⟩
      cases ih with
      | inl eqs =>
        subst eqs
        exact ⟨cs, [], rfl, toNext, .complete⟩
      | inr cond =>
        obtain ⟨cs₁, cs₂, eqs, path', loop⟩ := cond
        exact ⟨cs, cs₁ ++ cs₂, by simp [eqs], toNext, .loop path' loop⟩
    case inr nej =>
      obtain ⟨cs₁, cs₂, eqs, path', loop⟩ := ih
      subst eqs
      cases step with
      | charStep h₁ h₂ step =>
        exact ⟨_ :: cs₁, cs₂, rfl, path'.cons (.charStep gti h₂ step), loop⟩
      | εStep h₁ h₂ step =>
        exact ⟨cs₁, cs₂, rfl, path'.cons (.εStep gti h₂ step), loop⟩
State after:
no goals

State before:
case base
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
i✝ : ℕ
h : nfa.nodes.size ≤ i✝
assm₁ : i✝ < (↑result).nodes.size
assm₂ : i✝ = nfa.nodes.size
⊢ if i✝ = nfa.nodes.size then
    [] = [] ∨
      ∃ cs₁ cs₂,
        [] = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, [] = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i✝ cs₁ ∧ starLoop eq cs₂
Tactic:
subst assm₂
State after:
case base
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
h : nfa.nodes.size ≤ nfa.nodes.size
assm₁ : nfa.nodes.size < (↑result).nodes.size
⊢ if nfa.nodes.size = nfa.nodes.size then
    [] = [] ∨
      ∃ cs₁ cs₂,
        [] = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else
    ∃ cs₁ cs₂,
      [] = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) nfa.nodes.size cs₁ ∧ starLoop eq cs₂

State before:
case base
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
h : nfa.nodes.size ≤ nfa.nodes.size
assm₁ : nfa.nodes.size < (↑result).nodes.size
⊢ if nfa.nodes.size = nfa.nodes.size then
    [] = [] ∨
      ∃ cs₁ cs₂,
        [] = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else
    ∃ cs₁ cs₂,
      [] = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) nfa.nodes.size cs₁ ∧ starLoop eq cs₂
Tactic:
simp
State after:
no goals

State before:
case step
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
⊢ if i = nfa.nodes.size then
    cs ++ cs' = [] ∨
      ∃ cs₁ cs₂,
        cs ++ cs' = cs₁ ++ cs₂ ∧
          (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else
    ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂
Tactic:
have ih := ih step.lt_right assm₂
State after:
case step
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
⊢ if i = nfa.nodes.size then
    cs ++ cs' = [] ∨
      ∃ cs₁ cs₂,
        cs ++ cs' = cs₁ ++ cs₂ ∧
          (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else
    ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂

State before:
case step
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
⊢ if i = nfa.nodes.size then
    cs ++ cs' = [] ∨
      ∃ cs₁ cs₂,
        cs ++ cs' = cs₁ ++ cs₂ ∧
          (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else
    ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂
Tactic:
split
State after:
case step.inl
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
h✝ : i = nfa.nodes.size
⊢ cs ++ cs' = [] ∨
    ∃ cs₁ cs₂,
      cs ++ cs' = cs₁ ++ cs₂ ∧
        (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂

case step.inr
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
h✝ : ¬i = nfa.nodes.size
⊢ ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂

State before:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
eqi : i = nfa.nodes.size
⊢ cs ++ cs' = [] ∨
    ∃ cs₁ cs₂,
      cs ++ cs' = cs₁ ++ cs₂ ∧
        (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
Tactic:
case inl eqi =>
  subst eqi
  have ⟨ge, node⟩ := rStart_of_spec eq
  simp [node]
  cases step with
  | charStep _ _ step => simp [node, NFA.Node.charStep] at step
  | εStep h₁ h₂ step =>
    apply Or.inr
    have : j = rStart_of eq := by
      simp [node, NFA.Node.εStep] at step
      cases step with
      | inl eq => exact eq
      | inr eq =>
        have : nfa.nodes.size ≤ j := le_of_pathIn_left path
        exact absurd next.isLt (Nat.not_lt_of_le (eq ▸ this))
    subst this
    simp [NFA.Node.εStep]
    have : rStart_of eq ≠ nfa.nodes.size := Nat.ne_of_gt ge
    simp [this] at ih
    exact ih
State after:
no goals

State before:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
nei : ¬i = nfa.nodes.size
⊢ ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂
Tactic:
case inr nei =>
  have gti : nfa.nodes.size < i := Nat.lt_of_le_of_ne step.h₁ (Ne.symm nei)
  split at ih
  case inl eqj =>
    have toNext : pathToNext result nfa.nodes.size (nfa.nodes.size + 1) i cs :=
      ⟨i, [], cs, rfl, .base gti, (eqj ▸ step).castStart' gti⟩
    cases ih with
    | inl eqs =>
      subst eqs
      exact ⟨cs, [], rfl, toNext, .complete⟩
    | inr cond =>
      obtain ⟨cs₁, cs₂, eqs, path', loop⟩ := cond
      exact ⟨cs, cs₁ ++ cs₂, by simp [eqs], toNext, .loop path' loop⟩
  case inr nej =>
    obtain ⟨cs₁, cs₂, eqs, path', loop⟩ := ih
    subst eqs
    cases step with
    | charStep h₁ h₂ step =>
      exact ⟨_ :: cs₁, cs₂, rfl, path'.cons (.charStep gti h₂ step), loop⟩
    | εStep h₁ h₂ step =>
      exact ⟨cs₁, cs₂, rfl, path'.cons (.εStep gti h₂ step), loop⟩
State after:
no goals

State before:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
eqi : i = nfa.nodes.size
⊢ cs ++ cs' = [] ∨
    ∃ cs₁ cs₂,
      cs ++ cs' = cs₁ ++ cs₂ ∧
        (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
Tactic:
subst eqi
State after:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
j k : ℕ
cs cs' : List Char
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
step : (↑result).stepIn nfa.nodes.size nfa.nodes.size j cs
assm₁ : nfa.nodes.size < (↑result).nodes.size
⊢ cs ++ cs' = [] ∨
    ∃ cs₁ cs₂,
      cs ++ cs' = cs₁ ++ cs₂ ∧
        (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂

State before:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
j k : ℕ
cs cs' : List Char
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
step : (↑result).stepIn nfa.nodes.size nfa.nodes.size j cs
assm₁ : nfa.nodes.size < (↑result).nodes.size
⊢ cs ++ cs' = [] ∨
    ∃ cs₁ cs₂,
      cs ++ cs' = cs₁ ++ cs₂ ∧
        (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
Tactic:
have ⟨ge, node⟩ := rStart_of_spec eq
State after:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
j k : ℕ
cs cs' : List Char
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
step : (↑result).stepIn nfa.nodes.size nfa.nodes.size j cs
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
⊢ cs ++ cs' = [] ∨
    ∃ cs₁ cs₂,
      cs ++ cs' = cs₁ ++ cs₂ ∧
        (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂

State before:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
j k : ℕ
cs cs' : List Char
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
step : (↑result).stepIn nfa.nodes.size nfa.nodes.size j cs
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
⊢ cs ++ cs' = [] ∨
    ∃ cs₁ cs₂,
      cs ++ cs' = cs₁ ++ cs₂ ∧
        (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
Tactic:
simp [node]
State after:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
j k : ℕ
cs cs' : List Char
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
step : (↑result).stepIn nfa.nodes.size nfa.nodes.size j cs
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
⊢ cs = [] ∧ cs' = [] ∨
    ∃ cs₁ cs₂,
      cs ++ cs' = cs₁ ++ cs₂ ∧
        (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂

State before:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
j k : ℕ
cs cs' : List Char
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
step : (↑result).stepIn nfa.nodes.size nfa.nodes.size j cs
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
⊢ cs = [] ∧ cs' = [] ∨
    ∃ cs₁ cs₂,
      cs ++ cs' = cs₁ ++ cs₂ ∧
        (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
Tactic:
cases step with
| charStep _ _ step => simp [node, NFA.Node.charStep] at step
| εStep h₁ h₂ step =>
  apply Or.inr
  have : j = rStart_of eq := by
    simp [node, NFA.Node.εStep] at step
    cases step with
    | inl eq => exact eq
    | inr eq =>
      have : nfa.nodes.size ≤ j := le_of_pathIn_left path
      exact absurd next.isLt (Nat.not_lt_of_le (eq ▸ this))
  subst this
  simp [NFA.Node.εStep]
  have : rStart_of eq ≠ nfa.nodes.size := Nat.ne_of_gt ge
  simp [this] at ih
  exact ih
State after:
no goals

State before:
case charStep
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
j k : ℕ
cs' : List Char
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
c✝ : Char
h₁✝ : nfa.nodes.size ≤ nfa.nodes.size
h₂✝ : nfa.nodes.size < (↑result).nodes.size
step : j ∈ (↑result)[nfa.nodes.size].charStep c✝
⊢ [c✝] = [] ∧ cs' = [] ∨
    ∃ cs₁ cs₂,
      [c✝] ++ cs' = cs₁ ++ cs₂ ∧
        (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
Tactic:
simp [node, NFA.Node.charStep] at step
State after:
no goals

State before:
case εStep
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
j k : ℕ
cs' : List Char
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
step : j ∈ (↑result)[nfa.nodes.size].εStep
⊢ [] = [] ∧ cs' = [] ∨
    ∃ cs₁ cs₂,
      [] ++ cs' = cs₁ ++ cs₂ ∧
        (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
Tactic:
apply Or.inr
State after:
case εStep.h
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
j k : ℕ
cs' : List Char
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
step : j ∈ (↑result)[nfa.nodes.size].εStep
⊢ ∃ cs₁ cs₂,
    [] ++ cs' = cs₁ ++ cs₂ ∧
      (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂

State before:
case εStep.h
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
j k : ℕ
cs' : List Char
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
step : j ∈ (↑result)[nfa.nodes.size].εStep
⊢ ∃ cs₁ cs₂,
    [] ++ cs' = cs₁ ++ cs₂ ∧
      (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
Tactic:
have : j = rStart_of eq := by
  simp [node, NFA.Node.εStep] at step
  cases step with
  | inl eq => exact eq
  | inr eq =>
    have : nfa.nodes.size ≤ j := le_of_pathIn_left path
    exact absurd next.isLt (Nat.not_lt_of_le (eq ▸ this))
State after:
case εStep.h
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
j k : ℕ
cs' : List Char
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
step : j ∈ (↑result)[nfa.nodes.size].εStep
this : j = rStart_of eq
⊢ ∃ cs₁ cs₂,
    [] ++ cs' = cs₁ ++ cs₂ ∧
      (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂

State before:
case εStep.h
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
j k : ℕ
cs' : List Char
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
step : j ∈ (↑result)[nfa.nodes.size].εStep
this : j = rStart_of eq
⊢ ∃ cs₁ cs₂,
    [] ++ cs' = cs₁ ++ cs₂ ∧
      (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
Tactic:
subst this
State after:
case εStep.h
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
k : ℕ
cs' : List Char
assm₂ : k = nfa.nodes.size
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
path : (↑result).pathIn nfa.nodes.size (rStart_of eq) k cs'
ih✝ :
  rStart_of eq < (↑result).nodes.size →
    k = nfa.nodes.size →
      if rStart_of eq = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂,
          cs' = cs₁ ++ cs₂ ∧
            (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
ih :
  if rStart_of eq = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else
    ∃ cs₁ cs₂,
      cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
step : rStart_of eq ∈ (↑result)[nfa.nodes.size].εStep
⊢ ∃ cs₁ cs₂,
    [] ++ cs' = cs₁ ++ cs₂ ∧
      (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂

State before:
case εStep.h
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
k : ℕ
cs' : List Char
assm₂ : k = nfa.nodes.size
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
path : (↑result).pathIn nfa.nodes.size (rStart_of eq) k cs'
ih✝ :
  rStart_of eq < (↑result).nodes.size →
    k = nfa.nodes.size →
      if rStart_of eq = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂,
          cs' = cs₁ ++ cs₂ ∧
            (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
ih :
  if rStart_of eq = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else
    ∃ cs₁ cs₂,
      cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
step : rStart_of eq ∈ (↑result)[nfa.nodes.size].εStep
⊢ ∃ cs₁ cs₂,
    [] ++ cs' = cs₁ ++ cs₂ ∧
      (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
Tactic:
simp [NFA.Node.εStep]
State after:
case εStep.h
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
k : ℕ
cs' : List Char
assm₂ : k = nfa.nodes.size
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
path : (↑result).pathIn nfa.nodes.size (rStart_of eq) k cs'
ih✝ :
  rStart_of eq < (↑result).nodes.size →
    k = nfa.nodes.size →
      if rStart_of eq = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂,
          cs' = cs₁ ++ cs₂ ∧
            (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
ih :
  if rStart_of eq = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else
    ∃ cs₁ cs₂,
      cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
step : rStart_of eq ∈ (↑result)[nfa.nodes.size].εStep
⊢ ∃ cs₁ cs₂,
    cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂

State before:
case εStep.h
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
k : ℕ
cs' : List Char
assm₂ : k = nfa.nodes.size
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
path : (↑result).pathIn nfa.nodes.size (rStart_of eq) k cs'
ih✝ :
  rStart_of eq < (↑result).nodes.size →
    k = nfa.nodes.size →
      if rStart_of eq = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂,
          cs' = cs₁ ++ cs₂ ∧
            (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
ih :
  if rStart_of eq = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else
    ∃ cs₁ cs₂,
      cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
step : rStart_of eq ∈ (↑result)[nfa.nodes.size].εStep
⊢ ∃ cs₁ cs₂,
    cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
Tactic:
have : rStart_of eq ≠ nfa.nodes.size := Nat.ne_of_gt ge
State after:
case εStep.h
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
k : ℕ
cs' : List Char
assm₂ : k = nfa.nodes.size
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
path : (↑result).pathIn nfa.nodes.size (rStart_of eq) k cs'
ih✝ :
  rStart_of eq < (↑result).nodes.size →
    k = nfa.nodes.size →
      if rStart_of eq = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂,
          cs' = cs₁ ++ cs₂ ∧
            (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
ih :
  if rStart_of eq = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else
    ∃ cs₁ cs₂,
      cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
step : rStart_of eq ∈ (↑result)[nfa.nodes.size].εStep
this : rStart_of eq ≠ nfa.nodes.size
⊢ ∃ cs₁ cs₂,
    cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂

State before:
case εStep.h
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
k : ℕ
cs' : List Char
assm₂ : k = nfa.nodes.size
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
path : (↑result).pathIn nfa.nodes.size (rStart_of eq) k cs'
ih✝ :
  rStart_of eq < (↑result).nodes.size →
    k = nfa.nodes.size →
      if rStart_of eq = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂,
          cs' = cs₁ ++ cs₂ ∧
            (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
ih :
  if rStart_of eq = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else
    ∃ cs₁ cs₂,
      cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
step : rStart_of eq ∈ (↑result)[nfa.nodes.size].εStep
this : rStart_of eq ≠ nfa.nodes.size
⊢ ∃ cs₁ cs₂,
    cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
Tactic:
simp [this] at ih
State after:
case εStep.h
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
k : ℕ
cs' : List Char
assm₂ : k = nfa.nodes.size
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
path : (↑result).pathIn nfa.nodes.size (rStart_of eq) k cs'
ih✝ :
  rStart_of eq < (↑result).nodes.size →
    k = nfa.nodes.size →
      if rStart_of eq = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂,
          cs' = cs₁ ++ cs₂ ∧
            (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
step : rStart_of eq ∈ (↑result)[nfa.nodes.size].εStep
this : rStart_of eq ≠ nfa.nodes.size
ih :
  ∃ cs₁ cs₂,
    cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
⊢ ∃ cs₁ cs₂,
    cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂

State before:
case εStep.h
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
k : ℕ
cs' : List Char
assm₂ : k = nfa.nodes.size
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
path : (↑result).pathIn nfa.nodes.size (rStart_of eq) k cs'
ih✝ :
  rStart_of eq < (↑result).nodes.size →
    k = nfa.nodes.size →
      if rStart_of eq = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂,
          cs' = cs₁ ++ cs₂ ∧
            (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
step : rStart_of eq ∈ (↑result)[nfa.nodes.size].εStep
this : rStart_of eq ≠ nfa.nodes.size
ih :
  ∃ cs₁ cs₂,
    cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
⊢ ∃ cs₁ cs₂,
    cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
Tactic:
exact ih
State after:
no goals

State before:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
j k : ℕ
cs' : List Char
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
step : j ∈ (↑result)[nfa.nodes.size].εStep
⊢ j = rStart_of eq
Tactic:
simp [node, NFA.Node.εStep] at step
State after:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
j k : ℕ
cs' : List Char
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
step : j = rStart_of eq ∨ j = ↑next
⊢ j = rStart_of eq

State before:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
j k : ℕ
cs' : List Char
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
step : j = rStart_of eq ∨ j = ↑next
⊢ j = rStart_of eq
Tactic:
cases step with
| inl eq => exact eq
| inr eq =>
  have : nfa.nodes.size ≤ j := le_of_pathIn_left path
  exact absurd next.isLt (Nat.not_lt_of_le (eq ▸ this))
State after:
no goals

State before:
case inl
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq✝ : nfa.pushRegex next r.star = result
j k : ℕ
cs' : List Char
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq✝) cs₁ ∧ starLoop eq✝ cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq✝ cs₂
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧
          (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq✝) cs₁ ∧ starLoop eq✝ cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq✝ cs₂
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq✝
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq✝) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
eq : j = rStart_of eq✝
⊢ j = rStart_of eq✝
Tactic:
exact eq
State after:
no goals

State before:
case inr
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq✝ : nfa.pushRegex next r.star = result
j k : ℕ
cs' : List Char
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq✝) cs₁ ∧ starLoop eq✝ cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq✝ cs₂
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧
          (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq✝) cs₁ ∧ starLoop eq✝ cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq✝ cs₂
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq✝
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq✝) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
eq : j = ↑next
⊢ j = rStart_of eq✝
Tactic:
have : nfa.nodes.size ≤ j := le_of_pathIn_left path
State after:
case inr
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq✝ : nfa.pushRegex next r.star = result
j k : ℕ
cs' : List Char
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq✝) cs₁ ∧ starLoop eq✝ cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq✝ cs₂
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧
          (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq✝) cs₁ ∧ starLoop eq✝ cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq✝ cs₂
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq✝
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq✝) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
eq : j = ↑next
this : nfa.nodes.size ≤ j
⊢ j = rStart_of eq✝

State before:
case inr
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i loopStart : ℕ
cs : List Char
eq✝ : nfa.pushRegex next r.star = result
j k : ℕ
cs' : List Char
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq✝) cs₁ ∧ starLoop eq✝ cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq✝ cs₂
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧
          (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq✝) cs₁ ∧ starLoop eq✝ cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq✝ cs₂
assm₁ : nfa.nodes.size < (↑result).nodes.size
ge : nfa.nodes.size + 1 ≤ rStart_of eq✝
node : (↑result)[nfa.nodes.size] = Node.split (rStart_of eq✝) ↑next
h₁ : nfa.nodes.size ≤ nfa.nodes.size
h₂ : nfa.nodes.size < (↑result).nodes.size
eq : j = ↑next
this : nfa.nodes.size ≤ j
⊢ j = rStart_of eq✝
Tactic:
exact absurd next.isLt (Nat.not_lt_of_le (eq ▸ this))
State after:
no goals

State before:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
nei : ¬i = nfa.nodes.size
⊢ ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂
Tactic:
have gti : nfa.nodes.size < i := Nat.lt_of_le_of_ne step.h₁ (Ne.symm nei)
State after:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
⊢ ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂

State before:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
ih :
  if j = nfa.nodes.size then
    cs' = [] ∨
      ∃ cs₁ cs₂,
        cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
  else ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
⊢ ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂
Tactic:
split at ih
State after:
case inl
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
h✝ : j = nfa.nodes.size
ih :
  cs' = [] ∨
    ∃ cs₁ cs₂,
      cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
⊢ ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂

case inr
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
h✝ : ¬j = nfa.nodes.size
ih : ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
⊢ ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂

State before:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
eqj : j = nfa.nodes.size
ih :
  cs' = [] ∨
    ∃ cs₁ cs₂,
      cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
⊢ ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂
Tactic:
case inl eqj =>
  have toNext : pathToNext result nfa.nodes.size (nfa.nodes.size + 1) i cs :=
    ⟨i, [], cs, rfl, .base gti, (eqj ▸ step).castStart' gti⟩
  cases ih with
  | inl eqs =>
    subst eqs
    exact ⟨cs, [], rfl, toNext, .complete⟩
  | inr cond =>
    obtain ⟨cs₁, cs₂, eqs, path', loop⟩ := cond
    exact ⟨cs, cs₁ ++ cs₂, by simp [eqs], toNext, .loop path' loop⟩
State after:
no goals

State before:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
nej : ¬j = nfa.nodes.size
ih : ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
⊢ ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂
Tactic:
case inr nej =>
  obtain ⟨cs₁, cs₂, eqs, path', loop⟩ := ih
  subst eqs
  cases step with
  | charStep h₁ h₂ step =>
    exact ⟨_ :: cs₁, cs₂, rfl, path'.cons (.charStep gti h₂ step), loop⟩
  | εStep h₁ h₂ step =>
    exact ⟨cs₁, cs₂, rfl, path'.cons (.εStep gti h₂ step), loop⟩
State after:
no goals

State before:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
eqj : j = nfa.nodes.size
ih :
  cs' = [] ∨
    ∃ cs₁ cs₂,
      cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
⊢ ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂
Tactic:
have toNext : pathToNext result nfa.nodes.size (nfa.nodes.size + 1) i cs :=
  ⟨i, [], cs, rfl, .base gti, (eqj ▸ step).castStart' gti⟩
State after:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
eqj : j = nfa.nodes.size
ih :
  cs' = [] ∨
    ∃ cs₁ cs₂,
      cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
toNext : (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs
⊢ ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂

State before:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
eqj : j = nfa.nodes.size
ih :
  cs' = [] ∨
    ∃ cs₁ cs₂,
      cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
toNext : (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs
⊢ ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂
Tactic:
cases ih with
| inl eqs =>
  subst eqs
  exact ⟨cs, [], rfl, toNext, .complete⟩
| inr cond =>
  obtain ⟨cs₁, cs₂, eqs, path', loop⟩ := cond
  exact ⟨cs, cs₁ ++ cs₂, by simp [eqs], toNext, .loop path' loop⟩
State after:
no goals

State before:
case inl
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
eqj : j = nfa.nodes.size
toNext : (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs
eqs : cs' = []
⊢ ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂
Tactic:
subst eqs
State after:
case inl
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
eqj : j = nfa.nodes.size
toNext : (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs
path : (↑result).pathIn nfa.nodes.size j k []
ih :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        [] = [] ∨
          ∃ cs₁ cs₂,
            [] = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else ∃ cs₁ cs₂, [] = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
⊢ ∃ cs₁ cs₂, cs ++ [] = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂

State before:
case inl
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
eqj : j = nfa.nodes.size
toNext : (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs
path : (↑result).pathIn nfa.nodes.size j k []
ih :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        [] = [] ∨
          ∃ cs₁ cs₂,
            [] = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else ∃ cs₁ cs₂, [] = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
⊢ ∃ cs₁ cs₂, cs ++ [] = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂
Tactic:
exact ⟨cs, [], rfl, toNext, .complete⟩
State after:
no goals

State before:
case inr
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
eqj : j = nfa.nodes.size
toNext : (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs
cond :
  ∃ cs₁ cs₂,
    cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
⊢ ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂
Tactic:
obtain ⟨cs₁, cs₂, eqs, path', loop⟩ := cond
State after:
case inr.intro.intro.intro.intro
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
eqj : j = nfa.nodes.size
toNext : (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs
cs₁ cs₂ : List Char
eqs : cs' = cs₁ ++ cs₂
path' : (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁
loop : starLoop eq cs₂
⊢ ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂

State before:
case inr.intro.intro.intro.intro
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
eqj : j = nfa.nodes.size
toNext : (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs
cs₁ cs₂ : List Char
eqs : cs' = cs₁ ++ cs₂
path' : (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁
loop : starLoop eq cs₂
⊢ ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂
Tactic:
exact ⟨cs, cs₁ ++ cs₂, by simp [eqs], toNext, .loop path' loop⟩
State after:
no goals

State before:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
eqj : j = nfa.nodes.size
toNext : (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs
cs₁ cs₂ : List Char
eqs : cs' = cs₁ ++ cs₂
path' : (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁
loop : starLoop eq cs₂
⊢ cs ++ cs' = cs ++ (cs₁ ++ cs₂)
Tactic:
simp [eqs]
State after:
no goals

State before:
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih✝ :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
nej : ¬j = nfa.nodes.size
ih : ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
⊢ ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂
Tactic:
obtain ⟨cs₁, cs₂, eqs, path', loop⟩ := ih
State after:
case intro.intro.intro.intro
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
nej : ¬j = nfa.nodes.size
cs₁ cs₂ : List Char
eqs : cs' = cs₁ ++ cs₂
path' : (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁
loop : starLoop eq cs₂
⊢ ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂

State before:
case intro.intro.intro.intro
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs cs' : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
path : (↑result).pathIn nfa.nodes.size j k cs'
ih :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs' = [] ∨
          ∃ cs₁ cs₂,
            cs' = cs₁ ++ cs₂ ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁ ∧ starLoop eq cs₂
      else
        ∃ cs₁ cs₂, cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁ ∧ starLoop eq cs₂
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
nej : ¬j = nfa.nodes.size
cs₁ cs₂ : List Char
eqs : cs' = cs₁ ++ cs₂
path' : (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁
loop : starLoop eq cs₂
⊢ ∃ cs₁ cs₂, cs ++ cs' = cs₁ ++ cs₂ ∧ (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁ ∧ starLoop eq cs₂
Tactic:
subst eqs
State after:
case intro.intro.intro.intro
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
nej : ¬j = nfa.nodes.size
cs₁ cs₂ : List Char
path' : (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁
loop : starLoop eq cs₂
path : (↑result).pathIn nfa.nodes.size j k (cs₁ ++ cs₂)
ih :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs₁ ++ cs₂ = [] ∨
          ∃ cs₁_1 cs₂_1,
            cs₁ ++ cs₂ = cs₁_1 ++ cs₂_1 ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁_1 ∧ starLoop eq cs₂_1
      else
        ∃ cs₁_1 cs₂_1,
          cs₁ ++ cs₂ = cs₁_1 ++ cs₂_1 ∧
            (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁_1 ∧ starLoop eq cs₂_1
⊢ ∃ cs₁_1 cs₂_1,
    cs ++ (cs₁ ++ cs₂) = cs₁_1 ++ cs₂_1 ∧
      (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁_1 ∧ starLoop eq cs₂_1

State before:
case intro.intro.intro.intro
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs✝ : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
cs : List Char
step : (↑result).stepIn nfa.nodes.size i j cs
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
nej : ¬j = nfa.nodes.size
cs₁ cs₂ : List Char
path' : (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁
loop : starLoop eq cs₂
path : (↑result).pathIn nfa.nodes.size j k (cs₁ ++ cs₂)
ih :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs₁ ++ cs₂ = [] ∨
          ∃ cs₁_1 cs₂_1,
            cs₁ ++ cs₂ = cs₁_1 ++ cs₂_1 ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁_1 ∧ starLoop eq cs₂_1
      else
        ∃ cs₁_1 cs₂_1,
          cs₁ ++ cs₂ = cs₁_1 ++ cs₂_1 ∧
            (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁_1 ∧ starLoop eq cs₂_1
⊢ ∃ cs₁_1 cs₂_1,
    cs ++ (cs₁ ++ cs₂) = cs₁_1 ++ cs₂_1 ∧
      (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁_1 ∧ starLoop eq cs₂_1
Tactic:
cases step with
| charStep h₁ h₂ step =>
  exact ⟨_ :: cs₁, cs₂, rfl, path'.cons (.charStep gti h₂ step), loop⟩
| εStep h₁ h₂ step =>
  exact ⟨cs₁, cs₂, rfl, path'.cons (.εStep gti h₂ step), loop⟩
State after:
no goals

State before:
case intro.intro.intro.intro.charStep
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
nej : ¬j = nfa.nodes.size
cs₁ cs₂ : List Char
path' : (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁
loop : starLoop eq cs₂
path : (↑result).pathIn nfa.nodes.size j k (cs₁ ++ cs₂)
ih :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs₁ ++ cs₂ = [] ∨
          ∃ cs₁_1 cs₂_1,
            cs₁ ++ cs₂ = cs₁_1 ++ cs₂_1 ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁_1 ∧ starLoop eq cs₂_1
      else
        ∃ cs₁_1 cs₂_1,
          cs₁ ++ cs₂ = cs₁_1 ++ cs₂_1 ∧
            (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁_1 ∧ starLoop eq cs₂_1
c✝ : Char
h₁ : nfa.nodes.size ≤ i
h₂ : i < (↑result).nodes.size
step : j ∈ (↑result)[i].charStep c✝
⊢ ∃ cs₁_1 cs₂_1,
    [c✝] ++ (cs₁ ++ cs₂) = cs₁_1 ++ cs₂_1 ∧
      (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁_1 ∧ starLoop eq cs₂_1
Tactic:
exact ⟨_ :: cs₁, cs₂, rfl, path'.cons (.charStep gti h₂ step), loop⟩
State after:
no goals

State before:
case intro.intro.intro.intro.εStep
nfa : NFA
next : Fin nfa.nodes.size
r : Expr
result : { nfa' // nfa.nodes.size < nfa'.nodes.size }
i✝ loopStart : ℕ
cs : List Char
eq : nfa.pushRegex next r.star = result
i j k : ℕ
assm₁ : i < (↑result).nodes.size
assm₂ : k = nfa.nodes.size
nei : ¬i = nfa.nodes.size
gti : nfa.nodes.size < i
nej : ¬j = nfa.nodes.size
cs₁ cs₂ : List Char
path' : (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁
loop : starLoop eq cs₂
path : (↑result).pathIn nfa.nodes.size j k (cs₁ ++ cs₂)
ih :
  j < (↑result).nodes.size →
    k = nfa.nodes.size →
      if j = nfa.nodes.size then
        cs₁ ++ cs₂ = [] ∨
          ∃ cs₁_1 cs₂_1,
            cs₁ ++ cs₂ = cs₁_1 ++ cs₂_1 ∧
              (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) (rStart_of eq) cs₁_1 ∧ starLoop eq cs₂_1
      else
        ∃ cs₁_1 cs₂_1,
          cs₁ ++ cs₂ = cs₁_1 ++ cs₂_1 ∧
            (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) j cs₁_1 ∧ starLoop eq cs₂_1
h₁ : nfa.nodes.size ≤ i
h₂ : i < (↑result).nodes.size
step : j ∈ (↑result)[i].εStep
⊢ ∃ cs₁_1 cs₂_1,
    [] ++ (cs₁ ++ cs₂) = cs₁_1 ++ cs₂_1 ∧
      (↑result).pathToNext nfa.nodes.size (nfa.nodes.size + 1) i cs₁_1 ∧ starLoop eq cs₂_1
Tactic:
exact ⟨cs₁, cs₂, rfl, path'.cons (.εStep gti h₂ step), loop⟩
State after:
no goals