@effekt-lang/effekt 0.2.1 → 0.2.2

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 (91) 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.effekt +221 -0
  8. package/libraries/chez/callcc/effekt.ss +31 -0
  9. package/libraries/chez/callcc/seq.ss +44 -0
  10. package/libraries/chez/callcc/seq0.ss +69 -0
  11. package/libraries/chez/callcc/tail.ss +76 -0
  12. package/libraries/chez/callcc/tail0.ss +89 -0
  13. package/libraries/chez/common/effekt_matching.ss +100 -0
  14. package/libraries/chez/common/effekt_primitives.ss +97 -0
  15. package/libraries/chez/common/immutable/cslist.effekt +31 -0
  16. package/libraries/chez/common/immutable/dequeue.effekt +78 -0
  17. package/libraries/chez/common/immutable/list.effekt +643 -0
  18. package/libraries/chez/common/immutable/option.effekt +39 -0
  19. package/libraries/chez/common/immutable/result.effekt +29 -0
  20. package/libraries/chez/common/io/args.effekt +20 -0
  21. package/libraries/chez/common/mutable/array.effekt +27 -0
  22. package/libraries/chez/common/mutable/dict.effekt +30 -0
  23. package/libraries/chez/common/mutable/heap.effekt +12 -0
  24. package/libraries/chez/common/test.effekt +59 -0
  25. package/libraries/chez/common/text/pregexp.scm +772 -0
  26. package/libraries/chez/common/text/regex.effekt +33 -0
  27. package/libraries/chez/common/text/string.effekt +46 -0
  28. package/libraries/chez/lift/effekt.effekt +217 -0
  29. package/libraries/chez/lift/effekt.ss +118 -0
  30. package/libraries/chez/monadic/effekt.effekt +218 -0
  31. package/libraries/chez/monadic/effekt.ss +84 -0
  32. package/libraries/chez/monadic/seq0.ss +76 -0
  33. package/libraries/js/effekt.effekt +284 -0
  34. package/libraries/js/effekt_builtins.js +26 -0
  35. package/libraries/js/effekt_matching.js +79 -0
  36. package/libraries/js/effekt_runtime.js +385 -0
  37. package/libraries/js/immutable/dequeue.effekt +78 -0
  38. package/libraries/js/immutable/list.effekt +643 -0
  39. package/libraries/js/immutable/option.effekt +49 -0
  40. package/libraries/js/immutable/result.effekt +29 -0
  41. package/libraries/js/io/args.effekt +9 -0
  42. package/libraries/js/io/async.effekt +28 -0
  43. package/libraries/js/io/async.js +2 -0
  44. package/libraries/js/io/file.effekt +50 -0
  45. package/libraries/js/io/file_include.js +13 -0
  46. package/libraries/js/mutable/array.effekt +98 -0
  47. package/libraries/js/mutable/heap.effekt +32 -0
  48. package/libraries/js/mutable/map.effekt +32 -0
  49. package/libraries/js/test.effekt +59 -0
  50. package/libraries/js/text/regex.effekt +34 -0
  51. package/libraries/js/text/string.effekt +64 -0
  52. package/libraries/js/unsafe/cont.effekt +11 -0
  53. package/libraries/js/web/dom.effekt +45 -0
  54. package/libraries/llvm/buffer.c +181 -0
  55. package/libraries/llvm/effekt.effekt +243 -0
  56. package/libraries/llvm/forward-declare-c.ll +24 -0
  57. package/libraries/llvm/hole.c +11 -0
  58. package/libraries/llvm/immutable/list.effekt +678 -0
  59. package/libraries/llvm/immutable/option.effekt +53 -0
  60. package/libraries/llvm/immutable/result.effekt +29 -0
  61. package/libraries/llvm/io/args.effekt +24 -0
  62. package/libraries/llvm/io.c +24 -0
  63. package/libraries/llvm/main.c +39 -0
  64. package/libraries/llvm/rts.ll +619 -0
  65. package/libraries/llvm/sanity.c +16 -0
  66. package/libraries/llvm/text/string.effekt +179 -0
  67. package/libraries/llvm/types.c +20 -0
  68. package/libraries/ml/effekt.effekt +267 -0
  69. package/libraries/ml/effekt.sml +63 -0
  70. package/libraries/ml/immutable/dequeue.effekt +81 -0
  71. package/libraries/ml/immutable/list.effekt +674 -0
  72. package/libraries/ml/immutable/option.effekt +53 -0
  73. package/libraries/ml/immutable/result.effekt +29 -0
  74. package/libraries/ml/immutable/seq.effekt +903 -0
  75. package/libraries/ml/internal/option.effekt +18 -0
  76. package/libraries/ml/io/args.effekt +41 -0
  77. package/libraries/ml/mutable/array.effekt +43 -0
  78. package/libraries/ml/random.effekt +85 -0
  79. package/libraries/ml/test.effekt +60 -0
  80. package/libraries/ml/text/regex.effekt +107 -0
  81. package/libraries/ml/text/string.effekt +81 -0
  82. package/licenses/THIRD-PARTY.txt +21 -0
  83. package/licenses/apache-2.0 - license-2.0.txt +202 -0
  84. package/licenses/eclipse public license, version 2.0 - epl-2.0.html +61 -0
  85. package/licenses/kiama-license.txt +373 -0
  86. package/licenses/kiama-readme.txt +186 -0
  87. package/licenses/mit license - mit-license.html +769 -0
  88. package/licenses/the apache software license, version 2.0 - license-2.0.txt +202 -0
  89. package/licenses/the bsd license - bsd-license.html +762 -0
  90. package/licenses/the mit license - mit.html +769 -0
  91. package/package.json +26 -18
@@ -0,0 +1,385 @@
1
+ const $runtime = (function() {
2
+
3
+ // Common Runtime
4
+ // --------------
5
+
6
+ // Regions
7
+ // TODO maybe use weak refs (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef)
8
+ function Cell(init) {
9
+ var _value = init;
10
+ const cell = ({
11
+ backup: function() {
12
+ var _backup = _value
13
+ var cell = this;
14
+ return () => { _value = _backup; return cell }
15
+ }
16
+ });
17
+ // $getOp and $putOp are auto generated from the compiler
18
+ cell[$getOp] = function() {
19
+ return _value
20
+ };
21
+ cell[$putOp] = function(v) {
22
+ _value = v;
23
+ return $effekt.unit;
24
+ };
25
+ return cell
26
+ }
27
+
28
+ function Arena() {
29
+ return {
30
+ fields: [], // Array[Cell],
31
+ fresh: function(init) {
32
+ const cell = Cell(init)
33
+ this.fields.push(cell)
34
+ return cell;
35
+ },
36
+ backup: function() {
37
+ return this.fields.map(c => c.backup())
38
+ },
39
+ restore: function(backup) {
40
+ this.fields = backup.map(c => c());
41
+ return this
42
+ }
43
+ }
44
+ }
45
+
46
+ const global = {
47
+ fresh: function(init) { return Cell(init) },
48
+ backup: function() {},
49
+ restore: function(_) {}
50
+ }
51
+
52
+ // Lists / Pairs
53
+ function Cons(head, tail) {
54
+ return { head: head, tail: tail }
55
+ }
56
+ const Nil = null
57
+
58
+ // reverseOnto[A, B, C](init: Frames[A, B], tail: Stack[B, C]): Stack[A, C]
59
+ function reverseOnto(init, tail) {
60
+ let rest = init;
61
+ let result = tail;
62
+ while (rest !== Nil) {
63
+ result = Cons(rest.head, result)
64
+ rest = rest.tail
65
+ }
66
+ return result
67
+ }
68
+
69
+ let _prompt = 2;
70
+
71
+ // Monadic Style Runtime
72
+ // ---------------------
73
+
74
+ const toplevel = 1;
75
+
76
+ // Result -- Trampoline
77
+ function Step(c, k) {
78
+ return { isStep: true, c: c, k: k }
79
+ }
80
+ function trampoline(r) {
81
+ var res = r
82
+ while (res !== null && res !== undefined && res.isStep) {
83
+ res = res.c.apply(res.k)
84
+ }
85
+ return res
86
+ }
87
+
88
+ // Frame = A => Control[B]
89
+
90
+ // Metacontinuations / Stacks
91
+ // (frames: List<Frame>, fields: [Cell], prompt: Int, tail: Stack) -> Stack
92
+ function Stack(frames, arena, prompt, tail) {
93
+ return { frames: frames, arena: arena, prompt: prompt, tail: tail }
94
+ }
95
+ function SubStack(frames, arena, backup, prompt, tail) {
96
+ return { frames: frames, arena: arena, backup: backup, prompt: prompt, tail: tail }
97
+ }
98
+ const EmptyStack = null;
99
+
100
+ // (stack: Stack<A, B>, a: A) -> Step<B>
101
+ function apply(stack, a) {
102
+ var s = stack;
103
+ while (true) {
104
+ if (s === EmptyStack) return a;
105
+ const fs = s.frames;
106
+ if (fs === Nil) { s = s.tail; continue }
107
+ const result = fs.head(a);
108
+ s.frames = fs.tail;
109
+ return Step(result, s)
110
+ }
111
+ }
112
+
113
+ // (subcont: Stack, stack: Stack) -> Stack
114
+ function pushSubcont(subcont, stack) {
115
+ var sub = subcont;
116
+ var s = stack;
117
+
118
+ while (sub !== EmptyStack) {
119
+ s = Stack(sub.frames, sub.arena.restore(sub.backup), sub.prompt, s)
120
+ sub = sub.tail
121
+ }
122
+ return s;
123
+ }
124
+
125
+ function flatMap(stack, f) {
126
+ if (stack === EmptyStack) { return Stack(Cons(f, Nil), Arena(), null, stack) }
127
+ var fs = stack.frames
128
+ // it should be safe to mutate the frames field, since they are copied in the subcont
129
+ stack.frames = Cons(f, fs)
130
+ return stack
131
+ }
132
+
133
+ function splitAt(stack, p) {
134
+ var sub = EmptyStack;
135
+ var s = stack;
136
+
137
+ while (s !== EmptyStack) {
138
+ const currentPrompt = s.prompt;
139
+ sub = SubStack(s.frames, s.arena, s.arena.backup(), currentPrompt, sub);
140
+ s = s.tail;
141
+ if (currentPrompt === p) { return Cons(sub, s) }
142
+ }
143
+ throw ("Prompt " + p + " not found")
144
+ }
145
+
146
+ function allocateInto(stack, p, cell) {
147
+ var s = stack;
148
+
149
+ while (s !== EmptyStack) {
150
+ const currentPrompt = s.prompt
151
+ if (currentPrompt === p) {
152
+ return s.fields.push(cell);
153
+ } else {
154
+ s = s.tail
155
+ }
156
+ }
157
+ throw ("Prompt " + p + " not found")
158
+ }
159
+
160
+ function withState(init, f) {
161
+ return Control(k => {
162
+ const cell = k.arena.fresh(init)
163
+ return Step(f(cell), k)
164
+ })
165
+ }
166
+
167
+ function withRegion(prog) {
168
+ return Control(k => {
169
+ return Step(prog(k.arena), k)
170
+ })
171
+ }
172
+
173
+ function withStateIn(prompt, init, f) {
174
+ const cell = Cell(init)
175
+
176
+ if (prompt === toplevel) {
177
+ return f(cell)
178
+ } else {
179
+ return Control(k => {
180
+ allocateInto(k, prompt, cell);
181
+ return Step(f(cell), k)
182
+ })
183
+ }
184
+ }
185
+
186
+ // Delimited Control
187
+ function Control(apply) {
188
+ const self = {
189
+ apply: apply,
190
+ run: () => trampoline(Step(self, Stack(Nil, global, toplevel, EmptyStack))),
191
+ then: f => Control(k => Step(self, flatMap(k, f))),
192
+ state: f => self.then(init => withState(init, f))
193
+ }
194
+ return self
195
+ }
196
+
197
+ const pure = a => Control(k => apply(k, a))
198
+
199
+ const delayed = a => Control(k => apply(k, a()))
200
+
201
+ const shift = (p, f) => Control(k => {
202
+ const split = splitAt(k, p)
203
+ const localCont = a => Control(k =>
204
+ Step(pure(a), pushSubcont(split.head, k)))
205
+ return Step(f(localCont), split.tail)
206
+ })
207
+
208
+ const callcc = f => Control(k => {
209
+ return f(a => trampoline(apply(k, a)))
210
+ })
211
+
212
+ const abort = Control(k => $effekt.unit)
213
+
214
+
215
+ const capture = f => {
216
+ // [abort; f
217
+ const action = () => f($effekt.unit).then(() => abort)
218
+ return shift(toplevel)(k =>
219
+ k({
220
+ shouldRun: false,
221
+ cont : () => k({ shouldRun: true, cont: action })
222
+ })).then(a => a.shouldRun ? a.cont() : $effekt.pure(a.cont))
223
+ }
224
+
225
+ //const reset = (p, c => Control(k => Step(c, Stack(Nil, Arena(), p, k)))
226
+
227
+ function handleMonadic(body) {
228
+ const p = _prompt++;
229
+ return Control(k => Step(body(p), Stack(Nil, Arena(), p, k)))
230
+ }
231
+
232
+ // Direct Style Runtime
233
+ // --------------------
234
+
235
+ // sealed trait Resumption[A, R]
236
+ // case class Empty[A]() extends Resumption[A, A]
237
+ // case class Segment[A, B, C](head: Stack[B, C], prompt: Prompt, tail: Resumption[A, B]) extends Resumption[A, C]
238
+ class Segment {
239
+ constructor(frames, prompt, region, backup, tail) {
240
+ this.frames = frames;
241
+ this.prompt = prompt;
242
+ this.region = region;
243
+ this.backup = backup;
244
+ this.tail = tail;
245
+ }
246
+ }
247
+ const Empty = null;
248
+
249
+ // TODO maybe inline later to save native frames
250
+ function handleOrRethrow(prompt, s, rest) {
251
+ if (!(s instanceof Suspension)) throw s;
252
+
253
+ const region = currentRegion
254
+ const k = new Segment(reverseOnto(s.frames, rest), prompt, region, region.backup(), s.cont)
255
+ if (s.prompt === prompt) {
256
+ return s.body((value) => rewind(k, () => value))
257
+ } else {
258
+ throw new Suspension(s.prompt, s.body, Nil, k)
259
+ }
260
+ }
261
+
262
+ function rewind(k, thunk) {
263
+ if (k === Empty) {
264
+ return thunk()
265
+ } else {
266
+ const prompt = k.prompt;
267
+ const region = k.region;
268
+ let rest = k.frames // the pure frames
269
+
270
+ // The trampoline
271
+ try {
272
+ enterRegion(region);
273
+ region.restore(k.backup);
274
+
275
+ let curr = rewind(k.tail, thunk)
276
+ while (rest !== Nil) {
277
+ const f = rest.head
278
+ rest = rest.tail
279
+ curr = f(curr)
280
+ }
281
+ return curr
282
+ } catch (s) {
283
+ return handleOrRethrow(prompt, s, rest)
284
+ } finally {
285
+ leaveRegion()
286
+ }
287
+ }
288
+ }
289
+
290
+
291
+ // case class Suspend[A, X, Y, R](
292
+ // body: Continuation[A, R] => R,
293
+ // prompt: Prompt,
294
+ // pure: Frames[X, Y],
295
+ // cont: Resumption[A, X]
296
+ // )
297
+ class Suspension {
298
+ constructor(p, body, frames, cont) {
299
+ this.prompt = p;
300
+ this.body = body;
301
+ this.frames = frames;
302
+ this.cont = cont;
303
+ }
304
+ }
305
+
306
+ // initially the toplevel region.
307
+ let currentRegion = global
308
+
309
+ // a stack of regions
310
+ let regions = []
311
+
312
+ function enterRegion(r) {
313
+ regions.push(currentRegion)
314
+ currentRegion = r
315
+ return r
316
+ }
317
+
318
+ function leaveRegion() {
319
+ const leftRegion = currentRegion
320
+ currentRegion = regions.pop()
321
+ return leftRegion
322
+ }
323
+
324
+ return {
325
+ // Common API
326
+ // -----------
327
+ constructor: (_, tag) => function() {
328
+ return { __tag: tag, __data: Array.from(arguments) }
329
+ },
330
+
331
+ hole: function() { throw "Implementation missing" },
332
+
333
+ // Monadic API
334
+ // -----------
335
+ pure: pure,
336
+ callcc: callcc,
337
+ capture: capture,
338
+ delayed: delayed,
339
+ handleMonadic: handleMonadic,
340
+ ref: Cell,
341
+ state: withState,
342
+ shift: shift,
343
+ _if: (c, thn, els) => c ? thn() : els(),
344
+ withRegion: withRegion,
345
+
346
+
347
+ // Direct style API
348
+ // ----------------
349
+ fresh: function(init) {
350
+ return currentRegion.fresh(init)
351
+ },
352
+
353
+ freshPrompt: function() { return ++_prompt; },
354
+
355
+ suspend: function(prompt, body) {
356
+ _stacksize = 0;
357
+ throw new Suspension(prompt, body, Nil, Empty)
358
+ },
359
+ suspend_bidirectional: function(prompt, caps, body) {
360
+ throw new Suspension(prompt, body, Cons(thunk => thunk.apply(null, caps), Nil), Empty)
361
+ },
362
+
363
+ // suspension: the raised exception.
364
+ push: function(suspension, frame) {
365
+ if (!(suspension instanceof Suspension)) throw suspension;
366
+ // Assuming `suspension` is a value or variable you want to return
367
+ throw new Suspension(suspension.prompt, suspension.body,
368
+ Cons(frame, suspension.frames), suspension.cont);
369
+ },
370
+
371
+ handle: function(prompt, s) {
372
+ return handleOrRethrow(prompt, s, Nil)
373
+ },
374
+
375
+ freshRegion: function() {
376
+ return enterRegion(new Arena)
377
+ },
378
+
379
+ leaveRegion: leaveRegion,
380
+
381
+ global: global
382
+ }
383
+ })()
384
+
385
+ Object.assign($effekt, $runtime);
@@ -0,0 +1,78 @@
1
+ module immutable/dequeue
2
+
3
+ import immutable/list
4
+ import immutable/option
5
+
6
+ // An implementation of a functional dequeue, using Okasaki's
7
+ // bankers dequeue implementation.
8
+ //
9
+ // Translation from the Haskell implementation:
10
+ // https://hackage.haskell.org/package/dequeue-0.1.12/docs/src/Data-Dequeue.html#Dequeue
11
+ record Dequeue[R](front: List[R], frontSize: Int, rear: List[R], rearSize: Int)
12
+
13
+ def emptyQueue[R](): Dequeue[R] = Dequeue(Nil(), 0, Nil(), 0)
14
+
15
+ def isEmpty[R](dq: Dequeue[R]): Boolean = dq match {
16
+ case Dequeue(f, fs, r, rs) => (fs == 0) && (rs == 0)
17
+ }
18
+
19
+ def size[R](dq: Dequeue[R]): Int = dq match {
20
+ case Dequeue(f, fs, r, rs) => fs + rs
21
+ }
22
+
23
+ def first[R](dq: Dequeue[R]): Option[R] = dq match {
24
+ case Dequeue(f, fs, r, rs) =>
25
+ if ((fs == 0) && (rs == 1)) { r.headOption }
26
+ else { f.headOption }
27
+ }
28
+
29
+ def last[R](dq: Dequeue[R]): Option[R] = dq match {
30
+ case Dequeue(f, fs, r, rs) =>
31
+ if ((fs == 1) && (rs == 0)) { f.headOption }
32
+ else { r.headOption }
33
+ }
34
+
35
+ def check[R](dq: Dequeue[R]): Dequeue[R] = dq match {
36
+ case Dequeue(f, fs, r, rs) =>
37
+ val c = 4;
38
+ val size1 = (fs + rs) / 2;
39
+ val size2 = (fs + rs) - size1;
40
+
41
+ if (fs > c * rs + 1) {
42
+ val front = f.take(size1);
43
+ val rear = r.append(f.drop(size1).reverse);
44
+ Dequeue(front, size1, rear, size2)
45
+ } else if (rs > c * fs + 1) {
46
+ val front = f.append(r.drop(size1).reverse);
47
+ val rear = r.take(size1);
48
+ Dequeue(front, size2, rear, size1)
49
+ } else {
50
+ dq
51
+ }
52
+ }
53
+
54
+ def pushFront[R](dq: Dequeue[R], el: R): Dequeue[R] = dq match {
55
+ case Dequeue(f, fs, r, rs) => Dequeue(Cons(el, f), fs + 1, r, rs).check
56
+ }
57
+
58
+ def popFront[R](dq: Dequeue[R]): Option[(R, Dequeue[R])] = dq match {
59
+ case Dequeue(Nil(), fs, Cons(x, Nil()), rs) =>
60
+ Some((x, emptyQueue()))
61
+ case Dequeue(Nil(), fs, r, rs) =>
62
+ None()
63
+ case Dequeue(Cons(x, rest), fs, r, rs) =>
64
+ Some((x, Dequeue(rest, fs - 1, r, rs).check))
65
+ }
66
+
67
+ def pushBack[R](dq: Dequeue[R], el: R): Dequeue[R] = dq match {
68
+ case Dequeue(f, fs, r, rs) => Dequeue(f, fs, Cons(el, r), rs + 1).check
69
+ }
70
+
71
+ def popBack[R](dq: Dequeue[R]): Option[(R, Dequeue[R])] = dq match {
72
+ case Dequeue(Cons(x, Nil()), fs, Nil(), rs) =>
73
+ Some((x, emptyQueue()))
74
+ case Dequeue(f, fs, Nil(), rs) =>
75
+ None()
76
+ case Dequeue(f, fs, Cons(x, rest), rs) =>
77
+ Some((x, Dequeue(f, fs, rest, rs - 1).check))
78
+ }