@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.
@@ -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) {
@@ -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[++n]);
80
+ while (data[n]) n++;
81
81
 
82
82
  return c_bytearray_construct(n, (uint8_t*)data);
83
83
  }
@@ -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
 
@@ -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 void @memcpy(ptr, ptr, i64)
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 @print(i64)
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 void @memcpy(ptr %newStack, ptr %stack, i64 %used)
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 %integer) {
733
- %argument = call ccc %Pos @coerceIntPos(%Int %integer)
734
- 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)
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(%Pos %boxed) {
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(%Pos %boxed, %Int %integer) {
761
- %argument = call ccc %Pos @coerceIntPos(%Int %integer)
762
- 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)
763
763
  ret void
764
764
  }
765
765
 
766
- define ccc void @run_Pos(%Pos %boxed, %Pos %argument) {
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
@@ -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);