@effekt-lang/effekt 0.55.0 → 0.57.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/chez/common/effekt_primitives.ss +10 -4
- 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 +133 -0
- 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/json.effekt +19 -19
- package/libraries/common/list.effekt +4 -3
- package/libraries/common/option.effekt +1 -1
- package/libraries/common/queue.effekt +3 -3
- package/libraries/common/random.effekt +1 -1
- 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/common/union_find.effekt +7 -7
- package/libraries/js/effekt_builtins.js +1 -1
- package/libraries/llvm/forward-declare-c.ll +2 -2
- package/libraries/llvm/io.c +2 -2
- package/libraries/llvm/panic.c +2 -0
- package/libraries/llvm/rts.ll +17 -38
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +3 -3
- package/licenses/mit license - mit-license.html +76 -45
- package/licenses/the bsd license - bsd-license.html +75 -46
- package/licenses/the mit license - mit.html +76 -45
- 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} }
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
module dictionary
|
|
2
|
+
|
|
3
|
+
import array
|
|
4
|
+
import bytearray
|
|
5
|
+
import stream
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/// A trie-based dictionary for efficient key-value storage with bytearray keys.
|
|
9
|
+
/// Supports String and ByteArray keys with fast lookup and insertion.
|
|
10
|
+
type Dictionary[A] {
|
|
11
|
+
Empty()
|
|
12
|
+
Leaf(value: A)
|
|
13
|
+
Branch(children: Array[Dictionary[A]])
|
|
14
|
+
Node(value: A, children: Array[Dictionary[A]])
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/// Insert a value with a String key.
|
|
18
|
+
def insert[A](trie: Dictionary[A], key: String, value: A): Dictionary[A] =
|
|
19
|
+
insert(trie, key.fromString, value)
|
|
20
|
+
|
|
21
|
+
/// Insert a key-value pair into the dictionary with a ByteArray key.
|
|
22
|
+
def insert[A](trie: Dictionary[A], key: ByteArray, value: A): Dictionary[A] = {
|
|
23
|
+
def go(trie: Dictionary[A], i: Int): Dictionary[A] =
|
|
24
|
+
if (i < key.size) {
|
|
25
|
+
trie match {
|
|
26
|
+
case Empty() =>
|
|
27
|
+
val child = go(Empty(), i + 1)
|
|
28
|
+
val children = array(256, Empty())
|
|
29
|
+
children.set(key.get(i).toInt, child)
|
|
30
|
+
Branch(children)
|
|
31
|
+
case Leaf(existing) =>
|
|
32
|
+
val child = go(Empty(), i + 1)
|
|
33
|
+
val children = array(256, Empty())
|
|
34
|
+
children.set(key.get(i).toInt, child)
|
|
35
|
+
Node(existing, children)
|
|
36
|
+
case Branch(children) =>
|
|
37
|
+
val child = go(children.get(key.get(i).toInt), i + 1)
|
|
38
|
+
children.set(key.get(i).toInt, child)
|
|
39
|
+
Branch(children)
|
|
40
|
+
case Node(existing, children) =>
|
|
41
|
+
val child = go(children.get(key.get(i).toInt), i + 1)
|
|
42
|
+
children.set(key.get(i).toInt, child)
|
|
43
|
+
Node(existing, children)
|
|
44
|
+
}
|
|
45
|
+
} else {
|
|
46
|
+
trie match {
|
|
47
|
+
case Empty() => Leaf(value)
|
|
48
|
+
case Leaf(_) => Leaf(value)
|
|
49
|
+
case Node(_, children) => Node(value, children)
|
|
50
|
+
case Branch(children) => Node(value, children)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
go(trie, 0)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/// Look up a value in the dictionary by string key.
|
|
57
|
+
def lookup[A](trie: Dictionary[A], key: String): Option[A] =
|
|
58
|
+
lookup(trie, key.fromString)
|
|
59
|
+
|
|
60
|
+
/// Look up a value in the dictionary by bytearray key.
|
|
61
|
+
def lookup[A](trie: Dictionary[A], key: ByteArray): Option[A] = {
|
|
62
|
+
def go(trie: Dictionary[A], i: Int): Option[A] =
|
|
63
|
+
if (i < key.size) {
|
|
64
|
+
trie match {
|
|
65
|
+
case Empty() => None()
|
|
66
|
+
case Leaf(_) => None()
|
|
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
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
trie match {
|
|
72
|
+
case Empty() => None()
|
|
73
|
+
case Leaf(value) => Some(value)
|
|
74
|
+
case Branch(_) => None()
|
|
75
|
+
case Node(value, _) => Some(value)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
go(trie, 0)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/// A record pairing a key with a value for use in streams.
|
|
82
|
+
record Tagged[A](key: ByteArray, value: A)
|
|
83
|
+
|
|
84
|
+
/// Collect key-value pairs from a stream of Tagged elements into a Dictionary.
|
|
85
|
+
def collect[A] { stream: () => Unit / emit[Tagged[A]] }: Dictionary[A] = {
|
|
86
|
+
var trie = Empty()
|
|
87
|
+
for[Tagged[A]] { stream() } { case Tagged(bytes, value) =>
|
|
88
|
+
trie = trie.insert(bytes, value)
|
|
89
|
+
}
|
|
90
|
+
return trie
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/// Emit all values stored in the dictionary as a push stream.
|
|
94
|
+
def each[A](trie: Dictionary[A]): Unit / emit[A] =
|
|
95
|
+
trie match {
|
|
96
|
+
case Empty() => ()
|
|
97
|
+
case Leaf(value) => do emit(value)
|
|
98
|
+
case Branch(children) =>
|
|
99
|
+
each(0, children.size) { i =>
|
|
100
|
+
each(children.get(i))
|
|
101
|
+
}
|
|
102
|
+
case Node(value, children) =>
|
|
103
|
+
do emit(value)
|
|
104
|
+
each(0, children.size) { i =>
|
|
105
|
+
each(children.get(i))
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/// Emit all key-value pairs stored in the dictionary as a push stream of Tagged elements.
|
|
110
|
+
def eachTagged[A](trie: Dictionary[A]): Unit / emit[Tagged[A]] = {
|
|
111
|
+
def fromBytesReverse(bytes: List[Byte], n: Int): ByteArray = {
|
|
112
|
+
val key = bytearray::allocate(n)
|
|
113
|
+
foreachIndex(bytes) { (i, b) => key.set(n - 1 - i, b) }
|
|
114
|
+
key
|
|
115
|
+
}
|
|
116
|
+
def go(trie: Dictionary[A], key: List[Byte], n: Int): Unit =
|
|
117
|
+
trie match {
|
|
118
|
+
case Empty() => ()
|
|
119
|
+
case Leaf(value) => do emit(Tagged(fromBytesReverse(key, n), value))
|
|
120
|
+
case Branch(children) =>
|
|
121
|
+
each(0, children.size) { i =>
|
|
122
|
+
go(children.get(i), Cons(i.toByte, key), n + 1)
|
|
123
|
+
}
|
|
124
|
+
case Node(value, children) =>
|
|
125
|
+
do emit(Tagged(fromBytesReverse(key, n), value))
|
|
126
|
+
each(0, children.size) { i =>
|
|
127
|
+
go(children.get(i), Cons(i.toByte, key), n + 1)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
go(trie, Nil(), 0)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
|
|
@@ -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
|
}
|
|
@@ -25,12 +25,12 @@ def handleJsonBuilder[R]{b: JsonBuilder}{ body: => R / JsonBuilder }: R = try bo
|
|
|
25
25
|
def bool(v) = resume(b.bool(v))
|
|
26
26
|
def number(n) = resume(b.number(n))
|
|
27
27
|
def string(s) = resume(b.string(s))
|
|
28
|
-
def list() = resume { {c} => b.list{c} }
|
|
29
|
-
def dict() = resume { {c} => b.dict{c} }
|
|
28
|
+
def list[T]() = resume { {c} => b.list{c} }
|
|
29
|
+
def dict[T]() = resume { {c} => b.dict{c} }
|
|
30
30
|
}
|
|
31
31
|
/// Make explicitly bound JsonObjectBuilder instance implicit
|
|
32
32
|
def handleJsonObjectBuilder[R]{b: JsonObjectBuilder}{ body: => R / JsonObjectBuilder }: R = try body() with JsonObjectBuilder {
|
|
33
|
-
def field(k) = resume { {c} => b.field(k){c} }
|
|
33
|
+
def field[T](k) = resume { {c} => b.field(k){c} }
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
// --------------------------------------------------------------------------------
|
|
@@ -49,8 +49,8 @@ def encodeJsonList[R]{ body: => R / JsonBuilder }: R / emit[String] = {
|
|
|
49
49
|
def bool(v) = { c(); resume(do bool(v)) }
|
|
50
50
|
def number(n) = { c(); resume(do number(n)) }
|
|
51
51
|
def string(s) = { c(); resume(do string(s)) }
|
|
52
|
-
def list() = resume { { b } => c(); do list{b} }
|
|
53
|
-
def dict() = resume { { b } => c(); do dict{b} }
|
|
52
|
+
def list[T]() = resume { { b } => c(); do list{b} }
|
|
53
|
+
def dict[T]() = resume { { b } => c(); do dict{b} }
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
do emit("]")
|
|
@@ -66,7 +66,7 @@ def encodeJsonObject[R]{ body: => R / JsonObjectBuilder }: R / emit[String] = {
|
|
|
66
66
|
}
|
|
67
67
|
val r = encodeJson {
|
|
68
68
|
try body() with JsonObjectBuilder {
|
|
69
|
-
def field(k) = resume { {b} => c(k); b() }
|
|
69
|
+
def field[T](k) = resume { {b} => c(k); b() }
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
do emit("}")
|
|
@@ -80,8 +80,8 @@ def encodeJson[R]{ body: => R / JsonBuilder }: R / emit[String] = {
|
|
|
80
80
|
def bool(v) = { resume(do emit( if(v){ "true" } else { "false" } )) }
|
|
81
81
|
def number(n) = { resume(do emit(show(n))) }
|
|
82
82
|
def string(s) = { resume(do emit(escape(s))) }
|
|
83
|
-
def list() = resume { {b} => encodeJsonList { b() } }
|
|
84
|
-
def dict() = resume { {b} => encodeJsonObject { b() } }
|
|
83
|
+
def list[T]() = resume { {b} => encodeJsonList { b() } }
|
|
84
|
+
def dict[T]() = resume { {b} => encodeJsonObject { b() } }
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
|
|
@@ -209,7 +209,7 @@ def decodeJsonList(): Unit / {Scan[Char], JsonBuilder, Exception[WrongFormat]} =
|
|
|
209
209
|
// --------------------------------------------------------------------------------
|
|
210
210
|
/// Ignore the generated calls to JsonObjectBuilder
|
|
211
211
|
def ignoreDict[R](){ body: => R / JsonObjectBuilder }: R = try body() with JsonObjectBuilder {
|
|
212
|
-
def field(k) = resume { {v} => ignore{v} }
|
|
212
|
+
def field[T](k) = resume { {v} => ignore{v} }
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
/// Ignore the generated calls to JsonBuilder
|
|
@@ -218,8 +218,8 @@ def ignore[R](){ body: => R / JsonBuilder }: R = try body() with JsonBuilder {
|
|
|
218
218
|
def bool(b) = resume(())
|
|
219
219
|
def null() = resume(())
|
|
220
220
|
def string(s) = resume(())
|
|
221
|
-
def list() = resume { {e} => ignore{e} }
|
|
222
|
-
def dict() = resume { {e} => ignoreDict{e} }
|
|
221
|
+
def list[T]() = resume { {e} => ignore{e} }
|
|
222
|
+
def dict[T]() = resume { {e} => ignoreDict{e} }
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
// --------------------------------------------------------------------------------
|
|
@@ -264,12 +264,12 @@ def build[R](){ body: => R / JsonBuilder }: (R, JsonValue) = {
|
|
|
264
264
|
def bool(b) = { r = Bool(b); resume(()) }
|
|
265
265
|
def null() = { r = Null(); resume(()) }
|
|
266
266
|
def string(s) = { r = String(s); resume(()) }
|
|
267
|
-
def list() = resume { {els} =>
|
|
267
|
+
def list[T]() = resume { {els} =>
|
|
268
268
|
val x = buildList {els}
|
|
269
269
|
r = List(x.second)
|
|
270
270
|
x.first
|
|
271
271
|
}
|
|
272
|
-
def dict() = resume { {fs} =>
|
|
272
|
+
def dict[T]() = resume { {fs} =>
|
|
273
273
|
val x = buildDict {fs}
|
|
274
274
|
r = Dict(x.second)
|
|
275
275
|
x.first
|
|
@@ -283,12 +283,12 @@ def buildList[R](){ body: => R / JsonBuilder }: (R, List[JsonValue]) = list::ret
|
|
|
283
283
|
def bool(b) = { do emit(Bool(b)); resume(()) }
|
|
284
284
|
def null() = { do emit(Null()); resume(()) }
|
|
285
285
|
def string(s) = { do emit(String(s)); resume(()) }
|
|
286
|
-
def list() = resume { {els} =>
|
|
286
|
+
def list[T]() = resume { {els} =>
|
|
287
287
|
val x = buildList {els}
|
|
288
288
|
do emit(List(x.second))
|
|
289
289
|
x.first
|
|
290
290
|
}
|
|
291
|
-
def dict() = resume { {fs} =>
|
|
291
|
+
def dict[T]() = resume { {fs} =>
|
|
292
292
|
val x = buildDict {fs}
|
|
293
293
|
do emit(Dict(x.second))
|
|
294
294
|
x.first
|
|
@@ -297,7 +297,7 @@ def buildList[R](){ body: => R / JsonBuilder }: (R, List[JsonValue]) = list::ret
|
|
|
297
297
|
}
|
|
298
298
|
def buildDict[R](){ body: => R / JsonObjectBuilder }: (R, List[(String, JsonValue)]) = list::returning::collect[(String, JsonValue), R] {
|
|
299
299
|
try body() with JsonObjectBuilder {
|
|
300
|
-
def field(k) = resume { {v} =>
|
|
300
|
+
def field[T](k) = resume { {v} =>
|
|
301
301
|
val x = build{v}
|
|
302
302
|
do emit((k, x.second))
|
|
303
303
|
x.first
|
|
@@ -325,7 +325,7 @@ namespace test {
|
|
|
325
325
|
with scanner[Char]
|
|
326
326
|
|
|
327
327
|
def k = new JsonObjectBuilder {
|
|
328
|
-
def field(k){v} = { println(k); ignore{v} }
|
|
328
|
+
def field[T](k){v} = { println(k); ignore{v} }
|
|
329
329
|
}
|
|
330
330
|
def jsonBuilder[R] {e: => R / JsonBuilder}: R = {
|
|
331
331
|
def d = new JsonBuilder {
|
|
@@ -333,8 +333,8 @@ namespace test {
|
|
|
333
333
|
def bool(b) = ()
|
|
334
334
|
def null() = println("NULL")
|
|
335
335
|
def string(s) = ()
|
|
336
|
-
def list(){e} = jsonBuilder{e}
|
|
337
|
-
def dict(){e} = handleJsonObjectBuilder{k}{e}
|
|
336
|
+
def list[T](){e} = jsonBuilder{e}
|
|
337
|
+
def dict[T](){e} = handleJsonObjectBuilder{k}{e}
|
|
338
338
|
}
|
|
339
339
|
handleJsonBuilder{d}{e}
|
|
340
340
|
}
|
|
@@ -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} =>
|
|
@@ -37,7 +37,7 @@ def foreach[A](self: Option[A]) { f: A => Unit }: Unit = self match {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
def value[A](self: Option[A]): A / Exception[MissingValue] = self match {
|
|
40
|
-
case None() => do raise(MissingValue(), "Trying to get the value of an empty option")
|
|
40
|
+
case None() => do raise(MissingValue(), "Trying to get the value of an empty option") match {}
|
|
41
41
|
case Some(v) => v
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -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
|
}
|