aboutsummaryrefslogtreecommitdiff
path: root/projects/std/src/Std/Lists.shed
blob: eb9ae8efecc79ad60f6e66f66586703e71b85f14 (plain)
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
struct List[T](array: Array[T]) {
    // TODO: generic effect
    fun forEach(this, func: fn (T) ! Io -> Unit) ! Io -> Unit {
        var index = 0;
        val size = this.array.size();

        while (index < size) {
            func!(this.array.unsafeGet(index));
            set index = index + 1;
        }
    }
}

struct ListBuilder[T](arrayBuilder: ArrayBuilder[T]) {
    fun add(this, element: T) -> ListBuilder[T] {
        if (this.arrayBuilder.size() < this.arrayBuilder.capacity()) {
            ListBuilder(this.arrayBuilder.unsafeAdd(element))
        } else {
            val newCapacity = this.arrayBuilder.capacity() * 2;
            val newArrayBuilder = this.arrayBuilder
                .unsafeEnlarge(.capacity = newCapacity)
                .unsafeAdd(element);
            ListBuilder(newArrayBuilder)
        }
    }

    fun build(this) -> List[T] {
        List(this.arrayBuilder.build())
    }
}

pub fun listBuilder[T]() -> ListBuilder[T] {
    ListBuilder[T](arrayBuilder[T](.capacity = 16))
}

native type Array[T] {
    // Precondition: the index is in the range [0, size).
    native fun unsafeGet(This, Int) -> T;

    native fun size(This) -> Int;
}

native type ArrayBuilder[T] {
    native fun capacity(This) -> Int;

    native fun size(This) -> Int;

    // Precondition: size < capacity.
    native fun unsafeAdd(This, T) -> ArrayBuilder[T];

    // Precondition: the new capacity is greater than or equal to the current
    // capacity.
    native fun unsafeEnlarge(This, .capacity: Int) -> ArrayBuilder[T];

    native fun build(This) -> Array[T];
}

native fun arrayBuilder[T](.capacity: Int) -> ArrayBuilder[T];