@effekt-lang/effekt 0.14.0 → 0.16.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.
@@ -19,24 +19,13 @@ effect read[A](): A / stop
19
19
  /// Signal from a producer to a consumer that there are no further values.
20
20
  effect stop(): Nothing
21
21
 
22
- /// Canonical handler of push streams that performs `action` for every
23
- /// value emitted by `stream`.
24
- def for[A, R] { stream: () => R / emit[A] } { action: A => Unit }: R =
25
- try {
26
- stream()
27
- } with emit[A] { value =>
28
- resume(action(value))
29
- }
30
-
31
22
  /// Like `for[A, R]`, but ignores the result of the stream, and consequently
32
23
  /// works for any type. Use this to annotate the type of stream elements
33
24
  /// `A` without having to also annotate `R`.
34
25
  ///
35
26
  /// e.g. for[Int] { prog() } { el => println(el) }
36
- def for[A] { stream: () => Any / emit[A] } { action: A => Unit }: Unit = {
37
- for[A, Any]{stream}{action}
38
- ()
39
- }
27
+ def for[A] { stream: () => Unit / emit[A] } { action: A => Unit }: Unit =
28
+ returning::for[A, Unit]{stream}{action}
40
29
 
41
30
  /// Turns a `list` into a producer of a push stream
42
31
  /// by emitting each contained value left-to-right.
@@ -81,20 +70,13 @@ def each(bytes: ByteArray): Unit / emit[Byte] = {
81
70
  // not seq
82
71
 
83
72
 
84
- def boundary[R] { program: () => R / stop }: Option[R] =
85
- try {
86
- Some(program())
87
- } with stop {
88
- None()
89
- }
90
-
91
- def boundary { program: () => Any / stop }: Unit = {
92
- boundary[Any]{program}
73
+ def boundary { program: () => Unit / stop }: Unit = {
74
+ returning::boundary[Unit]{program}
93
75
  ()
94
76
  }
95
77
 
96
78
  /// Run `program` forever until `stop` is thrown.
97
- def exhaustively { program: () => Any / stop }: Unit =
79
+ def exhaustively { program: () => Unit / stop }: Unit =
98
80
  try {
99
81
  def go(): Unit = {
100
82
  program()
@@ -105,6 +87,24 @@ def exhaustively { program: () => Any / stop }: Unit =
105
87
  ()
106
88
  }
107
89
 
90
+ def many[A] { action: () => A / stop }: Unit / emit[A] =
91
+ exhaustively { do emit(action()) }
92
+
93
+ def some[A] { action: () => A / stop }: Unit / { emit[A], stop } = {
94
+ do emit(action())
95
+ many { action() }
96
+ }
97
+
98
+ def optionally { program: () => Unit / stop }: Bool =
99
+ returning::optionally[Unit]{program}.isDefined
100
+
101
+ def attempt[R] { program: () => R / stop } { fallback: () => R }: R =
102
+ try {
103
+ program()
104
+ } with stop {
105
+ fallback()
106
+ }
107
+
108
108
 
109
109
  /// In Effekt lower bounds are inclusive and upper bounds are exclusive
110
110
  record Indexed[A](index: Int, value: A)
@@ -123,39 +123,13 @@ def rangeFrom(lower: Int): Unit / emit[Int] = {
123
123
  rangeFrom(lower + 1)
124
124
  }
125
125
 
126
+ def index[A] { stream: () => Unit / emit[A] }: Unit / emit[Indexed[A]] =
127
+ returning::index[A, Unit]{stream}
126
128
 
127
- def index[A, R] { stream: () => R / emit[A] }: R / emit[Indexed[A]] = {
128
- var i = 0;
129
- try {
130
- stream()
131
- } with emit[A] { v =>
132
- val c = i;
133
- i = c + 1;
134
- resume(do emit(Indexed(c, v)))
135
- }
136
- }
137
129
 
138
130
  /// If `number` is zero or negative it does nothing
139
- def limit[A, R](number: Int) { stream: () => R / emit[A] }: R / { emit[A], stop } = {
140
- if (number <= 0) do stop();
141
- var i = 1;
142
- try {
143
- stream()
144
- } with emit[A] { v =>
145
- if (i < number) {
146
- i = i + 1;
147
- resume(do emit(v))
148
- } else {
149
- do stop()
150
- }
151
- }
152
- }
153
-
154
- /// If `number` is zero or negative it does nothing
155
- def limit[A](number: Int) { stream: () => Any / emit[A] }: Unit / emit[A] =
156
- boundary {
157
- limit[A, Any](number){stream}
158
- }
131
+ def limit[A](number: Int) { stream: () => Unit / emit[A] }: Unit / {emit[A], stop} =
132
+ returning::limit[A, Unit](number){stream}
159
133
 
160
134
 
161
135
  /// If `number` is zero or negative it does nothing
@@ -166,61 +140,17 @@ def replicate[A](number: Int) { action: () => A }: Unit / emit[A] =
166
140
  }
167
141
 
168
142
 
169
- def sum[R] { stream : () => R / emit[Int] }: (R, Int) = {
170
- var s = 0;
171
- try {
172
- (stream(), s)
173
- } with emit[Int] { v =>
174
- s = s + v;
175
- resume(())
176
- }
177
- }
143
+ def sum { stream : () => Unit / emit[Int] }: Int =
144
+ returning::sum[Unit]{stream}.second
178
145
 
179
- def sum { stream : () => Any / emit[Int] }: Int =
180
- sum[Any]{stream}.second
146
+ def collectList[A] { stream: () => Unit / emit[A] }: List[A] =
147
+ returning::collectList[A, Unit]{stream}.second
181
148
 
182
- def collectList[A, R] { stream: () => R / emit[A] }: (R, List[A]) =
183
- try {
184
- (stream(), Nil())
185
- } with emit[A] { (v) =>
186
- val (r, vs) = resume(());
187
- (r, Cons(v, vs))
188
- }
189
-
190
- def collectList[A] { stream: () => Any / emit[A] }: List[A] =
191
- collectList[A, Any]{stream}.second
192
-
193
- def collectArray[A, R] { stream: () => R / emit[A] }: (R, Array[A]) = {
194
- var i = 0
195
- var a = array::allocate(1)
196
- try {
197
- (stream(), a.resize(i))
198
- } with emit[A] { (v) =>
199
- if (i >= a.size) { a = a.resize(2 * a.size) }
200
- a.unsafeSet(i, v)
201
- i = i + 1
202
- resume(())
203
- }
204
- }
205
-
206
- def collectArray[A] { stream: () => Any / emit[A] }: Array[A] =
207
- collectArray[A, Any]{stream}.second
208
-
209
- def collectBytes[R] { stream: () => R / emit[Byte] }: (R, ByteArray) = {
210
- var i = 0
211
- var a = bytearray::allocate(1)
212
- try {
213
- (stream(), a.resize(i))
214
- } with emit[Byte] { (v) =>
215
- if (i >= a.size) { a = a.resize(2 * a.size) }
216
- a.unsafeSet(i, v)
217
- i = i + 1
218
- resume(())
219
- }
220
- }
149
+ def collectArray[A] { stream: () => Unit / emit[A] }: Array[A] =
150
+ returning::collectArray[A, Unit]{stream}.second
221
151
 
222
- def collectBytes { stream: () => Any / emit[Byte] }: ByteArray =
223
- collectBytes[Any]{stream}.second
152
+ def collectBytes { stream: () => Unit / emit[Byte] }: ByteArray =
153
+ returning::collectBytes[Unit]{stream}.second
224
154
 
225
155
  def feed[T, R](list: List[T]) { reader: () => R / read[T] }: R = {
226
156
  var l = list
@@ -272,34 +202,12 @@ def feed[R](bytes: ByteArray) { reader: () => R / read[Byte] }: R = {
272
202
  }
273
203
  }
274
204
 
275
- def source[A, R] { stream: () => Any / emit[A] } { reader: () => R / read[A] }: R = {
276
- var next = box { None() }
277
- next = box {
278
- try {
279
- stream()
280
- None()
281
- } with emit[A] { (v) =>
282
- next = box { resume(()) }
283
- Some(v)
284
- }
285
- }
286
- try {
287
- reader()
288
- } with read[A] {
289
- resume {
290
- next().getOrElse { do stop() }
291
- }
292
- }
293
- }
294
-
295
- def source[A] { stream: () => Any / emit[A] } { reader: () => Any / read[A] }: Unit = {
296
- source[A, Any]{stream}{reader}
297
- ()
298
- }
205
+ def source[A] { stream: () => Unit / emit[A] } { reader: () => Unit / read[A] }: Unit =
206
+ returning::source[A, Unit]{stream}{reader}
299
207
 
300
208
  /// Combines two streams together producing a stream of pairs in lockstep.
301
- /// Given two streams of length `n` and `m`, it produces a stream of length `min(n, m)`.
302
- def zip[A, B] { stream1: () => Any / emit[A] } { stream2: () => Any / emit[B] } { action: (A, B) => Any }: Unit = {
209
+ /// Terminates when either of them terminates.
210
+ def zip[A, B] { stream1: () => Unit / emit[A] } { stream2: () => Unit / emit[B] } { action: (A, B) => Unit }: Unit = {
303
211
  with source[A] { stream1 }
304
212
  with source[B] { stream2 }
305
213
 
@@ -423,7 +331,7 @@ def encodeUTF8[R] { stream: () => R / emit[Char] }: R / emit[Byte] =
423
331
  resume(encodeChar(char))
424
332
  }
425
333
 
426
- def feed(string: String) { reader: () => Unit / read[Char] } =
334
+ def feed[R](string: String) { reader: () => R / read[Char] } =
427
335
  feed(string.fromString) {
428
336
  decodeUTF8 {
429
337
  reader()
@@ -437,10 +345,129 @@ def each(string: String): Unit / emit[Char] =
437
345
  }
438
346
  }
439
347
 
348
+ def collectString { stream: () => Unit / emit[Char] }: String =
349
+ returning::collectString[Unit]{stream}.second
350
+
351
+ namespace returning {
352
+
353
+ /// Canonical handler of push streams that performs `action` for every
354
+ /// value emitted by `stream`.
355
+ def for[A, R] { stream: () => R / emit[A] } { action: A => Unit }: R =
356
+ try {
357
+ stream()
358
+ } with emit[A] { value =>
359
+ resume(action(value))
360
+ }
361
+
362
+ def boundary[R] { program: () => R / stop }: Option[R] =
363
+ try {
364
+ Some(program())
365
+ } with stop {
366
+ None()
367
+ }
368
+
369
+ def optionally[R] { program: () => R / stop }: Option[R] =
370
+ try {
371
+ Some(program())
372
+ } with stop {
373
+ None()
374
+ }
375
+
376
+ def index[A, R] { stream: () => R / emit[A] }: R / emit[Indexed[A]] = {
377
+ var i = 0;
378
+ try {
379
+ stream()
380
+ } with emit[A] { v =>
381
+ val c = i;
382
+ i = c + 1;
383
+ resume(do emit(Indexed(c, v)))
384
+ }
385
+ }
386
+
387
+ /// If `number` is zero or negative it does nothing
388
+ def limit[A, R](number: Int) { stream: () => R / emit[A] }: R / { emit[A], stop } = {
389
+ if (number <= 0) do stop();
390
+ var i = 1;
391
+ try {
392
+ stream()
393
+ } with emit[A] { v =>
394
+ if (i < number) {
395
+ i = i + 1;
396
+ resume(do emit(v))
397
+ } else {
398
+ do stop()
399
+ }
400
+ }
401
+ }
402
+
403
+ def sum[R] { stream : () => R / emit[Int] }: (R, Int) = {
404
+ var s = 0;
405
+ try {
406
+ (stream(), s)
407
+ } with emit[Int] { v =>
408
+ s = s + v;
409
+ resume(())
410
+ }
411
+ }
412
+
413
+ def collectList[A, R] { stream: () => R / emit[A] }: (R, List[A]) =
414
+ try {
415
+ (stream(), Nil())
416
+ } with emit[A] { (v) =>
417
+ val (r, vs) = resume(());
418
+ (r, Cons(v, vs))
419
+ }
420
+
421
+ def collectArray[A, R] { stream: () => R / emit[A] }: (R, Array[A]) = {
422
+ var i = 0
423
+ var a = array::allocate(1)
424
+ try {
425
+ (stream(), a.resize(i))
426
+ } with emit[A] { (v) =>
427
+ if (i >= a.size) { a = a.resize(2 * a.size) }
428
+ a.unsafeSet(i, v)
429
+ i = i + 1
430
+ resume(())
431
+ }
432
+ }
433
+
434
+ def collectBytes[R] { stream: () => R / emit[Byte] }: (R, ByteArray) = {
435
+ var i = 0
436
+ var a = bytearray::allocate(1)
437
+ try {
438
+ (stream(), a.resize(i))
439
+ } with emit[Byte] { (v) =>
440
+ if (i >= a.size) { a = a.resize(2 * a.size) }
441
+ a.unsafeSet(i, v)
442
+ i = i + 1
443
+ resume(())
444
+ }
445
+ }
446
+
440
447
  def collectString[R] { stream: () => R / emit[Char] }: (R, String) = {
441
448
  val (result, bytes) = collectBytes[R] { encodeUTF8 { stream } }
442
449
  (result, bytes.toString)
443
450
  }
444
451
 
445
- def collectString { stream: () => Any / emit[Char] }: String =
446
- collectString[Any]{stream}.second
452
+ def source[A, R] { stream: () => Unit / emit[A] } { reader: () => R / read[A] }: R = {
453
+ var next = box { None() }
454
+ next = box {
455
+ try {
456
+ stream()
457
+ next = box { None() }
458
+ None()
459
+ } with emit[A] { (v) =>
460
+ next = box { resume(()) }
461
+ Some(v)
462
+ }
463
+ }
464
+ try {
465
+ reader()
466
+ } with read[A] {
467
+ resume {
468
+ next().getOrElse { do stop() }
469
+ }
470
+ }
471
+ }
472
+
473
+ }
@@ -32,13 +32,16 @@ struct Pos c_array_new(const Int size) {
32
32
 
33
33
  Int c_array_size(const struct Pos arr) {
34
34
  uint64_t *sizePtr = arr.obj + sizeof(struct Header);
35
- return *sizePtr;
35
+ uint64_t size = *sizePtr;
36
+ erasePositive(arr);
37
+ return size;
36
38
  }
37
39
 
38
40
  struct Pos c_array_get(const struct Pos arr, const Int index) {
39
41
  struct Pos *dataPtr = arr.obj + sizeof(struct Header) + sizeof(uint64_t);
40
42
  struct Pos element = dataPtr[index];
41
43
  sharePositive(element);
44
+ erasePositive(arr);
42
45
  return element;
43
46
  }
44
47
 
@@ -47,6 +50,7 @@ struct Pos c_array_set(const struct Pos arr, const Int index, const struct Pos v
47
50
  struct Pos element = dataPtr[index];
48
51
  erasePositive(element);
49
52
  dataPtr[index] = value;
53
+ erasePositive(arr);
50
54
  return Unit;
51
55
  }
52
56
 
@@ -29,30 +29,34 @@ struct Pos c_bytearray_new(const Int size) {
29
29
  }
30
30
 
31
31
  Int c_bytearray_size(const struct Pos arr) {
32
+ erasePositive(arr);
32
33
  return arr.tag;
33
34
  }
34
35
 
35
- uint8_t* c_bytearray_data(const struct Pos arr) {
36
- return arr.obj + sizeof(struct Header);
37
- }
38
-
39
36
  Byte c_bytearray_get(const struct Pos arr, const Int index) {
40
37
  Byte *dataPtr = arr.obj + sizeof(struct Header);
41
38
  Byte element = dataPtr[index];
39
+ erasePositive(arr);
42
40
  return element;
43
41
  }
44
42
 
45
43
  struct Pos c_bytearray_set(const struct Pos arr, const Int index, const Byte value) {
46
44
  Byte *dataPtr = arr.obj + sizeof(struct Header);
47
45
  dataPtr[index] = value;
46
+ erasePositive(arr);
48
47
  return Unit;
49
48
  }
50
49
 
50
+ // Internal Operations
51
+
52
+ uint8_t* c_bytearray_data(const struct Pos arr) {
53
+ uint8_t *data = arr.obj + sizeof(struct Header);
54
+ return data;
55
+ }
56
+
51
57
  struct Pos c_bytearray_construct(const uint64_t n, const uint8_t *data) {
52
58
  struct Pos arr = c_bytearray_new(n);
53
-
54
59
  memcpy(c_bytearray_data(arr), data, n);
55
-
56
60
  return arr;
57
61
  }
58
62
 
@@ -66,7 +70,7 @@ struct Pos c_bytearray_from_nullterminated_string(const char *data) {
66
70
  }
67
71
 
68
72
  char* c_bytearray_into_nullterminated_string(const struct Pos arr) {
69
- uint64_t size = c_bytearray_size(arr);
73
+ uint64_t size = arr.tag;
70
74
 
71
75
  char* result = (char*)malloc(size + 1);
72
76
 
@@ -125,12 +129,14 @@ struct Pos c_bytearray_show_Double(const Double x) {
125
129
 
126
130
  // TODO do this in Effekt
127
131
  struct Pos c_bytearray_concatenate(const struct Pos left, const struct Pos right) {
128
- const struct Pos concatenated = c_bytearray_new(c_bytearray_size(left) + c_bytearray_size(right));
129
- for (int64_t j = 0; j < c_bytearray_size(concatenated); ++j)
132
+ uint64_t left_size = left.tag;
133
+ uint64_t right_size = right.tag;
134
+ const struct Pos concatenated = c_bytearray_new(left_size + right_size);
135
+ for (uint64_t j = 0; j < concatenated.tag; ++j)
130
136
  c_bytearray_data(concatenated)[j]
131
- = j < c_bytearray_size(left)
137
+ = j < left_size
132
138
  ? c_bytearray_data(left)[j]
133
- : c_bytearray_data(right)[j - c_bytearray_size(left)];
139
+ : c_bytearray_data(right)[j - left_size];
134
140
 
135
141
  erasePositive(left);
136
142
  erasePositive(right);
@@ -139,8 +145,8 @@ struct Pos c_bytearray_concatenate(const struct Pos left, const struct Pos right
139
145
 
140
146
  // TODO do this in Effekt
141
147
  struct Pos c_bytearray_equal(const struct Pos left, const struct Pos right) {
142
- uint64_t left_size = c_bytearray_size(left);
143
- uint64_t right_size = c_bytearray_size(right);
148
+ uint64_t left_size = left.tag;
149
+ uint64_t right_size = right.tag;
144
150
  if (left_size != right_size) {
145
151
  erasePositive(left);
146
152
  erasePositive(right);
@@ -161,7 +167,7 @@ struct Pos c_bytearray_equal(const struct Pos left, const struct Pos right) {
161
167
  // TODO deprecate
162
168
  struct Pos c_bytearray_substring(const struct Pos str, uint64_t start, uint64_t end) {
163
169
  const struct Pos substr = c_bytearray_new(end - start);
164
- for (int64_t j = 0; j < c_bytearray_size(substr); ++j) {
170
+ for (uint64_t j = 0; j < substr.tag; ++j) {
165
171
  c_bytearray_data(substr)[j] = c_bytearray_data(str)[start+j];
166
172
  }
167
173
  erasePositive(str);
@@ -174,27 +180,27 @@ uint32_t c_bytearray_character_at(const struct Pos str, const uint64_t index) {
174
180
  uint8_t first_byte = bytes[index];
175
181
  uint32_t character = 0;
176
182
 
177
- uint32_t length = c_bytearray_size(str);
183
+ uint32_t size = str.tag;
178
184
 
179
185
  if (first_byte < 0x80) {
180
186
  // Single-byte character (0xxxxxxx)
181
187
  character = first_byte;
182
188
  } else if ((first_byte & 0xE0) == 0xC0) {
183
189
  // Two-byte character (110xxxxx 10xxxxxx)
184
- if (index + 1 < length) {
190
+ if (index + 1 < size) {
185
191
  character = ((first_byte & 0x1F) << 6) |
186
192
  (bytes[index + 1] & 0x3F);
187
193
  }
188
194
  } else if ((first_byte & 0xF0) == 0xE0) {
189
195
  // Three-byte character (1110xxxx 10xxxxxx 10xxxxxx)
190
- if (index + 2 < length) {
196
+ if (index + 2 < size) {
191
197
  character = ((first_byte & 0x0F) << 12) |
192
198
  ((bytes[index + 1] & 0x3F) << 6) |
193
199
  (bytes[index + 2] & 0x3F);
194
200
  }
195
201
  } else if ((first_byte & 0xF8) == 0xF0) {
196
202
  // Four-byte character (11110xxx 10xxxxxx 10xxxxxx 10xxxxxx)
197
- if (index + 3 < length) {
203
+ if (index + 3 < size) {
198
204
  character = ((first_byte & 0x07) << 18) |
199
205
  ((bytes[index + 1] & 0x3F) << 12) |
200
206
  ((bytes[index + 2] & 0x3F) << 6) |
@@ -20,7 +20,7 @@ void c_io_println_Double(const Double x) {
20
20
  }
21
21
 
22
22
  void c_io_println_String(String text) {
23
- for (int64_t j = 0; j < c_bytearray_size(text); ++j)
23
+ for (uint64_t j = 0; j < text.tag; ++j)
24
24
  putchar(c_bytearray_data(text)[j]);
25
25
  erasePositive(text);
26
26
  putchar('\n');
@@ -126,8 +126,8 @@ void c_fs_open(String path, struct Pos mode, Stack stack) {
126
126
  void c_fs_read(Int file, struct Pos buffer, Int offset, Int size, Int position, Stack stack) {
127
127
 
128
128
  uv_buf_t buf = uv_buf_init((char*)(c_bytearray_data(buffer) + offset), size);
129
- // erasePositive(buffer);
130
- // TODO we should erase the buffer but abort if this was the last reference
129
+ erasePositive(buffer);
130
+ // TODO panic if this was the last reference
131
131
 
132
132
  uv_fs_t* request = malloc(sizeof(uv_fs_t));
133
133
  request->data = stack;
@@ -144,8 +144,8 @@ void c_fs_read(Int file, struct Pos buffer, Int offset, Int size, Int position,
144
144
  void c_fs_write(Int file, struct Pos buffer, Int offset, Int size, Int position, Stack stack) {
145
145
 
146
146
  uv_buf_t buf = uv_buf_init((char*)(c_bytearray_data(buffer) + offset), size);
147
- // erasePositive(buffer);
148
- // TODO we should erase the buffer but abort if this was the last reference
147
+ erasePositive(buffer);
148
+ // TODO panic if this was the last reference
149
149
 
150
150
  uv_fs_t* request = malloc(sizeof(uv_fs_t));
151
151
  request->data = stack;
@@ -9,7 +9,6 @@
9
9
 
10
10
  #define DEBUG_REFCOUNT (false)
11
11
 
12
- #include "sanity.c"
13
12
  #include "types.c"
14
13
  #include "bytearray.c"
15
14
  #include "io.c"
@@ -31,6 +31,7 @@ struct Pos c_ref_get(const struct Pos ref) {
31
31
  struct Pos *fieldPtr = ref.obj + sizeof(struct Header);
32
32
  struct Pos element = *fieldPtr;
33
33
  sharePositive(element);
34
+ erasePositive(ref);
34
35
  return element;
35
36
  }
36
37
 
@@ -39,6 +40,7 @@ struct Pos c_ref_set(const struct Pos ref, const struct Pos value) {
39
40
  struct Pos element = *fieldPtr;
40
41
  erasePositive(element);
41
42
  *fieldPtr = value;
43
+ erasePositive(ref);
42
44
  return Unit;
43
45
  }
44
46
 
@@ -114,6 +114,26 @@ declare void @exit(i64)
114
114
  declare void @llvm.assume(i1)
115
115
 
116
116
 
117
+ ; Boxing (externs functions, hence ccc)
118
+ define ccc %Pos @box(%Neg %input) {
119
+ %vtable = extractvalue %Neg %input, 0
120
+ %heap_obj = extractvalue %Neg %input, 1
121
+ %vtable_as_int = ptrtoint ptr %vtable to i64
122
+ %pos_result = insertvalue %Pos undef, i64 %vtable_as_int, 0
123
+ %pos_result_with_heap = insertvalue %Pos %pos_result, ptr %heap_obj, 1
124
+ ret %Pos %pos_result_with_heap
125
+ }
126
+
127
+ define ccc %Neg @unbox(%Pos %input) {
128
+ %tag = extractvalue %Pos %input, 0
129
+ %heap_obj = extractvalue %Pos %input, 1
130
+ %vtable = inttoptr i64 %tag to ptr
131
+ %neg_result = insertvalue %Neg undef, ptr %vtable, 0
132
+ %neg_result_with_heap = insertvalue %Neg %neg_result, ptr %heap_obj, 1
133
+ ret %Neg %neg_result_with_heap
134
+ }
135
+
136
+
117
137
  ; Prompts
118
138
 
119
139
  define private %Prompt @currentPrompt(%Stack %stack) {
@@ -1,4 +1,4 @@
1
- <!doctype html><html lang=en><head><meta charset=utf-8><meta http-equiv=x-ua-compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><title>Eclipse Public License 2.0 (EPL) | The Eclipse Foundation</title><meta property="og:title" content="Eclipse Public License 2.0 (EPL) | The Eclipse Foundation"><meta name=twitter:title content="Eclipse Public License 2.0 (EPL) | The Eclipse Foundation"><meta name=description content="The Eclipse Foundation provides our global community of individuals and organisations with a mature, scalable, and business-friendly environment for open source …"><meta property="og:description" content="The Eclipse Foundation provides our global community of individuals and organisations with a mature, scalable, and business-friendly environment for open source …"><meta name=twitter:description content="The Eclipse Foundation provides our global community of individuals and organisations with a mature, scalable, and business-friendly environment for open source …"><meta name=author content="Wayne Beaton"><link href=/favicon.ico rel=icon type=image/x-icon><meta property="og:image" content="https://www.eclipse.org/images/logos/eclipse-foundation-400x400.png"><meta name=twitter:image content="https://www.eclipse.org/images/logos/eclipse-foundation-400x400.png"><meta name=twitter:card content="summary"><meta name=twitter:site content="@eclipsefdn"><meta name=twitter:creator content="@eclipsefdn"><meta property="og:url" content="https://www.eclipse.org/legal/epl-2.0/"><meta property="og:type" content="website"><meta property="og:site_name" content="Eclipse Foundation"><meta name=keywords content="epl,epl-2.0,legal,foundation,eclipse,eclipse public license,license,licenses"><meta name=generator content="Hugo 0.110.0"><link rel=canonical href=https://www.eclipse.org/legal/epl-2.0/><link rel=alternate href=/legal/epl-2.0/index.xml type=application/rss+xml title><link rel=stylesheet href="/public/css/styles.css?v=1734290143"><script>(function(e,t,n,s,o){e[s]=e[s]||[],e[s].push({"gtm.start":(new Date).getTime(),event:"gtm.js"});var a=t.getElementsByTagName(n)[0],i=t.createElement(n),r=s!="dataLayer"?"&l="+s:"";i.async=!0,i.src="https://www.googletagmanager.com/gtm.js?id="+o+r,a.parentNode.insertBefore(i,a)})(window,document,"script","dataLayer","GTM-5WLCZXC")</script><script>var tableClasses="table"</script><link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel=stylesheet type=text/css></head><body><noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-5WLCZXC" height=0 width=0 style=display:none;visibility:hidden></iframe></noscript><a class=sr-only href=#content>Skip to main content</a><header class="header-wrapper header-wrapper" id=header><div class=header-toolbar><div class=container><div class=header-toolbar-row><div class="toolbar-btn toolbar-search-btn dropdown"><button class=dropdown-toggle id=toolbar-search type=button data-toggle=dropdown tabindex=0 aria-label=Search>
1
+ <!doctype html><html lang=en><head><meta charset=utf-8><meta http-equiv=x-ua-compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><title>Eclipse Public License 2.0 (EPL) | The Eclipse Foundation</title><meta property="og:title" content="Eclipse Public License 2.0 (EPL) | The Eclipse Foundation"><meta name=twitter:title content="Eclipse Public License 2.0 (EPL) | The Eclipse Foundation"><meta name=description content="The Eclipse Foundation provides our global community of individuals and organisations with a mature, scalable, and business-friendly environment for open source …"><meta property="og:description" content="The Eclipse Foundation provides our global community of individuals and organisations with a mature, scalable, and business-friendly environment for open source …"><meta name=twitter:description content="The Eclipse Foundation provides our global community of individuals and organisations with a mature, scalable, and business-friendly environment for open source …"><meta name=author content="Wayne Beaton"><link href=/favicon.ico rel=icon type=image/x-icon><meta property="og:image" content="https://www.eclipse.org/images/logos/eclipse-foundation-400x400.png"><meta name=twitter:image content="https://www.eclipse.org/images/logos/eclipse-foundation-400x400.png"><meta name=twitter:card content="summary"><meta name=twitter:site content="@eclipsefdn"><meta name=twitter:creator content="@eclipsefdn"><meta property="og:url" content="https://www.eclipse.org/legal/epl-2.0/"><meta property="og:type" content="website"><meta property="og:site_name" content="Eclipse Foundation"><meta name=keywords content="epl,epl-2.0,legal,foundation,eclipse,eclipse public license,license,licenses"><meta name=generator content="Hugo 0.110.0"><link rel=canonical href=https://www.eclipse.org/legal/epl-2.0/><link rel=alternate href=/legal/epl-2.0/index.xml type=application/rss+xml title><link rel=stylesheet href="/public/css/styles.css?v=1736104525"><script>(function(e,t,n,s,o){e[s]=e[s]||[],e[s].push({"gtm.start":(new Date).getTime(),event:"gtm.js"});var a=t.getElementsByTagName(n)[0],i=t.createElement(n),r=s!="dataLayer"?"&l="+s:"";i.async=!0,i.src="https://www.googletagmanager.com/gtm.js?id="+o+r,a.parentNode.insertBefore(i,a)})(window,document,"script","dataLayer","GTM-5WLCZXC")</script><script>var tableClasses="table"</script><link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel=stylesheet type=text/css></head><body><noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-5WLCZXC" height=0 width=0 style=display:none;visibility:hidden></iframe></noscript><a class=sr-only href=#content>Skip to main content</a><header class="header-wrapper header-wrapper" id=header><div class=header-toolbar><div class=container><div class=header-toolbar-row><div class="toolbar-btn toolbar-search-btn dropdown"><button class=dropdown-toggle id=toolbar-search type=button data-toggle=dropdown tabindex=0 aria-label=Search>
2
2
  <i class="fa fa-search fa-lg" aria-role=none></i></button><div class="toolbar-search-bar-wrapper dropdown-menu dropdown-menu-right" aria-labelledby=toolbar-search><form action=https://www.eclipse.org/home/search method=get><div class=search-bar><input class=search-bar-input name=q placeholder=Search>
3
3
  <button>
4
4
  <i class="fa fa-search" type=submit></i></button></div></form></div></div><div class="toolbar-btn toolbar-user-menu-btn dropdown"><button class=dropdown-toggle id=toolbar-user-menu type=button data-toggle=dropdown tabindex=0 aria-label="User Menu">
@@ -57,5 +57,5 @@ open source software collaboration and innovation.</p></div><div class=mega-menu
57
57
  <i class="fa-brands fa-linkedin-in fa-stack-1x fa-inverse" aria-hidden=true></i>
58
58
  <span class=sr-only>Linkedin account</span></span></a></li></ul></div></div><div class="footer-sections row equal-height-md font-bold"><div class=col-md-15><div class=row><section id=footer-eclipse-foundation class="footer-section col-sm-8"><div class=menu-heading>Eclipse Foundation</div><ul class=nav><li><a href=https://www.eclipse.org/org/>About</a></li><li><a href=https://projects.eclipse.org/>Projects</a></li><li><a href=https://www.eclipse.org/collaborations/>Collaborations</a></li><li><a href=https://www.eclipse.org/membership/>Membership</a></li><li><a href=https://www.eclipse.org/sponsor/>Sponsor</a></li></ul></section><section id=footer-legal class="footer-section col-sm-8"><div class=menu-heading>Legal</div><ul class=nav><li><a href=https://www.eclipse.org/legal/privacy/>Privacy Policy</a></li><li><a href=https://www.eclipse.org/legal/terms-of-use/>Terms of Use</a></li><li><a href=https://www.eclipse.org/legal/compliance/>Compliance</a></li><li><a href=https://www.eclipse.org/org/documents/Community_Code_of_Conduct.php>Code of Conduct</a></li><li><a href=https://www.eclipse.org/legal/>Legal Resources</a></li><li><a class=toolbar-manage-cookies href=# onclick=event.preventDefault()>Manage Cookies</a></li></ul></section><section id=footer-more class="footer-section col-sm-8"><div class=menu-heading>More</div><ul class=nav><li><a href=https://www.eclipse.org/security/>Report a Vulnerability</a></li><li><a href=https://status.eclipse.org/>Service Status</a></li><li><a href=https://www.eclipse.org/org/foundation/contact.php>Contact Us</a></li><li><a href=https://www.eclipse.org/projects/support/>Support</a></li></ul></section></div></div><div id=footer-end class="footer-section col-md-8 col-md-offset-1 col-sm-24"><div class=footer-end-newsletter><form id=mc-embedded-subscribe-form action=https://eclipsecon.us6.list-manage.com/subscribe/post method=post novalidate target=_blank><label class=footer-end-newsletter-label for=email>Subscribe to our Newsletter</label><div class=footer-end-newsletter-input-wrapper><input class=footer-end-newsletter-input type=email id=email name=EMAIL autocomplete=email placeholder="Enter your email address"><div><i class="fa fa-solid fa-envelope fa-lg" aria-hidden=true></i></div></div><input type=hidden name=u value=eaf9e1f06f194eadc66788a85>
59
59
  <input type=hidden name=id value=46e57eacf1>
60
- <input id=mc-embedded-subscribe type=submit name=subscribe hidden></form></div></div></div><div class="col-sm-24 margin-top-20"><div class=row><div id=copyright class=col-md-16><p id=copyright-text>Copyright &copy; Eclipse Foundation AISBL. All Rights Reserved.</p></div></div></div><a href=# class=scrollup>Back to the top</a></div></footer><div id=footer-js><script src="/public/js/main.js?v1.0?v=1734290143"></script>
60
+ <input id=mc-embedded-subscribe type=submit name=subscribe hidden></form></div></div></div><div class="col-sm-24 margin-top-20"><div class=row><div id=copyright class=col-md-16><p id=copyright-text>Copyright &copy; Eclipse Foundation AISBL. All Rights Reserved.</p></div></div></div><a href=# class=scrollup>Back to the top</a></div></footer><div id=footer-js><script src="/public/js/main.js?v1.0?v=1736104525"></script>
61
61
  <script>(function(){})(jQuery,document)</script></div></body></html>