aboutsummaryrefslogtreecommitdiff
path: root/std/prelude/ranges.pk
diff options
context:
space:
mode:
Diffstat (limited to 'std/prelude/ranges.pk')
-rw-r--r--std/prelude/ranges.pk65
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