@effekt-lang/effekt 0.2.2 → 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 (96) hide show
  1. package/bin/effekt +0 -0
  2. package/bin/effekt.sh +1 -1
  3. package/libraries/chez/common/effekt_primitives.ss +10 -2
  4. package/libraries/chez/common/immutable/cslist.effekt +13 -7
  5. package/libraries/chez/common/mutable/dict.effekt +8 -10
  6. package/libraries/chez/common/text/regex.effekt +7 -9
  7. package/libraries/common/args.effekt +95 -0
  8. package/libraries/common/array.effekt +225 -0
  9. package/libraries/common/bench.effekt +60 -0
  10. package/libraries/common/buffer.effekt +123 -0
  11. package/libraries/common/bytes.effekt +125 -0
  12. package/libraries/{chez/common/immutable → common}/dequeue.effekt +18 -4
  13. package/libraries/common/effekt.effekt +764 -0
  14. package/libraries/common/exception.effekt +122 -0
  15. package/libraries/common/io/console.effekt +66 -0
  16. package/libraries/common/io/error.effekt +365 -0
  17. package/libraries/common/io/files.effekt +282 -0
  18. package/libraries/common/io/network.effekt +105 -0
  19. package/libraries/common/io/time.effekt +15 -0
  20. package/libraries/common/io.effekt +158 -0
  21. package/libraries/{llvm/immutable → common}/list.effekt +83 -74
  22. package/libraries/common/option.effekt +72 -0
  23. package/libraries/common/process.effekt +10 -0
  24. package/libraries/common/queue.effekt +140 -0
  25. package/libraries/common/ref.effekt +63 -0
  26. package/libraries/common/result.effekt +45 -0
  27. package/libraries/{ml/immutable → common}/seq.effekt +30 -19
  28. package/libraries/common/string.effekt +395 -0
  29. package/libraries/common/test.effekt +98 -0
  30. package/libraries/js/effekt_builtins.js +37 -6
  31. package/libraries/js/io.js +143 -0
  32. package/libraries/js/mutable/map.effekt +8 -9
  33. package/libraries/js/text/regex.effekt +7 -8
  34. package/libraries/js/unsafe/cont.effekt +2 -2
  35. package/libraries/js/web/dom.effekt +13 -13
  36. package/libraries/llvm/array.c +53 -0
  37. package/libraries/llvm/buffer.c +181 -76
  38. package/libraries/llvm/forward-declare-c.ll +27 -8
  39. package/libraries/llvm/io.c +543 -1
  40. package/libraries/llvm/io.ll +19 -0
  41. package/libraries/llvm/main.c +3 -1
  42. package/libraries/llvm/ref.c +45 -0
  43. package/libraries/llvm/rts.ll +496 -354
  44. package/libraries/llvm/types.c +23 -0
  45. package/libraries/ml/effekt.sml +2 -0
  46. package/libraries/ml/internal/mllist.effekt +9 -0
  47. package/libraries/ml/internal/mloption.effekt +18 -0
  48. package/libraries/ml/random.effekt +9 -9
  49. package/libraries/ml/text/regex.effekt +14 -19
  50. package/licenses/eclipse public license, version 2.0 - epl-2.0.html +2 -2
  51. package/licenses/mit license - mit-license.html +527 -57
  52. package/licenses/the bsd license - bsd-license.html +530 -55
  53. package/licenses/the mit license - mit.html +528 -58
  54. package/package.json +2 -2
  55. package/libraries/chez/callcc/effekt.effekt +0 -221
  56. package/libraries/chez/common/effekt_matching.ss +0 -100
  57. package/libraries/chez/common/immutable/list.effekt +0 -643
  58. package/libraries/chez/common/immutable/option.effekt +0 -39
  59. package/libraries/chez/common/immutable/result.effekt +0 -29
  60. package/libraries/chez/common/io/args.effekt +0 -20
  61. package/libraries/chez/common/mutable/array.effekt +0 -27
  62. package/libraries/chez/common/mutable/heap.effekt +0 -12
  63. package/libraries/chez/common/test.effekt +0 -59
  64. package/libraries/chez/common/text/string.effekt +0 -46
  65. package/libraries/chez/lift/effekt.effekt +0 -217
  66. package/libraries/chez/monadic/effekt.effekt +0 -218
  67. package/libraries/js/effekt.effekt +0 -284
  68. package/libraries/js/effekt_matching.js +0 -79
  69. package/libraries/js/immutable/dequeue.effekt +0 -78
  70. package/libraries/js/immutable/list.effekt +0 -643
  71. package/libraries/js/immutable/option.effekt +0 -49
  72. package/libraries/js/immutable/result.effekt +0 -29
  73. package/libraries/js/io/args.effekt +0 -9
  74. package/libraries/js/io/async.effekt +0 -28
  75. package/libraries/js/io/async.js +0 -2
  76. package/libraries/js/io/file.effekt +0 -50
  77. package/libraries/js/io/file_include.js +0 -13
  78. package/libraries/js/mutable/array.effekt +0 -98
  79. package/libraries/js/mutable/heap.effekt +0 -32
  80. package/libraries/js/test.effekt +0 -59
  81. package/libraries/js/text/string.effekt +0 -64
  82. package/libraries/llvm/effekt.effekt +0 -243
  83. package/libraries/llvm/immutable/option.effekt +0 -53
  84. package/libraries/llvm/immutable/result.effekt +0 -29
  85. package/libraries/llvm/io/args.effekt +0 -24
  86. package/libraries/llvm/text/string.effekt +0 -179
  87. package/libraries/ml/effekt.effekt +0 -267
  88. package/libraries/ml/immutable/dequeue.effekt +0 -81
  89. package/libraries/ml/immutable/list.effekt +0 -674
  90. package/libraries/ml/immutable/option.effekt +0 -53
  91. package/libraries/ml/immutable/result.effekt +0 -29
  92. package/libraries/ml/internal/option.effekt +0 -18
  93. package/libraries/ml/io/args.effekt +0 -41
  94. package/libraries/ml/mutable/array.effekt +0 -43
  95. package/libraries/ml/test.effekt +0 -60
  96. package/libraries/ml/text/string.effekt +0 -81
@@ -0,0 +1,143 @@
1
+
2
+ /**
3
+ * Maps the error code to a Effekt-stable (platform independent) numeric value.
4
+ *
5
+ * Tries to use most common errno integer values, but introduces fresh values (> 200)
6
+ * for those without common errno values.
7
+ */
8
+ function errnoToStableId(errorName) {
9
+ const errorMap = {
10
+ EPERM: 1,
11
+ ENOENT: 2,
12
+ ESRCH: 3,
13
+ EINTR: 4,
14
+ EIO: 5,
15
+ ENXIO: 6,
16
+ E2BIG: 7,
17
+ EBADF: 9,
18
+ EAGAIN: 11,
19
+ ENOMEM: 12,
20
+ EACCES: 13,
21
+ EFAULT: 14,
22
+ EBUSY: 16,
23
+ EEXIST: 17,
24
+ EXDEV: 18,
25
+ ENODEV: 19,
26
+ ENOTDIR: 20,
27
+ EISDIR: 21,
28
+ EINVAL: 22,
29
+ ENFILE: 23,
30
+ EMFILE: 24,
31
+ ENOTTY: 25,
32
+ ETXTBSY: 26,
33
+ EFBIG: 27,
34
+ ENOSPC: 28,
35
+ ESPIPE: 29,
36
+ EROFS: 30,
37
+ EMLINK: 31,
38
+ EPIPE: 32,
39
+ ERANGE: 34,
40
+ ENAMETOOLONG: 36,
41
+ ELOOP: 40,
42
+ EOVERFLOW: 75,
43
+ EFTYPE: 79,
44
+ EILSEQ: 84,
45
+ ENOTSOCK: 88,
46
+ EDESTADDRREQ: 89,
47
+ EMSGSIZE: 90,
48
+ EPROTOTYPE: 91,
49
+ ENOPROTOOPT: 92,
50
+ EPROTONOSUPPORT: 93,
51
+ ESOCKTNOSUPPORT: 94,
52
+ ENOTSUP: 95,
53
+ EAFNOSUPPORT: 97,
54
+ EADDRINUSE: 98,
55
+ EADDRNOTAVAIL: 99,
56
+ ENETDOWN: 100,
57
+ ENETUNREACH: 101,
58
+ ECONNABORTED: 103,
59
+ ECONNRESET: 104,
60
+ ENOBUFS: 105,
61
+ EISCONN: 106,
62
+ ENOTCONN: 107,
63
+ ETIMEDOUT: 110,
64
+ ECONNREFUSED: 111,
65
+ EHOSTUNREACH: 113,
66
+ EALREADY: 114,
67
+ ECANCELED: 125,
68
+ EAI_ADDRFAMILY: 200,
69
+ EAI_AGAIN: 201,
70
+ EAI_BADFLAGS: 202,
71
+ EAI_BADHINTS: 203,
72
+ EAI_CANCELED: 204,
73
+ EAI_FAIL: 205,
74
+ EAI_FAMILY: 206,
75
+ EAI_MEMORY: 207,
76
+ EAI_NODATA: 208,
77
+ EAI_NONAME: 209,
78
+ EAI_OVERFLOW: 210,
79
+ EAI_PROTOCOL: 211,
80
+ EAI_SERVICE: 212,
81
+ EAI_SOCKTYPE: 213,
82
+ ECHARSET: 215,
83
+ ENONET: 216,
84
+ UNKNOWN: 217,
85
+ EOF: 218,
86
+ EUNATCH: 219,
87
+ ESHUTDOWN: 220
88
+ };
89
+
90
+ return errorMap[errorName] || -1; // Default to -1 for unknown error names
91
+ }
92
+
93
+ function openFile(path, mode, onSuccess, onFailure) {
94
+ fs.open(path, mode,
95
+ (err, fd) => {
96
+ if (!!err) {
97
+ console.error(err)
98
+ return onFailure(errnoToStableId(err.code)).run();
99
+ } else {
100
+ return onSuccess(fd).run();
101
+ }
102
+ });
103
+ return $effekt.unit;
104
+ }
105
+
106
+ function readFile(fd, buffer, offset, onSuccess, onFailure) {
107
+ let position = offset === -1 ? null : offset;
108
+ fs.read(fd, toBuffer(buffer), 0, buffer.length, position,
109
+ (err, bytesRead) => {
110
+ if (!!err) {
111
+ return onFailure(errnoToStableId(err.code)).run()
112
+ } else {
113
+ return onSuccess(bytesRead).run()
114
+ }
115
+ })
116
+ return $effekt.unit;
117
+ }
118
+
119
+ /**
120
+ * @see {https://nodejs.org/api/fs.html#fswritefd-buffer-offset-length-position-callback
121
+ */
122
+ function writeFile(fd, buffer, offset, onSuccess, onFailure) {
123
+ let position = offset === -1 ? null : offset;
124
+ fs.write(fd, toBuffer(buffer), 0, buffer.length, position,
125
+ (err, bytesWritten) => {
126
+ if (!!err) {
127
+ return onFailure(errnoToStableId(err.code)).run()
128
+ } else {
129
+ return onSuccess(bytesWritten).run()
130
+ }
131
+ })
132
+ return $effekt.unit;
133
+ }
134
+
135
+
136
+
137
+ /**
138
+ * Nodejs file operations expect buffers, but we represent buffers as typed arrays.
139
+ * This function converts between the two without copying.
140
+ */
141
+ function toBuffer(buffer) {
142
+ return Buffer.from(buffer.buffer, buffer.byteOffset, buffer.byteLength)
143
+ }
@@ -1,21 +1,20 @@
1
1
  module mutable/map
2
2
 
3
- import mutable/array
4
- import immutable/option
3
+ import array
5
4
 
6
5
  // A mutable map, backed by a JavaScript Map.
7
6
  extern type Map[K, V]
8
7
 
9
8
  extern pure def emptyMap[K, V](): Map[K, V] =
10
- "new Map()"
9
+ js "new Map()"
11
10
 
12
11
  def get[K, V](m: Map[K, V], key: K): Option[V] =
13
- m.unsafeGet(key).undefinedToOption
12
+ undefinedToOption(m.unsafeGet(key))
14
13
 
15
14
  extern pure def unsafeGet[K, V](m: Map[K, V], key: K): V =
16
- "${m}.get(${key})"
15
+ js "${m}.get(${key})"
17
16
 
18
- extern """
17
+ extern js """
19
18
  function map$update(m, key, value) {
20
19
  m.set(key, value);
21
20
  return $effekt.unit
@@ -23,10 +22,10 @@ function map$update(m, key, value) {
23
22
  """
24
23
 
25
24
  extern io def update[K, V](m: Map[K, V], key: K, value: V): Unit =
26
- "map$update(${m}, ${key}, ${value})"
25
+ js "map$update(${m}, ${key}, ${value})"
27
26
 
28
27
  extern pure def values[K, V](map: Map[K, V]): Array[V] =
29
- "Array.from(${map}.values())"
28
+ js "Array.from(${map}.values())"
30
29
 
31
30
  extern pure def keys[K, V](map: Map[K, V]): Array[K] =
32
- "Array.from(${map}.keys())"
31
+ js "Array.from(${map}.keys())"
@@ -1,27 +1,26 @@
1
1
  module text/regex
2
2
 
3
- import text/string
4
- import immutable/option
3
+ import string
5
4
 
6
5
  extern type Regex
7
6
 
8
7
  record Match(matched: String, index: Int)
9
8
 
10
9
  extern pure def regex(str: String): Regex =
11
- "new RegExp(${str})"
10
+ js "new RegExp(${str})"
12
11
 
13
12
  def exec(reg: Regex, str: String): Option[Match] =
14
- reg.unsafeExec(str).undefinedToOption match {
13
+ undefinedToOption(reg.unsafeExec(str)) match {
15
14
  case None() => None()
16
15
  case Some(v) => Some(Match(v.matched, v.index))
17
16
  }
18
17
 
19
18
  // internal representation { matched: String, index: Int }
20
19
  extern type RegexMatch
21
- extern pure def matched(r: RegexMatch): String = "${r}.matched"
22
- extern pure def index(r: RegexMatch): Int = "${r}.index"
20
+ extern pure def matched(r: RegexMatch): String = js "${r}.matched"
21
+ extern pure def index(r: RegexMatch): Int = js "${r}.index"
23
22
 
24
- extern """
23
+ extern js """
25
24
  function regex$exec(reg, str) {
26
25
  var res = reg.exec(str);
27
26
  if (res === null) { return undefined }
@@ -31,4 +30,4 @@ function regex$exec(reg, str) {
31
30
 
32
31
  // internals
33
32
  extern io def unsafeExec(reg: Regex, str: String): RegexMatch =
34
- "regex$exec(${reg}, ${str})"
33
+ js "regex$exec(${reg}, ${str})"
@@ -4,8 +4,8 @@ module unsafe/cont
4
4
  extern type Cont[A, B]
5
5
 
6
6
  // we mark this as {io} since pure functions should not take block parameters.
7
- extern io def cont[A, B] { r: A => B / {} }: Cont[A, B] = "${box r}"
7
+ extern io def cont[A, B] { r: A => B / {} }: Cont[A, B] = js "${box r}"
8
8
 
9
9
  // This is unsafe if the continuation left the scope of the
10
10
  // capabilities it closed over
11
- extern control def apply[A, B](k: Cont[A, B], a: A): B / {} = "${k}(${a})"
11
+ extern control def apply[A, B](k: Cont[A, B], a: A): B / {} = js "${k}(${a})"
@@ -4,42 +4,42 @@ extern type Node
4
4
 
5
5
  // can be null
6
6
  extern pure def getElementById(id: String): Node =
7
- "document.getElementById(${id})"
7
+ js "document.getElementById(${id})"
8
8
 
9
9
  extern pure def createElement(tag: String): Node =
10
- "document.createElement(${tag})"
10
+ js "document.createElement(${tag})"
11
11
 
12
12
  extern pure def createTextNode(text: String): Node =
13
- "document.createTextNode(${text})"
13
+ js "document.createTextNode(${text})"
14
14
 
15
15
  extern pure def setAttribute(node: Node, key: String, value: String): Node =
16
- "${node}.setAttribute(${key}, ${value})"
16
+ js "${node}.setAttribute(${key}, ${value})"
17
17
 
18
18
  // the string return type is wrong here...
19
19
  extern pure def getAttribute(node: Node, key: String): String =
20
- "${node}.getAttribute(${key})"
20
+ js "${node}.getAttribute(${key})"
21
21
 
22
22
  extern pure def appendChild(node: Node, child: Node): Node =
23
- "${node}.appendChild(${child})"
23
+ js "${node}.appendChild(${child})"
24
24
 
25
25
  extern pure def innerHTML(node: Node, contents: String): Node =
26
- "(function() { ${node}.innerHTML = ${contents}; return ${node} })()"
26
+ js "(function() { ${node}.innerHTML = ${contents}; return ${node} })()"
27
27
 
28
28
  extern type IdleDeadline
29
29
 
30
30
  extern pure def requestIdleCallback(callback: (IdleDeadline) => Unit at {io}): Unit =
31
- "window.requestIdleCallback(deadline => ${callback}(deadline).run())"
31
+ js "window.requestIdleCallback(deadline => ${callback}(deadline).run())"
32
32
 
33
- extern pure def didDimeout(deadline: IdleDeadline): Boolean =
34
- "${deadline}.didTimeout"
33
+ extern pure def didDimeout(deadline: IdleDeadline): Bool =
34
+ js "${deadline}.didTimeout"
35
35
 
36
36
  extern pure def timeRemaining(deadline: IdleDeadline): Double =
37
- "${deadline}.timeRemaining()"
37
+ js "${deadline}.timeRemaining()"
38
38
 
39
39
  extern pure def onClick(node: Node, handler: () => Unit at {io}): Node =
40
- "(function() { ${node}.onclick = () => ${handler}().run(); return ${node} })()"
40
+ js "(function() { ${node}.onclick = () => ${handler}().run(); return ${node} })()"
41
41
 
42
42
  extern def sleep(n: Int): Unit =
43
- "$effekt.callcc(k => window.setTimeout(() => k(null), ${n}))"
43
+ js "$effekt.callcc(k => window.setTimeout(() => k(null), ${n}))"
44
44
 
45
45
  def clear(node: Node) = node.innerHTML("")
@@ -0,0 +1,53 @@
1
+ #ifndef EFFEKT_ARRAY_C
2
+ #define EFFEKT_ARRAY_C
3
+
4
+ /** We represent arrays like positive types.
5
+ * The tag is 0 and the obj points to memory with the following layout:
6
+ *
7
+ * +--[ Header ]--+------+------------+
8
+ * | Rc | Eraser | Size | Fields ... |
9
+ * +--------------+------+------------+
10
+ */
11
+
12
+ void c_array_erase_fields(void *envPtr) {
13
+ uint64_t *sizePtr = envPtr;
14
+ struct Pos *dataPtr = envPtr + sizeof(uint64_t);
15
+ uint64_t size = *sizePtr;
16
+ for (uint64_t i = 0; i < size; i++) {
17
+ erasePositive(dataPtr[i]);
18
+ }
19
+ }
20
+
21
+ struct Pos c_array_new(const Int size) {
22
+ void *objPtr = calloc(sizeof(struct Header) + sizeof(uint64_t) + size * sizeof(struct Pos), 1);
23
+ struct Header *headerPtr = objPtr;
24
+ uint64_t *sizePtr = objPtr + sizeof(struct Header);
25
+ *headerPtr = (struct Header) { .rc = 0, .eraser = c_array_erase_fields, };
26
+ *sizePtr = size;
27
+ return (struct Pos) {
28
+ .tag = 0,
29
+ .obj = objPtr,
30
+ };
31
+ }
32
+
33
+ Int c_array_size(const struct Pos arr) {
34
+ uint64_t *sizePtr = arr.obj + sizeof(struct Header);
35
+ return *sizePtr;
36
+ }
37
+
38
+ struct Pos c_array_get(const struct Pos arr, const Int index) {
39
+ struct Pos *dataPtr = arr.obj + sizeof(struct Header) + sizeof(uint64_t);
40
+ struct Pos element = dataPtr[index];
41
+ sharePositive(element);
42
+ return element;
43
+ }
44
+
45
+ struct Pos c_array_set(const struct Pos arr, const Int index, const struct Pos value) {
46
+ struct Pos *dataPtr = arr.obj + sizeof(struct Header) + sizeof(uint64_t);
47
+ struct Pos element = dataPtr[index];
48
+ erasePositive(element);
49
+ dataPtr[index] = value;
50
+ return Unit;
51
+ }
52
+
53
+ #endif