@effekt-lang/effekt 0.56.0 → 0.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/effekt +0 -0
- package/libraries/common/array.effekt +107 -104
- package/libraries/common/buffer.effekt +3 -3
- package/libraries/common/bytearray.effekt +41 -18
- package/libraries/common/control.effekt +27 -0
- package/libraries/common/dictionary.effekt +13 -13
- package/libraries/common/effekt.effekt +27 -24
- package/libraries/common/heap.effekt +23 -15
- package/libraries/common/io/filesystem.effekt +2 -2
- package/libraries/common/list.effekt +4 -3
- package/libraries/common/queue.effekt +3 -3
- package/libraries/common/ref.effekt +2 -2
- package/libraries/common/resizable_array.effekt +39 -73
- package/libraries/common/seq.effekt +7 -7
- package/libraries/common/stream.effekt +3 -22
- package/libraries/common/string.effekt +1 -1
- package/libraries/common/stringbuffer.effekt +1 -1
- package/libraries/llvm/rts.ll +1 -0
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +2 -2
- package/licenses/mit license - mit-license.html +16 -16
- package/licenses/the bsd license - bsd-license.html +17 -17
- package/licenses/the mit license - mit.html +16 -16
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@ module bytearray
|
|
|
2
2
|
|
|
3
3
|
import effekt
|
|
4
4
|
import stream
|
|
5
|
+
import control
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* A memory managed, mutable, fixed-length array of bytes.
|
|
@@ -22,12 +23,12 @@ extern type ByteArray
|
|
|
22
23
|
// = js "Uint8Array"
|
|
23
24
|
// = chez "bytevector"
|
|
24
25
|
|
|
25
|
-
/// Allocates a new bytearray with the given `size`, its values are
|
|
26
|
+
/// Allocates a new bytearray with the given `size`, its values are zero bytes.
|
|
26
27
|
extern def allocate(size: Int) at global: ByteArray =
|
|
27
28
|
js "(new Uint8Array(${size}))"
|
|
28
29
|
llvm """
|
|
29
30
|
%object_size = add i64 ${size}, 16
|
|
30
|
-
%object_alloc = tail call noalias ptr @
|
|
31
|
+
%object_alloc = tail call noalias ptr @calloc(i64 %object_size, i64 1)
|
|
31
32
|
store i64 0, ptr %object_alloc, align 8
|
|
32
33
|
%object_data_ptr = getelementptr inbounds i8, ptr %object_alloc, i64 8
|
|
33
34
|
store ptr @bytearray_erase_noop, ptr %object_data_ptr, align 8
|
|
@@ -48,9 +49,30 @@ extern def size(arr: ByteArray) at {}: Int =
|
|
|
48
49
|
chez "(bytevector-length ${arr})"
|
|
49
50
|
vm "bytearray::size(ByteArray)"
|
|
50
51
|
|
|
51
|
-
extern
|
|
52
|
-
|
|
52
|
+
extern js """
|
|
53
|
+
function bytearray$get(arr, index) {
|
|
54
|
+
if (index < 0 || index >= arr.length) throw 'Index out of bounds';
|
|
55
|
+
return arr[index];
|
|
56
|
+
}
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
extern llvm """
|
|
60
|
+
define void @assertInboundsByteArray(i64 %index, %Pos %arr) alwaysinline {
|
|
61
|
+
%size = extractvalue %Pos %arr, 0
|
|
62
|
+
%in_bounds = icmp ult i64 %index, %size
|
|
63
|
+
br i1 %in_bounds, label %ok, label %out
|
|
64
|
+
out:
|
|
65
|
+
call void @exit(i64 1)
|
|
66
|
+
unreachable
|
|
67
|
+
ok:
|
|
68
|
+
ret void
|
|
69
|
+
}
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
extern def get(arr: ByteArray, index: Int) at global: Byte =
|
|
73
|
+
js "bytearray$get(${arr}, ${index})"
|
|
53
74
|
llvm """
|
|
75
|
+
call void @assertInboundsByteArray(i64 ${index}, %Pos ${arr})
|
|
54
76
|
%arr_ptr = extractvalue %Pos ${arr}, 1
|
|
55
77
|
%arr_data_ptr = getelementptr inbounds i8, ptr %arr_ptr, i64 16
|
|
56
78
|
%element_ptr = getelementptr inbounds i8, ptr %arr_data_ptr, i64 ${index}
|
|
@@ -59,11 +81,12 @@ extern def unsafeGet(arr: ByteArray, index: Int) at global: Byte =
|
|
|
59
81
|
ret i8 %element
|
|
60
82
|
"""
|
|
61
83
|
chez "(bytevector-u8-ref ${arr} ${index})"
|
|
62
|
-
vm "bytearray::
|
|
84
|
+
vm "bytearray::get(ByteArray, Int)"
|
|
63
85
|
|
|
64
|
-
extern def
|
|
86
|
+
extern def set(arr: ByteArray, index: Int, value: Byte) at global: Unit =
|
|
65
87
|
js "bytearray$set(${arr}, ${index}, ${value})"
|
|
66
88
|
llvm """
|
|
89
|
+
call void @assertInboundsByteArray(i64 ${index}, %Pos ${arr})
|
|
67
90
|
%arr_ptr = extractvalue %Pos ${arr}, 1
|
|
68
91
|
%arr_data_ptr = getelementptr inbounds i8, ptr %arr_ptr, i64 16
|
|
69
92
|
%element_ptr = getelementptr inbounds i8, ptr %arr_data_ptr, i64 ${index}
|
|
@@ -72,13 +95,13 @@ extern def unsafeSet(arr: ByteArray, index: Int, value: Byte) at global: Unit =
|
|
|
72
95
|
ret %Pos zeroinitializer
|
|
73
96
|
"""
|
|
74
97
|
chez "(bytevector-u8-set! ${arr} ${index} ${value})"
|
|
75
|
-
vm "bytearray::
|
|
98
|
+
vm "bytearray::set(ByteArray, Int, Byte)"
|
|
76
99
|
|
|
77
100
|
/// Creates a new ByteArray of size `size` filled with the value `init`
|
|
78
101
|
def bytearray(size: Int, init: Byte): ByteArray = {
|
|
79
102
|
val arr = allocate(size);
|
|
80
103
|
each(0, size) { i =>
|
|
81
|
-
|
|
104
|
+
set(arr, i, init)
|
|
82
105
|
};
|
|
83
106
|
arr
|
|
84
107
|
}
|
|
@@ -88,7 +111,7 @@ def resize(source: ByteArray, size: Int): ByteArray = {
|
|
|
88
111
|
val n = min(source.size, target.size)
|
|
89
112
|
def go(i: Int): ByteArray =
|
|
90
113
|
if (i < n) {
|
|
91
|
-
target.
|
|
114
|
+
target.set(i, source.get(i))
|
|
92
115
|
go(i + 1)
|
|
93
116
|
} else {
|
|
94
117
|
target
|
|
@@ -98,22 +121,22 @@ def resize(source: ByteArray, size: Int): ByteArray = {
|
|
|
98
121
|
|
|
99
122
|
def foreach(arr: ByteArray){ action: Byte => Unit }: Unit =
|
|
100
123
|
each(0, arr.size) { i =>
|
|
101
|
-
action(arr.
|
|
124
|
+
action(arr.get(i))
|
|
102
125
|
}
|
|
103
126
|
|
|
104
|
-
def foreach(arr: ByteArray){ action: (Byte) {
|
|
127
|
+
def foreach(arr: ByteArray){ action: (Byte) {Label} => Unit }: Unit =
|
|
105
128
|
each(0, arr.size) { (i) {label} =>
|
|
106
|
-
action(arr.
|
|
129
|
+
action(arr.get(i)) {label}
|
|
107
130
|
}
|
|
108
131
|
|
|
109
132
|
def foreachIndex(arr: ByteArray){ action: (Int, Byte) => Unit }: Unit =
|
|
110
133
|
each(0, arr.size) { i =>
|
|
111
|
-
action(i, arr.
|
|
134
|
+
action(i, arr.get(i))
|
|
112
135
|
}
|
|
113
136
|
|
|
114
|
-
def foreachIndex(arr: ByteArray){ action: (Int, Byte) {
|
|
137
|
+
def foreachIndex(arr: ByteArray){ action: (Int, Byte) {Label} => Unit }: Unit =
|
|
115
138
|
each(0, arr.size) { (i) {label} =>
|
|
116
|
-
action(i, arr.
|
|
139
|
+
action(i, arr.get(i)) {label}
|
|
117
140
|
}
|
|
118
141
|
|
|
119
142
|
extern def fromString(str: String) at {}: ByteArray =
|
|
@@ -214,7 +237,7 @@ def each(bytes: ByteArray): Unit / emit[Byte] = {
|
|
|
214
237
|
val n = bytes.size
|
|
215
238
|
def go(i: Int): Unit = {
|
|
216
239
|
if (i < n) {
|
|
217
|
-
do emit(bytes.
|
|
240
|
+
do emit(bytes.get(i))
|
|
218
241
|
go(i + 1)
|
|
219
242
|
}
|
|
220
243
|
}
|
|
@@ -230,7 +253,7 @@ def feed[R](bytes: ByteArray) { reader: () => R / read[Byte] }: R = {
|
|
|
230
253
|
if (i < bytes.size) {
|
|
231
254
|
val c = i
|
|
232
255
|
i = c + 1
|
|
233
|
-
bytes.
|
|
256
|
+
bytes.get(c)
|
|
234
257
|
} else {
|
|
235
258
|
do stop()
|
|
236
259
|
}
|
|
@@ -249,7 +272,7 @@ namespace returning {
|
|
|
249
272
|
(stream(), a.resize(i))
|
|
250
273
|
} with emit[Byte] { (v) =>
|
|
251
274
|
if (i >= a.size) { a = a.resize(2 * a.size) }
|
|
252
|
-
a.
|
|
275
|
+
a.set(i, v)
|
|
253
276
|
i = i + 1
|
|
254
277
|
resume(())
|
|
255
278
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module control
|
|
2
|
+
|
|
3
|
+
import effekt
|
|
4
|
+
|
|
5
|
+
interface Label {
|
|
6
|
+
def break(): Unit
|
|
7
|
+
def continue(): Unit
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
def loop { f: {Label} => Unit }: Unit = try {
|
|
11
|
+
def go(): Unit = { f {label}; go() }
|
|
12
|
+
go()
|
|
13
|
+
} with label: Label {
|
|
14
|
+
def break() = ()
|
|
15
|
+
def continue() = loop { f }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/// Calls provided action repeatedly with support for breaking. `start` is inclusive, `end` is not.
|
|
19
|
+
def each(start: Int, end: Int) { action: (Int) {Label} => Unit } = {
|
|
20
|
+
var i = start;
|
|
21
|
+
loop { {l} =>
|
|
22
|
+
if (i < end) { val el = i; i = i + 1; action(el){l} }
|
|
23
|
+
else { l.break() }
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
def repeat(n: Int) { action: () {Label} => Unit } = each(0, n) { (n) {l} => action() {l} }
|
|
@@ -26,20 +26,20 @@ def insert[A](trie: Dictionary[A], key: ByteArray, value: A): Dictionary[A] = {
|
|
|
26
26
|
case Empty() =>
|
|
27
27
|
val child = go(Empty(), i + 1)
|
|
28
28
|
val children = array(256, Empty())
|
|
29
|
-
children.
|
|
29
|
+
children.set(key.get(i).toInt, child)
|
|
30
30
|
Branch(children)
|
|
31
31
|
case Leaf(existing) =>
|
|
32
32
|
val child = go(Empty(), i + 1)
|
|
33
33
|
val children = array(256, Empty())
|
|
34
|
-
children.
|
|
34
|
+
children.set(key.get(i).toInt, child)
|
|
35
35
|
Node(existing, children)
|
|
36
36
|
case Branch(children) =>
|
|
37
|
-
val child = go(children.
|
|
38
|
-
children.
|
|
37
|
+
val child = go(children.get(key.get(i).toInt), i + 1)
|
|
38
|
+
children.set(key.get(i).toInt, child)
|
|
39
39
|
Branch(children)
|
|
40
40
|
case Node(existing, children) =>
|
|
41
|
-
val child = go(children.
|
|
42
|
-
children.
|
|
41
|
+
val child = go(children.get(key.get(i).toInt), i + 1)
|
|
42
|
+
children.set(key.get(i).toInt, child)
|
|
43
43
|
Node(existing, children)
|
|
44
44
|
}
|
|
45
45
|
} else {
|
|
@@ -64,8 +64,8 @@ def lookup[A](trie: Dictionary[A], key: ByteArray): Option[A] = {
|
|
|
64
64
|
trie match {
|
|
65
65
|
case Empty() => None()
|
|
66
66
|
case Leaf(_) => None()
|
|
67
|
-
case Branch(children) => go(children.
|
|
68
|
-
case Node(_, children) => go(children.
|
|
67
|
+
case Branch(children) => go(children.get(key.get(i).toInt), i + 1)
|
|
68
|
+
case Node(_, children) => go(children.get(key.get(i).toInt), i + 1)
|
|
69
69
|
}
|
|
70
70
|
} else {
|
|
71
71
|
trie match {
|
|
@@ -97,12 +97,12 @@ def each[A](trie: Dictionary[A]): Unit / emit[A] =
|
|
|
97
97
|
case Leaf(value) => do emit(value)
|
|
98
98
|
case Branch(children) =>
|
|
99
99
|
each(0, children.size) { i =>
|
|
100
|
-
each(children.
|
|
100
|
+
each(children.get(i))
|
|
101
101
|
}
|
|
102
102
|
case Node(value, children) =>
|
|
103
103
|
do emit(value)
|
|
104
104
|
each(0, children.size) { i =>
|
|
105
|
-
each(children.
|
|
105
|
+
each(children.get(i))
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
|
|
@@ -110,7 +110,7 @@ def each[A](trie: Dictionary[A]): Unit / emit[A] =
|
|
|
110
110
|
def eachTagged[A](trie: Dictionary[A]): Unit / emit[Tagged[A]] = {
|
|
111
111
|
def fromBytesReverse(bytes: List[Byte], n: Int): ByteArray = {
|
|
112
112
|
val key = bytearray::allocate(n)
|
|
113
|
-
foreachIndex(bytes) { (i, b) => key.
|
|
113
|
+
foreachIndex(bytes) { (i, b) => key.set(n - 1 - i, b) }
|
|
114
114
|
key
|
|
115
115
|
}
|
|
116
116
|
def go(trie: Dictionary[A], key: List[Byte], n: Int): Unit =
|
|
@@ -119,12 +119,12 @@ def eachTagged[A](trie: Dictionary[A]): Unit / emit[Tagged[A]] = {
|
|
|
119
119
|
case Leaf(value) => do emit(Tagged(fromBytesReverse(key, n), value))
|
|
120
120
|
case Branch(children) =>
|
|
121
121
|
each(0, children.size) { i =>
|
|
122
|
-
go(children.
|
|
122
|
+
go(children.get(i), Cons(i.toByte, key), n + 1)
|
|
123
123
|
}
|
|
124
124
|
case Node(value, children) =>
|
|
125
125
|
do emit(Tagged(fromBytesReverse(key, n), value))
|
|
126
126
|
each(0, children.size) { i =>
|
|
127
|
-
go(children.
|
|
127
|
+
go(children.get(i), Cons(i.toByte, key), n + 1)
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
go(trie, Nil(), 0)
|
|
@@ -732,23 +732,37 @@ type OneOrBoth[A, B] {
|
|
|
732
732
|
|
|
733
733
|
// Control Flow
|
|
734
734
|
// ============
|
|
735
|
-
interface Control {
|
|
736
|
-
def break(): Unit
|
|
737
|
-
def continue(): Unit
|
|
738
|
-
}
|
|
739
735
|
|
|
740
|
-
|
|
741
|
-
|
|
736
|
+
/// Repeat `action` forever
|
|
737
|
+
def forever { action: () => Unit }: Nothing = {
|
|
738
|
+
def go(): Nothing = { action(); go() }
|
|
742
739
|
go()
|
|
743
740
|
}
|
|
744
741
|
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
742
|
+
/// Signal that we should stop.
|
|
743
|
+
effect stop(): Nothing
|
|
744
|
+
|
|
745
|
+
/// When the program stops, then to here.
|
|
746
|
+
def boundary { program: () => Unit / stop }: Unit =
|
|
747
|
+
try { program() } with stop { () }
|
|
748
|
+
|
|
749
|
+
/// Repeat `action` until `stop` is thrown.
|
|
750
|
+
def loop { action: () => Unit / stop }: Unit =
|
|
751
|
+
try {
|
|
752
|
+
def go(): Unit = { action(); go() }
|
|
753
|
+
go()
|
|
754
|
+
} with stop {
|
|
755
|
+
()
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
/// Repeat `action` until `stop` is thrown, supplying the iteration count.
|
|
759
|
+
def loop { action: Int => Unit / stop }: Unit =
|
|
760
|
+
try {
|
|
761
|
+
def go(i: Int): Unit = { action(i); go(i + 1) }
|
|
762
|
+
go(0)
|
|
763
|
+
} with stop {
|
|
764
|
+
()
|
|
765
|
+
}
|
|
752
766
|
|
|
753
767
|
/// Calls provided action repeatedly. `start` is inclusive, `end` is not.
|
|
754
768
|
def each(start: Int, end: Int) { action: (Int) => Unit } = {
|
|
@@ -758,19 +772,8 @@ def each(start: Int, end: Int) { action: (Int) => Unit } = {
|
|
|
758
772
|
loop(start)
|
|
759
773
|
}
|
|
760
774
|
|
|
761
|
-
/// Calls provided action repeatedly with support for breaking. `start` is inclusive, `end` is not.
|
|
762
|
-
def each(start: Int, end: Int) { action: (Int) {Control} => Unit } = {
|
|
763
|
-
var i = start;
|
|
764
|
-
loop { {l} =>
|
|
765
|
-
if (i < end) { val el = i; i = i + 1; action(el){l} }
|
|
766
|
-
else { l.break() }
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
|
|
770
775
|
def repeat(n: Int) { action: () => Unit } = each(0, n) { n => action() }
|
|
771
776
|
|
|
772
|
-
def repeat(n: Int) { action: () {Control} => Unit } = each(0, n) { (n) {l} => action() {l} }
|
|
773
|
-
|
|
774
777
|
// NOTE: This is emitted by the close hole code action: do not remove unless you also adjust the code action
|
|
775
778
|
/// Scopes a local computation
|
|
776
779
|
def locally[R] { p: => R } : R = p()
|
|
@@ -23,8 +23,8 @@ namespace internal {
|
|
|
23
23
|
arr.boundsCheck(idx) // idx > parent(idx), parent(parent(idx)) etc
|
|
24
24
|
|
|
25
25
|
def go(idx: Int): Unit = {
|
|
26
|
-
if (idx > 0 and (heap.cmp)(arr.
|
|
27
|
-
arr.
|
|
26
|
+
if (idx > 0 and (heap.cmp)(arr.get(parent(idx)), arr.get(idx)) is Greater()) {
|
|
27
|
+
arr.swap(parent(idx), idx)
|
|
28
28
|
go(parent(idx))
|
|
29
29
|
}
|
|
30
30
|
}
|
|
@@ -39,28 +39,28 @@ namespace internal {
|
|
|
39
39
|
|
|
40
40
|
def go(idx: Int): Unit = {
|
|
41
41
|
if (right(idx) < arr.size) {
|
|
42
|
-
val v = arr.
|
|
43
|
-
val l = arr.
|
|
44
|
-
val r = arr.
|
|
42
|
+
val v = arr.get(idx)
|
|
43
|
+
val l = arr.get(left(idx))
|
|
44
|
+
val r = arr.get(right(idx))
|
|
45
45
|
if (l < v && r < v) {
|
|
46
46
|
// swap with the smaller one
|
|
47
47
|
if (l < r) {
|
|
48
|
-
arr.
|
|
48
|
+
arr.swap(left(idx), idx)
|
|
49
49
|
go(left(idx))
|
|
50
50
|
} else {
|
|
51
|
-
arr.
|
|
51
|
+
arr.swap(right(idx), idx)
|
|
52
52
|
go(right(idx))
|
|
53
53
|
}
|
|
54
54
|
} else if (l < v) {
|
|
55
|
-
arr.
|
|
55
|
+
arr.swap(left(idx), idx)
|
|
56
56
|
go(left(idx))
|
|
57
57
|
} else if (r < v) {
|
|
58
|
-
arr.
|
|
58
|
+
arr.swap(right(idx), idx)
|
|
59
59
|
go(right(idx))
|
|
60
60
|
}
|
|
61
61
|
} else if (left(idx) < arr.size) {
|
|
62
|
-
if (arr.
|
|
63
|
-
arr.
|
|
62
|
+
if (arr.get(left(idx)) < arr.get(idx)) {
|
|
63
|
+
arr.swap(left(idx), idx)
|
|
64
64
|
go(left(idx))
|
|
65
65
|
}
|
|
66
66
|
} // else: we are at the bottom
|
|
@@ -79,6 +79,7 @@ def insert[T](heap: Heap[T], value: T): Unit = {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
/// find and return (but not remove) the minimal element in this heap
|
|
82
|
+
/// panics when heap is empty
|
|
82
83
|
///
|
|
83
84
|
/// O(1)
|
|
84
85
|
def findMin[T](heap: Heap[T]): T / Exception[OutOfBounds] = {
|
|
@@ -86,13 +87,20 @@ def findMin[T](heap: Heap[T]): T / Exception[OutOfBounds] = {
|
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
/// find and remove the minimal element in this heap
|
|
90
|
+
/// panics when heap is empty
|
|
89
91
|
///
|
|
90
92
|
/// O(log n)
|
|
91
93
|
def deleteMin[T](heap: Heap[T]): T / Exception[OutOfBounds] = {
|
|
92
|
-
val
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
val arr = heap.rawContents
|
|
95
|
+
val res = arr.get(0)
|
|
96
|
+
if (arr.size == 1) {
|
|
97
|
+
arr.popRight()
|
|
98
|
+
res
|
|
99
|
+
} else {
|
|
100
|
+
arr.set(0, arr.popRight())
|
|
101
|
+
internal::sinkDown(heap, 0)
|
|
102
|
+
res
|
|
103
|
+
}
|
|
96
104
|
}
|
|
97
105
|
|
|
98
106
|
/// Number of elements in the heap
|
|
@@ -102,7 +102,7 @@ def writeFile[R](path: String) { stream: () => R / emit[Byte] }: R / Exception[I
|
|
|
102
102
|
push(0, buffer.size)
|
|
103
103
|
offset = 0
|
|
104
104
|
}
|
|
105
|
-
buffer.
|
|
105
|
+
buffer.set(offset, byte)
|
|
106
106
|
offset = offset + 1
|
|
107
107
|
resume(())
|
|
108
108
|
}
|
|
@@ -135,7 +135,7 @@ def readFile[R](path: String) { reader: () => R / read[Byte] }: R / Exception[IO
|
|
|
135
135
|
pull()
|
|
136
136
|
offset = 0
|
|
137
137
|
}
|
|
138
|
-
val byte = buffer.
|
|
138
|
+
val byte = buffer.get(offset)
|
|
139
139
|
offset = offset + 1
|
|
140
140
|
return byte
|
|
141
141
|
}
|
|
@@ -2,8 +2,9 @@ module list
|
|
|
2
2
|
|
|
3
3
|
import effekt
|
|
4
4
|
import option
|
|
5
|
-
import
|
|
5
|
+
import control
|
|
6
6
|
import stream
|
|
7
|
+
import exception
|
|
7
8
|
|
|
8
9
|
/// Immutable linked list for finite sequences of elements.
|
|
9
10
|
type List[A] {
|
|
@@ -123,7 +124,7 @@ def foreach[A](l: List[A]) { f: (A) => Unit } : Unit = l match {
|
|
|
123
124
|
/// Traverse a list, applying the given action on every element.
|
|
124
125
|
///
|
|
125
126
|
/// O(N)
|
|
126
|
-
def foreach[A](l: List[A]) { f: (A) {
|
|
127
|
+
def foreach[A](l: List[A]) { f: (A) {Label} => Unit } : Unit = {
|
|
127
128
|
var remainder = l
|
|
128
129
|
loop { {label} =>
|
|
129
130
|
remainder match {
|
|
@@ -151,7 +152,7 @@ def foreachIndex[A](list: List[A]){ f: (Int, A) => Unit }: Unit = {
|
|
|
151
152
|
/// Traverse a list, applying the given action on every element and its (zero-based) index.
|
|
152
153
|
///
|
|
153
154
|
/// O(N)
|
|
154
|
-
def foreachIndex[A](list: List[A]){ f: (Int, A) {
|
|
155
|
+
def foreachIndex[A](list: List[A]){ f: (Int, A) {Label} => Unit }: Unit = {
|
|
155
156
|
var remainder = list
|
|
156
157
|
var i = -1
|
|
157
158
|
loop { {label} =>
|
|
@@ -49,7 +49,7 @@ def emptyQueue[T](initialCapacity: Int): Queue[T] at global = {
|
|
|
49
49
|
val oldSize = capacity.get
|
|
50
50
|
val newSize = capacity.get * 2
|
|
51
51
|
val oldContents = contents.get
|
|
52
|
-
val newContents = array
|
|
52
|
+
val newContents = array[Option[T]](newSize, None())
|
|
53
53
|
|
|
54
54
|
if (head.get < tail.get) {
|
|
55
55
|
// The queue does not wrap around; direct copy is possible.
|
|
@@ -93,12 +93,12 @@ def emptyQueue[T](initialCapacity: Int): Queue[T] at global = {
|
|
|
93
93
|
resizeTo(size.get + 1)
|
|
94
94
|
head.set(mod(head.get - 1 + capacity.get, capacity.get))
|
|
95
95
|
size.set(size.get + 1)
|
|
96
|
-
contents.get.
|
|
96
|
+
contents.get.set(head.get, Some(el))
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
def pushBack(el: T) = {
|
|
100
100
|
resizeTo(size.get + 1)
|
|
101
|
-
contents.get.
|
|
101
|
+
contents.get.set(tail.get, Some(el))
|
|
102
102
|
size.set(size.get + 1)
|
|
103
103
|
tail.set(mod(tail.get + 1, capacity.get))
|
|
104
104
|
}
|
|
@@ -30,12 +30,12 @@ extern type Ref[T]
|
|
|
30
30
|
|
|
31
31
|
/// Allocates a new reference, keeping its value _undefined_.
|
|
32
32
|
/// Prefer using `ref` constructor instead to ensure that the value is defined.
|
|
33
|
-
extern def
|
|
33
|
+
extern def unsafeAllocate[T]() at global: Ref[T] =
|
|
34
34
|
js "{ value: undefined }"
|
|
35
35
|
chez "(box #f)"
|
|
36
36
|
llvm """
|
|
37
37
|
; sizeof Header + sizeof Pos = 32
|
|
38
|
-
%ref = tail call noalias ptr @
|
|
38
|
+
%ref = tail call noalias ptr @calloc(i64 noundef 32, i64 1)
|
|
39
39
|
%refEraser = getelementptr ptr, ptr %ref, i64 1
|
|
40
40
|
%fieldTag = getelementptr ptr, ptr %ref, i64 2
|
|
41
41
|
%fieldData_pointer = getelementptr ptr, ptr %ref, i64 3
|