@effekt-lang/effekt 0.2.2 → 0.4.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.
Files changed (95) hide show
  1. package/README.md +6 -18
  2. package/bin/effekt +0 -0
  3. package/bin/effekt.sh +1 -1
  4. package/libraries/chez/common/effekt_primitives.ss +10 -2
  5. package/libraries/chez/common/immutable/cslist.effekt +13 -7
  6. package/libraries/chez/common/mutable/dict.effekt +8 -10
  7. package/libraries/chez/common/text/regex.effekt +7 -9
  8. package/libraries/common/args.effekt +68 -0
  9. package/libraries/common/array.effekt +220 -0
  10. package/libraries/common/bench.effekt +86 -0
  11. package/libraries/common/buffer.effekt +123 -0
  12. package/libraries/common/bytes.effekt +125 -0
  13. package/libraries/{js/immutable → common}/dequeue.effekt +18 -4
  14. package/libraries/common/effekt.effekt +725 -0
  15. package/libraries/common/exception.effekt +121 -0
  16. package/libraries/common/io/console.effekt +62 -0
  17. package/libraries/common/io/error.effekt +474 -0
  18. package/libraries/common/io/filesystem.effekt +274 -0
  19. package/libraries/common/io/network.effekt +81 -0
  20. package/libraries/common/io/time.effekt +12 -0
  21. package/libraries/common/io.effekt +88 -0
  22. package/libraries/{llvm/immutable → common}/list.effekt +101 -74
  23. package/libraries/common/option.effekt +72 -0
  24. package/libraries/common/process.effekt +9 -0
  25. package/libraries/common/queue.effekt +140 -0
  26. package/libraries/common/ref.effekt +60 -0
  27. package/libraries/common/result.effekt +45 -0
  28. package/libraries/{ml/immutable → common}/seq.effekt +30 -19
  29. package/libraries/common/string/tty.effekt +66 -0
  30. package/libraries/common/string.effekt +361 -0
  31. package/libraries/common/test.effekt +160 -0
  32. package/libraries/js/effekt_builtins.js +37 -6
  33. package/libraries/js/mutable/map.effekt +8 -9
  34. package/libraries/js/text/regex.effekt +7 -8
  35. package/libraries/js/unsafe/cont.effekt +2 -2
  36. package/libraries/js/web/dom.effekt +13 -13
  37. package/libraries/llvm/array.c +53 -0
  38. package/libraries/llvm/buffer.c +181 -76
  39. package/libraries/llvm/forward-declare-c.ll +27 -8
  40. package/libraries/llvm/io.c +423 -1
  41. package/libraries/llvm/main.c +6 -1
  42. package/libraries/llvm/ref.c +45 -0
  43. package/libraries/llvm/rts.ll +515 -354
  44. package/libraries/llvm/types.c +32 -0
  45. package/licenses/eclipse public license, version 2.0 - epl-2.0.html +4 -4
  46. package/licenses/mit license - mit-license.html +532 -62
  47. package/licenses/the bsd license - bsd-license.html +535 -60
  48. package/licenses/the mit license - mit.html +532 -62
  49. package/package.json +2 -2
  50. package/libraries/chez/callcc/effekt.effekt +0 -221
  51. package/libraries/chez/common/effekt_matching.ss +0 -100
  52. package/libraries/chez/common/immutable/dequeue.effekt +0 -78
  53. package/libraries/chez/common/immutable/list.effekt +0 -643
  54. package/libraries/chez/common/immutable/option.effekt +0 -39
  55. package/libraries/chez/common/immutable/result.effekt +0 -29
  56. package/libraries/chez/common/io/args.effekt +0 -20
  57. package/libraries/chez/common/mutable/array.effekt +0 -27
  58. package/libraries/chez/common/mutable/heap.effekt +0 -12
  59. package/libraries/chez/common/test.effekt +0 -59
  60. package/libraries/chez/common/text/string.effekt +0 -46
  61. package/libraries/chez/lift/effekt.effekt +0 -217
  62. package/libraries/chez/lift/effekt.ss +0 -118
  63. package/libraries/chez/monadic/effekt.effekt +0 -218
  64. package/libraries/js/effekt.effekt +0 -284
  65. package/libraries/js/effekt_matching.js +0 -79
  66. package/libraries/js/immutable/list.effekt +0 -643
  67. package/libraries/js/immutable/option.effekt +0 -49
  68. package/libraries/js/immutable/result.effekt +0 -29
  69. package/libraries/js/io/args.effekt +0 -9
  70. package/libraries/js/io/async.effekt +0 -28
  71. package/libraries/js/io/async.js +0 -2
  72. package/libraries/js/io/file.effekt +0 -50
  73. package/libraries/js/io/file_include.js +0 -13
  74. package/libraries/js/mutable/array.effekt +0 -98
  75. package/libraries/js/mutable/heap.effekt +0 -32
  76. package/libraries/js/test.effekt +0 -59
  77. package/libraries/js/text/string.effekt +0 -64
  78. package/libraries/llvm/effekt.effekt +0 -243
  79. package/libraries/llvm/immutable/option.effekt +0 -53
  80. package/libraries/llvm/immutable/result.effekt +0 -29
  81. package/libraries/llvm/io/args.effekt +0 -24
  82. package/libraries/llvm/text/string.effekt +0 -179
  83. package/libraries/ml/effekt.effekt +0 -267
  84. package/libraries/ml/effekt.sml +0 -63
  85. package/libraries/ml/immutable/dequeue.effekt +0 -81
  86. package/libraries/ml/immutable/list.effekt +0 -674
  87. package/libraries/ml/immutable/option.effekt +0 -53
  88. package/libraries/ml/immutable/result.effekt +0 -29
  89. package/libraries/ml/internal/option.effekt +0 -18
  90. package/libraries/ml/io/args.effekt +0 -41
  91. package/libraries/ml/mutable/array.effekt +0 -43
  92. package/libraries/ml/random.effekt +0 -85
  93. package/libraries/ml/test.effekt +0 -60
  94. package/libraries/ml/text/regex.effekt +0 -107
  95. package/libraries/ml/text/string.effekt +0 -81
@@ -1,7 +1,11 @@
1
1
  #ifndef EFFEKT_IO_C
2
2
  #define EFFEKT_IO_C
3
3
 
4
- // println
4
+ #include <uv.h>
5
+ #include <string.h> // to compare flag names
6
+
7
+ // Println
8
+ // -------
5
9
 
6
10
  void c_io_println_Int(const Int n) {
7
11
  printf("%" PRId64 "\n", n);
@@ -18,7 +22,425 @@ void c_io_println_Double(const Double x) {
18
22
  void c_io_println_String(String text) {
19
23
  for (uint64_t j = 0; j < c_buffer_length(text); ++j)
20
24
  putchar(c_buffer_bytes(text)[j]);
25
+ erasePositive(text);
21
26
  putchar('\n');
22
27
  }
23
28
 
29
+
30
+ // Lib UV Bindings
31
+ // ---------------
32
+ // Ideas behind the LLVM / libuv implementation.
33
+ //
34
+ // Share memory between Effekt-buffers and libuv buffers
35
+ // -----------------------------------------------------
36
+ // A libuv buffer is a {ptr, i64} where i64 is the capacity
37
+ // while our buffer (from buffer.c, which is ref-counted) is a %Pos with a
38
+ // pointer and a length. The data ptr is shared between the two such that
39
+ // libuv (and underlying mechanisms) can directly write into our buffer without
40
+ // copying. Since our buffer is ref-counted, this has the advantage that we
41
+ // do not need to manually memory manage the buffer.
42
+ //
43
+ //
44
+ // Stacks in Data-fields
45
+ // ------------------------
46
+ // In order to return back to Effekt in the callback, we store a pointer
47
+ // to the Effekt stack into the user-definable data-field (at address 0)
48
+ // in each request object.
49
+ //
50
+ //
51
+ // TODO
52
+ // - pooling of request objects (benchmark first!)
53
+
54
+
55
+ void c_resume_int_fs(uv_fs_t* request) {
56
+ int64_t result = (int64_t)request->result;
57
+ Stack stack = (Stack)request->data;
58
+
59
+ uv_fs_req_cleanup(request);
60
+ free(request);
61
+
62
+ resume_Int(stack, result);
63
+ }
64
+
65
+ int modeFlags(struct Pos mode) {
66
+ switch (mode.tag) {
67
+ case 0: // ReadOnly()
68
+ return UV_FS_O_RDONLY;
69
+ case 1: // WriteOnly()
70
+ return UV_FS_O_WRONLY | UV_FS_O_CREAT | UV_FS_O_TRUNC;
71
+ case 2: // AppendOnly()
72
+ return UV_FS_O_WRONLY | UV_FS_O_CREAT | UV_FS_O_APPEND;
73
+ case 3: // ReadWrite()
74
+ return UV_FS_O_RDWR | UV_FS_O_CREAT | UV_FS_O_TRUNC;
75
+ case 4: // ReadAppend()
76
+ return UV_FS_O_RDWR | UV_FS_O_CREAT | UV_FS_O_APPEND;
77
+ case 5: // AppendExclusive()
78
+ return UV_FS_O_WRONLY | UV_FS_O_CREAT | UV_FS_O_APPEND | UV_FS_O_EXCL;
79
+ case 6: // ReadAppendExclusive()
80
+ return UV_FS_O_RDWR | UV_FS_O_CREAT | UV_FS_O_APPEND | UV_FS_O_EXCL;
81
+ case 7: // AppendSync()
82
+ return UV_FS_O_WRONLY | UV_FS_O_CREAT | UV_FS_O_APPEND | UV_FS_O_SYNC;
83
+ case 8: // ReadAppendSync()
84
+ return UV_FS_O_RDWR | UV_FS_O_CREAT | UV_FS_O_APPEND | UV_FS_O_SYNC;
85
+ case 9: // ReadSync()
86
+ return UV_FS_O_RDONLY | UV_FS_O_SYNC;
87
+ case 10: // ReadWriteSync()
88
+ return UV_FS_O_RDWR | UV_FS_O_SYNC;
89
+ case 11: // WriteExclusive()
90
+ return UV_FS_O_WRONLY | UV_FS_O_CREAT | UV_FS_O_TRUNC | UV_FS_O_EXCL;
91
+ case 12: // ReadWriteExclusive()
92
+ return UV_FS_O_RDWR | UV_FS_O_CREAT | UV_FS_O_TRUNC | UV_FS_O_EXCL;
93
+ default:
94
+ // Invalid tag value
95
+ return -1;
96
+ }
97
+ }
98
+
99
+ void c_fs_open(struct Pos path, struct Pos mode, Stack stack) {
100
+
101
+ // Convert the Effekt String to a 0-terminated string
102
+ char* path_str = c_buffer_as_null_terminated_string(path);
103
+ erasePositive((struct Pos) path);
104
+
105
+ // Convert the Effekt String representing the opening mode to libuv flags
106
+ int flags = modeFlags(mode);
107
+ erasePositive((struct Pos) mode);
108
+
109
+ uv_fs_t* request = malloc(sizeof(uv_fs_t));
110
+ request->data = stack;
111
+
112
+ int result = uv_fs_open(uv_default_loop(), request, path_str, flags, 0666, c_resume_int_fs);
113
+
114
+ if (result < 0) {
115
+ uv_fs_req_cleanup(request);
116
+ free(request);
117
+ resume_Int(stack, result);
118
+ }
119
+
120
+ // We must free the string either way, since libuv copies it into the request
121
+ free(path_str);
122
+
123
+ return;
124
+ }
125
+
126
+ void c_fs_read(Int fd, struct Pos buffer, Int offset, Stack stack) {
127
+
128
+ char* bytes = (char*)c_buffer_bytes(buffer); // libuv expects signed integers
129
+ uv_buf_t buf = uv_buf_init(bytes, c_buffer_length(buffer));
130
+ // erasePositive(buffer);
131
+ // TODO we should erase the buffer but abort if this was the last reference
132
+
133
+ uv_fs_t* request = malloc(sizeof(uv_fs_t));
134
+ request->data = stack;
135
+
136
+ int result = uv_fs_read(uv_default_loop(), request, fd, &buf, 1, offset, c_resume_int_fs);
137
+
138
+ if (result < 0) {
139
+ uv_fs_req_cleanup(request);
140
+ free(request);
141
+ resume_Int(stack, result);
142
+ }
143
+ }
144
+
145
+ void c_fs_write(Int fd, struct Pos buffer, Int offset, Stack stack) {
146
+
147
+ char* bytes = (char*)c_buffer_bytes(buffer); // libuv expects signed integers
148
+ uv_buf_t buf = uv_buf_init(bytes, c_buffer_length(buffer));
149
+ // erasePositive(buffer);
150
+ // TODO we should erase the buffer but abort if this was the last reference
151
+
152
+ uv_fs_t* request = malloc(sizeof(uv_fs_t));
153
+ request->data = stack;
154
+
155
+ int result = uv_fs_write(uv_default_loop(), request, fd, &buf, 1, offset, c_resume_int_fs);
156
+
157
+ if (result < 0) {
158
+ uv_fs_req_cleanup(request);
159
+ free(request);
160
+ resume_Int(stack, result);
161
+ }
162
+ }
163
+
164
+ void c_fs_close(Int fd, Stack stack) {
165
+
166
+ uv_fs_t* request = malloc(sizeof(uv_fs_t));
167
+ request->data = stack;
168
+
169
+ int result = uv_fs_close(uv_default_loop(), request, fd, c_resume_int_fs);
170
+
171
+ if (result < 0) {
172
+ uv_fs_req_cleanup(request);
173
+ free(request);
174
+ resume_Int(stack, result);
175
+ }
176
+ }
177
+
178
+
179
+ /**
180
+ * Maps the libuv error code to a stable (platform independent) numeric value.
181
+ *
182
+ * Tries to use most common errno integer values, but introduces fresh values (> 200)
183
+ * for those without common errno values.
184
+ */
185
+ Int c_error_number(Int errno) {
186
+ switch (errno) {
187
+ case UV_EPERM: return 1; // EPERM
188
+ case UV_ENOENT: return 2; // ENOENT
189
+ case UV_ESRCH: return 3; // ESRCH
190
+ case UV_EINTR: return 4; // EINTR
191
+ case UV_EIO: return 5; // EIO
192
+ case UV_ENXIO: return 6; // ENXIO
193
+ case UV_E2BIG: return 7; // E2BIG
194
+ case UV_EBADF: return 9; // EBADF
195
+ case UV_EAGAIN: return 11; // EAGAIN
196
+ case UV_ENOMEM: return 12; // ENOMEM
197
+ case UV_EACCES: return 13; // EACCES
198
+ case UV_EFAULT: return 14; // EFAULT
199
+ case UV_EBUSY: return 16; // EBUSY
200
+ case UV_EEXIST: return 17; // EEXIST
201
+ case UV_EXDEV: return 18; // EXDEV
202
+ case UV_ENODEV: return 19; // ENODEV
203
+ case UV_ENOTDIR: return 20; // ENOTDIR
204
+ case UV_EISDIR: return 21; // EISDIR
205
+ case UV_EINVAL: return 22; // EINVAL
206
+ case UV_ENFILE: return 23; // ENFILE
207
+ case UV_EMFILE: return 24; // EMFILE
208
+ case UV_ENOTTY: return 25; // ENOTTY
209
+ case UV_ETXTBSY: return 26; // ETXTBSY
210
+ case UV_EFBIG: return 27; // EFBIG
211
+ case UV_ENOSPC: return 28; // ENOSPC
212
+ case UV_ESPIPE: return 29; // ESPIPE
213
+ case UV_EROFS: return 30; // EROFS
214
+ case UV_EMLINK: return 31; // EMLINK
215
+ case UV_EPIPE: return 32; // EPIPE
216
+ case UV_ERANGE: return 34; // ERANGE
217
+ case UV_ENAMETOOLONG: return 36; // ENAMETOOLONG
218
+ case UV_ELOOP: return 40; // ELOOP
219
+ case UV_EOVERFLOW: return 75; // EOVERFLOW
220
+ case UV_EFTYPE: return 79; // EFTYPE
221
+ case UV_EILSEQ: return 84; // EILSEQ
222
+ case UV_ENOTSOCK: return 88; // ENOTSOCK
223
+ case UV_EDESTADDRREQ: return 89; // EDESTADDRREQ
224
+ case UV_EMSGSIZE: return 90; // EMSGSIZE
225
+ case UV_EPROTOTYPE: return 91; // EPROTOTYPE
226
+ case UV_ENOPROTOOPT: return 92; // ENOPROTOOPT
227
+ case UV_EPROTONOSUPPORT: return 93; // EPROTONOSUPPORT
228
+ case UV_ESOCKTNOSUPPORT: return 94; // ESOCKTNOSUPPORT
229
+ case UV_ENOTSUP: return 95; // EOPNOTSUPP
230
+ case UV_EAFNOSUPPORT: return 97; // EAFNOSUPPORT
231
+ case UV_EADDRINUSE: return 98; // EADDRINUSE
232
+ case UV_EADDRNOTAVAIL: return 99; // EADDRNOTAVAIL
233
+ case UV_ENETDOWN: return 100; // ENETDOWN
234
+ case UV_ENETUNREACH: return 101; // ENETUNREACH
235
+ case UV_ECONNABORTED: return 103; // ECONNABORTED
236
+ case UV_ECONNRESET: return 104; // ECONNRESET
237
+ case UV_ENOBUFS: return 105; // ENOBUFS
238
+ case UV_EISCONN: return 106; // EISCONN
239
+ case UV_ENOTCONN: return 107; // ENOTCONN
240
+ case UV_ETIMEDOUT: return 110; // ETIMEDOUT
241
+ case UV_ECONNREFUSED: return 111; // ECONNREFUSED
242
+ case UV_EHOSTUNREACH: return 113; // EHOSTUNREACH
243
+ case UV_EALREADY: return 114; // EALREADY
244
+ case UV_ECANCELED: return 125; // ECANCELED
245
+
246
+ case UV_EAI_ADDRFAMILY: return 200; // Fresh unique value
247
+ case UV_EAI_AGAIN: return 201; // Fresh unique value
248
+ case UV_EAI_BADFLAGS: return 202; // Fresh unique value
249
+ case UV_EAI_BADHINTS: return 203; // Fresh unique value
250
+ case UV_EAI_CANCELED: return 204; // Fresh unique value
251
+ case UV_EAI_FAIL: return 205; // Fresh unique value
252
+ case UV_EAI_FAMILY: return 206; // Fresh unique value
253
+ case UV_EAI_MEMORY: return 207; // Fresh unique value
254
+ case UV_EAI_NODATA: return 208; // Fresh unique value
255
+ case UV_EAI_NONAME: return 209; // Fresh unique value
256
+ case UV_EAI_OVERFLOW: return 210; // Fresh unique value
257
+ case UV_EAI_PROTOCOL: return 211; // Fresh unique value
258
+ case UV_EAI_SERVICE: return 212; // Fresh unique value
259
+ case UV_EAI_SOCKTYPE: return 213; // Fresh unique value
260
+ case UV_ECHARSET: return 215; // Fresh unique value
261
+ case UV_ENONET: return 216; // Fresh unique value
262
+ case UV_UNKNOWN: return 217; // Fresh unique value
263
+ case UV_EOF: return 218; // Fresh unique value
264
+
265
+ case UV_ESHUTDOWN: return 220; // Fresh unique value
266
+
267
+ // Not available in libuv1-dev on ubuntu
268
+ //case UV_EUNATCH: return 219; // Fresh unique value
269
+
270
+ default: return -1; // Unknown error
271
+ }
272
+ }
273
+
274
+ void c_resume_unit_timer(uv_timer_t* handle) {
275
+ Stack stack = handle->data;
276
+
277
+ uv_timer_stop(handle);
278
+ uv_close((uv_handle_t*)handle, (uv_close_cb)free);
279
+
280
+ resume_Pos(stack, Unit);
281
+ }
282
+
283
+ void c_timer_start(Int millis, Stack stack) {
284
+ uv_timer_t* timer = malloc(sizeof(uv_timer_t));
285
+ timer->data = stack;
286
+
287
+ uv_timer_init(uv_default_loop(), timer);
288
+
289
+ uv_timer_start(timer, c_resume_unit_timer, millis, 0);
290
+ }
291
+
292
+ void c_yield(Stack stack) {
293
+ c_timer_start(0, stack);
294
+ }
295
+
296
+
297
+ // Promises
298
+ // --------
299
+
300
+ typedef enum { UNRESOLVED, RESOLVED } promise_state_t;
301
+
302
+ typedef struct Listeners {
303
+ Stack head;
304
+ struct Listeners* tail;
305
+ } Listeners;
306
+
307
+ typedef struct {
308
+ uint64_t rc;
309
+ void* eraser;
310
+ promise_state_t state;
311
+ // state of {
312
+ // case UNRESOLVED => Possibly empty (head is NULL) list of listeners
313
+ // case RESOLVED => Pos (the result)
314
+ // }
315
+ union {
316
+ struct Pos value;
317
+ Listeners listeners;
318
+ } payload;
319
+ } Promise;
320
+
321
+ void c_promise_erase_listeners(void *envPtr) {
322
+ // envPtr points to a Promise _after_ the eraser, so let's adjust it to point to the promise.
323
+ Promise *promise = (Promise*) (envPtr - offsetof(Promise, state));
324
+ promise_state_t state = promise->state;
325
+
326
+ Stack head;
327
+ Listeners* tail;
328
+ Listeners* current;
329
+
330
+ switch (state) {
331
+ case UNRESOLVED:
332
+ head = promise->payload.listeners.head;
333
+ tail = promise->payload.listeners.tail;
334
+ if (head != NULL) {
335
+ // Erase head
336
+ eraseStack(head);
337
+ // Erase tail
338
+ current = tail;
339
+ while (current != NULL) {
340
+ head = current->head;
341
+ tail = current->tail;
342
+ free(current);
343
+ eraseStack(head);
344
+ current = tail;
345
+ };
346
+ };
347
+ break;
348
+ case RESOLVED:
349
+ erasePositive(promise->payload.value);
350
+ break;
351
+ }
352
+ }
353
+
354
+ void c_promise_resume_listeners(Listeners* listeners, struct Pos value) {
355
+ if (listeners != NULL) {
356
+ Stack head = listeners->head;
357
+ Listeners* tail = listeners->tail;
358
+ free(listeners);
359
+ c_promise_resume_listeners(tail, value);
360
+ sharePositive(value);
361
+ resume_Pos(head, value);
362
+ }
363
+ }
364
+
365
+ void c_promise_resolve(struct Pos promise, struct Pos value, Stack stack) {
366
+ Promise* p = (Promise*)promise.obj;
367
+
368
+ Stack head;
369
+ Listeners* tail;
370
+
371
+ switch (p->state) {
372
+ case UNRESOLVED:
373
+ head = p->payload.listeners.head;
374
+ tail = p->payload.listeners.tail;
375
+
376
+ p->state = RESOLVED;
377
+ p->payload.value = value;
378
+ resume_Pos(stack, Unit);
379
+
380
+ if (head != NULL) {
381
+ // Execute tail
382
+ c_promise_resume_listeners(tail, value);
383
+ // Execute head
384
+ sharePositive(value);
385
+ resume_Pos(head, value);
386
+ };
387
+ break;
388
+ case RESOLVED:
389
+ erasePositive(promise);
390
+ erasePositive(value);
391
+ eraseStack(stack);
392
+ fprintf(stderr, "ERROR: Promise already resolved\n");
393
+ exit(1);
394
+ break;
395
+ }
396
+ // TODO stack overflow?
397
+ // We need to erase the promise now, since we consume it.
398
+ erasePositive(promise);
399
+ }
400
+
401
+ void c_promise_await(struct Pos promise, Stack stack) {
402
+ Promise* p = (Promise*)promise.obj;
403
+
404
+ Stack head;
405
+ Listeners* tail;
406
+ Listeners* node;
407
+ struct Pos value;
408
+
409
+ switch (p->state) {
410
+ case UNRESOLVED:
411
+ head = p->payload.listeners.head;
412
+ tail = p->payload.listeners.tail;
413
+ if (head != NULL) {
414
+ node = (Listeners*)malloc(sizeof(Listeners));
415
+ node->head = head;
416
+ node->tail = tail;
417
+ p->payload.listeners.head = stack;
418
+ p->payload.listeners.tail = node;
419
+ } else {
420
+ p->payload.listeners.head = stack;
421
+ };
422
+ break;
423
+ case RESOLVED:
424
+ value = p->payload.value;
425
+ sharePositive(value);
426
+ resume_Pos(stack, value);
427
+ break;
428
+ };
429
+ // TODO hmm, stack overflow?
430
+ erasePositive(promise);
431
+ }
432
+
433
+ struct Pos c_promise_make() {
434
+ Promise* promise = (Promise*)malloc(sizeof(Promise));
435
+
436
+ promise->rc = 0;
437
+ promise->eraser = c_promise_erase_listeners;
438
+ promise->state = UNRESOLVED;
439
+ promise->payload.listeners.head = NULL;
440
+ promise->payload.listeners.tail = NULL;
441
+
442
+ return (struct Pos) { .tag = 0, .obj = promise, };
443
+ }
444
+
445
+
24
446
  #endif
@@ -14,6 +14,8 @@
14
14
  #include "buffer.c"
15
15
  #include "io.c"
16
16
  #include "hole.c"
17
+ #include "ref.c"
18
+ #include "array.c"
17
19
 
18
20
 
19
21
  extern void effektMain();
@@ -22,7 +24,7 @@ int program_argc;
22
24
  char** program_argv;
23
25
 
24
26
  struct Pos c_get_arg(uint64_t idx) {
25
- if(idx < program_argc) {
27
+ if(idx < (uint64_t)program_argc) {
26
28
  return c_buffer_construct_from_null_terminated_string(program_argv[idx]);
27
29
  } else {
28
30
  return c_buffer_construct_zeroed(1);
@@ -36,4 +38,7 @@ int main(int argc, char *argv[]) {
36
38
  program_argc = argc;
37
39
  program_argv = argv;
38
40
  effektMain();
41
+ uv_loop_t *loop = uv_default_loop();
42
+ uv_run(loop, UV_RUN_DEFAULT);
43
+ uv_loop_close(loop);
39
44
  }
@@ -0,0 +1,45 @@
1
+ #ifndef EFFEKT_REF_C
2
+ #define EFFEKT_REF_C
3
+
4
+ /** We represent references like positive types.
5
+ * The tag is 0 and the obj points to memory with the following layout:
6
+ *
7
+ * +--[ Header ]--------------+------------+
8
+ * | ReferenceCount | Eraser | Field |
9
+ * +--------------------------+------------+
10
+ */
11
+
12
+ void c_ref_erase_field(void *envPtr) {
13
+ struct Pos *fieldPtr = envPtr;
14
+ struct Pos element = *fieldPtr;
15
+ erasePositive(element);
16
+ }
17
+
18
+ struct Pos c_ref_fresh(const struct Pos value) {
19
+ void *objPtr = malloc(sizeof(struct Header) + sizeof(struct Pos));
20
+ struct Header *headerPtr = objPtr;
21
+ struct Pos *fieldPtr = objPtr + sizeof(struct Header);
22
+ *headerPtr = (struct Header) { .rc = 0, .eraser = c_ref_erase_field, };
23
+ *fieldPtr = value;
24
+ return (struct Pos) {
25
+ .tag = 0,
26
+ .obj = objPtr,
27
+ };
28
+ }
29
+
30
+ struct Pos c_ref_get(const struct Pos ref) {
31
+ struct Pos *fieldPtr = ref.obj + sizeof(struct Header);
32
+ struct Pos element = *fieldPtr;
33
+ sharePositive(element);
34
+ return element;
35
+ }
36
+
37
+ struct Pos c_ref_set(const struct Pos ref, const struct Pos value) {
38
+ struct Pos *fieldPtr = ref.obj + sizeof(struct Header);
39
+ struct Pos element = *fieldPtr;
40
+ erasePositive(element);
41
+ *fieldPtr = value;
42
+ return Unit;
43
+ }
44
+
45
+ #endif