aboutsummaryrefslogtreecommitdiff
path: root/std/prelude/ranges.pk
blob: e3af8a42f05ae53ed4daea322545452ce37a1e90 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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