@effekt-lang/effekt 0.78.0 → 0.80.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 +1 -1
- package/libraries/common/bytearray.effekt +1 -1
- package/libraries/common/dictionary.effekt +243 -53
- package/libraries/common/effekt.effekt +1 -1
- package/libraries/common/io/filesystem.effekt +7 -7
- package/libraries/common/io/network.effekt +6 -6
- package/libraries/common/io/signal.effekt +10 -10
- package/libraries/common/io/time.effekt +1 -1
- package/libraries/common/io.effekt +4 -4
- package/libraries/common/map.effekt +194 -100
- package/libraries/common/process.effekt +6 -5
- package/libraries/common/random.effekt +14 -1
- package/libraries/common/set.effekt +9 -19
- package/libraries/common/sourcepos.effekt +75 -0
- package/libraries/common/test.effekt +57 -56
- package/libraries/js/effekt_runtime.js +19 -3
- package/libraries/llvm/bytearray.c +1 -1
- package/libraries/llvm/io.c +17 -17
- package/libraries/llvm/rts.ll +30 -29
- package/libraries/llvm/types.c +3 -3
- package/licenses/mit license - mit-license.html +28 -28
- package/licenses/the bsd license - bsd-license.html +27 -27
- package/licenses/the mit license - mit.html +27 -27
- package/package.json +1 -1
|
@@ -1,102 +1,103 @@
|
|
|
1
1
|
import tty
|
|
2
2
|
import process
|
|
3
3
|
import bench
|
|
4
|
+
import sourcepos
|
|
4
5
|
|
|
5
6
|
interface Assertion {
|
|
6
|
-
def assert(condition: Bool, msg: String): Unit
|
|
7
|
+
def assert(condition: Bool, msg: String, ?sourcePosition: SourcePosition): Unit
|
|
7
8
|
}
|
|
8
9
|
|
|
9
|
-
def assertTrue(condition: Bool, msg: String) =
|
|
10
|
-
do assert(condition, msg)
|
|
10
|
+
def assertTrue(condition: Bool, msg: String, ?sourcePosition: SourcePosition) =
|
|
11
|
+
do assert(condition, msg, sourcePosition)
|
|
11
12
|
|
|
12
|
-
def assertTrue(condition: Bool) =
|
|
13
|
-
do assert(condition, "Assertion failed")
|
|
13
|
+
def assertTrue(condition: Bool, ?sourcePosition: SourcePosition) =
|
|
14
|
+
do assert(condition, "Assertion failed", sourcePosition)
|
|
14
15
|
|
|
15
|
-
def assertFalse(condition: Bool, msg: String) =
|
|
16
|
-
do assert(not(condition), msg)
|
|
16
|
+
def assertFalse(condition: Bool, msg: String, ?sourcePosition: SourcePosition) =
|
|
17
|
+
do assert(not(condition), msg, sourcePosition)
|
|
17
18
|
|
|
18
|
-
def assertFalse(condition: Bool) =
|
|
19
|
-
do assert(not(condition), "Assertion failed")
|
|
19
|
+
def assertFalse(condition: Bool, ?sourcePosition: SourcePosition) =
|
|
20
|
+
do assert(not(condition), "Assertion failed", sourcePosition)
|
|
20
21
|
|
|
21
|
-
def assert(obtained: Int, expected: Int, msg: String): Unit / Assertion =
|
|
22
|
-
assertEqual(obtained, expected, msg) { (x, y) => x == y }
|
|
22
|
+
def assert(obtained: Int, expected: Int, msg: String, ?sourcePosition: SourcePosition): Unit / Assertion =
|
|
23
|
+
assertEqual(obtained, expected, msg, sourcePosition) { (x, y) => x == y }
|
|
23
24
|
|
|
24
|
-
def assert(obtained: Bool, expected: Bool, msg: String): Unit / Assertion =
|
|
25
|
-
assertEqual(obtained, expected, msg) { (x, y) => x == y }
|
|
25
|
+
def assert(obtained: Bool, expected: Bool, msg: String, ?sourcePosition: SourcePosition): Unit / Assertion =
|
|
26
|
+
assertEqual(obtained, expected, msg, sourcePosition) { (x, y) => x == y }
|
|
26
27
|
|
|
27
|
-
def assert(obtained: Char, expected: Char, msg: String): Unit / Assertion =
|
|
28
|
-
assertEqual(obtained, expected, msg) { (x, y) => x == y }
|
|
28
|
+
def assert(obtained: Char, expected: Char, msg: String, ?sourcePosition: SourcePosition): Unit / Assertion =
|
|
29
|
+
assertEqual(obtained, expected, msg, sourcePosition) { (x, y) => x == y }
|
|
29
30
|
|
|
30
|
-
def assert(obtained: String, expected: String, msg: String): Unit / Assertion =
|
|
31
|
-
assertEqual(obtained, expected, msg) { (x, y) => x == y }
|
|
31
|
+
def assert(obtained: String, expected: String, msg: String, ?sourcePosition: SourcePosition): Unit / Assertion =
|
|
32
|
+
assertEqual(obtained, expected, msg, sourcePosition) { (x, y) => x == y }
|
|
32
33
|
|
|
33
|
-
def assert(obtained: Int, expected: Int): Unit / { Assertion, Formatted } =
|
|
34
|
-
assertEqual(obtained, expected) { (x, y) => x == y } { x => show(x) }
|
|
34
|
+
def assert(obtained: Int, expected: Int, ?sourcePosition: SourcePosition): Unit / { Assertion, Formatted } =
|
|
35
|
+
assertEqual(obtained, expected, sourcePosition) { (x, y) => x == y } { x => show(x) }
|
|
35
36
|
|
|
36
|
-
def assert(obtained: Byte, expected: Byte): Unit / { Assertion, Formatted } =
|
|
37
|
-
assertEqual(obtained, expected) { (x, y) => x == y } { x => show(x) }
|
|
37
|
+
def assert(obtained: Byte, expected: Byte, ?sourcePosition: SourcePosition): Unit / { Assertion, Formatted } =
|
|
38
|
+
assertEqual(obtained, expected, sourcePosition) { (x, y) => x == y } { x => show(x) }
|
|
38
39
|
|
|
39
|
-
def assert(obtained: Bool, expected: Bool): Unit / { Assertion, Formatted } =
|
|
40
|
-
assertEqual(obtained, expected) { (x, y) => x == y } { x => show(x) }
|
|
40
|
+
def assert(obtained: Bool, expected: Bool, ?sourcePosition: SourcePosition): Unit / { Assertion, Formatted } =
|
|
41
|
+
assertEqual(obtained, expected, sourcePosition) { (x, y) => x == y } { x => show(x) }
|
|
41
42
|
|
|
42
|
-
def assert(obtained: Char, expected: Char): Unit / { Assertion, Formatted } =
|
|
43
|
-
assertEqual(obtained, expected) { (x, y) => x == y } { x => show(x) }
|
|
43
|
+
def assert(obtained: Char, expected: Char, ?sourcePosition: SourcePosition): Unit / { Assertion, Formatted } =
|
|
44
|
+
assertEqual(obtained, expected, sourcePosition) { (x, y) => x == y } { x => show(x) }
|
|
44
45
|
|
|
45
|
-
def assert(obtained: String, expected: String): Unit / { Assertion, Formatted } =
|
|
46
|
-
assertEqual(obtained, expected) { (x, y) => x == y } { x => show(x) }
|
|
46
|
+
def assert(obtained: String, expected: String, ?sourcePosition: SourcePosition): Unit / { Assertion, Formatted } =
|
|
47
|
+
assertEqual(obtained, expected, sourcePosition) { (x, y) => x == y } { x => show(x) }
|
|
47
48
|
|
|
48
|
-
def assertEqual[A](obtained: A, expected: A, msg: String): Unit / Assertion =
|
|
49
|
-
assertEqual(obtained, expected, msg) { (x, y) => x.genericEquals(y) }
|
|
49
|
+
def assertEqual[A](obtained: A, expected: A, msg: String, ?sourcePosition: SourcePosition): Unit / Assertion =
|
|
50
|
+
assertEqual(obtained, expected, msg, sourcePosition) { (x, y) => x.genericEquals(y) }
|
|
50
51
|
|
|
51
|
-
def assertEqual[A](obtained: A, expected: A): Unit / { Assertion, Formatted } =
|
|
52
|
-
assertEqual(obtained, expected) { (x, y) => x.genericEquals(y) } { x => x.genericShow }
|
|
52
|
+
def assertEqual[A](obtained: A, expected: A, ?sourcePosition: SourcePosition): Unit / { Assertion, Formatted } =
|
|
53
|
+
assertEqual(obtained, expected, sourcePosition) { (x, y) => x.genericEquals(y) } { x => x.genericShow }
|
|
53
54
|
|
|
54
|
-
def assertEqual[A](obtained: A, expected: A, msg: String) { equals: (A, A) => Bool }: Unit / Assertion =
|
|
55
|
-
do assert(equals(obtained, expected), msg)
|
|
55
|
+
def assertEqual[A](obtained: A, expected: A, msg: String, ?sourcePosition: SourcePosition) { equals: (A, A) => Bool }: Unit / Assertion =
|
|
56
|
+
do assert(equals(obtained, expected), msg, sourcePosition)
|
|
56
57
|
|
|
57
|
-
def assertEqual[A](obtained: A, expected: A) { equals: (A, A) => Bool } { show: A => String }: Unit / { Assertion, Formatted } =
|
|
58
|
-
do assert(equals(obtained, expected), Formatted::tryEmit(Escape::RESET) ++ "Expected: ".dim ++ show(expected).green ++ "\n Obtained: ".dim ++ show(obtained).red)
|
|
58
|
+
def assertEqual[A](obtained: A, expected: A, ?sourcePosition: SourcePosition) { equals: (A, A) => Bool } { show: A => String }: Unit / { Assertion, Formatted } =
|
|
59
|
+
do assert(equals(obtained, expected), Formatted::tryEmit(Escape::RESET) ++ "Expected: ".dim ++ show(expected).green ++ "\n Obtained: ".dim ++ show(obtained).red, sourcePosition)
|
|
59
60
|
// NOTE: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
60
61
|
// Here's an accidental capture! Can we prevent this somehow nicely?
|
|
61
62
|
|
|
62
|
-
def assertNotThrown[E](ex: on[E]) { body: => Unit / Exception[E] }: Unit / Assertion =
|
|
63
|
-
ex.default { do assert(false, "Unexpected Exception") } {body}
|
|
63
|
+
def assertNotThrown[E](ex: on[E], ?sourcePosition: SourcePosition) { body: => Unit / Exception[E] }: Unit / Assertion =
|
|
64
|
+
ex.default { do assert(false, "Unexpected Exception", sourcePosition) } {body}
|
|
64
65
|
|
|
65
|
-
def assertNoThrow[E] { body: => Unit / Exception[E] }: Unit / Assertion =
|
|
66
|
-
on[E].default{ do assert(false, "Unexpected Exception") } {body}
|
|
66
|
+
def assertNoThrow[E](?sourcePosition: SourcePosition) { body: => Unit / Exception[E] }: Unit / Assertion =
|
|
67
|
+
on[E].default{ do assert(false, "Unexpected Exception", sourcePosition) } {body}
|
|
67
68
|
|
|
68
|
-
def assertThrown[E](ex: on[E]) { body: => Unit / Exception[E] }: Unit / Assertion =
|
|
69
|
-
do assert(ex.default { true } { body(); false }, "Expected Exception, but exited normally")
|
|
69
|
+
def assertThrown[E](ex: on[E], ?sourcePosition: SourcePosition) { body: => Unit / Exception[E] }: Unit / Assertion =
|
|
70
|
+
do assert(ex.default { true } { body(); false }, "Expected Exception, but exited normally", sourcePosition)
|
|
70
71
|
|
|
71
|
-
def assertThrows[E] { body: => Unit / Exception[E] }: Unit / Assertion =
|
|
72
|
-
do assert(on[E].default { true } { body(); false }, "Expected Exception, but exited normally")
|
|
72
|
+
def assertThrows[E](?sourcePosition: SourcePosition) { body: => Unit / Exception[E] }: Unit / Assertion =
|
|
73
|
+
do assert(on[E].default { true } { body(); false }, "Expected Exception, but exited normally", sourcePosition)
|
|
73
74
|
|
|
74
|
-
def assertFail { body: => Unit / fail }: Unit / Assertion =
|
|
75
|
-
do assert(succeeds {body}, "Expected 'fail', but exited normally")
|
|
75
|
+
def assertFail(?sourcePosition: SourcePosition) { body: => Unit / fail }: Unit / Assertion =
|
|
76
|
+
do assert(succeeds {body}, "Expected 'fail', but exited normally", sourcePosition)
|
|
76
77
|
|
|
77
|
-
def assertNoFail { body: => Unit / fail }: Unit / Assertion =
|
|
78
|
-
onFail { do assert(false, "Unexpected 'fail'") } {body}
|
|
78
|
+
def assertNoFail(?sourcePosition: SourcePosition) { body: => Unit / fail }: Unit / Assertion =
|
|
79
|
+
onFail { do assert(false, "Unexpected 'fail'", sourcePosition) } {body}
|
|
79
80
|
|
|
80
81
|
|
|
81
82
|
interface Test {
|
|
82
|
-
def success(name: String, duration: Int): Unit
|
|
83
|
-
def failure(name: String, msg: String, duration: Int): Unit
|
|
83
|
+
def success(name: String, duration: Int, ?sourcePosition: SourcePosition): Unit
|
|
84
|
+
def failure(name: String, msg: String, duration: Int, ?sourcePosition: SourcePosition): Unit
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
/// Runs the `body` as a test under the given `name`
|
|
87
88
|
/// See `suite` for examples.
|
|
88
|
-
def test(name: String) { body: => Unit / Assertion } = {
|
|
89
|
+
def test(name: String, ?sourcePosition: SourcePosition) { body: => Unit / Assertion } = {
|
|
89
90
|
val startTime = bench::relativeTimestamp()
|
|
90
91
|
try {
|
|
91
92
|
body()
|
|
92
93
|
val duration = Duration::diff(startTime, bench::relativeTimestamp())
|
|
93
|
-
do success(name, duration)
|
|
94
|
+
do success(name, duration, sourcePosition)
|
|
94
95
|
} with Assertion {
|
|
95
|
-
def assert(condition, msg) =
|
|
96
|
+
def assert(condition, msg, assertSourcePosition) =
|
|
96
97
|
if (condition) resume(())
|
|
97
98
|
else {
|
|
98
99
|
val duration = Duration::diff(startTime, bench::relativeTimestamp())
|
|
99
|
-
do failure(name, msg, duration)
|
|
100
|
+
do failure(name, msg, duration, assertSourcePosition)
|
|
100
101
|
}
|
|
101
102
|
}
|
|
102
103
|
}
|
|
@@ -138,17 +139,17 @@ def suite(name: String, printTimes: Bool) { body: => Unit / { Test, Formatted }
|
|
|
138
139
|
val totalDuration = timed {
|
|
139
140
|
try { body() } with Test {
|
|
140
141
|
// 2a) Handle a passing test on success
|
|
141
|
-
def success(name, duration) = {
|
|
142
|
+
def success(name, duration, sourcePosition) = {
|
|
142
143
|
passed = passed + 1
|
|
143
144
|
println("✓".green ++ " " ++ name ++ duration.ms)
|
|
144
145
|
resume(())
|
|
145
146
|
}
|
|
146
147
|
|
|
147
148
|
// 2b) Handle a failing test on failure, additionally printing its message
|
|
148
|
-
def failure(name, msg, duration) = {
|
|
149
|
+
def failure(name, msg, duration, sourcePosition) = {
|
|
149
150
|
failed = failed + 1
|
|
150
151
|
println("✕".red ++ " " ++ name ++ duration.ms)
|
|
151
|
-
println(" " ++ msg.red)
|
|
152
|
+
println(" " ++ msg.red ++ " at " ++ sourcePosition.toGccStyleString())
|
|
152
153
|
resume(())
|
|
153
154
|
}
|
|
154
155
|
}
|
|
@@ -58,6 +58,7 @@ class Arena {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
function snapshot(s) {
|
|
61
|
+
if (s === null) return null
|
|
61
62
|
const snap = { store: s, root: s.root, generation: s.generation }
|
|
62
63
|
s.generation = s.generation + 1
|
|
63
64
|
return snap
|
|
@@ -85,9 +86,13 @@ function reroot(target) {
|
|
|
85
86
|
node.value = Mem
|
|
86
87
|
cur = node
|
|
87
88
|
}
|
|
89
|
+
|
|
90
|
+
// 3. Reclaim the path to reuse the buffer eagerly
|
|
91
|
+
_rerootPath.length = 0
|
|
88
92
|
}
|
|
89
93
|
|
|
90
94
|
function restore(store, snap) {
|
|
95
|
+
if (snap === null) return // nothing saved ~> nothing to restore
|
|
91
96
|
if (snap.root.value !== Mem) {
|
|
92
97
|
// fast path: continuation is resumed immediately with no writes in between
|
|
93
98
|
reroot(snap.root)
|
|
@@ -99,7 +104,18 @@ function restore(store, snap) {
|
|
|
99
104
|
// Common Runtime
|
|
100
105
|
// --------------
|
|
101
106
|
const TOPLEVEL_K = (x, ks) => { throw { computationIsDone: true, result: x } }
|
|
102
|
-
const TOPLEVEL_KS = { stack: null, prompt: Symbol("toplevel"), arena:
|
|
107
|
+
const TOPLEVEL_KS = { stack: null, prompt: Symbol("toplevel"), arena: null, rest: null }
|
|
108
|
+
|
|
109
|
+
// The first variable in a scope creates its arena; until then `ks.arena` is null.
|
|
110
|
+
function VAR(init, ks) {
|
|
111
|
+
const arena = ks.arena !== null ? ks.arena : (ks.arena = new Arena())
|
|
112
|
+
return arena.fresh(init)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function REGION(ks) {
|
|
116
|
+
const arena = ks.arena !== null ? ks.arena : (ks.arena = new Arena())
|
|
117
|
+
return arena.newRegion()
|
|
118
|
+
}
|
|
103
119
|
|
|
104
120
|
function THUNK(f) {
|
|
105
121
|
f.thunk = true
|
|
@@ -109,7 +125,7 @@ function THUNK(f) {
|
|
|
109
125
|
function CAPTURE(body) {
|
|
110
126
|
return (ks, k) => {
|
|
111
127
|
const res = body(x => TRAMPOLINE(() => k(x, ks)))
|
|
112
|
-
if (res
|
|
128
|
+
if (typeof res === "function") return res
|
|
113
129
|
else throw { computationIsDone: true, result: $effekt.unit }
|
|
114
130
|
}
|
|
115
131
|
}
|
|
@@ -120,7 +136,7 @@ const RETURN = (x, ks) => ks.rest.stack(x, ks.rest)
|
|
|
120
136
|
function RESET(prog, ks, k) {
|
|
121
137
|
const prompt = Symbol(); // gensym
|
|
122
138
|
const rest = { stack: k, prompt: ks.prompt, arena: ks.arena, rest: ks.rest }
|
|
123
|
-
return prog(prompt, { stack: null, prompt, arena:
|
|
139
|
+
return prog(prompt, { stack: null, prompt, arena: null, rest }, RETURN)
|
|
124
140
|
}
|
|
125
141
|
|
|
126
142
|
function SHIFT(p, body, ks, k) {
|
|
@@ -77,7 +77,7 @@ struct Pos c_bytearray_construct(const uint64_t n, const uint8_t *data) {
|
|
|
77
77
|
|
|
78
78
|
struct Pos c_bytearray_from_nullterminated_string(const char *data) {
|
|
79
79
|
uint64_t n = 0;
|
|
80
|
-
while (data[
|
|
80
|
+
while (data[n]) n++;
|
|
81
81
|
|
|
82
82
|
return c_bytearray_construct(n, (uint8_t*)data);
|
|
83
83
|
}
|
package/libraries/llvm/io.c
CHANGED
|
@@ -383,18 +383,18 @@ Int c_tcp_bind(String host, Int port) {
|
|
|
383
383
|
|
|
384
384
|
typedef struct {
|
|
385
385
|
Stack stack;
|
|
386
|
-
struct
|
|
386
|
+
struct Neg handler;
|
|
387
387
|
} tcp_listen_closure_t;
|
|
388
388
|
|
|
389
389
|
void c_tcp_listen_cb(uv_stream_t* server, int status) {
|
|
390
390
|
tcp_listen_closure_t* listen_closure = (tcp_listen_closure_t*)server->data;
|
|
391
391
|
Stack closure_stack = listen_closure->stack;
|
|
392
|
-
struct
|
|
392
|
+
struct Neg closure_handler = listen_closure->handler;
|
|
393
393
|
|
|
394
394
|
if (status < 0) {
|
|
395
395
|
server->data = NULL;
|
|
396
396
|
free(listen_closure);
|
|
397
|
-
|
|
397
|
+
eraseNegative(closure_handler);
|
|
398
398
|
resume_Int(closure_stack, status);
|
|
399
399
|
return;
|
|
400
400
|
}
|
|
@@ -406,7 +406,7 @@ void c_tcp_listen_cb(uv_stream_t* server, int status) {
|
|
|
406
406
|
free(client);
|
|
407
407
|
server->data = NULL;
|
|
408
408
|
free(listen_closure);
|
|
409
|
-
|
|
409
|
+
eraseNegative(closure_handler);
|
|
410
410
|
resume_Int(closure_stack, result);
|
|
411
411
|
return;
|
|
412
412
|
}
|
|
@@ -416,16 +416,16 @@ void c_tcp_listen_cb(uv_stream_t* server, int status) {
|
|
|
416
416
|
uv_close((uv_handle_t*)client, (uv_close_cb)free);
|
|
417
417
|
server->data = NULL;
|
|
418
418
|
free(listen_closure);
|
|
419
|
-
|
|
419
|
+
eraseNegative(closure_handler);
|
|
420
420
|
resume_Int(closure_stack, result);
|
|
421
421
|
return;
|
|
422
422
|
}
|
|
423
423
|
|
|
424
|
-
|
|
424
|
+
shareNegative(closure_handler);
|
|
425
425
|
run_Int(closure_handler, (int64_t)client);
|
|
426
426
|
}
|
|
427
427
|
|
|
428
|
-
void c_tcp_listen(Int listener, struct
|
|
428
|
+
void c_tcp_listen(Int listener, struct Neg handler, Stack stack) {
|
|
429
429
|
uv_stream_t* server = (uv_stream_t*)listener;
|
|
430
430
|
|
|
431
431
|
tcp_listen_closure_t* listen_closure = malloc(sizeof(tcp_listen_closure_t));
|
|
@@ -436,7 +436,7 @@ void c_tcp_listen(Int listener, struct Pos handler, Stack stack) {
|
|
|
436
436
|
int result = uv_listen(server, SOMAXCONN, c_tcp_listen_cb);
|
|
437
437
|
if (result < 0) {
|
|
438
438
|
free(listen_closure);
|
|
439
|
-
|
|
439
|
+
eraseNegative(handler);
|
|
440
440
|
resume_Int(stack, result);
|
|
441
441
|
return;
|
|
442
442
|
}
|
|
@@ -451,9 +451,9 @@ void c_tcp_shutdown(Int handle, Stack stack) {
|
|
|
451
451
|
|
|
452
452
|
if (listen_closure) {
|
|
453
453
|
Stack closure_stack = listen_closure->stack;
|
|
454
|
-
struct
|
|
454
|
+
struct Neg closure_handler = listen_closure->handler;
|
|
455
455
|
free(listen_closure);
|
|
456
|
-
|
|
456
|
+
eraseNegative(closure_handler);
|
|
457
457
|
resume_Int(closure_stack, 0);
|
|
458
458
|
}
|
|
459
459
|
}
|
|
@@ -601,7 +601,7 @@ static void subproc_alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_
|
|
|
601
601
|
}
|
|
602
602
|
|
|
603
603
|
typedef struct {
|
|
604
|
-
struct
|
|
604
|
+
struct Neg handler;
|
|
605
605
|
} subproc_stream_cb_closure_t;
|
|
606
606
|
void subproc_stream_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {
|
|
607
607
|
subproc_stream_cb_closure_t* clos = (subproc_stream_cb_closure_t*)(stream->data);
|
|
@@ -611,12 +611,12 @@ void subproc_stream_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
|
|
|
611
611
|
run_Pos(clos->handler, chunk);
|
|
612
612
|
} else {
|
|
613
613
|
uv_read_stop(stream);
|
|
614
|
-
|
|
614
|
+
eraseNegative(clos->handler);
|
|
615
615
|
free(clos);
|
|
616
616
|
if (buf->base) free(buf->base);
|
|
617
617
|
}
|
|
618
618
|
}
|
|
619
|
-
struct Pos subproc_options_on_stream(struct Pos opts, size_t id, uv_stdio_flags flags, struct
|
|
619
|
+
struct Pos subproc_options_on_stream(struct Pos opts, size_t id, uv_stdio_flags flags, struct Neg callback) {
|
|
620
620
|
uv_process_options_t* options = (uv_process_options_t*)opts.obj;
|
|
621
621
|
|
|
622
622
|
options->stdio[id].flags = UV_CREATE_PIPE | flags;
|
|
@@ -631,13 +631,13 @@ struct Pos subproc_options_on_stream(struct Pos opts, size_t id, uv_stdio_flags
|
|
|
631
631
|
|
|
632
632
|
return opts;
|
|
633
633
|
}
|
|
634
|
-
struct Pos c_spawn_options_on_stdout(struct Pos opts, struct
|
|
634
|
+
struct Pos c_spawn_options_on_stdout(struct Pos opts, struct Neg callback) {
|
|
635
635
|
return subproc_options_on_stream(opts, 1, UV_WRITABLE_PIPE, callback);
|
|
636
636
|
}
|
|
637
|
-
struct Pos c_spawn_options_on_stderr(struct Pos opts, struct
|
|
637
|
+
struct Pos c_spawn_options_on_stderr(struct Pos opts, struct Neg callback) {
|
|
638
638
|
return subproc_options_on_stream(opts, 2, UV_WRITABLE_PIPE, callback);
|
|
639
639
|
}
|
|
640
|
-
struct Pos c_spawn_options_pipe_stdin(struct Pos opts, struct
|
|
640
|
+
struct Pos c_spawn_options_pipe_stdin(struct Pos opts, struct Neg callback) {
|
|
641
641
|
return subproc_options_on_stream(opts, 0, UV_READABLE_PIPE, callback);
|
|
642
642
|
}
|
|
643
643
|
|
|
@@ -754,7 +754,7 @@ void c_spawn(struct Pos cmd, struct Pos args, struct Pos options, Stack stack) {
|
|
|
754
754
|
subproc_stream_cb_closure_t* clos = (subproc_stream_cb_closure_t*)(stream->data);
|
|
755
755
|
struct Pos str = (struct Pos) { .tag = 0, .obj = stream, };
|
|
756
756
|
run_Pos(clos->handler, str);
|
|
757
|
-
|
|
757
|
+
eraseNegative(clos->handler);
|
|
758
758
|
free(clos);
|
|
759
759
|
}
|
|
760
760
|
if(opts->stdio[1].flags & UV_CREATE_PIPE)
|
package/libraries/llvm/rts.ll
CHANGED
|
@@ -91,9 +91,6 @@
|
|
|
91
91
|
%Double = type double
|
|
92
92
|
%Byte = type i8
|
|
93
93
|
%Char = type i64
|
|
94
|
-
%Bool = type %Pos
|
|
95
|
-
%Unit = type %Pos
|
|
96
|
-
%String = type %Pos
|
|
97
94
|
|
|
98
95
|
; Foreign imports
|
|
99
96
|
|
|
@@ -101,7 +98,7 @@ declare ptr @malloc(i64)
|
|
|
101
98
|
declare void @free(ptr)
|
|
102
99
|
declare ptr @realloc(ptr, i64)
|
|
103
100
|
declare noalias ptr @calloc(i64, i64)
|
|
104
|
-
declare
|
|
101
|
+
declare ptr @memcpy(ptr, ptr, i64)
|
|
105
102
|
declare i64 @llvm.ctlz.i64 (i64 , i1)
|
|
106
103
|
declare i64 @llvm.fshr.i64(i64, i64, i64)
|
|
107
104
|
declare double @llvm.sqrt.f64(double)
|
|
@@ -117,8 +114,7 @@ declare double @log1p(double)
|
|
|
117
114
|
; Intrinsic versions of the following two only added in LLVM 19
|
|
118
115
|
declare double @atan(double)
|
|
119
116
|
declare double @tan(double)
|
|
120
|
-
declare void @
|
|
121
|
-
declare void @exit(i64)
|
|
117
|
+
declare void @exit(i32)
|
|
122
118
|
declare void @llvm.assume(i1)
|
|
123
119
|
|
|
124
120
|
|
|
@@ -162,7 +158,7 @@ define private void @shareObject(%Object %object) alwaysinline {
|
|
|
162
158
|
|
|
163
159
|
next:
|
|
164
160
|
%objectReferenceCount = getelementptr %Header, ptr %object, i64 0, i32 0
|
|
165
|
-
%referenceCount = load %ReferenceCount, ptr %objectReferenceCount, !alias.scope !14, !noalias !24
|
|
161
|
+
%referenceCount = load %ReferenceCount, ptr %objectReferenceCount, !alias.scope !14, !noalias !24, !range !41
|
|
166
162
|
%referenceCount.1 = add %ReferenceCount %referenceCount, 1
|
|
167
163
|
store %ReferenceCount %referenceCount.1, ptr %objectReferenceCount, !alias.scope !14, !noalias !24
|
|
168
164
|
br label %done
|
|
@@ -189,7 +185,7 @@ define private void @eraseObject(%Object %object) alwaysinline {
|
|
|
189
185
|
|
|
190
186
|
next:
|
|
191
187
|
%objectReferenceCount = getelementptr %Header, ptr %object, i64 0, i32 0
|
|
192
|
-
%referenceCount = load %ReferenceCount, ptr %objectReferenceCount, !alias.scope !14, !noalias !24
|
|
188
|
+
%referenceCount = load %ReferenceCount, ptr %objectReferenceCount, !alias.scope !14, !noalias !24, !range !41
|
|
193
189
|
switch %ReferenceCount %referenceCount, label %decr [%ReferenceCount 0, label %free]
|
|
194
190
|
|
|
195
191
|
decr:
|
|
@@ -334,10 +330,8 @@ realloc:
|
|
|
334
330
|
|
|
335
331
|
define private %StackPointer @stackAllocate(%Stack %stack, i64 %n) alwaysinline {
|
|
336
332
|
%stackPointer_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1
|
|
337
|
-
%limit_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 2
|
|
338
333
|
|
|
339
334
|
%currentStackPointer = load %StackPointer, ptr %stackPointer_pointer, !alias.scope !11, !noalias !21
|
|
340
|
-
%limit = load %Limit, ptr %limit_pointer, !alias.scope !11, !noalias !21
|
|
341
335
|
%nextStackPointer = getelementptr i8, %StackPointer %currentStackPointer, i64 %n
|
|
342
336
|
|
|
343
337
|
store %StackPointer %nextStackPointer, ptr %stackPointer_pointer, !alias.scope !11, !noalias !21
|
|
@@ -486,7 +480,7 @@ define private {%Resumption, %Stack} @shift(%Stack %stack, %Prompt %prompt) {
|
|
|
486
480
|
|
|
487
481
|
define private void @erasePrompt(%Prompt %prompt) alwaysinline {
|
|
488
482
|
%referenceCount_pointer = getelementptr %PromptValue, %Prompt %prompt, i64 0, i32 0
|
|
489
|
-
%referenceCount = load %ReferenceCount, ptr %referenceCount_pointer, !alias.scope !13, !noalias !23
|
|
483
|
+
%referenceCount = load %ReferenceCount, ptr %referenceCount_pointer, !alias.scope !13, !noalias !23, !range !41
|
|
490
484
|
switch %ReferenceCount %referenceCount, label %decrement [%ReferenceCount 0, label %free]
|
|
491
485
|
|
|
492
486
|
decrement:
|
|
@@ -501,7 +495,7 @@ free:
|
|
|
501
495
|
|
|
502
496
|
define private void @sharePrompt(%Prompt %prompt) alwaysinline {
|
|
503
497
|
%referenceCount_pointer = getelementptr %PromptValue, %Prompt %prompt, i64 0, i32 0
|
|
504
|
-
%referenceCount = load %ReferenceCount, ptr %referenceCount_pointer, !alias.scope !13, !noalias !23
|
|
498
|
+
%referenceCount = load %ReferenceCount, ptr %referenceCount_pointer, !alias.scope !13, !noalias !23, !range !41
|
|
505
499
|
%newReferenceCount = add %ReferenceCount %referenceCount, 1
|
|
506
500
|
store %ReferenceCount %newReferenceCount, ptr %referenceCount_pointer, !alias.scope !13, !noalias !23
|
|
507
501
|
ret void
|
|
@@ -544,7 +538,7 @@ define private %Stack @copyStack(%Stack %stack) alwaysinline {
|
|
|
544
538
|
%newStackPointer = getelementptr i8, %Stack %newStack, i64 %used
|
|
545
539
|
%newLimit = getelementptr i8, %Stack %newStack, i64 %size
|
|
546
540
|
|
|
547
|
-
call
|
|
541
|
+
%copied = call ptr @memcpy(ptr %newStack, ptr %stack, i64 %used)
|
|
548
542
|
|
|
549
543
|
%newStackPointer_pointer = getelementptr %StackValue, %Stack %newStack, i64 0, i32 1
|
|
550
544
|
%newLimit_pointer = getelementptr %StackValue, %Stack %newStack, i64 0, i32 2
|
|
@@ -569,7 +563,7 @@ define private %Resumption @uniqueStack(%Resumption %resumption) alwaysinline {
|
|
|
569
563
|
|
|
570
564
|
entry:
|
|
571
565
|
%referenceCount_pointer = getelementptr %StackValue, %Resumption %resumption, i64 0, i32 0
|
|
572
|
-
%referenceCount = load %ReferenceCount, ptr %referenceCount_pointer, !alias.scope !11, !noalias !21
|
|
566
|
+
%referenceCount = load %ReferenceCount, ptr %referenceCount_pointer, !alias.scope !11, !noalias !21, !range !41
|
|
573
567
|
switch %ReferenceCount %referenceCount, label %copy [%ReferenceCount 0, label %done]
|
|
574
568
|
|
|
575
569
|
done:
|
|
@@ -613,7 +607,7 @@ stop:
|
|
|
613
607
|
|
|
614
608
|
define void @shareResumption(%Resumption %resumption) alwaysinline {
|
|
615
609
|
%referenceCount_pointer = getelementptr %StackValue, %Resumption %resumption, i64 0, i32 0
|
|
616
|
-
%referenceCount = load %ReferenceCount, ptr %referenceCount_pointer, !alias.scope !11, !noalias !21
|
|
610
|
+
%referenceCount = load %ReferenceCount, ptr %referenceCount_pointer, !alias.scope !11, !noalias !21, !range !41
|
|
617
611
|
%referenceCount.1 = add %ReferenceCount %referenceCount, 1
|
|
618
612
|
store %ReferenceCount %referenceCount.1, ptr %referenceCount_pointer, !alias.scope !11, !noalias !21
|
|
619
613
|
ret void
|
|
@@ -621,7 +615,7 @@ define void @shareResumption(%Resumption %resumption) alwaysinline {
|
|
|
621
615
|
|
|
622
616
|
define void @eraseResumption(%Resumption %resumption) alwaysinline {
|
|
623
617
|
%referenceCount_pointer = getelementptr %StackValue, %Resumption %resumption, i64 0, i32 0
|
|
624
|
-
%referenceCount = load %ReferenceCount, ptr %referenceCount_pointer, !alias.scope !11, !noalias !21
|
|
618
|
+
%referenceCount = load %ReferenceCount, ptr %referenceCount_pointer, !alias.scope !11, !noalias !21, !range !41
|
|
625
619
|
switch %ReferenceCount %referenceCount, label %decr [%ReferenceCount 0, label %free]
|
|
626
620
|
|
|
627
621
|
decr:
|
|
@@ -729,9 +723,11 @@ define private %Stack @withEmptyStack() {
|
|
|
729
723
|
ret %Stack %stack
|
|
730
724
|
}
|
|
731
725
|
|
|
732
|
-
define ccc void @resume_Int(%Stack %stack, %Int %
|
|
733
|
-
%
|
|
734
|
-
|
|
726
|
+
define ccc void @resume_Int(%Stack %stack, %Int %argument) {
|
|
727
|
+
%stackPointer = call ccc %StackPointer @stackDeallocate(%Stack %stack, i64 24)
|
|
728
|
+
%returnAddressPointer = getelementptr %FrameHeader, %StackPointer %stackPointer, i64 0, i32 0
|
|
729
|
+
%returnAddress = load %ReturnAddress, ptr %returnAddressPointer, !alias.scope !12, !noalias !22
|
|
730
|
+
tail call tailcc void %returnAddress(%Int %argument, %Stack %stack)
|
|
735
731
|
ret void
|
|
736
732
|
}
|
|
737
733
|
|
|
@@ -743,9 +739,7 @@ define ccc void @resume_Pos(%Stack %stack, %Pos %argument) {
|
|
|
743
739
|
ret void
|
|
744
740
|
}
|
|
745
741
|
|
|
746
|
-
define ccc void @run(%
|
|
747
|
-
|
|
748
|
-
%function = call %Neg @coercePosNeg(%Pos %boxed)
|
|
742
|
+
define ccc void @run(%Neg %function) {
|
|
749
743
|
%stack = call %Stack @withEmptyStack()
|
|
750
744
|
|
|
751
745
|
%arrayPointer = extractvalue %Neg %function, 0
|
|
@@ -757,15 +751,19 @@ define ccc void @run(%Pos %boxed) {
|
|
|
757
751
|
ret void
|
|
758
752
|
}
|
|
759
753
|
|
|
760
|
-
define ccc void @run_Int(%
|
|
761
|
-
%
|
|
762
|
-
|
|
754
|
+
define ccc void @run_Int(%Neg %function, %Int %argument) {
|
|
755
|
+
%stack = call %Stack @withEmptyStack()
|
|
756
|
+
|
|
757
|
+
%arrayPointer = extractvalue %Neg %function, 0
|
|
758
|
+
%object = extractvalue %Neg %function, 1
|
|
759
|
+
%functionPointerPointer = getelementptr ptr, ptr %arrayPointer, i64 0
|
|
760
|
+
%functionPointer = load ptr, ptr %functionPointerPointer, !alias.scope !15, !noalias !25
|
|
761
|
+
|
|
762
|
+
tail call tailcc %Pos %functionPointer(%Object %object, %Int %argument, %Stack %stack)
|
|
763
763
|
ret void
|
|
764
764
|
}
|
|
765
765
|
|
|
766
|
-
define ccc void @run_Pos(%
|
|
767
|
-
|
|
768
|
-
%function = call ccc %Neg @coercePosNeg(%Pos %boxed)
|
|
766
|
+
define ccc void @run_Pos(%Neg %function, %Pos %argument) {
|
|
769
767
|
%stack = call %Stack @withEmptyStack()
|
|
770
768
|
|
|
771
769
|
%arrayPointer = extractvalue %Neg %function, 0
|
|
@@ -914,4 +912,7 @@ define ccc %CObject @coercePosObj(%Pos %input) {
|
|
|
914
912
|
!22 = !{!1, !3, !4, !5} ; not stackPointer
|
|
915
913
|
!23 = !{!1, !2, !4, !5} ; not prompt
|
|
916
914
|
!24 = !{!1, !2, !3, !5} ; not object
|
|
917
|
-
!25 = !{!1, !2, !3, !4 } ; not vtable
|
|
915
|
+
!25 = !{!1, !2, !3, !4 } ; not vtable
|
|
916
|
+
|
|
917
|
+
; Ranges
|
|
918
|
+
!41 = !{i64 0, i64 9223372036854775807} ; positive i64
|
package/libraries/llvm/types.c
CHANGED
|
@@ -38,9 +38,9 @@ typedef struct StackValue* Stack;
|
|
|
38
38
|
extern void resume_Int(Stack, Int);
|
|
39
39
|
extern void resume_Pos(Stack, struct Pos);
|
|
40
40
|
|
|
41
|
-
extern void run(struct
|
|
42
|
-
extern void run_Int(struct
|
|
43
|
-
extern void run_Pos(struct
|
|
41
|
+
extern void run(struct Neg);
|
|
42
|
+
extern void run_Int(struct Neg, Int);
|
|
43
|
+
extern void run_Pos(struct Neg, struct Pos);
|
|
44
44
|
|
|
45
45
|
// Reference counting primitives defined in LLVM
|
|
46
46
|
extern void eraseNegative(struct Neg);
|