@effekt-lang/effekt 0.62.0 → 0.63.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 CHANGED
Binary file
@@ -10,14 +10,14 @@ import exception
10
10
  /// A mutable 0-indexed fixed-sized array.
11
11
  extern type Array[T]
12
12
 
13
- /** We represent arrays like positive types.
14
- * The tag is 0 and the obj points to memory with the following layout:
15
- *
16
- * +--[ Header ]--+------+------------+
17
- * | Rc | Eraser | Size | Fields ... |
18
- * +--------------+------+------------+
19
- */
20
-
13
+ /// We represent arrays like positive types.
14
+ /// The tag is 0 and the obj points to memory with the following layout:
15
+ ///
16
+ /// ```
17
+ /// +--[ Header ]--+------+------------+
18
+ /// | Rc | Eraser | Size | Fields ... |
19
+ /// +--------------+------+------------+
20
+ /// ```
21
21
  extern llvm """
22
22
  define void @array_erase_fields(ptr %array_pointer) {
23
23
  entry:
@@ -201,17 +201,13 @@ def resize[T](source: Array[T], size: Int): Array[T] = {
201
201
  go(0)
202
202
  }
203
203
 
204
- /**
205
- * Creates a copy of `arr`
206
- */
204
+ /// Creates a copy of `arr`
207
205
  def copy[T](array: Array[T]): Array[T] =
208
206
  array.resize(array.size)
209
207
 
210
- /**
211
- * Copies `length`-many elements from `from` to `to`
212
- * starting at `start` (in `from`) and `offset` (in `to`)
213
- * Panics if any of those are out of bounds.
214
- */
208
+ /// Copies `length`-many elements from `from` to `to`
209
+ /// starting at `start` (in `from`) and `offset` (in `to`)
210
+ /// Panics if any of those are out of bounds.
215
211
  def copy[T](from: Array[T], start: Int, to: Array[T], offset: Int, length: Int): Unit = {
216
212
  def go(i: Int, j: Int, n: Int): Unit =
217
213
  if (n > 0) {
@@ -226,7 +222,7 @@ def copy[T](from: Array[T], start: Int, to: Array[T], offset: Int, length: Int):
226
222
 
227
223
  /// Swap the value at index i with that at index j.
228
224
  /// Panics if the indices are out bounds.
229
- ///
225
+ ///
230
226
  /// O(1)
231
227
  def swap[A](arr: Array[A], i: Int, j: Int): Unit = {
232
228
  val tmp = arr.get(i)
@@ -235,7 +231,7 @@ def swap[A](arr: Array[A], i: Int, j: Int): Unit = {
235
231
  }
236
232
 
237
233
  /// Converts the given array into a list.
238
- ///
234
+ ///
239
235
  /// O(N)
240
236
  def toList[T](arr: Array[T]): List[T] = {
241
237
  var i = arr.size - 1;
@@ -280,7 +276,7 @@ def foreachIndex[T](arr: Array[T]){ action: (Int, T) {Label} => Unit }: Unit =
280
276
  }
281
277
 
282
278
  /// Sum the elements of the array.
283
- ///
279
+ ///
284
280
  /// O(N)
285
281
  def sum(arr: Array[Int]): Int = {
286
282
  var acc = 0
@@ -291,7 +287,7 @@ def sum(arr: Array[Int]): Int = {
291
287
  }
292
288
 
293
289
  /// Checks whether two given arrays are equal with respect to an equalty funciton defined on their element.
294
- ///
290
+ ///
295
291
  /// O(N)
296
292
  def equals[A](this: Array[A], other: Array[A]) { eq: (A, A) => Bool }: Bool = {
297
293
  if (this.size != other.size) false
@@ -330,7 +326,7 @@ def mapped[A, B](arr: Array[A]) { f: A => B }: Array[B] = {
330
326
  }
331
327
 
332
328
  /// Reverses an array in-place.
333
- ///
329
+ ///
334
330
  /// O(N)
335
331
  def reverse[A](arr: Array[A]): Unit = {
336
332
  val size = arr.size()
@@ -346,12 +342,12 @@ def reverse[A](arr: Array[A]): Unit = {
346
342
  }
347
343
  }
348
344
  /// Creates a new array with elements in reverse order.
349
- ///
345
+ ///
350
346
  /// O(N)
351
347
  def reversed[A](arr: Array[A]): Array[A] = {
352
348
  val size = arr.size()
353
349
  val result = unsafeAllocate[A](size)
354
-
350
+
355
351
  // Copy elements in reverse order to new array
356
352
  each(0, size) { i =>
357
353
  val value = arr.get(i)
@@ -381,7 +377,7 @@ def foldRight[A, B](arr: Array[A], init: B) { f: (A, B) => B }: B = {
381
377
  /// Filters a given array with respect to a given predicate such that a
382
378
  /// new array containing all the elements for which the predicate
383
379
  /// holds is allocated.
384
- ///
380
+ ///
385
381
  /// O(N)
386
382
  def filtered[A](arr: Array[A]) { shouldKeep: A => Bool }: Array[A] = {
387
383
  val res = arr.copy()
@@ -434,15 +430,15 @@ def count[A](arr: Array[A]) { predicate: A => Bool }: Int = {
434
430
  def take[A](arr: Array[A], n: Int): Array[A] = {
435
431
  val len = min(max(0, n), arr.size)
436
432
  val result = unsafeAllocate[A](len)
437
- each(0, len) { i =>
433
+ each(0, len) { i =>
438
434
  result.set(i, arr.get(i))
439
435
  }
440
436
  result
441
437
  }
442
438
 
443
- // Drop first n elements.
439
+ /// Drop first n elements.
444
440
  /// Returns a new array.
445
- ///
441
+ ///
446
442
  /// O(N)
447
443
  def drop[A](arr: Array[A], n: Int): Array[A] = {
448
444
  val start = min(max(0, n), arr.size)
@@ -533,7 +529,7 @@ def partioned[A](arr: Array[A]) { pred: A => Bool }: (Array[A], Array[A]) = {
533
529
  }
534
530
 
535
531
  /// Get the _first_ index of the last occurance of `elem`, if there is any.
536
- ///
532
+ ///
537
533
  /// O(N)
538
534
  def indexOf[A](arr: Array[A], toFind: A) { eq: (A, A) => Bool }: Option[Int] = {
539
535
  var found = None[Int]()
@@ -547,7 +543,7 @@ def indexOf[A](arr: Array[A], toFind: A) { eq: (A, A) => Bool }: Option[Int] = {
547
543
  }
548
544
 
549
545
  /// Get the _last_ index of the last occurance of `elem`, if there is any.
550
- ///
546
+ ///
551
547
  /// O(N)
552
548
  def lastIndexOf[A](arr: Array[A], toFind: A) { eq: (A, A) => Bool }: Option[Int] = {
553
549
  var lastFound = None[Int]()
@@ -560,7 +556,7 @@ def lastIndexOf[A](arr: Array[A], toFind: A) { eq: (A, A) => Bool }: Option[Int]
560
556
  }
561
557
 
562
558
  /// Perform binary search to find the index of a given element.
563
- ///
559
+ ///
564
560
  /// O(log N)
565
561
  def binarySearch[A](arr: Array[A], toFind: A) { ord: (A, A) => Ordering }: Option[Int] = {
566
562
  def binarySearch(lowerIdx: Int, upperIdx: Int): Option[Int] = {
@@ -579,26 +575,24 @@ def binarySearch[A](arr: Array[A], toFind: A) { ord: (A, A) => Ordering }: Optio
579
575
  }
580
576
 
581
577
  /// Sort an array in-place using provided comparison function.
582
- /// Note: sort is unstable since it uses QuickSort (unlike list::sortBy)
578
+ /// Note: `sort` is unstable since it uses QuickSort (unlike `list::sortBy`)
583
579
  ///
584
580
  /// O(N log N) average case
585
581
  def sort[A](arr: Array[A]) { ord: (A, A) => Ordering }: Unit = {
586
582
  def partition(low: Int, high: Int): Int = {
587
583
  val pivot = arr.get(high)
588
584
  var i = low - 1
589
-
585
+
590
586
  each(low, high) { j =>
591
- ord(arr.get(j), pivot) match {
592
- case Less() =>
593
- i = i + 1
594
- swap(arr, i, j)
595
- case _ => ()
587
+ if (ord(arr.get(j), pivot) is Less()) {
588
+ i = i + 1
589
+ swap(arr, i, j)
596
590
  }
597
591
  }
598
592
  swap(arr, i + 1, high)
599
593
  i + 1
600
594
  }
601
-
595
+
602
596
  def quickSort(low: Int, high: Int): Unit = {
603
597
  if (low < high) {
604
598
  val par = partition(low, high)
@@ -606,13 +600,13 @@ def sort[A](arr: Array[A]) { ord: (A, A) => Ordering }: Unit = {
606
600
  quickSort(par + 1, high)
607
601
  }
608
602
  }
609
-
603
+
610
604
  quickSort(0, arr.size - 1)
611
605
  }
612
606
 
613
607
  /// Sort an array using provided comparison function.
614
608
  /// A newly allocated sorted array is returned as result, i.e., the sorting is not in-place.
615
- /// Note: sort is unstable since it uses QuickSort (unlike list::sortBy)
609
+ /// Note: `sorted` is unstable since it uses QuickSort (unlike `list::sortBy`)
616
610
  ///
617
611
  /// O(N log N) average case
618
612
  def sorted[A](arr: Array[A]) { ord: (A, A) => Ordering }: Array[A] = {
@@ -665,6 +659,7 @@ def each[T](array: Array[T]): Unit / emit[T] = {
665
659
  go(0)
666
660
  }
667
661
 
662
+ /// Connects `array` as a producer to a given pull stream `reader` acting as a consumer.
668
663
  def feed[T, R](array: Array[T]) { reader: () => R / read[T] }: R = {
669
664
  var i = 0
670
665
  try {
@@ -682,10 +677,15 @@ def feed[T, R](array: Array[T]) { reader: () => R / read[T] }: R = {
682
677
  }
683
678
  }
684
679
 
680
+ /// Collects elements emitted by a push stream producer `stream` into a new array,
681
+ /// discarding the result of the producer.
685
682
  def collect[A] { stream: () => Unit / emit[A] }: Array[A] =
686
683
  returning::collect[A, Unit]{stream}.second
687
684
 
688
685
  namespace returning {
686
+
687
+ /// Collects elements emitted by a push stream producer `stream` into a new array,
688
+ /// returning the result of the producer as well as the collected array.
689
689
  def collect[A, R] { stream: () => R / emit[A] }: (R, Array[A]) = {
690
690
  var i = 0
691
691
  var a = unsafeAllocate(1)
@@ -3,6 +3,7 @@ module bytearray
3
3
  import effekt
4
4
  import stream
5
5
  import control
6
+ import array
6
7
 
7
8
  /**
8
9
  * A memory managed, mutable, fixed-length array of bytes.
@@ -106,6 +107,16 @@ def bytearray(size: Int, init: Byte): ByteArray = {
106
107
  arr
107
108
  }
108
109
 
110
+ /// Builds a new ByteArray of size `size` from a computation `index` which gets an index
111
+ /// and returns a byte that will be on that position in the resulting array
112
+ def build(size: Int) { index: Int => Byte }: ByteArray = {
113
+ val arr = allocate(size);
114
+ each(0, size) { i =>
115
+ set(arr, i, index(i))
116
+ };
117
+ arr
118
+ }
119
+
109
120
  def resize(source: ByteArray, size: Int): ByteArray = {
110
121
  val target = allocate(size)
111
122
  val n = min(source.size, target.size)
@@ -119,6 +130,34 @@ def resize(source: ByteArray, size: Int): ByteArray = {
119
130
  go(0)
120
131
  }
121
132
 
133
+ /// Sorts a given bytearray `arr` in-place using a counting sort,
134
+ /// allocating a temporary array of 256 integers for said counting.
135
+ ///
136
+ /// O(N)
137
+ def sort(arr: ByteArray): Unit = {
138
+ val length = arr.size
139
+ if (length <= 1) {
140
+ ()
141
+ } else {
142
+ // Count occurrences of each byte value
143
+ // (maps 0..255 to its count in the byte array)
144
+ val counts = array::allocateZeros(256)
145
+ each(0, length) { i =>
146
+ val byte = arr.get(i).toInt
147
+ counts.set(byte, counts.get(byte) + 1)
148
+ }
149
+
150
+ // Write back in sorted order (like RLE decoding)
151
+ var pos = 0
152
+ counts.foreachIndex { (n, count) =>
153
+ count.repeat {
154
+ arr.set(pos, n.toByte)
155
+ pos = pos + 1
156
+ }
157
+ }
158
+ }
159
+ }
160
+
122
161
  def foreach(arr: ByteArray){ action: Byte => Unit }: Unit =
123
162
  each(0, arr.size) { i =>
124
163
  action(arr.get(i))
@@ -0,0 +1,337 @@
1
+ import option
2
+ import stringbuffer
3
+ import stream
4
+ import char
5
+ import io/error
6
+ import bytearray
7
+
8
+ // assumes by default:
9
+ // BE byteorder, BE bitorder, unsigned
10
+
11
+ // Wrappers
12
+ // --------
13
+ /// A with explicit big-endian order
14
+ record BE[A](raw: A)
15
+ /// A with explicit little-endian order
16
+ record LE[A](raw: A)
17
+ /// A with explicit width in current unit
18
+ /// (bits for bitstreams, bytes for bytestreams)
19
+ record OfWidth[A](raw: A, width: Int)
20
+ /// explicitly signed A
21
+ record Signed[A](raw: A)
22
+
23
+ /// Bits
24
+ type Bit { B0(); B1() }
25
+
26
+ /// not on Bits
27
+ def not(b: Bit): Bit = b match {
28
+ case B0() => B1()
29
+ case B1() => B0()
30
+ }
31
+
32
+ /// Splices allowed in hex/byte stream literals
33
+ effect HexSplices = {
34
+ splice[Char], splice[String],
35
+ splice[Unit],
36
+ splice[Int],
37
+ splice[Byte],
38
+ splice[BE[Int]], splice[LE[Int]],
39
+ splice[LE[Signed[Int]]], splice[OfWidth[LE[Int]]], splice[OfWidth[LE[Signed[Int]]]],
40
+ splice[BE[Signed[Int]]], splice[OfWidth[BE[Int]]], splice[OfWidth[BE[Signed[Int]]]],
41
+ splice[ByteArray]
42
+ }
43
+
44
+ // Splitting
45
+ // ---------
46
+
47
+ /// emit bytes of the given int as a w bytes in little-endian byte order
48
+ def bytesLE(int: Int, w: Int): Unit / emit[Byte] = {
49
+ var c = int
50
+ repeat(w){
51
+ do emit(mod(c, 256).toByte)
52
+ c = c / 256
53
+ }
54
+ }
55
+
56
+ /// emit bytes of the given int as a 4 bytes in little-endian byte order
57
+ def bytesLE(int: Int): Unit / emit[Byte] = bytesLE(int, 4)
58
+
59
+ /// emit bytes of the given int as a w bytes in big-endian byte order
60
+ def bytesBE(n: Int, width: Int): Unit / emit[Byte] = {
61
+ var shift = bitwiseShl(width - 1, 3)
62
+ repeat(width) {
63
+ do emit(bitwiseAnd(bitwiseShr(n, shift), 255).toByte)
64
+ shift = shift - 8
65
+ }
66
+ }
67
+
68
+ /// emit bytes of the given int as a 4 bytes in big-endian byte order
69
+ def bytesBE(n: Int): Unit / emit[Byte] = bytesBE(n, 4)
70
+
71
+ /// emit bytes of the given int as width bytes (in 2s-complement) in little-endian byte order
72
+ def signedBytesLE(int: Int, width: Int): Unit / emit[Byte] =
73
+ if (int < 0) {
74
+ bytesLE(bitwiseNot(neg(int)) + 1, width)
75
+ } else {
76
+ bytesLE(int, width)
77
+ }
78
+ /// emit bytes of the given int as width bytes (in 2s-complement) in big-endian byte order
79
+ def signedBytesBE(int: Int, width: Int): Unit / emit[Byte] = {
80
+ if (int < 0) {
81
+ bytesBE(bitwiseNot(neg(int)) + 1, width)
82
+ } else {
83
+ bytesBE(int, width)
84
+ }
85
+ }
86
+
87
+ /// emit bytes of the given int as 4 bytes (in 2s-complement) in little-endian byte order
88
+ def signedBytesLE(int: Int): Unit / emit[Byte] = signedBytesLE(int, 4)
89
+
90
+ /// emit bytes of the given int as 4 bytes (in 2s-complement) in big-endian byte order
91
+ def signedBytesBE(int: Int): Unit / emit[Byte] = signedBytesBE(int, 4)
92
+
93
+
94
+
95
+ // Splicers
96
+ // --------
97
+
98
+ /// Splicer to emit the bytes in hex notation given, plus eventual splices
99
+ /// Ignores whitespace
100
+ def hex{ body: => Unit / { write, HexSplices } }: Unit / emit[Byte] = {
101
+ try {
102
+ try {
103
+ body()
104
+ }
105
+ with splice[String] { s =>
106
+ feed(s){ loop { do splice[Char](do read[Char]()) } }
107
+ resume(())
108
+ }
109
+ with splice[ByteArray] { ba =>
110
+ ba.foreach{ b => do splice[Byte](b) }
111
+ resume(())
112
+ }
113
+ }
114
+ with write { s =>
115
+ feed(s){
116
+ loop {
117
+ attempt {
118
+ val upper: Int = hexDigitValue(do read[Char]())
119
+ val lower: Int = hexDigitValue(do read[Char]())
120
+ do emit[Byte]((16 * upper + lower).toByte)
121
+ } { () }
122
+ }
123
+ }
124
+ resume(())
125
+ }
126
+ with splice[Char] { c => do emit[Byte](c.toInt.toByte); resume(()) }
127
+ with splice[Byte] { b => do emit(b); resume(()) }
128
+ with splice[Unit] { u => resume(()) }
129
+ with splice[Int] { n => bytesBE(n); resume(()) }
130
+ with splice[LE[Int]] { w => bytesLE(w.raw); resume(()) }
131
+ with splice[BE[Int]] { v => bytesBE(v.raw); resume(()) }
132
+ with splice[LE[Signed[Int]]] { w => signedBytesLE(w.raw.raw); resume(()) }
133
+ with splice[OfWidth[LE[Int]]] { w => bytesLE(w.raw.raw, w.width); resume(()) }
134
+ with splice[OfWidth[LE[Signed[Int]]]] { w => signedBytesLE(w.raw.raw.raw, w.width); resume(()) }
135
+ with splice[BE[Signed[Int]]] { w => signedBytesBE(w.raw.raw); resume(()) }
136
+ with splice[OfWidth[BE[Int]]] { w => bytesBE(w.raw.raw, w.width); resume(()) }
137
+ with splice[OfWidth[BE[Signed[Int]]]] { w => signedBytesBE(w.raw.raw.raw, w.width); resume(()) }
138
+ }
139
+
140
+ /// convert the given hex notation to an integer (big-endian)
141
+ def x{ body: => Unit / { write, HexSplices } }: Int = {
142
+ var res = 0
143
+ for[Byte]{ hex{body} }{ v => res = res * 256 + v.toInt }
144
+ res
145
+ }
146
+
147
+
148
+ // Sub-Byte
149
+ // ========
150
+
151
+ // From/to Bytes
152
+ // -------------
153
+ /// emit bits of the given Byte as 8 Bits in little-endian bit order
154
+ def bitsLE(byte: Byte): Unit / emit[Bit] = {
155
+ val v = byte.toInt
156
+ var mask = 1
157
+ repeat(8){
158
+ bitwiseAnd(v, mask) match {
159
+ case 0 => do emit(B0())
160
+ case _ => do emit(B1())
161
+ }
162
+ mask = mask * 2
163
+ }
164
+ }
165
+
166
+ /// emit bits of the given Byte as 8 Bits in big-endian bit order
167
+ def bitsBE(byte: Byte): Unit / emit[Bit] = {
168
+ val v = byte.toInt
169
+ var mask = 128
170
+ repeat(8){
171
+ bitwiseAnd(v, mask) match {
172
+ case 0 => do emit(B0())
173
+ case _ => do emit(B1())
174
+ }
175
+ mask = mask / 2
176
+ }
177
+ }
178
+
179
+ /// emit bits of the given Byte as width Bits in little-endian bit order
180
+ def bitsLE(v: Int, width: Int): Unit / emit[Bit] = {
181
+ var mask = 1
182
+ repeat(width){
183
+ bitwiseAnd(v, mask) match {
184
+ case 0 => do emit(B0())
185
+ case _ => do emit(B1())
186
+ }
187
+ mask = mask * 2
188
+ }
189
+ }
190
+
191
+ /// emit bits of the given int as width Bits in big-endian bit order
192
+ def bitsBE(v: Int, width: Int): Unit / emit[Bit] = {
193
+ var mask = bitwiseShl(1, width - 1)
194
+ repeat(width){
195
+ bitwiseAnd(v, mask) match {
196
+ case 0 => do emit(B0())
197
+ case _ => do emit(B1())
198
+ }
199
+ mask = mask / 2
200
+ }
201
+ }
202
+
203
+ /// emit bits of the given int as 32 Bits in big-endian bit order
204
+ def bitsBE(int: Int): Unit / emit[Bit] = bitsBE(int, 32)
205
+
206
+ /// collect bits in big-endian bit order into an Int
207
+ def collectBitsBE{ body: => Unit / emit[Bit] }: Int = {
208
+ var res = 0
209
+ try body() with emit[Bit] { b =>
210
+ res = b match {
211
+ case B0() => res * 2
212
+ case B1() => res * 2 + 1
213
+ }
214
+ resume(())
215
+ }
216
+ res
217
+ }
218
+
219
+ /// split emitted bytes and emit the individual bits in big-endian bit order
220
+ def ungroupBytesBE{ body: => Unit / emit[Byte] }: Unit / emit[Bit] =
221
+ for[Byte]{body}{ b => bitsBE(b) }
222
+
223
+ /// streaming negation in 2s-complement for little-endian bitstreams
224
+ def twoscomplementLE{ body: => Unit / emit[Bit] }: Unit / emit[Bit] = {
225
+ var carry = true
226
+ try body()
227
+ with emit[Bit] {
228
+ case B0() => if(carry) { do emit(B0()) } else { do emit(B1()) }; resume(())
229
+ case B1() => if(carry) { do emit(B1()); carry = false } else { do emit(B0()) }; resume(())
230
+ }
231
+ }
232
+
233
+ /// group 8 bits into a byte each, big-endian bit order.
234
+ /// NOTE: The remainder is dropped.
235
+ def groupBytesBE{ body: => Unit / emit[Bit] }: Unit / emit[Byte] = {
236
+ var next = 0
237
+ var p = 128
238
+ for[Bit]{body}{ b =>
239
+ b match {
240
+ case B0() => ()
241
+ case B1() => next = next + p
242
+ }
243
+ p = p / 2
244
+ if(p == 0) {
245
+ do emit(next.toByte)
246
+ next = 0
247
+ p = 128
248
+ }
249
+ }
250
+ }
251
+
252
+ /// group 8 bits into a byte each, little-endian bit order.
253
+ /// NOTE: The remainder is dropped.
254
+ def groupBytesLE{ body: => Unit / emit[Bit] }: Unit / emit[Byte] = {
255
+ var next = 0
256
+ var p = 1
257
+ for[Bit]{body}{ b =>
258
+ b match {
259
+ case B0() => ()
260
+ case B1() => next = next + p
261
+ }
262
+ p = p * 2
263
+ if(p == 256) {
264
+ do emit(next.toByte)
265
+ next = 0
266
+ p = 1
267
+ }
268
+ }
269
+ }
270
+
271
+ // Literals/splices
272
+ // ----------------
273
+ /// Splices allowed in bit stream literals
274
+ effect BitSplices = {
275
+ splice[Unit], splice[Bit],
276
+ splice[Byte],
277
+ splice[LE[Int]], splice[BE[Int]],
278
+ splice[LE[Signed[Int]]], splice[BE[Signed[Int]]],
279
+ splice[OfWidth[LE[Int]]], splice[OfWidth[BE[Int]]],
280
+ splice[OfWidth[LE[Signed[Int]]]], splice[OfWidth[BE[Signed[Int]]]]
281
+ }
282
+ /// Splicer to emit the bits in binary notation given, plus evenutal splices
283
+ /// Ignores whitespace
284
+ def bit{ body: => Unit / { write, BitSplices } }: Unit / emit[Bit] = {
285
+ try {
286
+ ungroupBytesBE{
287
+ try {
288
+ body()
289
+ }
290
+ with splice[LE[Int]] { i => bytesLE(i.raw); resume(()) }
291
+ with splice[BE[Int]] { i => bytesBE(i.raw); resume(()) }
292
+ with splice[LE[Signed[Int]]] { i => signedBytesLE(i.raw.raw); resume(()) }
293
+ with splice[BE[Signed[Int]]] { i => signedBytesBE(i.raw.raw); resume(()) }
294
+ }
295
+ }
296
+ with write { s =>
297
+ feed(s){
298
+ loop {
299
+ do read[Char]() match {
300
+ case '0' => do emit(B0())
301
+ case '1' => do emit(B1())
302
+ case _ => ()
303
+ }
304
+ }
305
+ }
306
+ resume(())
307
+ }
308
+ with splice[Unit] { _ => resume(()) }
309
+ with splice[Bit] { b => do emit(b); resume(()) }
310
+ with splice[Byte] { b => bitsBE(b); resume(()) }
311
+ with splice[OfWidth[LE[Int]]] { i =>
312
+ bitsLE(i.raw.raw, i.width)
313
+ resume(())
314
+ }
315
+ with splice[OfWidth[LE[Signed[Int]]]] { i =>
316
+ if(i.raw.raw.raw < 0){
317
+ twoscomplementLE{ bitsLE(0 - i.raw.raw.raw, i.width) }
318
+ } else {
319
+ bitsLE(i.raw.raw.raw, i.width)
320
+ }
321
+ resume(())
322
+ }
323
+ with splice[OfWidth[BE[Int]]] { i =>
324
+ bitsBE(i.raw.raw, i.width)
325
+ resume(())
326
+ }
327
+ with splice[OfWidth[BE[Signed[Int]]]] { i =>
328
+ list::collect[Bit]{
329
+ if(i.raw.raw.raw < 0){
330
+ twoscomplementLE{ bitsLE(0 - i.raw.raw.raw, i.width) }
331
+ } else {
332
+ bitsLE(i.raw.raw.raw, i.width)
333
+ }
334
+ }.reverse.each
335
+ resume(())
336
+ }
337
+ }
@@ -321,6 +321,27 @@ extern def infixNeq(x: Bool, y: Bool) at {}: Bool =
321
321
  ret %Pos %adt_boolean
322
322
  """
323
323
 
324
+ extern def infixEq(x: Byte, y: Byte) at {}: Bool =
325
+ js "${x} === ${y}"
326
+ chez "(equal? ${x} ${y})"
327
+ llvm """
328
+ %z = icmp eq %Byte ${x}, ${y}
329
+ %fat_z = zext i1 %z to i64
330
+ %adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
331
+ ret %Pos %adt_boolean
332
+ """
333
+ vm "effekt::infixEq(Byte, Byte)"
334
+
335
+ extern def infixNeq(x: Byte, y: Byte) at {}: Bool =
336
+ js "${x} !== ${y}"
337
+ chez "(not (equal? ${x} ${y}))"
338
+ llvm """
339
+ %z = icmp ne %Byte ${x}, ${y}
340
+ %fat_z = zext i1 %z to i64
341
+ %adt_boolean = insertvalue %Pos zeroinitializer, i64 %fat_z, 0
342
+ ret %Pos %adt_boolean
343
+ """
344
+ vm "effekt::infixNeq(Byte, Byte)"
324
345
 
325
346
  // Math ops
326
347
  // ========
@@ -682,13 +703,19 @@ extern def bitwiseXor(x: Int, y: Int) at {}: Int =
682
703
  llvm "%z = xor %Int ${x}, ${y} ret %Int %z"
683
704
  vm "effekt::bitwiseXor(Int, Int)"
684
705
 
706
+ extern def bitwiseNot(x: Int) at {}: Int =
707
+ js "(~${x})"
708
+ chez "(lognot ${x})"
709
+ llvm "%z = xor %Int ${x}, -1 ret %Int %z"
710
+ vm "effekt::bitwiseNot(Int)"
711
+
685
712
 
686
713
  // Byte operations
687
714
  // ===============
688
715
  extern def toByte(n: Int) at {}: Byte =
689
- js "${n}"
716
+ js "(${n} & 0xFF)"
690
717
  llvm "%z = trunc %Int ${n} to %Byte ret %Byte %z"
691
- chez "${n}"
718
+ chez "(logand ${n} 255)"
692
719
 
693
720
  extern def toInt(n: Byte) at {}: Int =
694
721
  js "${n}"