@effekt-lang/effekt 0.79.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 CHANGED
Binary file
@@ -182,7 +182,7 @@ namespace internal {
182
182
  extern def listen(listener: Int, handler: Connection => Unit at {io, async, global}) at async: Int =
183
183
  jsNode "$effekt.capture(k => tcp$listen(${listener}, ${handler}, k))"
184
184
  llvm """
185
- notail call void @c_tcp_listen(%Int ${listener}, %Pos ${handler}, %Stack %stack)
185
+ notail call void @c_tcp_listen(%Int ${listener}, %Neg ${handler}, %Stack %stack)
186
186
  ret void
187
187
  """
188
188
 
@@ -12,7 +12,7 @@ extern def spawn[T](task: () => T at {io, async, global}) at async: Unit =
12
12
  js "$effekt.capture(k => { setTimeout(() => k($effekt.unit), 0); return $effekt.run(${task}) })"
13
13
  llvm """
14
14
  notail call void @c_yield(%Stack %stack)
15
- notail call void @run(%Pos ${task})
15
+ notail call void @run(%Neg ${task})
16
16
  ret void
17
17
  """
18
18
 
@@ -48,7 +48,7 @@ extern def onStdout(opts: SpawnOptions, callback: String => Unit at {io, global}
48
48
  };
49
49
  return old; })()"""
50
50
  llvm """
51
- %opts = call %Pos @c_spawn_options_on_stdout(%Pos ${opts}, %Pos ${callback})
51
+ %opts = call %Pos @c_spawn_options_on_stdout(%Pos ${opts}, %Neg ${callback})
52
52
  ret %Pos %opts
53
53
  """
54
54
  extern def onStderr(opts: SpawnOptions, callback: String => Unit at {io, global}) at {}: SpawnOptions =
@@ -64,7 +64,7 @@ extern def onStderr(opts: SpawnOptions, callback: String => Unit at {io, global}
64
64
  };
65
65
  return old; })()"""
66
66
  llvm """
67
- %opts = call %Pos @c_spawn_options_on_stderr(%Pos ${opts}, %Pos ${callback})
67
+ %opts = call %Pos @c_spawn_options_on_stderr(%Pos ${opts}, %Neg ${callback})
68
68
  ret %Pos %opts
69
69
  """
70
70
  extern type WritableStream =
@@ -84,7 +84,7 @@ extern def withStdin(opts: SpawnOptions, callback: WritableStream => Unit at {io
84
84
  return old;
85
85
  })()"""
86
86
  llvm """
87
- %opts = call %Pos @c_spawn_options_pipe_stdin(%Pos ${opts}, %Pos ${callback})
87
+ %opts = call %Pos @c_spawn_options_pipe_stdin(%Pos ${opts}, %Neg ${callback})
88
88
  ret %Pos %opts
89
89
  """
90
90
  extern def write(to: WritableStream, s: String) at io: Unit =
@@ -0,0 +1,75 @@
1
+ module sourcepos
2
+ import io/error
3
+ import io/filesystem
4
+ import stringbuffer
5
+ import tty
6
+
7
+ def toGccStyleString(sp: SourcePosition): String = {
8
+ s"${sp.file}:${sp.startLine.show()}:${sp.startColumn.show()}"
9
+ }
10
+ def toClangStyleString = toGccStyleString
11
+ def toMsvcStyleString(sp: SourcePosition): String = {
12
+ s"${sp.file}(${sp.startLine.show()},${sp.startColumn.show()})"
13
+ }
14
+ def toPythonStyleString(sp: SourcePosition): String = {
15
+ s"File \"${sp.file}\", line ${sp.startLine.show()}"
16
+ }
17
+
18
+ def getSourceLine(file: String, line: Int): String / {Exception[IOError], stop} = {
19
+ with stringBuffer
20
+ with readFileUTF8(file)
21
+ var currentLine = 1
22
+ while (currentLine < line) {
23
+ val c = do next()
24
+ if (c == '\n' || c == '\r') {
25
+ currentLine += 1
26
+ }
27
+ }
28
+ var c = do next()
29
+ while (c != '\n' && c != '\r') {
30
+ do write(c.toString)
31
+ c = do next()
32
+ }
33
+ }
34
+ def getSourceText(sp: SourcePosition): String / {Exception[IOError], stop} = {
35
+ with stringBuffer
36
+ with readFileUTF8(sp.file)
37
+ var currentLine = 1
38
+ var currentColumn = 1
39
+ while (currentLine < sp.startLine || currentColumn < sp.startColumn) {
40
+ val c = do next()
41
+ if (c == '\n' || c == '\r') {
42
+ currentLine += 1
43
+ currentColumn = 0
44
+ }
45
+ }
46
+ var c = do next()
47
+ while (currentLine <= sp.endLine && currentColumn <= sp.endColumn) {
48
+ do write(c.toString)
49
+ if (c == '\n' || c == '\r') {
50
+ currentLine += 1
51
+ currentColumn = 0
52
+ }
53
+ c = do next()
54
+ }
55
+ }
56
+
57
+ def getMarkedSource(sp: SourcePosition): String / Formatted = {
58
+ try {
59
+ if (sp.startLine == sp.endLine) {
60
+ val line = getSourceLine(sp.file, sp.startLine)
61
+ val mline = line.substring(0, sp.startColumn) ++ line.substring(sp.startColumn, sp.endColumn + 1).red ++ line.substring(sp.endColumn + 1)
62
+ return mline ++ "\n" ++ " ".repeat(sp.startColumn - 1) ++ "^".repeat(sp.endColumn - sp.startColumn)
63
+ } else {
64
+ val prefix = getSourceLine(sp.file, sp.startLine).substring(0, sp.startColumn)
65
+ val suffix = getSourceLine(sp.file, sp.endLine).substring(sp.endColumn + 1)
66
+ val text = getSourceText(sp)
67
+ return prefix ++ text.red ++ suffix
68
+ }
69
+ } with stop {
70
+ "(invalid source position)"
71
+ } with Exception[IOError] {
72
+ def raise(e, m) =
73
+ "(can't open source file: " ++ m ++ ")"
74
+ }
75
+ }
@@ -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: new Arena(), rest: null }
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 instanceof Function) return 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: new Arena(), rest }, RETURN)
139
+ return prog(prompt, { stack: null, prompt, arena: null, rest }, RETURN)
124
140
  }
125
141
 
126
142
  function SHIFT(p, body, ks, k) {
@@ -383,18 +383,18 @@ Int c_tcp_bind(String host, Int port) {
383
383
 
384
384
  typedef struct {
385
385
  Stack stack;
386
- struct Pos handler;
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 Pos closure_handler = listen_closure->handler;
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
- erasePositive(closure_handler);
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
- erasePositive(closure_handler);
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
- erasePositive(closure_handler);
419
+ eraseNegative(closure_handler);
420
420
  resume_Int(closure_stack, result);
421
421
  return;
422
422
  }
423
423
 
424
- sharePositive(closure_handler);
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 Pos handler, Stack stack) {
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
- erasePositive(handler);
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 Pos closure_handler = listen_closure->handler;
454
+ struct Neg closure_handler = listen_closure->handler;
455
455
  free(listen_closure);
456
- erasePositive(closure_handler);
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 Pos handler;
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
- erasePositive(clos->handler);
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 Pos callback) {
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 Pos callback) {
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 Pos callback) {
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 Pos callback) {
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
- erasePositive(clos->handler);
757
+ eraseNegative(clos->handler);
758
758
  free(clos);
759
759
  }
760
760
  if(opts->stdio[1].flags & UV_CREATE_PIPE)
@@ -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
 
@@ -726,9 +723,11 @@ define private %Stack @withEmptyStack() {
726
723
  ret %Stack %stack
727
724
  }
728
725
 
729
- define ccc void @resume_Int(%Stack %stack, %Int %integer) {
730
- %argument = call ccc %Pos @coerceIntPos(%Int %integer)
731
- call ccc void @resume_Pos(%Stack %stack, %Pos %argument)
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)
732
731
  ret void
733
732
  }
734
733
 
@@ -740,9 +739,7 @@ define ccc void @resume_Pos(%Stack %stack, %Pos %argument) {
740
739
  ret void
741
740
  }
742
741
 
743
- define ccc void @run(%Pos %boxed) {
744
-
745
- %function = call %Neg @coercePosNeg(%Pos %boxed)
742
+ define ccc void @run(%Neg %function) {
746
743
  %stack = call %Stack @withEmptyStack()
747
744
 
748
745
  %arrayPointer = extractvalue %Neg %function, 0
@@ -754,15 +751,19 @@ define ccc void @run(%Pos %boxed) {
754
751
  ret void
755
752
  }
756
753
 
757
- define ccc void @run_Int(%Pos %boxed, %Int %integer) {
758
- %argument = call ccc %Pos @coerceIntPos(%Int %integer)
759
- call ccc %Pos @run_Pos(%Pos %boxed, %Pos %argument)
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)
760
763
  ret void
761
764
  }
762
765
 
763
- define ccc void @run_Pos(%Pos %boxed, %Pos %argument) {
764
-
765
- %function = call ccc %Neg @coercePosNeg(%Pos %boxed)
766
+ define ccc void @run_Pos(%Neg %function, %Pos %argument) {
766
767
  %stack = call %Stack @withEmptyStack()
767
768
 
768
769
  %arrayPointer = extractvalue %Neg %function, 0
@@ -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 Pos);
42
- extern void run_Int(struct Pos, Int);
43
- extern void run_Pos(struct Pos, struct Pos);
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);