diff options
Diffstat (limited to 'std/prelude/ranges.pk')
-rw-r--r-- | std/prelude/ranges.pk | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/std/prelude/ranges.pk b/std/prelude/ranges.pk new file mode 100644 index 0000000..e3af8a4 --- /dev/null +++ b/std/prelude/ranges.pk @@ -0,0 +1,65 @@ +## std.ranges: Ranges of integers and other things. For iteration. +## This module is imported by default. + +type Range[T] = struct + start: T + end: T + +type RangeInclusive[T] = struct + start: T + end: T + done: bool + +## Exclusive ranges. Useful for iteration. +## Includes `from`, does not include `to`. +pub func ..(from: int, to: int): Range[int] = + { from, to } + +## Inclusive ranges. Useful for ranges. +## Includes `from` and `to`. +pub func ..=(from: int, to: int): RangeInclusive[int] = + { from, to, done: false } + +# todo: implement for all types that can increment or smth idk +pub func next[T: int](self: mut Range[T]): T? = + if self.start < self.end: + result = Some(self.start) + self.start += 1 + else: + result = None + +# todo: We don't need a mutable Range here to peek. +# How does this interact with interfaces? +pub func peek[T: int](self: mut Range[T]): T? = + self.peek_nth(0) + +pub func peek_nth[T: int](self: mut Range[T], i: uint): T? = + let res = self.start + i + if res < self.end: + return Some(res) + else: + return None + +pub func next[T: int](self: mut RangeInclusive[T]): T? = + if self.done: + return None + elif self.start < self.end: + let res = self.start + self.start += 1 + return Some(res) + elif self.start == self.end: + self.done = true + return Some(self.start) + else: + self.done = true + return None + +pub func peek[T: int](self: mut RangeInclusive[T]): T? = + self.peek_nth(0) + +pub func peek_nth[T: int](self: mut RangeInclusive[T], i: uint): T? = + let res = self.start + i + if res <= self.end: + return Some(res) + else: + return None |