@effekt-lang/effekt 0.2.1 → 0.3.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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +36 -0
  3. package/bin/effekt +0 -0
  4. package/bin/effekt.sh +2 -0
  5. package/libraries/chez/THIRD-PARTY.txt +11 -0
  6. package/libraries/chez/callcc/datatype.ss +188 -0
  7. package/libraries/chez/callcc/effekt.ss +31 -0
  8. package/libraries/chez/callcc/seq.ss +44 -0
  9. package/libraries/chez/callcc/seq0.ss +69 -0
  10. package/libraries/chez/callcc/tail.ss +76 -0
  11. package/libraries/chez/callcc/tail0.ss +89 -0
  12. package/libraries/chez/common/effekt_primitives.ss +105 -0
  13. package/libraries/chez/common/immutable/cslist.effekt +37 -0
  14. package/libraries/chez/common/mutable/dict.effekt +28 -0
  15. package/libraries/chez/common/text/pregexp.scm +772 -0
  16. package/libraries/chez/common/text/regex.effekt +31 -0
  17. package/libraries/chez/lift/effekt.ss +118 -0
  18. package/libraries/chez/monadic/effekt.ss +84 -0
  19. package/libraries/chez/monadic/seq0.ss +76 -0
  20. package/libraries/common/args.effekt +95 -0
  21. package/libraries/common/array.effekt +225 -0
  22. package/libraries/common/bench.effekt +60 -0
  23. package/libraries/common/buffer.effekt +123 -0
  24. package/libraries/common/bytes.effekt +125 -0
  25. package/libraries/common/dequeue.effekt +92 -0
  26. package/libraries/common/effekt.effekt +764 -0
  27. package/libraries/common/exception.effekt +122 -0
  28. package/libraries/common/io/console.effekt +66 -0
  29. package/libraries/common/io/error.effekt +365 -0
  30. package/libraries/common/io/files.effekt +282 -0
  31. package/libraries/common/io/network.effekt +105 -0
  32. package/libraries/common/io/time.effekt +15 -0
  33. package/libraries/common/io.effekt +158 -0
  34. package/libraries/common/list.effekt +687 -0
  35. package/libraries/common/option.effekt +72 -0
  36. package/libraries/common/process.effekt +10 -0
  37. package/libraries/common/queue.effekt +140 -0
  38. package/libraries/common/ref.effekt +63 -0
  39. package/libraries/common/result.effekt +45 -0
  40. package/libraries/common/seq.effekt +914 -0
  41. package/libraries/common/string.effekt +395 -0
  42. package/libraries/common/test.effekt +98 -0
  43. package/libraries/js/effekt_builtins.js +57 -0
  44. package/libraries/js/effekt_runtime.js +385 -0
  45. package/libraries/js/io.js +143 -0
  46. package/libraries/js/mutable/map.effekt +31 -0
  47. package/libraries/js/text/regex.effekt +33 -0
  48. package/libraries/js/unsafe/cont.effekt +11 -0
  49. package/libraries/js/web/dom.effekt +45 -0
  50. package/libraries/llvm/array.c +53 -0
  51. package/libraries/llvm/buffer.c +286 -0
  52. package/libraries/llvm/forward-declare-c.ll +43 -0
  53. package/libraries/llvm/hole.c +11 -0
  54. package/libraries/llvm/io.c +566 -0
  55. package/libraries/llvm/io.ll +19 -0
  56. package/libraries/llvm/main.c +41 -0
  57. package/libraries/llvm/ref.c +45 -0
  58. package/libraries/llvm/rts.ll +761 -0
  59. package/libraries/llvm/sanity.c +16 -0
  60. package/libraries/llvm/types.c +43 -0
  61. package/libraries/ml/effekt.sml +65 -0
  62. package/libraries/ml/internal/mllist.effekt +9 -0
  63. package/libraries/ml/internal/mloption.effekt +18 -0
  64. package/libraries/ml/random.effekt +85 -0
  65. package/libraries/ml/text/regex.effekt +102 -0
  66. package/licenses/THIRD-PARTY.txt +21 -0
  67. package/licenses/apache-2.0 - license-2.0.txt +202 -0
  68. package/licenses/eclipse public license, version 2.0 - epl-2.0.html +61 -0
  69. package/licenses/kiama-license.txt +373 -0
  70. package/licenses/kiama-readme.txt +186 -0
  71. package/licenses/mit license - mit-license.html +1239 -0
  72. package/licenses/the apache software license, version 2.0 - license-2.0.txt +202 -0
  73. package/licenses/the bsd license - bsd-license.html +1237 -0
  74. package/licenses/the mit license - mit.html +1239 -0
  75. package/package.json +26 -18
@@ -0,0 +1,123 @@
1
+ module buffer
2
+
3
+ import array
4
+
5
+ // TODO (in Effekt compiler)
6
+ // - [ ] fix allocating into actually global region
7
+ // - [ ] fix exceptions on objects
8
+ // - [X] allow omitting braces after `at` for singleton regions
9
+
10
+ record BufferOverflow()
11
+
12
+ /**
13
+ * Fixed-size ring buffers (queues) where one can write
14
+ * elements to the head and read from the tail.
15
+ */
16
+ interface Buffer[T] {
17
+ /**
18
+ * The remaining capacity
19
+ */
20
+ def capacity(): Int
21
+
22
+ /**
23
+ * Is this buffer full?
24
+ */
25
+ def full?(): Bool
26
+
27
+ /**
28
+ * Is this buffer empty?
29
+ */
30
+ def empty?(): Bool
31
+
32
+ /**
33
+ * Read an element from the tail of the buffer
34
+ */
35
+ def read(): Option[T]
36
+
37
+ /**
38
+ * Write an element to the head of the buffer
39
+ */
40
+ def write(el: T): Unit / Exception[BufferOverflow]
41
+ }
42
+
43
+ def emptyBuffer[T](capacity: Int): Buffer[T] at {global} = {
44
+ if (capacity == 1) refBuffer()
45
+ else arrayBuffer(capacity)
46
+ }
47
+ def arrayBuffer[T](initialCapacity: Int): Buffer[T] at {global} = {
48
+ // TODO allocate buffer (and array) into a region r.
49
+ val contents = emptyArray[T](initialCapacity)
50
+ var head in global = 0
51
+ var tail in global = 0
52
+
53
+ def size(): Int =
54
+ if (tail >= head) { tail - head }
55
+ else { initialCapacity - head + tail }
56
+
57
+ def capacity(): Int = initialCapacity - size()
58
+
59
+ def buffer = new Buffer[T] {
60
+ def capacity() = capacity()
61
+ def full?() = capacity() <= 0
62
+ def empty?() = size() <= 0
63
+ def read() = {
64
+ if (buffer.empty?) None()
65
+ else {
66
+ val result: T = contents.remove(head).getOrElse { <> };
67
+ head = mod(head + 1, initialCapacity)
68
+ Some(result)
69
+ }
70
+ }
71
+ def write(el: T) = {
72
+ if (buffer.full?) <> // raise(BufferOverflow())
73
+
74
+ contents.put(tail, el)
75
+ tail = mod(tail + 1, initialCapacity)
76
+ }
77
+ }
78
+ buffer
79
+ }
80
+ def refBuffer[T](): Buffer[T] at {global} = {
81
+ var content: Option[T] in global = None()
82
+ new Buffer[T] {
83
+ def capacity() = if (content.isEmpty) 1 else 0
84
+ def full?() = content.isDefined
85
+ def empty?() = isEmpty(content)
86
+ def read() = {
87
+ val res = content
88
+ content = None()
89
+ res
90
+ }
91
+ def write(el: T) = content match {
92
+ case Some(v) =>
93
+ <> // do raise(BufferOverflow(), "Cannot read element from buffer")
94
+ case None() =>
95
+ content = Some(el)
96
+ }
97
+ }
98
+ }
99
+
100
+ namespace examples {
101
+ def main() = ignore[BufferOverflow] {
102
+ // Buffer with capacity 1
103
+ def b = emptyBuffer[Int](1);
104
+ println(b.capacity);
105
+ println(b.full?);
106
+
107
+ b.write(17);
108
+ println(b.read());
109
+
110
+ // buffer with capacity 3
111
+ def ringbuffer = emptyBuffer[Int](3);
112
+ ringbuffer.write(1);
113
+ ringbuffer.write(2);
114
+ println(ringbuffer.read());
115
+ ringbuffer.write(3);
116
+ println(ringbuffer.read());
117
+ println(ringbuffer.read());
118
+ ringbuffer.write(4);
119
+ ringbuffer.write(5);
120
+ println(ringbuffer.read());
121
+ println(ringbuffer.read());
122
+ }
123
+ }
@@ -0,0 +1,125 @@
1
+ module bytes
2
+
3
+ /**
4
+ * A memory managed, mutable, fixed-length buffer of bytes.
5
+ */
6
+ extern type Bytes
7
+ // = llvm "%Pos"
8
+ // = js "Uint8Array"
9
+
10
+ /**
11
+ * Allocates new bytes with the given `capacity`, setting its values to `0`.
12
+ */
13
+ extern io def bytes(capacity: Int): Bytes =
14
+ js "(new Uint8Array(${capacity}))"
15
+ llvm """
16
+ %buf = call %Pos @c_buffer_construct_uninitialized(i64 ${capacity})
17
+ ret %Pos %buf
18
+ """
19
+
20
+ def copy(b: Bytes): Bytes = {
21
+ val len = b.size
22
+ val clone = bytes(len)
23
+ copy(b, clone, 0, 0, len)
24
+ clone
25
+ }
26
+
27
+ extern io def copy(from: Bytes, to: Bytes, startFrom: Int, startTo: Int, length: Int): Unit =
28
+ js "bytes$copy(${from}, ${to}, ${startFrom}, ${startTo}, ${length})"
29
+ llvm """
30
+ call void @c_buffer_copy(%Pos ${from}, %Pos ${to}, i64 ${startFrom}, i64 ${startTo}, i64 ${length})
31
+ ; return Unit
32
+ ret %Pos zeroinitializer
33
+ """
34
+
35
+ extern pure def size(b: Bytes): Int =
36
+ js "${b}.length"
37
+ llvm """
38
+ %size = call i64 @c_buffer_length(%Pos ${b})
39
+ ret i64 %size
40
+ """
41
+
42
+ extern io def read(b: Bytes, index: Int): Byte =
43
+ js "(${b})[${index}]"
44
+ llvm """
45
+ %byte = call i8 @c_buffer_index(%Pos ${b}, i64 ${index})
46
+ ret i8 %byte
47
+ """
48
+
49
+ // TODO should return the number of bytes written.
50
+ extern io def write(b: Bytes, index: Int, value: Byte): Unit =
51
+ js "bytes$set(${b}, ${index}, ${value})"
52
+ llvm """
53
+ call void @c_buffer_set(%Pos ${b}, i64 ${index}, i8 ${value})
54
+ ; return Unit
55
+ ret %Pos zeroinitializer
56
+ """
57
+
58
+ /**
59
+ * Returns an *aliased* slice of b starting at offset with the given length
60
+ */
61
+ def slice(b: Bytes, offset: Int, length: Int): Bytes = {
62
+ def validOffset() = offset >= 0 && offset < b.size
63
+ def validLength() = length >= 0 && (offset + length) <= b.size
64
+ if (validOffset() && validLength()) unsafe::slice(b, offset, length)
65
+ else panic("Invalid slice of bytes (size: " ++ b.size.show ++ ", offset: " ++ offset.show ++ ", length: " ++ length.show ++ ")")
66
+ }
67
+
68
+
69
+ /**
70
+ * Returns a view into the buffer, with the length truncated to n
71
+ */
72
+ def truncated(b: Bytes, n: Int): Bytes =
73
+ b.slice(0, n)
74
+
75
+ extern pure def fromUTF8(s: String): Bytes =
76
+ js "(new TextEncoder().encode(${s}))"
77
+ llvm """
78
+ %copy = call %Pos @c_buffer_clone(%Pos ${s})
79
+ ret %Pos %copy
80
+ """
81
+
82
+ extern pure def toUTF8(b: Bytes): String =
83
+ js "(new TextDecoder('utf-8').decode(${b}))"
84
+ // assuming the buffer is already in UTF-8
85
+ llvm """
86
+ %copy = call %Pos @c_buffer_clone(%Pos ${b})
87
+ ret %Pos %copy
88
+ """
89
+
90
+ namespace unsafe {
91
+ /**
92
+ * Unsafe: offset and length are not checked.
93
+ */
94
+ extern io def slice(b: Bytes, offset: Int, length: Int): Bytes =
95
+ js "new Uint8Array(${b}.buffer, ${offset}, ${length})"
96
+ llvm """
97
+ %buf = call %Pos @c_buffer_slice(%Pos ${b}, i64 ${offset}, i64 ${length})
98
+ ret %Pos %buf
99
+ """
100
+
101
+ }
102
+
103
+
104
+ extern js """
105
+ function bytes$set(bytes, index, value) {
106
+ bytes[index] = value;
107
+ return $effekt.unit;
108
+ }
109
+
110
+ function bytes$clone(original) {
111
+ let copy = new Uint8Array(original.length);
112
+ copy.set(original);
113
+ return copy;
114
+ }
115
+
116
+ function bytes$copy(from, to, startFrom, startTo, length) {
117
+ // Check bounds
118
+ if (startFrom + length > from.length || startTo + length > to.length) {
119
+ throw new RangeError('Index out of bounds');
120
+ }
121
+
122
+ // Create a subarray of 'from' and set it into 'to'
123
+ to.set(from.subarray(startFrom, startFrom + length), startTo);
124
+ }
125
+ """
@@ -0,0 +1,92 @@
1
+ module dequeue
2
+
3
+
4
+ // An implementation of a functional dequeue, using Okasaki's
5
+ // bankers dequeue implementation.
6
+ //
7
+ // Translation from the Haskell implementation:
8
+ // https://hackage.haskell.org/package/dequeue-0.1.12/docs/src/Data-Dequeue.html#Dequeue
9
+ record Dequeue[R](front: List[R], frontSize: Int, rear: List[R], rearSize: Int)
10
+
11
+ def emptyQueue[R](): Dequeue[R] = Dequeue(Nil(), 0, Nil(), 0)
12
+
13
+ def isEmpty[R](dq: Dequeue[R]): Bool = dq match {
14
+ case Dequeue(f, fs, r, rs) => (fs == 0) && (rs == 0)
15
+ }
16
+
17
+ def size[R](dq: Dequeue[R]): Int = dq match {
18
+ case Dequeue(f, fs, r, rs) => fs + rs
19
+ }
20
+
21
+ def first[R](dq: Dequeue[R]): Option[R] = dq match {
22
+ case Dequeue(f, fs, r, rs) =>
23
+ if ((fs == 0) && (rs == 1)) { r.headOption }
24
+ else { f.headOption }
25
+ }
26
+
27
+ def last[R](dq: Dequeue[R]): Option[R] = dq match {
28
+ case Dequeue(f, fs, r, rs) =>
29
+ if ((fs == 1) && (rs == 0)) { f.headOption }
30
+ else { r.headOption }
31
+ }
32
+
33
+ def check[R](dq: Dequeue[R]): Dequeue[R] = dq match {
34
+ case Dequeue(f, fs, r, rs) =>
35
+ val c = 4;
36
+ val size1 = (fs + rs) / 2;
37
+ val size2 = (fs + rs) - size1;
38
+
39
+ if (fs > c * rs + 1) {
40
+ val front = f.take(size1);
41
+ val rear = r.append(f.drop(size1).reverse);
42
+ Dequeue(front, size1, rear, size2)
43
+ } else if (rs > c * fs + 1) {
44
+ val front = f.append(r.drop(size1).reverse);
45
+ val rear = r.take(size1);
46
+ Dequeue(front, size2, rear, size1)
47
+ } else {
48
+ dq
49
+ }
50
+ }
51
+
52
+ def pushFront[R](dq: Dequeue[R], el: R): Dequeue[R] = dq match {
53
+ case Dequeue(f, fs, r, rs) => Dequeue(Cons(el, f), fs + 1, r, rs).check
54
+ }
55
+
56
+ def popFront[R](dq: Dequeue[R]): Option[(R, Dequeue[R])] = dq match {
57
+ case Dequeue(Nil(), fs, Cons(x, Nil()), rs) =>
58
+ Some((x, emptyQueue()))
59
+ case Dequeue(Nil(), fs, r, rs) =>
60
+ None()
61
+ case Dequeue(Cons(x, rest), fs, r, rs) =>
62
+ Some((x, Dequeue(rest, fs - 1, r, rs).check))
63
+ }
64
+
65
+ def pushBack[R](dq: Dequeue[R], el: R): Dequeue[R] = dq match {
66
+ case Dequeue(f, fs, r, rs) => Dequeue(f, fs, Cons(el, r), rs + 1).check
67
+ }
68
+
69
+ def popBack[R](dq: Dequeue[R]): Option[(R, Dequeue[R])] = dq match {
70
+ case Dequeue(Cons(x, Nil()), fs, Nil(), rs) =>
71
+ Some((x, emptyQueue()))
72
+ case Dequeue(f, fs, Nil(), rs) =>
73
+ None()
74
+ case Dequeue(f, fs, Cons(x, rest), rs) =>
75
+ Some((x, Dequeue(f, fs, rest, rs - 1).check))
76
+ }
77
+
78
+
79
+ def show[A](d: Dequeue[A]) { showA: A => String }: String = {
80
+ val Dequeue(front, frontSize, rear, rearSize) = d;
81
+ "Dequeue(" ++ show(front){showA} ++ ", " ++ show(frontSize) ++ ", " ++
82
+ show(rear){showA} ++ ", " ++ show(rearSize) ++ ")"
83
+ }
84
+ def show(l: Dequeue[Int]): String = show(l) { e => show(e) }
85
+ def show(l: Dequeue[Double]): String = show(l) { e => show(e) }
86
+ def show(l: Dequeue[Bool]): String = show(l) { e => show(e) }
87
+ def show(l: Dequeue[String]): String = show(l) { e => e }
88
+
89
+ def println(l: Dequeue[Int]): Unit = println(show(l))
90
+ def println(l: Dequeue[Double]): Unit = println(show(l))
91
+ def println(l: Dequeue[Bool]): Unit = println(show(l))
92
+ def println(l: Dequeue[String]): Unit = println(show(l))