@effekt-lang/effekt 0.61.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 +0 -0
- package/libraries/common/array.effekt +40 -40
- package/libraries/common/bytearray.effekt +39 -0
- package/libraries/common/bytestream.effekt +337 -0
- package/libraries/common/effekt.effekt +33 -5
- package/libraries/common/io/env.effekt +74 -0
- package/libraries/common/io/network.effekt +101 -12
- package/libraries/common/json.effekt +7 -7
- package/libraries/common/list.effekt +5 -0
- package/libraries/common/map.effekt +4 -0
- package/libraries/common/partial.effekt +7 -0
- package/libraries/common/resizable_array.effekt +99 -38
- package/libraries/common/scanner.effekt +27 -30
- package/libraries/common/set.effekt +4 -0
- package/libraries/common/stream.effekt +46 -2
- package/libraries/common/stringbuffer.effekt +30 -32
- package/libraries/common/test.effekt +10 -0
- package/libraries/llvm/io.c +39 -0
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +10 -6
- package/licenses/mit license - mit-license.html +46 -37
- package/licenses/the bsd license - bsd-license.html +45 -37
- package/licenses/the mit license - mit.html +46 -37
- package/package.json +1 -1
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
212
|
-
|
|
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
|
-
|
|
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)
|
|
592
|
-
|
|
593
|
-
|
|
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:
|
|
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}"
|
|
@@ -790,9 +817,9 @@ def locally[R] { p: => R } : R = p()
|
|
|
790
817
|
//
|
|
791
818
|
// "foo ${42} bar ${43}"
|
|
792
819
|
//
|
|
793
|
-
// to the following stream of `
|
|
820
|
+
// to the following stream of `write`s and `splice[Int]`s:
|
|
794
821
|
//
|
|
795
|
-
// do
|
|
822
|
+
// do write("foo "); do splice(42); do write(" bar "); do splice(43)
|
|
796
823
|
//
|
|
797
824
|
// The stream is wrapped into a handler function, which defaults to `stringbuffer::s`
|
|
798
825
|
//
|
|
@@ -800,7 +827,8 @@ def locally[R] { p: => R } : R = p()
|
|
|
800
827
|
//
|
|
801
828
|
// but can be specified by prefixing the string interpolation `custom"..."`.
|
|
802
829
|
|
|
803
|
-
effect
|
|
830
|
+
effect write(s: String): Unit
|
|
831
|
+
|
|
804
832
|
effect splice[A](x: A): Unit
|
|
805
833
|
|
|
806
834
|
|