@effekt-lang/effekt 0.47.0 → 0.48.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.
@@ -1,12 +1,7 @@
1
1
  module stream
2
2
 
3
- import array
4
- import bytearray
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
+ }
@@ -1,5 +1,6 @@
1
1
  module stringbuffer
2
2
 
3
+ import effekt
3
4
  import bytearray
4
5
 
5
6
  interface StringBuffer {