@effekt-lang/effekt 0.47.0 → 0.49.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/array.effekt +53 -0
- package/libraries/common/buffer.effekt +2 -2
- package/libraries/common/bytearray.effekt +55 -0
- package/libraries/common/char.effekt +87 -0
- package/libraries/common/effekt.effekt +3 -0
- package/libraries/common/io/error.effekt +11 -0
- package/libraries/common/io/filesystem.effekt +71 -9
- package/libraries/common/io/network.effekt +97 -65
- package/libraries/common/io.effekt +1 -2
- package/libraries/common/json.effekt +5 -5
- package/libraries/common/list.effekt +154 -18
- package/libraries/common/map.effekt +35 -1
- package/libraries/common/queue.effekt +1 -1
- package/libraries/common/random.effekt +1 -0
- package/libraries/common/ref.effekt +4 -0
- package/libraries/common/seq.effekt +1 -1
- package/libraries/common/set.effekt +24 -1
- package/libraries/common/stream.effekt +2 -360
- package/libraries/common/string.effekt +30 -0
- package/libraries/common/stringbuffer.effekt +1 -0
- package/libraries/llvm/io.c +281 -8
- package/libraries/llvm/main.c +1 -2
- package/libraries/llvm/rts.ll +14 -7
- package/libraries/llvm/types.c +3 -3
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +2 -2
- package/licenses/mit license - mit-license.html +48 -48
- package/licenses/the bsd license - bsd-license.html +49 -51
- package/licenses/the mit license - mit.html +47 -49
- package/package.json +1 -1
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
module stream
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import map
|
|
6
|
-
import set
|
|
7
|
-
|
|
8
|
-
import io/filesystem
|
|
9
|
-
import io/error
|
|
3
|
+
import effekt
|
|
4
|
+
import option
|
|
10
5
|
|
|
11
6
|
// Effects
|
|
12
7
|
// -------
|
|
@@ -53,68 +48,6 @@ def fix[T] { one: T => Unit / emit[T] } { stream: => Unit / emit[T] }: Unit =
|
|
|
53
48
|
resume(())
|
|
54
49
|
}
|
|
55
50
|
|
|
56
|
-
/// Turns a `list` into a producer of a push stream
|
|
57
|
-
/// by emitting each contained value left-to-right.
|
|
58
|
-
def each[A](list: List[A]): Unit / emit[A] =
|
|
59
|
-
list match {
|
|
60
|
-
case Nil() => ()
|
|
61
|
-
case Cons(head, tail) =>
|
|
62
|
-
do emit(head)
|
|
63
|
-
each(tail)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/// Turns an `array` into a producer of a push stream
|
|
67
|
-
/// by emitting each contained value from 0 to length - 1.
|
|
68
|
-
def each[T](array: Array[T]): Unit / emit[T] = {
|
|
69
|
-
val n = array.size
|
|
70
|
-
def go(i: Int): Unit = {
|
|
71
|
-
if (i < n) {
|
|
72
|
-
do emit(array.unsafeGet(i))
|
|
73
|
-
go(i + 1)
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
go(0)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/// Turns `bytes` into a producer of a push stream
|
|
80
|
-
/// by emitting each contained value from 0 to length - 1.
|
|
81
|
-
def each(bytes: ByteArray): Unit / emit[Byte] = {
|
|
82
|
-
val n = bytes.size
|
|
83
|
-
def go(i: Int): Unit = {
|
|
84
|
-
if (i < n) {
|
|
85
|
-
do emit(bytes.unsafeGet(i))
|
|
86
|
-
go(i + 1)
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
go(0)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/// Turns a `map` into a producer of a push stream
|
|
93
|
-
/// of `(key, value)` pairs by emitting each contained *in order*.
|
|
94
|
-
def each[K, V](map: Map[K, V]): Unit / emit[(K, V)] =
|
|
95
|
-
map.foreach { (k, v) => do emit((k, v)) }
|
|
96
|
-
|
|
97
|
-
/// Turns a `map` into a producer of a push stream
|
|
98
|
-
/// of its keys by emitting each contained *in order*.
|
|
99
|
-
def eachKey[K, V](map: Map[K, V]): Unit / emit[K] =
|
|
100
|
-
map.foreach { (k, _v) => do emit(k) }
|
|
101
|
-
|
|
102
|
-
/// Turns a `map` into a producer of a push stream
|
|
103
|
-
/// of its values by emitting each contained.
|
|
104
|
-
def eachValue[K, V](map: Map[K, V]): Unit / emit[V] =
|
|
105
|
-
map.foreach { (_k, v) => do emit(v) }
|
|
106
|
-
|
|
107
|
-
/// Turns a `set` into a producer of a push stream
|
|
108
|
-
/// by emitting each contained *in order*.
|
|
109
|
-
def each[A](set: Set[A]): Unit / emit[A] =
|
|
110
|
-
set.foreach { x => do emit(x) }
|
|
111
|
-
|
|
112
|
-
// not option
|
|
113
|
-
// not dequeue
|
|
114
|
-
// not queue
|
|
115
|
-
// not result
|
|
116
|
-
// not seq
|
|
117
|
-
|
|
118
51
|
|
|
119
52
|
def boundary { program: () => Unit / stop }: Unit = {
|
|
120
53
|
returning::boundary[Unit]{program}
|
|
@@ -202,87 +135,6 @@ def sum { stream: () => Unit / emit[Int] }: Int =
|
|
|
202
135
|
def product { stream: () => Unit / emit[Int] }: Int =
|
|
203
136
|
returning::product[Unit]{stream}.second
|
|
204
137
|
|
|
205
|
-
def collectList[A] { stream: () => Unit / emit[A] }: List[A] =
|
|
206
|
-
returning::collectList[A, Unit]{stream}.second
|
|
207
|
-
|
|
208
|
-
def collectArray[A] { stream: () => Unit / emit[A] }: Array[A] =
|
|
209
|
-
returning::collectArray[A, Unit]{stream}.second
|
|
210
|
-
|
|
211
|
-
def collectBytes { stream: () => Unit / emit[Byte] }: ByteArray =
|
|
212
|
-
returning::collectBytes[Unit]{stream}.second
|
|
213
|
-
|
|
214
|
-
def feed[T, R](list: List[T]) { reader: () => R / read[T] }: R = {
|
|
215
|
-
var l = list
|
|
216
|
-
try {
|
|
217
|
-
reader()
|
|
218
|
-
} with read[T] {
|
|
219
|
-
resume {
|
|
220
|
-
l match {
|
|
221
|
-
case Nil() => do stop()
|
|
222
|
-
case Cons(value, rest) =>
|
|
223
|
-
l = rest
|
|
224
|
-
return value
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
def collectMap[K, V, R](compare: (K, K) => Ordering at {}) { stream: () => R / emit[(K, V)] }: (R, Map[K, V]) =
|
|
231
|
-
try {
|
|
232
|
-
(stream(), map::empty(compare))
|
|
233
|
-
} with emit[(K, V)] { case (k, v) =>
|
|
234
|
-
val (r, map) = resume(());
|
|
235
|
-
(r, map.put(k, v))
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
def collectMap[K, V](compare: (K, K) => Ordering at {}) { stream: () => Any / emit[(K, V)] }: Map[K, V] =
|
|
239
|
-
collectMap[K, V, Any](compare){stream}.second
|
|
240
|
-
|
|
241
|
-
def collectSet[A, R](compare: (A, A) => Ordering at {}) { stream: () => R / emit[A] }: (R, Set[A]) =
|
|
242
|
-
try {
|
|
243
|
-
(stream(), set::empty(compare))
|
|
244
|
-
} with emit[A] { (v) =>
|
|
245
|
-
val (r, set) = resume(());
|
|
246
|
-
(r, set.insert(v))
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
def collectSet[A](compare: (A, A) => Ordering at {}) { stream: () => Any / emit[A] }: Set[A] =
|
|
250
|
-
collectSet[A, Any](compare){stream}.second
|
|
251
|
-
|
|
252
|
-
def feed[T, R](array: Array[T]) { reader: () => R / read[T] }: R = {
|
|
253
|
-
var i = 0
|
|
254
|
-
try {
|
|
255
|
-
reader()
|
|
256
|
-
} with read[T] {
|
|
257
|
-
resume {
|
|
258
|
-
if (i < array.size) {
|
|
259
|
-
val c = i
|
|
260
|
-
i = c + 1
|
|
261
|
-
array.unsafeGet(c)
|
|
262
|
-
} else {
|
|
263
|
-
do stop()
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
def feed[R](bytes: ByteArray) { reader: () => R / read[Byte] }: R = {
|
|
270
|
-
var i = 0
|
|
271
|
-
try {
|
|
272
|
-
reader()
|
|
273
|
-
} with read[Byte] {
|
|
274
|
-
resume {
|
|
275
|
-
if (i < bytes.size) {
|
|
276
|
-
val c = i
|
|
277
|
-
i = c + 1
|
|
278
|
-
bytes.unsafeGet(c)
|
|
279
|
-
} else {
|
|
280
|
-
do stop()
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
138
|
def source[A] { stream: () => Unit / emit[A] } { reader: () => Unit / read[A] }: Unit =
|
|
287
139
|
returning::source[A, Unit]{stream}{reader}
|
|
288
140
|
|
|
@@ -319,155 +171,6 @@ def zipLongest[A, B] { stream1: () => Unit / emit[A] } { stream2: () => Unit / e
|
|
|
319
171
|
}
|
|
320
172
|
}
|
|
321
173
|
|
|
322
|
-
def writeFile[R](path: String) { stream: () => R / emit[Byte] }: R / Exception[IOError] = {
|
|
323
|
-
|
|
324
|
-
val file = openForWriting(path);
|
|
325
|
-
with on[IOError].finalize { close(file) }
|
|
326
|
-
|
|
327
|
-
val chunkSize = 1048576 // 1MB
|
|
328
|
-
val buffer = bytearray::allocate(chunkSize)
|
|
329
|
-
var offset = 0
|
|
330
|
-
|
|
331
|
-
def push(i: Int, n: Int): Unit = {
|
|
332
|
-
val r = write(file, buffer, i, n, -1)
|
|
333
|
-
if (r < n) {
|
|
334
|
-
push(i + r, n - r)
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
try {
|
|
339
|
-
val r = stream()
|
|
340
|
-
push(0, offset)
|
|
341
|
-
return r
|
|
342
|
-
} with emit[Byte] { (byte) =>
|
|
343
|
-
if (offset >= buffer.size) {
|
|
344
|
-
push(0, buffer.size)
|
|
345
|
-
offset = 0
|
|
346
|
-
}
|
|
347
|
-
buffer.unsafeSet(offset, byte)
|
|
348
|
-
offset = offset + 1
|
|
349
|
-
resume(())
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
def readFile[R](path: String) { reader: () => R / read[Byte] }: R / Exception[IOError] = {
|
|
354
|
-
|
|
355
|
-
val file = openForReading(path);
|
|
356
|
-
with on[IOError].finalize { close(file) }
|
|
357
|
-
|
|
358
|
-
val chunkSize = 1048576 // 1MB
|
|
359
|
-
val buffer = bytearray::allocate(chunkSize)
|
|
360
|
-
var offset = 0
|
|
361
|
-
var length = 0
|
|
362
|
-
|
|
363
|
-
def pull(): Unit / stop = {
|
|
364
|
-
read(file, buffer, 0, chunkSize, -1) match {
|
|
365
|
-
case 0 =>
|
|
366
|
-
do stop()
|
|
367
|
-
case n =>
|
|
368
|
-
length = n
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
try {
|
|
373
|
-
reader()
|
|
374
|
-
} with read[Byte] {
|
|
375
|
-
resume {
|
|
376
|
-
if (offset >= length) {
|
|
377
|
-
pull()
|
|
378
|
-
offset = 0
|
|
379
|
-
}
|
|
380
|
-
val byte = buffer.unsafeGet(offset)
|
|
381
|
-
offset = offset + 1
|
|
382
|
-
return byte
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
def decodeChar(): Char / {read[Byte], stop} = {
|
|
388
|
-
val b = do read().toInt
|
|
389
|
-
if (b < 128) {
|
|
390
|
-
b.toChar
|
|
391
|
-
} else if (b < 224) {
|
|
392
|
-
val part1 = bitwiseShl(bitwiseAnd(b, 31), 6)
|
|
393
|
-
val part2 = bitwiseAnd(do read().toInt, 63)
|
|
394
|
-
bitwiseOr(part1, part2).toChar
|
|
395
|
-
} else if (b < 240) {
|
|
396
|
-
val part1 = bitwiseShl(bitwiseAnd(b, 15), 12)
|
|
397
|
-
val part2 = bitwiseShl(bitwiseAnd(do read().toInt, 63), 6)
|
|
398
|
-
val part3 = bitwiseAnd(do read().toInt, 63)
|
|
399
|
-
bitwiseOr(bitwiseOr(part1, part2), part3).toChar
|
|
400
|
-
} else {
|
|
401
|
-
val part1 = bitwiseShl(bitwiseAnd(b, 7), 18)
|
|
402
|
-
val part2 = bitwiseShl(bitwiseAnd(do read().toInt, 63), 12)
|
|
403
|
-
val part3 = bitwiseShl(bitwiseAnd(do read().toInt, 63), 6)
|
|
404
|
-
val part4 = bitwiseAnd(do read().toInt, 63)
|
|
405
|
-
bitwiseOr(bitwiseOr(bitwiseOr(part1, part2), part3), part4).toChar
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
def encodeChar(char: Char): Unit / emit[Byte] = {
|
|
410
|
-
val code = char.toInt
|
|
411
|
-
if (code < 128) {
|
|
412
|
-
do emit(code.toByte)
|
|
413
|
-
} else if (code < 2048) {
|
|
414
|
-
do emit(bitwiseOr(192, bitwiseShr(code, 6)).toByte)
|
|
415
|
-
do emit(bitwiseOr(128, bitwiseAnd(code, 63)).toByte)
|
|
416
|
-
} else if (code < 65536) {
|
|
417
|
-
do emit(bitwiseOr(224, bitwiseShr(code, 12)).toByte)
|
|
418
|
-
do emit(bitwiseOr(128, bitwiseAnd(bitwiseShr(code, 6), 63)).toByte)
|
|
419
|
-
do emit(bitwiseOr(128, bitwiseAnd(code, 63)).toByte)
|
|
420
|
-
} else {
|
|
421
|
-
do emit(bitwiseOr(240, bitwiseShr(code, 18)).toByte)
|
|
422
|
-
do emit(bitwiseOr(128, bitwiseAnd(bitwiseShr(code, 12), 63)).toByte)
|
|
423
|
-
do emit(bitwiseOr(128, bitwiseAnd(bitwiseShr(code, 6), 63)).toByte)
|
|
424
|
-
do emit(bitwiseOr(128, bitwiseAnd(code, 63)).toByte)
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
def decodeUTF8[R] { reader: () => R / read[Char] }: R / read[Byte] =
|
|
429
|
-
try {
|
|
430
|
-
reader()
|
|
431
|
-
} with read[Char] {
|
|
432
|
-
resume { decodeChar() }
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
def encodeUTF8[R] { stream: () => R / emit[Char] }: R / emit[Byte] =
|
|
436
|
-
try {
|
|
437
|
-
stream()
|
|
438
|
-
} with emit[Char] { char =>
|
|
439
|
-
resume(encodeChar(char))
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
def writeFileUTF8[R](path: String) { stream: () => R / emit[Char] }: R / Exception[IOError] =
|
|
443
|
-
writeFile(path) { encodeUTF8 { stream() } }
|
|
444
|
-
|
|
445
|
-
def readFileUTF8[R](path: String) { reader: () => R / read[Char] }: R / Exception[IOError] =
|
|
446
|
-
readFile(path) { decodeUTF8 { reader() } }
|
|
447
|
-
|
|
448
|
-
def feed[R](string: String) { reader: () => R / read[Char] } =
|
|
449
|
-
feed(string.fromString) {
|
|
450
|
-
decodeUTF8 {
|
|
451
|
-
reader()
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
def each(string: String): Unit / emit[Char] =
|
|
456
|
-
feed(string) {
|
|
457
|
-
exhaustively {
|
|
458
|
-
do emit[Char](do read[Char]())
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
def collectString { stream: () => Unit / emit[Char] }: String =
|
|
463
|
-
returning::collectString[Unit]{stream}.second
|
|
464
|
-
|
|
465
|
-
def writeLine { body: () => Unit / emit[Char] }: Unit / emit[Char] =
|
|
466
|
-
returning::writeLine[Unit]{body}
|
|
467
|
-
|
|
468
|
-
def readLine { body: () => Unit / read[Char] }: Unit / {read[Char], stop} =
|
|
469
|
-
returning::readLine[Unit]{body}
|
|
470
|
-
|
|
471
174
|
namespace internal {
|
|
472
175
|
effect snapshot(): Unit
|
|
473
176
|
}
|
|
@@ -640,67 +343,6 @@ def product[R] { stream: () => R / emit[Int] }: (R, Int) = {
|
|
|
640
343
|
}
|
|
641
344
|
}
|
|
642
345
|
|
|
643
|
-
def collectList[A, R] { stream: () => R / emit[A] }: (R, List[A]) =
|
|
644
|
-
try {
|
|
645
|
-
(stream(), Nil())
|
|
646
|
-
} with emit[A] { (v) =>
|
|
647
|
-
val (r, vs) = resume(());
|
|
648
|
-
(r, Cons(v, vs))
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
def collectArray[A, R] { stream: () => R / emit[A] }: (R, Array[A]) = {
|
|
652
|
-
var i = 0
|
|
653
|
-
var a = array::allocate(1)
|
|
654
|
-
try {
|
|
655
|
-
(stream(), a.resize(i))
|
|
656
|
-
} with emit[A] { (v) =>
|
|
657
|
-
if (i >= a.size) { a = a.resize(2 * a.size) }
|
|
658
|
-
a.unsafeSet(i, v)
|
|
659
|
-
i = i + 1
|
|
660
|
-
resume(())
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
def collectBytes[R] { stream: () => R / emit[Byte] }: (R, ByteArray) = {
|
|
665
|
-
var i = 0
|
|
666
|
-
var a = bytearray::allocate(1)
|
|
667
|
-
try {
|
|
668
|
-
(stream(), a.resize(i))
|
|
669
|
-
} with emit[Byte] { (v) =>
|
|
670
|
-
if (i >= a.size) { a = a.resize(2 * a.size) }
|
|
671
|
-
a.unsafeSet(i, v)
|
|
672
|
-
i = i + 1
|
|
673
|
-
resume(())
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
def collectString[R] { stream: () => R / emit[Char] }: (R, String) = {
|
|
678
|
-
val (result, bytes) = collectBytes[R] { encodeUTF8 { stream } }
|
|
679
|
-
(result, bytes.toString)
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
def writeLine[R] { body: () => R / emit[Char] }: R / emit[Char] = {
|
|
683
|
-
val result = body()
|
|
684
|
-
do emit('\n')
|
|
685
|
-
return result
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
def readLine[R] { body: () => R / read[Char] }: R / {read[Char], stop} = {
|
|
689
|
-
var stopped = false
|
|
690
|
-
try {
|
|
691
|
-
body()
|
|
692
|
-
} with read[Char] {
|
|
693
|
-
if(stopped){
|
|
694
|
-
resume { do stop() }
|
|
695
|
-
} else {
|
|
696
|
-
do read[Char] match {
|
|
697
|
-
case '\n' => stopped = true; resume { do stop() }
|
|
698
|
-
case char => resume { return char }
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
|
|
704
346
|
def source[A, R] { stream: () => Unit / emit[A] } { reader: () => R / read[A] }: R = {
|
|
705
347
|
var next = box { None() }
|
|
706
348
|
next = box {
|
|
@@ -2,10 +2,12 @@ module string
|
|
|
2
2
|
|
|
3
3
|
import effekt
|
|
4
4
|
import option
|
|
5
|
+
import stream
|
|
5
6
|
import list
|
|
6
7
|
import exception
|
|
7
8
|
import result
|
|
8
9
|
import char
|
|
10
|
+
import bytearray
|
|
9
11
|
|
|
10
12
|
// TODO
|
|
11
13
|
// - [ ] handle unicode codepoints (that can span two indices) correctly
|
|
@@ -229,3 +231,31 @@ extern def unsafeCharAt(str: String, n: Int) at {}: Char =
|
|
|
229
231
|
ret %Int %x
|
|
230
232
|
"""
|
|
231
233
|
vm "string::unsafeCharAt(String, Int)"
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
// Streaming
|
|
237
|
+
// ---------
|
|
238
|
+
|
|
239
|
+
def feed[R](string: String) { reader: () => R / read[Char] } =
|
|
240
|
+
feed(string.fromString) {
|
|
241
|
+
decodeUTF8 {
|
|
242
|
+
reader()
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
def each(string: String): Unit / emit[Char] =
|
|
247
|
+
feed(string) {
|
|
248
|
+
exhaustively {
|
|
249
|
+
do emit[Char](do read[Char]())
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
def collect { stream: () => Unit / emit[Char] }: String =
|
|
254
|
+
returning::collect[Unit]{stream}.second
|
|
255
|
+
|
|
256
|
+
namespace returning {
|
|
257
|
+
def collect[R] { stream: () => R / emit[Char] }: (R, String) = {
|
|
258
|
+
val (result, bytes) = bytearray::returning::collect[R] { encodeUTF8 { stream } }
|
|
259
|
+
(result, bytes.toString)
|
|
260
|
+
}
|
|
261
|
+
}
|