Source src/silo:std.iter
1##! Lazy iteration protocol and adapter types. 2##! 3##! Defines the `Iterator` trait (the `@lang(iterator)` item) and two 4##! concrete wrapper records: `CharsIter` for `Str` codepoint 5##! iteration and `Peekable` for one-slot lookahead over any underlying 6##! `Iterator`. 7 8:use 9 :open core Option None Some Char AnyInt Str 10 :open traits Ord 11 :open collections Foldable 12:end 13 14# si[impl coll.iterator] 15# si[impl lang.iterator] 16## Lazy, stateful element-at-a-time iteration protocol. 17## Returns `Some item` on advance, `None` on exhaustion. 18@lang(iterator) 19:trait(pub) Iterator | item 20 ## Advance one element; returns the iterator and an optional value. 21 ## ( Self -> Self (Option item) ) 22 .next ( Self -> Self (Option item) ) 23:end 24 25## Lazy character iterator over a Str. 26## Tracks the UTF-8 byte position of the next codepoint to yield. 27:record(pub) CharsIter .str Str .pos AnyInt :end 28 29:impl Iterator CharsIter | Char 30 .next ( CharsIter -> CharsIter (Option Char) ) 31 pop-> it 32 it .pos it .str str-len ≥ :if it None :ret :end 33 it .pos it .str str-next-char pop-> ch pop-> new-pos 34 new-pos it .pos<- 35 ch Some ; 36:end 37 38## Construct a `CharsIter` over the given `Str`, starting at position 0. 39## The lazy iterator form is named `chars-iter` to avoid colliding with 40## `StrExt`'s eager `.chars` method (which returns `(Vec Codepoint)`). 41## ( Str -> CharsIter ) 42:fn(pub) chars-iter ( Str -> CharsIter ) 0 CharsIter :end 43 44# Foldable for CharsIter (via Iterator .next) 45:impl Foldable CharsIter 46 .fold ( CharsIter acc [acc Char -> acc] -> acc ) 47 pop-> f pop-> acc pop-> it 48 :loop 49 it .next pop-> opt pop-> it 50 opt :match 51 | None => :break 52 | Some e => acc e f .call 53 :end 54 pop-> acc 55 :end acc ; 56 .for-each ( CharsIter [Char ->] -> ) 57 pop-> f pop-> it 58 :loop 59 it .next pop-> opt pop-> it 60 opt :match 61 | None => :ret 62 | Some e => e f .call 63 :end 64 :end ; 65:end 66 67# si[impl stdlib.iter.peekable] 68## Lookahead protocol for iterators that support inspecting the next 69## element without consuming it. Every `Peekable` MUST also be an 70## `Iterator` — the associated `item` type is shared with the iterator's 71## `item` via the `(Iterator Self | item)` constraint. 72## 73## Types with a natural one-slot lookahead (token streams, buffered 74## readers, lookahead parsers) implement this trait directly. There is 75## no auto-wrapper for "any Iterator"; callers that need lookahead over 76## a plain Iterator MUST provide their own `:impl`. 77:trait(pub) Peekable | item { (Iterator Self | item) } 78 ## Return the next element without consuming it. 79 ## Successive `.peek` calls without an intervening `.next` MUST return 80 ## the same value. The returned `Self` MAY be the same handle with an 81 ## internally populated cache. 82 ## ( Self -> Self (Option item) ) 83 .peek ( Self -> Self (Option item) ) 84:end