Skip to content

Commit c0efa39

Browse files
committed
feat: split iterators are finite
1 parent 69d8d63 commit c0efa39

File tree

3 files changed

+86
-18
lines changed

3 files changed

+86
-18
lines changed

src/Init/Data/Iterators/Basic.lean

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,12 @@ theorem IterM.TerminationMeasures.Finite.rel_of_skip
705705
Rel ⟨it'⟩ ⟨it⟩ := by
706706
exact .single ⟨_, rfl, h⟩
707707

708+
theorem IterM.TerminationMeasures.Finite.rel_trans
709+
{α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator α m β]
710+
{it it' it'' : TerminationMeasures.Finite α m} :
711+
it.Rel it' → it'.Rel it'' → it.Rel it'' :=
712+
.trans
713+
708714
macro_rules | `(tactic| decreasing_trivial) => `(tactic|
709715
first
710716
| exact IterM.TerminationMeasures.Finite.rel_of_yield ‹_›

src/Init/Data/String/Pattern/Basic.lean

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,24 @@ where
120120
| .done .. => none
121121
termination_by Std.Iterators.Iter.finitelyManySteps searcher
122122

123+
theorem finitelyManySteps_rel_nextMatch {s : Slice} {searcher : Std.Iter (α := σ s) (SearchStep s)}
124+
{next : Std.Iter (α := σ s) (SearchStep s)} {p q : s.Pos} :
125+
nextMatch searcher = some (next, p, q) →
126+
next.finitelyManySteps.Rel searcher.finitelyManySteps := by
127+
rw [nextMatch]
128+
fun_induction nextMatch.go with
129+
| case1 start middle p' q' hstart hstep =>
130+
simp only [Option.some.injEq, Prod.mk.injEq, and_imp]
131+
rintro rfl rfl rfl
132+
exact Std.Iterators.Iter.TerminationMeasures.Finite.rel_of_yield hstart
133+
| case2 start middle p' q' hstart hstep ih =>
134+
refine (Std.Iterators.IterM.TerminationMeasures.Finite.rel_trans · ?_) ∘ ih
135+
exact Std.Iterators.Iter.TerminationMeasures.Finite.rel_of_yield hstart
136+
| case3 start middle hstart hstep ih =>
137+
refine (Std.Iterators.IterM.TerminationMeasures.Finite.rel_trans · ?_) ∘ ih
138+
exact Std.Iterators.Iter.TerminationMeasures.Finite.rel_of_skip hstart
139+
| case4 => simp_all
140+
123141
/--
124142
Tries to skip the {name}`searcher` until the next {name}`SearchStep.rejected` and return it. If no
125143
reject is found until the end returns {name}`none`.

src/Init/Data/String/Slice.lean

Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -171,25 +171,34 @@ Examples:
171171
def split [ToForwardSearcher ρ σ] (s : Slice) (pat : ρ) : Std.Iter (α := SplitIterator ρ) Slice :=
172172
{ internalState := .operating s s.startPos (ToForwardSearcher.toSearcher s pat) }
173173

174-
inductive SplitInclusiveIterator (ρ : Type) [ToForwardSearcher ρ σ] where
175-
| operating (s : Slice) (currPos : s.Pos) (searcher : Std.Iter (α := σ s) (SearchStep s))
174+
inductive SplitInclusiveIterator (ρ : Type) (s : Slice) [ToForwardSearcher ρ σ] where
175+
| operating (currPos : s.Pos) (searcher : Std.Iter (α := σ s) (SearchStep s))
176176
| atEnd
177177
deriving Inhabited
178178

179179
namespace SplitInclusiveIterator
180180

181181
variable [ToForwardSearcher ρ σ]
182182

183-
instance [Pure m] : Std.Iterators.Iterator (SplitInclusiveIterator ρ) m Slice where
184-
IsPlausibleStep := fun _ _ => True
183+
instance [Pure m] : Std.Iterators.Iterator (SplitInclusiveIterator ρ s) m Slice where
184+
IsPlausibleStep it
185+
| .yield it' out =>
186+
match it.internalState, it'.internalState with
187+
| .operating _ searcher, .operating _ searcher' =>
188+
searcher'.finitelyManySteps.Rel searcher.finitelyManySteps
189+
| .operating _ searcher, .atEnd => True
190+
| .atEnd, _ => False
191+
| .skip _ => False
192+
| .done => True
185193
step := fun ⟨iter⟩ =>
186194
match iter with
187-
| .operating s currPos searcher =>
188-
match Internal.nextMatch searcher with
195+
| .operating currPos searcher =>
196+
match h : Internal.nextMatch searcher with
189197
| some (searcher, _, endPos) =>
190198
let slice := s.replaceStartEnd! currPos endPos
191-
let nextIt := ⟨.operating s endPos searcher⟩
192-
pure (.deflate ⟨.yield nextIt slice, by simp⟩)
199+
let nextIt := ⟨.operating endPos searcher⟩
200+
pure (.deflate ⟨.yield nextIt slice,
201+
by simpa [nextIt] using Pattern.Internal.finitelyManySteps_rel_nextMatch h⟩)
193202
| none =>
194203
if currPos != s.endPos then
195204
let slice := s.replaceStart currPos
@@ -198,22 +207,57 @@ instance [Pure m] : Std.Iterators.Iterator (SplitInclusiveIterator ρ) m Slice w
198207
pure (.deflate ⟨.done, by simp⟩)
199208
| .atEnd => pure (.deflate ⟨.done, by simp⟩)
200209

210+
private def toOption : SplitInclusiveIterator ρ s → Option (Std.Iter (α := σ s) (SearchStep s))
211+
| .operating _ s => some s
212+
| .atEnd => none
213+
214+
private instance {s} [Std.Iterators.Finite (σ s) Id] : WellFoundedRelation (SplitInclusiveIterator ρ s) where
215+
rel := InvImage (Option.lt (InvImage Std.Iterators.IterM.TerminationMeasures.Finite.Rel Std.Iterators.Iter.finitelyManySteps)) SplitInclusiveIterator.toOption
216+
wf := by
217+
apply InvImage.wf
218+
apply Option.wellFounded_lt
219+
apply InvImage.wf
220+
exact WellFoundedRelation.wf
221+
222+
private def finitenessRelation [Std.Iterators.Finite (σ s) Id] :
223+
Std.Iterators.FinitenessRelation (SplitInclusiveIterator ρ s) Id where
224+
rel := InvImage WellFoundedRelation.rel (fun it => it.internalState)
225+
wf := InvImage.wf _ WellFoundedRelation.wf
226+
subrelation {it it'} h := by
227+
simp_wf
228+
obtain ⟨step, h, h'⟩ := h
229+
match step with
230+
| .yield it'' out =>
231+
obtain rfl : it' = it'' := by simpa [Std.Iterators.IterStep.successor] using h.symm
232+
simp only [Std.Iterators.IterM.IsPlausibleStep, Std.Iterators.Iterator.IsPlausibleStep] at h'
233+
revert h'
234+
match it.internalState, it'.internalState with
235+
| .operating _ searcher, .operating _ searcher' =>
236+
simp [SplitInclusiveIterator.toOption, Option.lt]
237+
| .operating _ searcher, .atEnd =>
238+
simp [SplitInclusiveIterator.toOption, Option.lt]
239+
| .atEnd, _ => simp
240+
241+
@[no_expose]
242+
instance [Std.Iterators.Finite (σ s) Id] : Std.Iterators.Finite (SplitInclusiveIterator ρ s) Id :=
243+
.of_finitenessRelation finitenessRelation
244+
201245
-- TODO: Finiteness after we have a notion of lawful searcher
202246

203-
instance [Monad m] [Monad n] :
204-
Std.Iterators.IteratorCollect (SplitInclusiveIterator ρ) m n :=
247+
instance [Monad m] [Monad n] {s} :
248+
Std.Iterators.IteratorCollect (SplitInclusiveIterator ρ s) m n :=
205249
.defaultImplementation
206250

207-
instance [Monad m] [Monad n] :
208-
Std.Iterators.IteratorCollectPartial (SplitInclusiveIterator ρ) m n :=
251+
instance [Monad m] [Monad n] {s} :
252+
Std.Iterators.IteratorCollectPartial (SplitInclusiveIterator ρ s) m n :=
209253
.defaultImplementation
210254

211-
instance [Monad m] [Monad n] :
212-
Std.Iterators.IteratorLoop (SplitInclusiveIterator ρ) m n :=
255+
instance [Monad m] [Monad n] {s} :
256+
Std.Iterators.IteratorLoop (SplitInclusiveIterator ρ s) m n :=
213257
.defaultImplementation
214258

215-
instance [Monad m] [Monad n] :
216-
Std.Iterators.IteratorLoopPartial (SplitInclusiveIterator ρ) m n :=
259+
instance [Monad m] [Monad n] {s} :
260+
Std.Iterators.IteratorLoopPartial (SplitInclusiveIterator ρ s) m n :=
217261
.defaultImplementation
218262

219263
end SplitInclusiveIterator
@@ -232,8 +276,8 @@ Examples:
232276
-/
233277
@[specialize pat]
234278
def splitInclusive [ToForwardSearcher ρ σ] (s : Slice) (pat : ρ) :
235-
Std.Iter (α := SplitInclusiveIterator ρ) Slice :=
236-
{ internalState := .operating s s.startPos (ToForwardSearcher.toSearcher s pat) }
279+
Std.Iter (α := SplitInclusiveIterator ρ s) Slice :=
280+
{ internalState := .operating s.startPos (ToForwardSearcher.toSearcher s pat) }
237281

238282
/--
239283
If {name}`pat` matches a prefix of {name}`s`, returns the remainder. Returns {name}`none` otherwise.

0 commit comments

Comments
 (0)