@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.
- package/README.md +6 -18
- package/bin/effekt +0 -0
- package/bin/effekt.sh +1 -1
- package/libraries/chez/common/effekt_primitives.ss +10 -2
- package/libraries/chez/common/immutable/cslist.effekt +13 -7
- package/libraries/chez/common/mutable/dict.effekt +8 -10
- package/libraries/chez/common/text/regex.effekt +7 -9
- package/libraries/common/args.effekt +68 -0
- package/libraries/common/array.effekt +220 -0
- package/libraries/common/bench.effekt +86 -0
- package/libraries/common/buffer.effekt +123 -0
- package/libraries/common/bytes.effekt +125 -0
- package/libraries/{js/immutable → common}/dequeue.effekt +18 -4
- package/libraries/common/effekt.effekt +725 -0
- package/libraries/common/exception.effekt +121 -0
- package/libraries/common/io/console.effekt +62 -0
- package/libraries/common/io/error.effekt +474 -0
- package/libraries/common/io/filesystem.effekt +274 -0
- package/libraries/common/io/network.effekt +81 -0
- package/libraries/common/io/time.effekt +12 -0
- package/libraries/common/io.effekt +88 -0
- package/libraries/{llvm/immutable → common}/list.effekt +101 -74
- package/libraries/common/option.effekt +72 -0
- package/libraries/common/process.effekt +9 -0
- package/libraries/common/queue.effekt +140 -0
- package/libraries/common/ref.effekt +60 -0
- package/libraries/common/result.effekt +45 -0
- package/libraries/{ml/immutable → common}/seq.effekt +30 -19
- package/libraries/common/string/tty.effekt +66 -0
- package/libraries/common/string.effekt +361 -0
- package/libraries/common/test.effekt +160 -0
- package/libraries/js/effekt_builtins.js +37 -6
- package/libraries/js/mutable/map.effekt +8 -9
- package/libraries/js/text/regex.effekt +7 -8
- package/libraries/js/unsafe/cont.effekt +2 -2
- package/libraries/js/web/dom.effekt +13 -13
- package/libraries/llvm/array.c +53 -0
- package/libraries/llvm/buffer.c +181 -76
- package/libraries/llvm/forward-declare-c.ll +27 -8
- package/libraries/llvm/io.c +423 -1
- package/libraries/llvm/main.c +6 -1
- package/libraries/llvm/ref.c +45 -0
- package/libraries/llvm/rts.ll +515 -354
- package/libraries/llvm/types.c +32 -0
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +4 -4
- package/licenses/mit license - mit-license.html +532 -62
- package/licenses/the bsd license - bsd-license.html +535 -60
- package/licenses/the mit license - mit.html +532 -62
- package/package.json +2 -2
- package/libraries/chez/callcc/effekt.effekt +0 -221
- package/libraries/chez/common/effekt_matching.ss +0 -100
- package/libraries/chez/common/immutable/dequeue.effekt +0 -78
- package/libraries/chez/common/immutable/list.effekt +0 -643
- package/libraries/chez/common/immutable/option.effekt +0 -39
- package/libraries/chez/common/immutable/result.effekt +0 -29
- package/libraries/chez/common/io/args.effekt +0 -20
- package/libraries/chez/common/mutable/array.effekt +0 -27
- package/libraries/chez/common/mutable/heap.effekt +0 -12
- package/libraries/chez/common/test.effekt +0 -59
- package/libraries/chez/common/text/string.effekt +0 -46
- package/libraries/chez/lift/effekt.effekt +0 -217
- package/libraries/chez/lift/effekt.ss +0 -118
- package/libraries/chez/monadic/effekt.effekt +0 -218
- package/libraries/js/effekt.effekt +0 -284
- package/libraries/js/effekt_matching.js +0 -79
- package/libraries/js/immutable/list.effekt +0 -643
- package/libraries/js/immutable/option.effekt +0 -49
- package/libraries/js/immutable/result.effekt +0 -29
- package/libraries/js/io/args.effekt +0 -9
- package/libraries/js/io/async.effekt +0 -28
- package/libraries/js/io/async.js +0 -2
- package/libraries/js/io/file.effekt +0 -50
- package/libraries/js/io/file_include.js +0 -13
- package/libraries/js/mutable/array.effekt +0 -98
- package/libraries/js/mutable/heap.effekt +0 -32
- package/libraries/js/test.effekt +0 -59
- package/libraries/js/text/string.effekt +0 -64
- package/libraries/llvm/effekt.effekt +0 -243
- package/libraries/llvm/immutable/option.effekt +0 -53
- package/libraries/llvm/immutable/result.effekt +0 -29
- package/libraries/llvm/io/args.effekt +0 -24
- package/libraries/llvm/text/string.effekt +0 -179
- package/libraries/ml/effekt.effekt +0 -267
- package/libraries/ml/effekt.sml +0 -63
- package/libraries/ml/immutable/dequeue.effekt +0 -81
- package/libraries/ml/immutable/list.effekt +0 -674
- package/libraries/ml/immutable/option.effekt +0 -53
- package/libraries/ml/immutable/result.effekt +0 -29
- package/libraries/ml/internal/option.effekt +0 -18
- package/libraries/ml/io/args.effekt +0 -41
- package/libraries/ml/mutable/array.effekt +0 -43
- package/libraries/ml/random.effekt +0 -85
- package/libraries/ml/test.effekt +0 -60
- package/libraries/ml/text/regex.effekt +0 -107
- package/libraries/ml/text/string.effekt +0 -81
package/libraries/llvm/io.c
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
#ifndef EFFEKT_IO_C
|
|
2
2
|
#define EFFEKT_IO_C
|
|
3
3
|
|
|
4
|
-
|
|
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
|
package/libraries/llvm/main.c
CHANGED
|
@@ -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
|