@effekt-lang/effekt 0.66.0 → 0.68.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/bin/effekt +0 -0
- package/libraries/common/args.effekt +2 -2
- package/libraries/common/array.effekt +8 -9
- package/libraries/common/bytearray.effekt +7 -14
- package/libraries/common/bytestream.effekt +4 -4
- package/libraries/common/char.effekt +10 -16
- package/libraries/common/dictionary.effekt +44 -43
- package/libraries/common/effekt.effekt +18 -61
- package/libraries/common/io/channel.effekt +2 -2
- package/libraries/common/io/console.effekt +2 -1
- package/libraries/common/io/filesystem.effekt +5 -5
- package/libraries/common/io/network.effekt +2 -2
- package/libraries/common/io/promise.effekt +2 -2
- package/libraries/common/io/signal.effekt +86 -22
- package/libraries/common/json.effekt +16 -42
- package/libraries/common/list.effekt +4 -4
- package/libraries/common/process.effekt +6 -2
- package/libraries/common/random.effekt +29 -7
- package/libraries/common/ref.effekt +4 -4
- package/libraries/common/regex.effekt +6 -8
- package/libraries/common/resizable_array.effekt +4 -4
- package/libraries/common/scanner.effekt +36 -41
- package/libraries/common/stream.effekt +76 -36
- package/libraries/common/string.effekt +3 -8
- package/libraries/llvm/io.c +0 -55
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +2 -2
- package/licenses/mit license - mit-license.html +34 -32
- package/licenses/the bsd license - bsd-license.html +33 -31
- package/licenses/the mit license - mit.html +34 -32
- package/package.json +1 -1
package/bin/effekt
CHANGED
|
Binary file
|
|
@@ -7,7 +7,7 @@ extern def commandLineArgs() at io: List[String] =
|
|
|
7
7
|
vm { Nil() }
|
|
8
8
|
|
|
9
9
|
namespace js {
|
|
10
|
-
extern type Args
|
|
10
|
+
extern type Args = js "Array[String]"
|
|
11
11
|
|
|
12
12
|
extern def nativeArgs() at io: Args = js "process.argv.slice(1)"
|
|
13
13
|
|
|
@@ -26,7 +26,7 @@ namespace js {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
namespace chez {
|
|
29
|
-
extern type Args
|
|
29
|
+
extern type Args = chez "CSList[String]"
|
|
30
30
|
|
|
31
31
|
extern def nativeArgs() at io: Args =
|
|
32
32
|
chez "(cdr (command-line))"
|
|
@@ -8,7 +8,10 @@ import list
|
|
|
8
8
|
import exception
|
|
9
9
|
|
|
10
10
|
/// A mutable 0-indexed fixed-sized array.
|
|
11
|
-
extern type Array[T]
|
|
11
|
+
extern type Array[T] =
|
|
12
|
+
js "Array"
|
|
13
|
+
chez "vector"
|
|
14
|
+
llvm "%Pos"
|
|
12
15
|
|
|
13
16
|
/// We represent arrays like positive types.
|
|
14
17
|
/// The tag is 0 and the obj points to memory with the following layout:
|
|
@@ -57,7 +60,6 @@ extern def unsafeAllocate[T](size: Int) at global: Array[T] =
|
|
|
57
60
|
%ret_pos = insertvalue %Pos { i64 0, ptr poison }, ptr %calloc, 1
|
|
58
61
|
ret %Pos %ret_pos
|
|
59
62
|
"""
|
|
60
|
-
vm "array::unsafeAllocate(Int)"
|
|
61
63
|
|
|
62
64
|
/// Fills a given array in-place.
|
|
63
65
|
def fill[T](arr: Array[T], filler: T): Unit = {
|
|
@@ -96,7 +98,6 @@ extern def size[T](arr: Array[T]) at {}: Int =
|
|
|
96
98
|
tail call void @erasePositive(%Pos ${arr})
|
|
97
99
|
ret i64 %size
|
|
98
100
|
"""
|
|
99
|
-
vm "array::size[T](Array[T])"
|
|
100
101
|
|
|
101
102
|
extern llvm """
|
|
102
103
|
define void @assertInbounds(i64 %index, %Pos %arr) alwaysinline {
|
|
@@ -138,7 +139,6 @@ extern def get[T](arr: Array[T], index: Int) at global: T =
|
|
|
138
139
|
tail call void @erasePositive(%Pos ${arr})
|
|
139
140
|
ret %Pos %element
|
|
140
141
|
"""
|
|
141
|
-
vm "array::get[T](Array[T], Int)"
|
|
142
142
|
|
|
143
143
|
extern js """
|
|
144
144
|
function array$set(arr, index, value) {
|
|
@@ -165,7 +165,6 @@ extern def set[T](arr: Array[T], index: Int, value: T) at global: Unit =
|
|
|
165
165
|
tail call void @erasePositive(%Pos ${arr})
|
|
166
166
|
ret %Pos zeroinitializer
|
|
167
167
|
"""
|
|
168
|
-
vm "array::set[T](Array[T], Int, T)"
|
|
169
168
|
|
|
170
169
|
// Derived operations:
|
|
171
170
|
|
|
@@ -659,12 +658,12 @@ def each[T](array: Array[T]): Unit / emit[T] = {
|
|
|
659
658
|
go(0)
|
|
660
659
|
}
|
|
661
660
|
|
|
662
|
-
/// Connects `array` as a producer to a given pull stream `
|
|
663
|
-
def feed[T, R](array: Array[T]) {
|
|
661
|
+
/// Connects `array` as a producer to a given pull stream `driver` acting as a consumer.
|
|
662
|
+
def feed[T, R](array: Array[T]) { driver: () => R / next[T] }: R = {
|
|
664
663
|
var i = 0
|
|
665
664
|
try {
|
|
666
|
-
|
|
667
|
-
} with
|
|
665
|
+
driver()
|
|
666
|
+
} with next[T] {
|
|
668
667
|
resume {
|
|
669
668
|
if (i < array.size) {
|
|
670
669
|
val c = i
|
|
@@ -19,10 +19,10 @@ import array
|
|
|
19
19
|
*
|
|
20
20
|
* The eraser does nothing.
|
|
21
21
|
*/
|
|
22
|
-
extern type ByteArray
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
extern type ByteArray =
|
|
23
|
+
llvm "%Pos"
|
|
24
|
+
js "Uint8Array"
|
|
25
|
+
chez "bytevector"
|
|
26
26
|
|
|
27
27
|
/// Allocates a new bytearray with the given `size`, its values are zero bytes.
|
|
28
28
|
extern def allocate(size: Int) at global: ByteArray =
|
|
@@ -38,7 +38,6 @@ extern def allocate(size: Int) at global: ByteArray =
|
|
|
38
38
|
ret %Pos %ret_object2
|
|
39
39
|
"""
|
|
40
40
|
chez "(make-bytevector ${size})"
|
|
41
|
-
vm "bytearray::allocate(Int)"
|
|
42
41
|
|
|
43
42
|
extern def size(arr: ByteArray) at {}: Int =
|
|
44
43
|
js "${arr}.length"
|
|
@@ -48,7 +47,6 @@ extern def size(arr: ByteArray) at {}: Int =
|
|
|
48
47
|
ret i64 %size
|
|
49
48
|
"""
|
|
50
49
|
chez "(bytevector-length ${arr})"
|
|
51
|
-
vm "bytearray::size(ByteArray)"
|
|
52
50
|
|
|
53
51
|
extern js """
|
|
54
52
|
function bytearray$get(arr, index) {
|
|
@@ -82,7 +80,6 @@ extern def get(arr: ByteArray, index: Int) at global: Byte =
|
|
|
82
80
|
ret i8 %element
|
|
83
81
|
"""
|
|
84
82
|
chez "(bytevector-u8-ref ${arr} ${index})"
|
|
85
|
-
vm "bytearray::get(ByteArray, Int)"
|
|
86
83
|
|
|
87
84
|
extern def set(arr: ByteArray, index: Int, value: Byte) at global: Unit =
|
|
88
85
|
js "bytearray$set(${arr}, ${index}, ${value})"
|
|
@@ -96,7 +93,6 @@ extern def set(arr: ByteArray, index: Int, value: Byte) at global: Unit =
|
|
|
96
93
|
ret %Pos zeroinitializer
|
|
97
94
|
"""
|
|
98
95
|
chez "(bytevector-u8-set! ${arr} ${index} ${value})"
|
|
99
|
-
vm "bytearray::set(ByteArray, Int, Byte)"
|
|
100
96
|
|
|
101
97
|
/// Creates a new ByteArray of size `size` filled with the value `init`
|
|
102
98
|
def bytearray(size: Int, init: Byte): ByteArray = {
|
|
@@ -184,7 +180,6 @@ extern def fromString(str: String) at {}: ByteArray =
|
|
|
184
180
|
ret %Pos ${str}
|
|
185
181
|
"""
|
|
186
182
|
chez "(string->utf8 ${str})"
|
|
187
|
-
vm "bytearray::fromString(String)"
|
|
188
183
|
|
|
189
184
|
extern def toString(arr: ByteArray) at {}: String =
|
|
190
185
|
js "(new TextDecoder('utf-8').decode(${arr}))"
|
|
@@ -193,7 +188,6 @@ extern def toString(arr: ByteArray) at {}: String =
|
|
|
193
188
|
ret %Pos ${arr}
|
|
194
189
|
"""
|
|
195
190
|
chez "(utf8->string ${arr})"
|
|
196
|
-
vm "bytearray::toString(ByteArray)"
|
|
197
191
|
|
|
198
192
|
extern js """
|
|
199
193
|
function bytearray$set(bytes, index, value) {
|
|
@@ -247,7 +241,6 @@ extern def compareByteArrayImpl(b1: ByteArray, b2: ByteArray) at {}: Int =
|
|
|
247
241
|
ret %Int %x
|
|
248
242
|
"""
|
|
249
243
|
chez "(bytearray$compare ${b1} ${b2})"
|
|
250
|
-
vm "bytearray::compare(ByteArray, ByteArray)"
|
|
251
244
|
|
|
252
245
|
def compareByteArray(b1: ByteArray, b2: ByteArray): Ordering = {
|
|
253
246
|
val ret = compareByteArrayImpl(b1, b2)
|
|
@@ -283,11 +276,11 @@ def each(bytes: ByteArray): Unit / emit[Byte] = {
|
|
|
283
276
|
go(0)
|
|
284
277
|
}
|
|
285
278
|
|
|
286
|
-
def feed[R](bytes: ByteArray) {
|
|
279
|
+
def feed[R](bytes: ByteArray) { driver: () => R / next[Byte] }: R = {
|
|
287
280
|
var i = 0
|
|
288
281
|
try {
|
|
289
|
-
|
|
290
|
-
} with
|
|
282
|
+
driver()
|
|
283
|
+
} with next[Byte] {
|
|
291
284
|
resume {
|
|
292
285
|
if (i < bytes.size) {
|
|
293
286
|
val c = i
|
|
@@ -103,7 +103,7 @@ def hex{ body: => Unit / { write, HexSplices } }: Unit / emit[Byte] = {
|
|
|
103
103
|
body()
|
|
104
104
|
}
|
|
105
105
|
with splice[String] { s =>
|
|
106
|
-
feed(s){ loop { do splice[Char](do
|
|
106
|
+
feed(s){ loop { do splice[Char](do next[Char]()) } }
|
|
107
107
|
resume(())
|
|
108
108
|
}
|
|
109
109
|
with splice[ByteArray] { ba =>
|
|
@@ -115,8 +115,8 @@ def hex{ body: => Unit / { write, HexSplices } }: Unit / emit[Byte] = {
|
|
|
115
115
|
feed(s){
|
|
116
116
|
loop {
|
|
117
117
|
attempt {
|
|
118
|
-
val upper: Int = hexDigitValue(do
|
|
119
|
-
val lower: Int = hexDigitValue(do
|
|
118
|
+
val upper: Int = hexDigitValue(do next[Char]())
|
|
119
|
+
val lower: Int = hexDigitValue(do next[Char]())
|
|
120
120
|
do emit[Byte]((16 * upper + lower).toByte)
|
|
121
121
|
} { () }
|
|
122
122
|
}
|
|
@@ -296,7 +296,7 @@ def bit{ body: => Unit / { write, BitSplices } }: Unit / emit[Bit] = {
|
|
|
296
296
|
with write { s =>
|
|
297
297
|
feed(s){
|
|
298
298
|
loop {
|
|
299
|
-
do
|
|
299
|
+
do next[Char]() match {
|
|
300
300
|
case '0' => do emit(B0())
|
|
301
301
|
case '1' => do emit(B1())
|
|
302
302
|
case _ => ()
|
|
@@ -97,13 +97,11 @@ extern def toInt(ch: Char) at {}: Int =
|
|
|
97
97
|
js "${ch}"
|
|
98
98
|
chez "${ch}"
|
|
99
99
|
llvm "ret %Int ${ch}"
|
|
100
|
-
vm "string::toInt(Char)"
|
|
101
100
|
|
|
102
101
|
extern def toChar(codepoint: Int) at {}: Char =
|
|
103
102
|
js "${codepoint}"
|
|
104
103
|
chez "${codepoint}"
|
|
105
104
|
llvm "ret %Int ${codepoint}"
|
|
106
|
-
vm "string::toChar(Int)"
|
|
107
105
|
|
|
108
106
|
|
|
109
107
|
extern def infixLt(x: Char, y: Char) at {}: Bool =
|
|
@@ -115,7 +113,6 @@ extern def infixLt(x: Char, y: Char) at {}: Bool =
|
|
|
115
113
|
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
116
114
|
ret %Pos %adt_boolean
|
|
117
115
|
"""
|
|
118
|
-
vm "string::infixLt(Char, Char)"
|
|
119
116
|
|
|
120
117
|
extern def infixLte(x: Char, y: Char) at {}: Bool =
|
|
121
118
|
js "(${x} <= ${y})"
|
|
@@ -126,7 +123,6 @@ extern def infixLte(x: Char, y: Char) at {}: Bool =
|
|
|
126
123
|
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
127
124
|
ret %Pos %adt_boolean
|
|
128
125
|
"""
|
|
129
|
-
vm "string::infixLte(Char, Char)"
|
|
130
126
|
|
|
131
127
|
extern def infixGt(x: Char, y: Char) at {}: Bool =
|
|
132
128
|
js "(${x} > ${y})"
|
|
@@ -137,7 +133,6 @@ extern def infixGt(x: Char, y: Char) at {}: Bool =
|
|
|
137
133
|
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
138
134
|
ret %Pos %adt_boolean
|
|
139
135
|
"""
|
|
140
|
-
vm "string::infixGt(Char, Char)"
|
|
141
136
|
|
|
142
137
|
extern def infixGte(x: Char, y: Char) at {}: Bool =
|
|
143
138
|
js "(${x} >= ${y})"
|
|
@@ -148,7 +143,6 @@ extern def infixGte(x: Char, y: Char) at {}: Bool =
|
|
|
148
143
|
%adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
|
|
149
144
|
ret %Pos %adt_boolean
|
|
150
145
|
"""
|
|
151
|
-
vm "string::infixGte(Char, Char)"
|
|
152
146
|
|
|
153
147
|
|
|
154
148
|
/**
|
|
@@ -175,24 +169,24 @@ extern def charWidth(c: Char) at {}: Int =
|
|
|
175
169
|
js "(${c} > 0xffff) ? 2 : 1"
|
|
176
170
|
|
|
177
171
|
|
|
178
|
-
def decodeChar(): Char / {
|
|
179
|
-
val b = do
|
|
172
|
+
def decodeChar(): Char / {next[Byte], stop} = {
|
|
173
|
+
val b = do next().toInt
|
|
180
174
|
if (b < 128) {
|
|
181
175
|
b.toChar
|
|
182
176
|
} else if (b < 224) {
|
|
183
177
|
val part1 = bitwiseShl(bitwiseAnd(b, 31), 6)
|
|
184
|
-
val part2 = bitwiseAnd(do
|
|
178
|
+
val part2 = bitwiseAnd(do next().toInt, 63)
|
|
185
179
|
bitwiseOr(part1, part2).toChar
|
|
186
180
|
} else if (b < 240) {
|
|
187
181
|
val part1 = bitwiseShl(bitwiseAnd(b, 15), 12)
|
|
188
|
-
val part2 = bitwiseShl(bitwiseAnd(do
|
|
189
|
-
val part3 = bitwiseAnd(do
|
|
182
|
+
val part2 = bitwiseShl(bitwiseAnd(do next().toInt, 63), 6)
|
|
183
|
+
val part3 = bitwiseAnd(do next().toInt, 63)
|
|
190
184
|
bitwiseOr(bitwiseOr(part1, part2), part3).toChar
|
|
191
185
|
} else {
|
|
192
186
|
val part1 = bitwiseShl(bitwiseAnd(b, 7), 18)
|
|
193
|
-
val part2 = bitwiseShl(bitwiseAnd(do
|
|
194
|
-
val part3 = bitwiseShl(bitwiseAnd(do
|
|
195
|
-
val part4 = bitwiseAnd(do
|
|
187
|
+
val part2 = bitwiseShl(bitwiseAnd(do next().toInt, 63), 12)
|
|
188
|
+
val part3 = bitwiseShl(bitwiseAnd(do next().toInt, 63), 6)
|
|
189
|
+
val part4 = bitwiseAnd(do next().toInt, 63)
|
|
196
190
|
bitwiseOr(bitwiseOr(bitwiseOr(part1, part2), part3), part4).toChar
|
|
197
191
|
}
|
|
198
192
|
}
|
|
@@ -216,10 +210,10 @@ def encodeChar(char: Char): Unit / emit[Byte] = {
|
|
|
216
210
|
}
|
|
217
211
|
}
|
|
218
212
|
|
|
219
|
-
def decodeUTF8[R] { reader: () => R /
|
|
213
|
+
def decodeUTF8[R] { reader: () => R / next[Char] }: R / next[Byte] =
|
|
220
214
|
try {
|
|
221
215
|
reader()
|
|
222
|
-
} with
|
|
216
|
+
} with next[Char] {
|
|
223
217
|
resume { decodeChar() }
|
|
224
218
|
}
|
|
225
219
|
|
|
@@ -1,26 +1,33 @@
|
|
|
1
1
|
module dictionary
|
|
2
2
|
|
|
3
|
+
import ref
|
|
3
4
|
import array
|
|
4
5
|
import bytearray
|
|
5
6
|
import stream
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/// Supports String and ByteArray keys with fast lookup and insertion.
|
|
10
|
-
type Dictionary[A] {
|
|
8
|
+
/// Internal trie node type.
|
|
9
|
+
type Trie[A] {
|
|
11
10
|
Empty()
|
|
12
11
|
Leaf(value: A)
|
|
13
|
-
Branch(children: Array[
|
|
14
|
-
Node(value: A, children: Array[
|
|
12
|
+
Branch(children: Array[Trie[A]])
|
|
13
|
+
Node(value: A, children: Array[Trie[A]])
|
|
15
14
|
}
|
|
16
15
|
|
|
16
|
+
/// A mutable trie-based dictionary for efficient key-value storage with bytearray keys.
|
|
17
|
+
type Dictionary[A] = Ref[Trie[A]]
|
|
18
|
+
|
|
19
|
+
/// A record pairing a key with a value for use in streams.
|
|
20
|
+
record Tagged[A](key: ByteArray, value: A)
|
|
21
|
+
|
|
22
|
+
def empty[A](): Dictionary[A] = ref(Empty())
|
|
23
|
+
|
|
17
24
|
/// Insert a value with a String key.
|
|
18
|
-
def insert[A](
|
|
19
|
-
insert(
|
|
25
|
+
def insert[A](dictionary: Dictionary[A], key: String, value: A): Unit =
|
|
26
|
+
insert(dictionary, key.fromString, value)
|
|
20
27
|
|
|
21
28
|
/// Insert a key-value pair into the dictionary with a ByteArray key.
|
|
22
|
-
def insert[A](
|
|
23
|
-
def go(trie:
|
|
29
|
+
def insert[A](dictionary: Dictionary[A], key: ByteArray, value: A): Unit = {
|
|
30
|
+
def go(trie: Trie[A], i: Int): Trie[A] =
|
|
24
31
|
if (i < key.size) {
|
|
25
32
|
trie match {
|
|
26
33
|
case Empty() =>
|
|
@@ -50,16 +57,16 @@ def insert[A](trie: Dictionary[A], key: ByteArray, value: A): Dictionary[A] = {
|
|
|
50
57
|
case Branch(children) => Node(value, children)
|
|
51
58
|
}
|
|
52
59
|
}
|
|
53
|
-
go(
|
|
60
|
+
dictionary.set(go(dictionary.get, 0))
|
|
54
61
|
}
|
|
55
62
|
|
|
56
63
|
/// Look up a value in the dictionary by string key.
|
|
57
|
-
def lookup[A](
|
|
58
|
-
lookup(
|
|
64
|
+
def lookup[A](dictionary: Dictionary[A], key: String): Option[A] =
|
|
65
|
+
lookup(dictionary, key.fromString)
|
|
59
66
|
|
|
60
67
|
/// Look up a value in the dictionary by bytearray key.
|
|
61
|
-
def lookup[A](
|
|
62
|
-
def go(trie:
|
|
68
|
+
def lookup[A](dictionary: Dictionary[A], key: ByteArray): Option[A] = {
|
|
69
|
+
def go(trie: Trie[A], i: Int): Option[A] =
|
|
63
70
|
if (i < key.size) {
|
|
64
71
|
trie match {
|
|
65
72
|
case Empty() => None()
|
|
@@ -75,45 +82,41 @@ def lookup[A](trie: Dictionary[A], key: ByteArray): Option[A] = {
|
|
|
75
82
|
case Node(value, _) => Some(value)
|
|
76
83
|
}
|
|
77
84
|
}
|
|
78
|
-
go(
|
|
85
|
+
go(dictionary.get, 0)
|
|
79
86
|
}
|
|
80
87
|
|
|
81
|
-
///
|
|
82
|
-
record Tagged[A](key: ByteArray, value: A)
|
|
83
|
-
|
|
84
|
-
/// Collect key-value pairs from a stream of Tagged elements into a Dictionary.
|
|
88
|
+
/// Collect key-value pairs from a stream of Tagged elements into a fresh Dictionary.
|
|
85
89
|
def collect[A] { stream: () => Unit / emit[Tagged[A]] }: Dictionary[A] = {
|
|
86
|
-
|
|
90
|
+
val dictionary = ref(Empty())
|
|
87
91
|
for[Tagged[A]] { stream() } { case Tagged(bytes, value) =>
|
|
88
|
-
|
|
92
|
+
dictionary.insert(bytes, value)
|
|
89
93
|
}
|
|
90
|
-
return
|
|
94
|
+
return dictionary
|
|
91
95
|
}
|
|
92
96
|
|
|
93
97
|
/// Emit all values stored in the dictionary as a push stream.
|
|
94
|
-
def each[A](
|
|
95
|
-
trie
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
each(children.get(i))
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
98
|
+
def each[A](dictionary: Dictionary[A]): Unit / emit[A] = {
|
|
99
|
+
def go(trie: Trie[A]): Unit / emit[A] =
|
|
100
|
+
trie match {
|
|
101
|
+
case Empty() => ()
|
|
102
|
+
case Leaf(value) => do emit(value)
|
|
103
|
+
case Branch(children) =>
|
|
104
|
+
each(0, children.size) { i => go(children.get(i)) }
|
|
105
|
+
case Node(value, children) =>
|
|
106
|
+
do emit(value)
|
|
107
|
+
each(0, children.size) { i => go(children.get(i)) }
|
|
108
|
+
}
|
|
109
|
+
go(dictionary.get)
|
|
110
|
+
}
|
|
108
111
|
|
|
109
112
|
/// Emit all key-value pairs stored in the dictionary as a push stream of Tagged elements.
|
|
110
|
-
def eachTagged[A](
|
|
113
|
+
def eachTagged[A](dictionary: Dictionary[A]): Unit / emit[Tagged[A]] = {
|
|
111
114
|
def fromBytesReverse(bytes: List[Byte], n: Int): ByteArray = {
|
|
112
115
|
val key = bytearray::allocate(n)
|
|
113
116
|
foreachIndex(bytes) { (i, b) => key.set(n - 1 - i, b) }
|
|
114
117
|
key
|
|
115
118
|
}
|
|
116
|
-
def go(trie:
|
|
119
|
+
def go(trie: Trie[A], key: List[Byte], n: Int): Unit =
|
|
117
120
|
trie match {
|
|
118
121
|
case Empty() => ()
|
|
119
122
|
case Leaf(value) => do emit(Tagged(fromBytesReverse(key, n), value))
|
|
@@ -127,7 +130,5 @@ def eachTagged[A](trie: Dictionary[A]): Unit / emit[Tagged[A]] = {
|
|
|
127
130
|
go(children.get(i), Cons(i.toByte, key), n + 1)
|
|
128
131
|
}
|
|
129
132
|
}
|
|
130
|
-
go(
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
|
|
133
|
+
go(dictionary.get, Nil(), 0)
|
|
134
|
+
}
|