@effekt-lang/effekt 0.5.0 → 0.7.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/bytearray.effekt +71 -0
- package/libraries/common/effekt.effekt +8 -8
- package/libraries/common/io/console.effekt +1 -2
- package/libraries/common/io/filesystem.effekt +46 -62
- package/libraries/common/io/network.effekt +9 -9
- package/libraries/common/io/time.effekt +1 -1
- package/libraries/common/io.effekt +5 -5
- package/libraries/common/ref.effekt +1 -1
- package/libraries/common/string.effekt +3 -14
- package/libraries/js/effekt_builtins.js +5 -1
- package/libraries/js/effekt_runtime.js +185 -352
- package/libraries/llvm/bytearray.c +209 -0
- package/libraries/llvm/forward-declare-c.ll +23 -23
- package/libraries/llvm/io.c +13 -15
- package/libraries/llvm/main.c +3 -3
- package/libraries/llvm/rts.ll +267 -159
- package/libraries/llvm/types.c +3 -2
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +2 -2
- package/package.json +1 -1
- package/libraries/common/bytes.effekt +0 -115
- package/libraries/js/unsafe/cont.effekt +0 -11
- package/libraries/llvm/buffer.c +0 -286
- package/licenses/mit license - mit-license.html +0 -1240
- package/licenses/the bsd license - bsd-license.html +0 -1236
- package/licenses/the mit license - mit.html +0 -1240
|
@@ -1,385 +1,218 @@
|
|
|
1
|
-
const $runtime = (function() {
|
|
2
1
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
|
2
|
+
// Common Runtime
|
|
3
|
+
// --------------
|
|
4
|
+
function Cell(init, region) {
|
|
5
|
+
const cell = {
|
|
6
|
+
value: init,
|
|
7
|
+
backup: function() {
|
|
8
|
+
const _backup = cell.value;
|
|
9
|
+
// restore function (has a STRONG reference to `this`)
|
|
10
|
+
return () => { cell.value = _backup; return cell }
|
|
121
11
|
}
|
|
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
12
|
}
|
|
13
|
+
return cell;
|
|
14
|
+
}
|
|
132
15
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
16
|
+
const global = {
|
|
17
|
+
fresh: Cell
|
|
18
|
+
}
|
|
136
19
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
20
|
+
function Arena(_region) {
|
|
21
|
+
const region = _region;
|
|
22
|
+
return {
|
|
23
|
+
fresh: function(init) {
|
|
24
|
+
const cell = Cell(init);
|
|
25
|
+
// region keeps track what to backup, but we do not need to backup unreachable cells
|
|
26
|
+
region.push(new WeakRef(cell))
|
|
27
|
+
return cell;
|
|
28
|
+
},
|
|
29
|
+
region: _region,
|
|
30
|
+
newRegion: function() {
|
|
31
|
+
// a region aggregates weak references
|
|
32
|
+
const nested = Arena([])
|
|
33
|
+
// this doesn't work yet, since Arena.backup doesn't return a thunk
|
|
34
|
+
region.push(new WeakRef(nested))
|
|
35
|
+
return nested;
|
|
36
|
+
},
|
|
37
|
+
backup: function() {
|
|
38
|
+
const _backup = []
|
|
39
|
+
let nextIndex = 0;
|
|
40
|
+
for (const ref of region) {
|
|
41
|
+
// console.log(ref)
|
|
42
|
+
const cell = ref.deref()
|
|
43
|
+
// only backup live cells
|
|
44
|
+
if (cell) {
|
|
45
|
+
_backup[nextIndex] = cell.backup()
|
|
46
|
+
nextIndex++
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function restore() {
|
|
50
|
+
const region = []
|
|
51
|
+
let nextIndex = 0;
|
|
52
|
+
for (const restoreCell of _backup) {
|
|
53
|
+
region[nextIndex] = new WeakRef(restoreCell())
|
|
54
|
+
nextIndex++
|
|
55
|
+
}
|
|
56
|
+
return Arena(region)
|
|
155
57
|
}
|
|
58
|
+
return restore;
|
|
156
59
|
}
|
|
157
|
-
throw ("Prompt " + p + " not found")
|
|
158
60
|
}
|
|
61
|
+
}
|
|
159
62
|
|
|
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
63
|
|
|
167
|
-
|
|
168
|
-
return Control(k => {
|
|
169
|
-
return Step(prog(k.arena), k)
|
|
170
|
-
})
|
|
171
|
-
}
|
|
64
|
+
let _prompt = 1;
|
|
172
65
|
|
|
173
|
-
|
|
174
|
-
|
|
66
|
+
const TOPLEVEL_K = (x, ks) => { throw { computationIsDone: true, result: x } }
|
|
67
|
+
const TOPLEVEL_KS = { prompt: 0, arena: Arena([]), rest: null }
|
|
175
68
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
allocateInto(k, prompt, cell);
|
|
181
|
-
return Step(f(cell), k)
|
|
182
|
-
})
|
|
183
|
-
}
|
|
184
|
-
}
|
|
69
|
+
function THUNK(f) {
|
|
70
|
+
f.thunk = true
|
|
71
|
+
return f
|
|
72
|
+
}
|
|
185
73
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
then: f => Control(k => Step(self, flatMap(k, f))),
|
|
192
|
-
state: f => self.then(init => withState(init, f))
|
|
193
|
-
}
|
|
194
|
-
return self
|
|
74
|
+
function CAPTURE(body) {
|
|
75
|
+
return (ks, k) => {
|
|
76
|
+
const res = body(x => TRAMPOLINE(() => k(x, ks)))
|
|
77
|
+
if (res instanceof Function) return res
|
|
78
|
+
else throw { computationIsDone: true, result: $effekt.unit }
|
|
195
79
|
}
|
|
80
|
+
}
|
|
196
81
|
|
|
197
|
-
|
|
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
|
-
})
|
|
82
|
+
const RETURN = (x, ks) => ks.rest.stack(x, ks.rest)
|
|
211
83
|
|
|
212
|
-
|
|
84
|
+
// const r = ks.arena.newRegion(); body
|
|
85
|
+
// const x = r.alloc(init); body
|
|
213
86
|
|
|
87
|
+
// HANDLE(ks, ks, (p, ks, k) => { STMT })
|
|
88
|
+
function RESET(prog, ks, k) {
|
|
89
|
+
const prompt = _prompt++;
|
|
90
|
+
const rest = { stack: k, prompt: ks.prompt, arena: ks.arena, rest: ks.rest }
|
|
91
|
+
return prog(prompt, { prompt, arena: Arena([]), rest }, RETURN)
|
|
92
|
+
}
|
|
214
93
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
k({
|
|
220
|
-
shouldRun: false,
|
|
221
|
-
cont : () => k({ shouldRun: true, cont: action })
|
|
222
|
-
})).then(a => a.shouldRun ? a.cont() : $effekt.pure(a.cont))
|
|
94
|
+
function DEALLOC(ks) {
|
|
95
|
+
const arena = ks.arena
|
|
96
|
+
if (!!arena) {
|
|
97
|
+
arena.length = arena.length - 1
|
|
223
98
|
}
|
|
99
|
+
}
|
|
224
100
|
|
|
225
|
-
|
|
101
|
+
function SHIFT(p, body, ks, k) {
|
|
226
102
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// Direct Style Runtime
|
|
233
|
-
// --------------------
|
|
103
|
+
// TODO avoid constructing this object
|
|
104
|
+
let meta = { stack: k, prompt: ks.prompt, arena: ks.arena, rest: ks.rest }
|
|
105
|
+
let cont = null
|
|
234
106
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
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
|
-
}
|
|
107
|
+
while (!!meta && meta.prompt !== p) {
|
|
108
|
+
cont = { stack: meta.stack, prompt: meta.prompt, backup: meta.arena.backup(), rest: cont }
|
|
109
|
+
meta = meta.rest
|
|
246
110
|
}
|
|
247
|
-
|
|
111
|
+
if (!meta) { throw `Prompt not found ${p}` }
|
|
248
112
|
|
|
249
|
-
//
|
|
250
|
-
|
|
251
|
-
|
|
113
|
+
// package the prompt itself
|
|
114
|
+
cont = { stack: meta.stack, prompt: meta.prompt, backup: meta.arena.backup(), rest: cont }
|
|
115
|
+
meta = meta.rest
|
|
252
116
|
|
|
253
|
-
|
|
254
|
-
|
|
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
|
-
}
|
|
117
|
+
function resumeValue(a, ks, k) {
|
|
118
|
+
return resumeComp((ks, k) => k(a, ks), ks, k)
|
|
260
119
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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
|
-
}
|
|
120
|
+
function resumeComp(c, ks, k) {
|
|
121
|
+
//console.log("Resuming", ks.arena)
|
|
122
|
+
let meta = { stack: k, prompt: ks.prompt, arena: ks.arena, rest: ks.rest }
|
|
123
|
+
let toRewind = cont
|
|
124
|
+
while (!!toRewind) {
|
|
125
|
+
meta = { stack: toRewind.stack, prompt: toRewind.prompt, arena: toRewind.backup(), rest: meta }
|
|
126
|
+
toRewind = toRewind.rest
|
|
287
127
|
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
128
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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
|
-
}
|
|
129
|
+
const k2 = meta.stack // TODO instead copy meta here, like elsewhere?
|
|
130
|
+
meta.stack = null
|
|
131
|
+
return () => c(meta, k2)
|
|
304
132
|
}
|
|
305
133
|
|
|
306
|
-
|
|
307
|
-
|
|
134
|
+
let k1 = meta.stack
|
|
135
|
+
meta.stack = null
|
|
136
|
+
return body(resumeValue, resumeComp, meta, k1)
|
|
137
|
+
}
|
|
308
138
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
function leaveRegion() {
|
|
319
|
-
const leftRegion = currentRegion
|
|
320
|
-
currentRegion = regions.pop()
|
|
321
|
-
return leftRegion
|
|
139
|
+
function RUN_TOPLEVEL(comp) {
|
|
140
|
+
try {
|
|
141
|
+
let a = comp(TOPLEVEL_KS, TOPLEVEL_K)
|
|
142
|
+
while (true) { a = a() }
|
|
143
|
+
} catch (e) {
|
|
144
|
+
if (e.computationIsDone) return e.result
|
|
145
|
+
else throw e
|
|
322
146
|
}
|
|
147
|
+
}
|
|
323
148
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
149
|
+
// trampolines the given computation (like RUN_TOPLEVEL, but doesn't provide continuations)
|
|
150
|
+
function TRAMPOLINE(comp) {
|
|
151
|
+
let a = comp;
|
|
152
|
+
try {
|
|
153
|
+
while (true) {
|
|
154
|
+
a = a()
|
|
155
|
+
}
|
|
156
|
+
} catch (e) {
|
|
157
|
+
if (e.computationIsDone) return e.result
|
|
158
|
+
else throw e
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// keeps the current trampoline going and dispatches the given task
|
|
163
|
+
function RUN(task) {
|
|
164
|
+
return () => task(TOPLEVEL_KS, TOPLEVEL_K)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// aborts the current continuation
|
|
168
|
+
function ABORT(value) {
|
|
169
|
+
throw { computationIsDone: true, result: value }
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
// "Public API" used in FFI
|
|
174
|
+
// ------------------------
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Captures the current continuation as a WHOLE and makes it available
|
|
178
|
+
* as argument to the passed body. For example:
|
|
179
|
+
*
|
|
180
|
+
* $effekt.capture(k => ... k(42) ...)
|
|
181
|
+
*
|
|
182
|
+
* The body
|
|
183
|
+
*
|
|
184
|
+
* $effekt.capture(k => >>> ... <<<)
|
|
185
|
+
*
|
|
186
|
+
* conceptually runs on the _native_ JS call stack. You can call JS functions,
|
|
187
|
+
* like `setTimeout` etc., but you are not expected or required to return an
|
|
188
|
+
* Effekt value like `$effekt.unit`. If you want to run an Effekt computation
|
|
189
|
+
* like in `io::spawn`, you can use `$effekt.run`.
|
|
190
|
+
*
|
|
191
|
+
* Advanced usage details:
|
|
192
|
+
*
|
|
193
|
+
* The value returned by the function passed to `capture` returns
|
|
194
|
+
* - a function: the returned function will be passed to the
|
|
195
|
+
* Effekt runtime, which performs trampolining.
|
|
196
|
+
* In this case, the Effekt runtime will keep running, though the
|
|
197
|
+
* continuation has been removed.
|
|
198
|
+
*
|
|
199
|
+
* - another value (like `undefined`): the Effekt runtime will terminate.
|
|
200
|
+
*/
|
|
201
|
+
$effekt.capture = CAPTURE
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Used to call Effekt function arguments in the JS FFI, like in `io::spawn`.
|
|
205
|
+
*
|
|
206
|
+
* Requires an active Effekt runtime (trampoline).
|
|
207
|
+
*/
|
|
208
|
+
$effekt.run = RUN
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Used to call Effekt function arguments in the JS FFI, like in `network::listen`.
|
|
212
|
+
*
|
|
213
|
+
* This function should be used when _no_ Effekt runtime is available. For instance,
|
|
214
|
+
* in callbacks passed to the NodeJS eventloop.
|
|
215
|
+
*
|
|
216
|
+
* If a runtime is available, use `$effekt.run`, instead.
|
|
217
|
+
*/
|
|
218
|
+
$effekt.runToplevel = RUN_TOPLEVEL
|