xbintsc 0.1.8 → 0.1.10

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 (93) hide show
  1. package/README.md +12 -7
  2. package/dist/src/binder/binder.d.ts +35 -1
  3. package/dist/src/binder/binder.js +138 -0
  4. package/dist/src/binder/binder.js.map +1 -1
  5. package/dist/src/codegen/generator/calls.d.ts +4 -0
  6. package/dist/src/codegen/generator/calls.js +114 -32
  7. package/dist/src/codegen/generator/calls.js.map +1 -1
  8. package/dist/src/codegen/generator/context.d.ts +2 -0
  9. package/dist/src/codegen/generator/context.js +36 -0
  10. package/dist/src/codegen/generator/context.js.map +1 -1
  11. package/dist/src/codegen/generator/expressions.d.ts +4 -1
  12. package/dist/src/codegen/generator/expressions.js +73 -2
  13. package/dist/src/codegen/generator/expressions.js.map +1 -1
  14. package/dist/src/codegen/generator/module.d.ts +5 -1
  15. package/dist/src/codegen/generator/module.js +107 -6
  16. package/dist/src/codegen/generator/module.js.map +1 -1
  17. package/dist/src/codegen/generator/state.d.ts +2 -0
  18. package/dist/src/codegen/generator/state.js +46 -0
  19. package/dist/src/codegen/generator/state.js.map +1 -1
  20. package/dist/src/codegen/generator/statements.js +9 -1
  21. package/dist/src/codegen/generator/statements.js.map +1 -1
  22. package/dist/src/codegen/generator/tables.d.ts +6 -0
  23. package/dist/src/codegen/generator/tables.js +40 -0
  24. package/dist/src/codegen/generator/tables.js.map +1 -1
  25. package/dist/src/driver/compiler.js +23 -7
  26. package/dist/src/driver/compiler.js.map +1 -1
  27. package/dist/src/driver/modules.d.ts +24 -0
  28. package/dist/src/driver/modules.js +347 -0
  29. package/dist/src/driver/modules.js.map +1 -0
  30. package/dist/src/extensions/node/fs/fs-ops.d.ts +6 -0
  31. package/dist/src/extensions/node/fs/fs-ops.js +18 -0
  32. package/dist/src/extensions/node/fs/fs-ops.js.map +1 -0
  33. package/dist/src/extensions/node/fs/index.d.ts +3 -1
  34. package/dist/src/extensions/node/fs/index.js +11 -3
  35. package/dist/src/extensions/node/fs/index.js.map +1 -1
  36. package/dist/src/extensions/node/fs/write-file.d.ts +5 -0
  37. package/dist/src/extensions/node/fs/write-file.js +8 -0
  38. package/dist/src/extensions/node/fs/write-file.js.map +1 -0
  39. package/dist/src/extensions/node/index.d.ts +2 -1
  40. package/dist/src/extensions/node/index.js +7 -3
  41. package/dist/src/extensions/node/index.js.map +1 -1
  42. package/dist/src/extensions/node/os/index.d.ts +9 -0
  43. package/dist/src/extensions/node/os/index.js +14 -0
  44. package/dist/src/extensions/node/os/index.js.map +1 -0
  45. package/dist/src/extensions/node/path/index.d.ts +10 -0
  46. package/dist/src/extensions/node/path/index.js +15 -0
  47. package/dist/src/extensions/node/path/index.js.map +1 -0
  48. package/dist/src/extensions/node/process/index.d.ts +10 -0
  49. package/dist/src/extensions/node/process/index.js +15 -0
  50. package/dist/src/extensions/node/process/index.js.map +1 -0
  51. package/dist/src/parser/expressions.js +3 -0
  52. package/dist/src/parser/expressions.js.map +1 -1
  53. package/dist/tests/codegen/llvm.test.js +1 -1
  54. package/dist/tests/codegen/llvm.test.js.map +1 -1
  55. package/dist/tests/e2e/compile.test.js +141 -0
  56. package/dist/tests/e2e/compile.test.js.map +1 -1
  57. package/dist/tests/extensions/registry.test.js +9 -3
  58. package/dist/tests/extensions/registry.test.js.map +1 -1
  59. package/package.json +1 -1
  60. package/runtime/ext_node/fs/fs_common.h +166 -0
  61. package/runtime/ext_node/fs/fs_ops.c +342 -0
  62. package/runtime/ext_node/fs/read_file.c +12 -6
  63. package/runtime/ext_node/fs/write_file.c +47 -0
  64. package/runtime/ext_node/os/os.c +165 -0
  65. package/runtime/ext_node/path/path.c +324 -0
  66. package/runtime/ext_node/process/process.c +137 -0
  67. package/runtime/rt.h +61 -4
  68. package/runtime/rt_internal.h +63 -0
  69. package/runtime/xt_builtins.c +47 -1
  70. package/runtime/xt_containers.c +95 -8
  71. package/runtime/xt_io.c +122 -0
  72. package/runtime/xt_promise.c +292 -0
  73. package/runtime/xt_stdlib.c +59 -5
  74. package/runtime/xt_stdlib2.c +1043 -0
  75. package/scripts/build-runtime.mjs +5 -0
  76. package/src/binder/binder.ts +196 -0
  77. package/src/codegen/generator/calls.ts +124 -33
  78. package/src/codegen/generator/context.ts +35 -1
  79. package/src/codegen/generator/expressions.ts +79 -2
  80. package/src/codegen/generator/module.ts +112 -6
  81. package/src/codegen/generator/state.ts +48 -0
  82. package/src/codegen/generator/statements.ts +7 -1
  83. package/src/codegen/generator/tables.ts +43 -0
  84. package/src/driver/compiler.ts +28 -7
  85. package/src/driver/modules.ts +377 -0
  86. package/src/extensions/node/fs/fs-ops.ts +20 -0
  87. package/src/extensions/node/fs/index.ts +11 -3
  88. package/src/extensions/node/fs/write-file.ts +10 -0
  89. package/src/extensions/node/index.ts +7 -3
  90. package/src/extensions/node/os/index.ts +16 -0
  91. package/src/extensions/node/path/index.ts +17 -0
  92. package/src/extensions/node/process/index.ts +17 -0
  93. package/src/parser/expressions.ts +3 -0
@@ -0,0 +1,324 @@
1
+ /*
2
+ * Node.js `path` module for xbintsc.
3
+ *
4
+ * Exposed through namespace dispatch: the compiler lowers `path.<name>(...)`
5
+ * to `xt_path_static(<name>, argc, argv)`. Paths are handled with POSIX
6
+ * semantics (`/` separator), matching Node's `path.posix` on every platform.
7
+ *
8
+ * Implemented: join, resolve, normalize, dirname, basename, extname,
9
+ * isAbsolute, relative.
10
+ */
11
+
12
+ #include "rt.h"
13
+
14
+ #include <stdio.h>
15
+ #include <stdlib.h>
16
+ #include <string.h>
17
+ #include <unistd.h>
18
+
19
+ #define XT_PATH_MAX 4096
20
+
21
+ static int xt_path_is_absolute(const char *path) { return path && path[0] == '/'; }
22
+
23
+ static void xt_path_normalize(const char *input, char *out, size_t size) {
24
+ int absolute = input[0] == '/';
25
+ size_t length = strlen(input);
26
+ char *copy = (char *)malloc(length + 1);
27
+ if (!copy) {
28
+ out[0] = '\0';
29
+ return;
30
+ }
31
+ memcpy(copy, input, length + 1);
32
+
33
+ size_t capacity = 8;
34
+ size_t count = 0;
35
+ char **segments = (char **)malloc(sizeof(char *) * capacity);
36
+ if (!segments) {
37
+ free(copy);
38
+ out[0] = '\0';
39
+ return;
40
+ }
41
+
42
+ size_t i = 0;
43
+ while (i < length) {
44
+ while (i < length && copy[i] == '/') i++;
45
+ if (i >= length) break;
46
+ size_t start = i;
47
+ while (i < length && copy[i] != '/') i++;
48
+ if (i < length) {
49
+ copy[i] = '\0';
50
+ i++;
51
+ } else {
52
+ copy[i] = '\0';
53
+ }
54
+ char *segment = copy + start;
55
+ if (strcmp(segment, ".") == 0) continue;
56
+ if (strcmp(segment, "..") == 0) {
57
+ if (count > 0 && strcmp(segments[count - 1], "..") != 0) {
58
+ count--;
59
+ } else if (!absolute) {
60
+ if (count == capacity) {
61
+ capacity *= 2;
62
+ segments = (char **)realloc(segments, sizeof(char *) * capacity);
63
+ }
64
+ segments[count++] = segment;
65
+ }
66
+ continue;
67
+ }
68
+ if (count == capacity) {
69
+ capacity *= 2;
70
+ segments = (char **)realloc(segments, sizeof(char *) * capacity);
71
+ }
72
+ segments[count++] = segment;
73
+ }
74
+
75
+ size_t position = 0;
76
+ if (absolute && position < size) out[position++] = '/';
77
+ for (size_t s = 0; s < count; s++) {
78
+ size_t segmentLength = strlen(segments[s]);
79
+ if (position + segmentLength + 2 > size) break;
80
+ if (s > 0) out[position++] = '/';
81
+ memcpy(out + position, segments[s], segmentLength);
82
+ position += segmentLength;
83
+ }
84
+ out[position] = '\0';
85
+ if (position == 0) {
86
+ out[0] = '.';
87
+ out[1] = '\0';
88
+ }
89
+ free(segments);
90
+ free(copy);
91
+ }
92
+
93
+ static void xt_path_absolute(const char *path, char *out, size_t size) {
94
+ if (xt_path_is_absolute(path)) {
95
+ snprintf(out, size, "%s", path);
96
+ } else {
97
+ char cwd[XT_PATH_MAX];
98
+ if (!getcwd(cwd, sizeof(cwd))) cwd[0] = '\0';
99
+ snprintf(out, size, "%s/%s", cwd, path);
100
+ }
101
+ char normalized[XT_PATH_MAX];
102
+ xt_path_normalize(out, normalized, sizeof(normalized));
103
+ snprintf(out, size, "%s", normalized);
104
+ }
105
+
106
+ typedef struct {
107
+ char *storage;
108
+ char **segments;
109
+ size_t count;
110
+ } xt_path_parts;
111
+
112
+ static void xt_path_split(const char *path, xt_path_parts *parts) {
113
+ size_t length = strlen(path);
114
+ parts->storage = (char *)malloc(length + 1);
115
+ parts->count = 0;
116
+ parts->segments = NULL;
117
+ if (!parts->storage) return;
118
+ memcpy(parts->storage, path, length + 1);
119
+
120
+ size_t capacity = 8;
121
+ parts->segments = (char **)malloc(sizeof(char *) * capacity);
122
+ if (!parts->segments) return;
123
+
124
+ size_t i = 0;
125
+ while (i < length) {
126
+ while (i < length && parts->storage[i] == '/') i++;
127
+ if (i >= length) break;
128
+ size_t start = i;
129
+ while (i < length && parts->storage[i] != '/') i++;
130
+ if (i < length) {
131
+ parts->storage[i] = '\0';
132
+ i++;
133
+ } else {
134
+ parts->storage[i] = '\0';
135
+ }
136
+ if (parts->count == capacity) {
137
+ capacity *= 2;
138
+ parts->segments = (char **)realloc(parts->segments, sizeof(char *) * capacity);
139
+ }
140
+ parts->segments[parts->count++] = parts->storage + start;
141
+ }
142
+ }
143
+
144
+ static void xt_path_parts_free(xt_path_parts *parts) {
145
+ free(parts->segments);
146
+ free(parts->storage);
147
+ }
148
+
149
+ /* ------------------------------------------------------------------------- */
150
+ /* Individual operations */
151
+ /* ------------------------------------------------------------------------- */
152
+
153
+ static xt_value xt_path_join(int32_t argc, xt_value *argv) {
154
+ size_t total = 1;
155
+ for (int32_t i = 0; i < argc; i++) {
156
+ const char *part = xt_string_data(xt_to_string(argv[i]));
157
+ if (part) total += strlen(part) + 1;
158
+ }
159
+ char *joined = (char *)malloc(total);
160
+ if (!joined) return xt_undefined();
161
+ joined[0] = '\0';
162
+ for (int32_t i = 0; i < argc; i++) {
163
+ const char *part = xt_string_data(xt_to_string(argv[i]));
164
+ if (!part || part[0] == '\0') continue;
165
+ if (joined[0] != '\0') strcat(joined, "/");
166
+ strcat(joined, part);
167
+ }
168
+ char normalized[XT_PATH_MAX];
169
+ xt_path_normalize(joined, normalized, sizeof(normalized));
170
+ free(joined);
171
+ return xt_string_from_cstr(normalized);
172
+ }
173
+
174
+ static xt_value xt_path_resolve(int32_t argc, xt_value *argv) {
175
+ char result[XT_PATH_MAX];
176
+ result[0] = '\0';
177
+ for (int32_t i = 0; i < argc; i++) {
178
+ const char *part = xt_string_data(xt_to_string(argv[i]));
179
+ if (!part || part[0] == '\0') continue;
180
+ if (xt_path_is_absolute(part)) {
181
+ snprintf(result, sizeof(result), "%s", part);
182
+ } else if (result[0] == '\0') {
183
+ snprintf(result, sizeof(result), "%s", part);
184
+ } else {
185
+ size_t used = strlen(result);
186
+ snprintf(result + used, sizeof(result) - used, "/%s", part);
187
+ }
188
+ }
189
+ if (result[0] == '\0') {
190
+ if (!getcwd(result, sizeof(result))) result[0] = '\0';
191
+ } else if (!xt_path_is_absolute(result)) {
192
+ char cwd[XT_PATH_MAX];
193
+ if (!getcwd(cwd, sizeof(cwd))) cwd[0] = '\0';
194
+ char combined[XT_PATH_MAX];
195
+ snprintf(combined, sizeof(combined), "%s/%s", cwd, result);
196
+ snprintf(result, sizeof(result), "%s", combined);
197
+ }
198
+ char normalized[XT_PATH_MAX];
199
+ xt_path_normalize(result, normalized, sizeof(normalized));
200
+ return xt_string_from_cstr(normalized);
201
+ }
202
+
203
+ static xt_value xt_path_dirname(const char *path) {
204
+ size_t length = strlen(path);
205
+ while (length > 1 && path[length - 1] == '/') length--;
206
+ size_t i = length;
207
+ while (i > 0 && path[i - 1] != '/') i--;
208
+ if (i == 0) return xt_string_from_cstr(".");
209
+ size_t end = i - 1;
210
+ if (end == 0) return xt_string_from_cstr("/");
211
+ while (end > 1 && path[end - 1] == '/') end--;
212
+ return xt_string_new(path, end);
213
+ }
214
+
215
+ static xt_value xt_path_basename(const char *path, const char *extension) {
216
+ size_t length = strlen(path);
217
+ while (length > 0 && path[length - 1] == '/') length--;
218
+ if (length == 0) return xt_string_from_cstr("");
219
+ size_t start = length;
220
+ while (start > 0 && path[start - 1] != '/') start--;
221
+ size_t end = length;
222
+ if (extension && extension[0] != '\0') {
223
+ size_t extensionLength = strlen(extension);
224
+ if (end - start > extensionLength &&
225
+ strncmp(path + end - extensionLength, extension, extensionLength) == 0) {
226
+ end -= extensionLength;
227
+ }
228
+ }
229
+ return xt_string_new(path + start, end - start);
230
+ }
231
+
232
+ static xt_value xt_path_extname(const char *path) {
233
+ size_t length = strlen(path);
234
+ size_t start = 0;
235
+ for (size_t i = 0; i < length; i++) {
236
+ if (path[i] == '/') start = i + 1;
237
+ }
238
+ size_t dot = length;
239
+ for (size_t i = start; i < length; i++) {
240
+ if (path[i] == '.') dot = i;
241
+ }
242
+ if (dot == length || dot == start) return xt_string_from_cstr("");
243
+ return xt_string_new(path + dot, length - dot);
244
+ }
245
+
246
+ static xt_value xt_path_relative(const char *from, const char *to) {
247
+ char fromAbsolute[XT_PATH_MAX];
248
+ char toAbsolute[XT_PATH_MAX];
249
+ xt_path_absolute(from, fromAbsolute, sizeof(fromAbsolute));
250
+ xt_path_absolute(to, toAbsolute, sizeof(toAbsolute));
251
+
252
+ xt_path_parts fromParts;
253
+ xt_path_parts toParts;
254
+ xt_path_split(fromAbsolute, &fromParts);
255
+ xt_path_split(toAbsolute, &toParts);
256
+
257
+ size_t common = 0;
258
+ while (common < fromParts.count && common < toParts.count &&
259
+ strcmp(fromParts.segments[common], toParts.segments[common]) == 0) {
260
+ common++;
261
+ }
262
+
263
+ char result[XT_PATH_MAX];
264
+ result[0] = '\0';
265
+ size_t position = 0;
266
+ for (size_t i = common; i < fromParts.count && position + 3 < sizeof(result); i++) {
267
+ if (position > 0) result[position++] = '/';
268
+ result[position++] = '.';
269
+ result[position++] = '.';
270
+ }
271
+ for (size_t i = common; i < toParts.count; i++) {
272
+ size_t segmentLength = strlen(toParts.segments[i]);
273
+ if (position + segmentLength + 2 > sizeof(result)) break;
274
+ if (position > 0) result[position++] = '/';
275
+ memcpy(result + position, toParts.segments[i], segmentLength);
276
+ position += segmentLength;
277
+ }
278
+ result[position] = '\0';
279
+
280
+ xt_path_parts_free(&fromParts);
281
+ xt_path_parts_free(&toParts);
282
+ return xt_string_from_cstr(result);
283
+ }
284
+
285
+ /* ------------------------------------------------------------------------- */
286
+ /* Dispatch */
287
+ /* ------------------------------------------------------------------------- */
288
+
289
+ xt_value xt_path_static(xt_value name, int32_t argc, xt_value *argv) {
290
+ const char *method = xt_string_data(name);
291
+ if (!method) return xt_undefined();
292
+
293
+ if (strcmp(method, "join") == 0) return xt_path_join(argc, argv);
294
+ if (strcmp(method, "resolve") == 0) return xt_path_resolve(argc, argv);
295
+ if (strcmp(method, "isAbsolute") == 0) {
296
+ const char *path = argc > 0 ? xt_string_data(xt_to_string(argv[0])) : NULL;
297
+ return xt_bool(xt_path_is_absolute(path));
298
+ }
299
+ if (strcmp(method, "normalize") == 0) {
300
+ const char *path = argc > 0 ? xt_string_data(xt_to_string(argv[0])) : "";
301
+ char normalized[XT_PATH_MAX];
302
+ xt_path_normalize(path ? path : "", normalized, sizeof(normalized));
303
+ return xt_string_from_cstr(normalized);
304
+ }
305
+ if (strcmp(method, "dirname") == 0) {
306
+ const char *path = argc > 0 ? xt_string_data(xt_to_string(argv[0])) : "";
307
+ return xt_path_dirname(path ? path : "");
308
+ }
309
+ if (strcmp(method, "basename") == 0) {
310
+ const char *path = argc > 0 ? xt_string_data(xt_to_string(argv[0])) : "";
311
+ const char *extension = argc > 1 ? xt_string_data(xt_to_string(argv[1])) : NULL;
312
+ return xt_path_basename(path ? path : "", extension);
313
+ }
314
+ if (strcmp(method, "extname") == 0) {
315
+ const char *path = argc > 0 ? xt_string_data(xt_to_string(argv[0])) : "";
316
+ return xt_path_extname(path ? path : "");
317
+ }
318
+ if (strcmp(method, "relative") == 0) {
319
+ const char *from = argc > 0 ? xt_string_data(xt_to_string(argv[0])) : "";
320
+ const char *to = argc > 1 ? xt_string_data(xt_to_string(argv[1])) : "";
321
+ return xt_path_relative(from ? from : "", to ? to : "");
322
+ }
323
+ return xt_undefined();
324
+ }
@@ -0,0 +1,137 @@
1
+ /*
2
+ * Node.js `process` object for xbintsc.
3
+ *
4
+ * The compiler lowers `process.<method>(...)` to
5
+ * `xt_process_call(<method>, argc, argv)` and `process.<property>` to
6
+ * `xt_process_get(<property>)`. Provided: cwd, exit, uptime, hrtime and the
7
+ * platform/arch/pid/argv/env properties.
8
+ */
9
+
10
+ #include "rt.h"
11
+
12
+ #include <stdio.h>
13
+ #include <stdlib.h>
14
+ #include <string.h>
15
+ #include <time.h>
16
+
17
+ #if defined(_WIN32)
18
+ extern char **_environ;
19
+ #define XT_ENVIRON _environ
20
+ #include <process.h>
21
+ #define xt_getpid _getpid
22
+ #else
23
+ extern char **environ;
24
+ #define XT_ENVIRON environ
25
+ #include <unistd.h>
26
+ #define xt_getpid getpid
27
+ #endif
28
+
29
+ static const char *xt_process_platform(void) {
30
+ #if defined(_WIN32)
31
+ return "win32";
32
+ #elif defined(__APPLE__)
33
+ return "darwin";
34
+ #elif defined(__linux__)
35
+ return "linux";
36
+ #else
37
+ return "unknown";
38
+ #endif
39
+ }
40
+
41
+ static const char *xt_process_arch(void) {
42
+ #if defined(__x86_64__) || defined(_M_X64)
43
+ return "x64";
44
+ #elif defined(__aarch64__) || defined(_M_ARM64)
45
+ return "arm64";
46
+ #elif defined(__i386__) || defined(_M_IX86)
47
+ return "ia32";
48
+ #elif defined(__arm__)
49
+ return "arm";
50
+ #else
51
+ return "unknown";
52
+ #endif
53
+ }
54
+
55
+ static xt_value xt_process_env(void) {
56
+ xt_value object = xt_object_new();
57
+ if (!XT_ENVIRON) return object;
58
+ for (char **entry = XT_ENVIRON; *entry; entry++) {
59
+ const char *equals = strchr(*entry, '=');
60
+ if (!equals) continue;
61
+ xt_value key = xt_string_new(*entry, (size_t)(equals - *entry));
62
+ xt_object_set(object, key, xt_string_from_cstr(equals + 1));
63
+ }
64
+ return object;
65
+ }
66
+
67
+ static xt_value xt_process_argv(void) {
68
+ int32_t count = xt_program_argc;
69
+ if (count <= 0 || !xt_program_argv) return xt_array_new(0, NULL);
70
+ xt_value *items = (xt_value *)malloc(sizeof(xt_value) * (size_t)count);
71
+ if (!items) return xt_array_new(0, NULL);
72
+ for (int32_t i = 0; i < count; i++) items[i] = xt_string_from_cstr(xt_program_argv[i]);
73
+ xt_value result = xt_array_new(count, items);
74
+ free(items);
75
+ return result;
76
+ }
77
+
78
+ xt_value xt_process_call(xt_value name, int32_t argc, xt_value *argv) {
79
+ const char *method = xt_string_data(name);
80
+ if (!method) return xt_undefined();
81
+
82
+ if (strcmp(method, "cwd") == 0) {
83
+ char buffer[4096];
84
+ if (!getcwd(buffer, sizeof(buffer))) return xt_undefined();
85
+ return xt_string_from_cstr(buffer);
86
+ }
87
+ if (strcmp(method, "exit") == 0) {
88
+ int code = argc > 0 ? (int)xt_to_number(argv[0]) : 0;
89
+ exit(code);
90
+ return xt_undefined();
91
+ }
92
+ if (strcmp(method, "uptime") == 0) {
93
+ return xt_number((double)clock() / (double)CLOCKS_PER_SEC);
94
+ }
95
+ if (strcmp(method, "hrtime") == 0) {
96
+ struct timespec now;
97
+ #if defined(CLOCK_MONOTONIC)
98
+ clock_gettime(CLOCK_MONOTONIC, &now);
99
+ #else
100
+ now.tv_sec = (long)time(NULL);
101
+ now.tv_nsec = 0;
102
+ #endif
103
+ xt_value items[2];
104
+ items[0] = xt_number((double)now.tv_sec);
105
+ items[1] = xt_number((double)now.tv_nsec);
106
+ return xt_array_new(2, items);
107
+ }
108
+ if (strcmp(method, "getuid") == 0) {
109
+ #if defined(_WIN32)
110
+ return xt_number(0);
111
+ #else
112
+ return xt_number((double)getuid());
113
+ #endif
114
+ }
115
+ return xt_undefined();
116
+ }
117
+
118
+ xt_value xt_process_get(xt_value name) {
119
+ const char *key = xt_string_data(name);
120
+ if (!key) return xt_undefined();
121
+
122
+ if (strcmp(key, "platform") == 0) return xt_string_from_cstr(xt_process_platform());
123
+ if (strcmp(key, "arch") == 0) return xt_string_from_cstr(xt_process_arch());
124
+ if (strcmp(key, "pid") == 0) return xt_number((double)xt_getpid());
125
+ if (strcmp(key, "ppid") == 0) {
126
+ #if defined(_WIN32)
127
+ return xt_number(0);
128
+ #else
129
+ return xt_number((double)getppid());
130
+ #endif
131
+ }
132
+ if (strcmp(key, "version") == 0) return xt_string_from_cstr("v0.0.0");
133
+ if (strcmp(key, "argv") == 0) return xt_process_argv();
134
+ if (strcmp(key, "env") == 0) return xt_process_env();
135
+ if (strcmp(key, "title") == 0) return xt_string_from_cstr("xbintsc");
136
+ return xt_undefined();
137
+ }
package/runtime/rt.h CHANGED
@@ -89,16 +89,23 @@ int32_t xt_string_length_value(xt_value value);
89
89
 
90
90
  /* -- function calling convention ----------------------------------------- */
91
91
  /* Every compiled function has the signature:
92
- * xt_value fn(xt_value env, int32_t argc, xt_value *argv);
93
- * `env` carries captured values for closures (XT_UNDEFINED when there are
94
- * none) and `argv` carries the actual arguments. */
95
- typedef xt_value (*xt_code_fn)(xt_value env, int32_t argc, xt_value *argv);
92
+ * xt_value fn(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv);
93
+ * `thisValue` is the JavaScript `this` binding (XT_UNDEFINED for plain calls),
94
+ * `env` is the closure value carrying captured variables, and `argv` carries
95
+ * the actual arguments. */
96
+ typedef xt_value (*xt_code_fn)(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv);
96
97
 
97
98
  xt_value xt_arg(int32_t argc, xt_value *argv, int32_t index);
98
99
  xt_value xt_closure_new(void *fn, int32_t env_count, xt_value *env);
99
100
  xt_value xt_closure_call(xt_value fn, int32_t argc, xt_value *argv);
101
+ xt_value xt_call_with_this(xt_value fn, xt_value thisValue, int32_t argc, xt_value *argv);
100
102
  xt_value xt_closure_env(xt_value fn, int32_t index);
101
103
  int32_t xt_closure_arity(xt_value fn);
104
+ xt_value xt_this(void);
105
+ xt_value xt_new(xt_value ctor, int32_t argc, xt_value *argv);
106
+ xt_value xt_instance_of(xt_value value, xt_value ctor);
107
+ xt_value xt_function_set_prototype(xt_value fn, xt_value proto);
108
+ xt_value xt_function_get_prototype(xt_value fn);
102
109
 
103
110
  /* -- conversions ---------------------------------------------------------- */
104
111
  int xt_truthy(xt_value v);
@@ -136,7 +143,14 @@ xt_value xt_not(xt_value a);
136
143
 
137
144
  /* -- objects -------------------------------------------------------------- */
138
145
  xt_value xt_object_new(void);
146
+ xt_value xt_object_new_with_proto(xt_value proto);
139
147
  xt_value xt_object_get(xt_value obj, xt_value key);
148
+ xt_value xt_object_get_prototype(xt_value obj);
149
+ xt_value xt_object_set_prototype(xt_value obj, xt_value proto);
150
+ xt_value xt_object_freeze(xt_value obj);
151
+ int xt_object_is_frozen(xt_value obj);
152
+ xt_value xt_object_from_entries(xt_value entries);
153
+ xt_value xt_object_has_own(xt_value obj, xt_value key);
140
154
  xt_value xt_object_get_cstr(xt_value obj, const char *key);
141
155
  xt_value xt_object_set(xt_value obj, xt_value key, xt_value value);
142
156
  xt_value xt_object_has(xt_value obj, xt_value key);
@@ -151,6 +165,32 @@ xt_value xt_object_spread(xt_value target, xt_value source);
151
165
  xt_value xt_call_method(xt_value target, xt_value name, int32_t argc, xt_value *argv);
152
166
  /** Implements `Math.<name>(...)`; the name is interned by the compiler. */
153
167
  xt_value xt_math_call(xt_value name, int32_t argc, xt_value *argv);
168
+ /** Implements `JSON.parse` / `JSON.stringify`. */
169
+ xt_value xt_json_parse(int32_t argc, xt_value *argv);
170
+ xt_value xt_json_stringify(int32_t argc, xt_value *argv);
171
+ /** Implements `Array.<name>(...)` statics and the `Array(...)` constructor. */
172
+ xt_value xt_array_static(xt_value name, int32_t argc, xt_value *argv);
173
+ /** Implements `Object.<name>(...)` statics. */
174
+ xt_value xt_object_static(xt_value name, int32_t argc, xt_value *argv);
175
+ /** Implements `Number.<name>(...)` / `String.<name>(...)` statics. */
176
+ xt_value xt_number_static(xt_value name, int32_t argc, xt_value *argv);
177
+ xt_value xt_string_static(xt_value name, int32_t argc, xt_value *argv);
178
+ /** Map / Set constructors and dispatch. */
179
+ xt_value xt_map_ctor(int32_t argc, xt_value *argv);
180
+ xt_value xt_set_ctor(int32_t argc, xt_value *argv);
181
+ xt_value xt_date_ctor(int32_t argc, xt_value *argv);
182
+ xt_value xt_date_static(xt_value name, int32_t argc, xt_value *argv);
183
+ xt_value xt_regexp_ctor(int32_t argc, xt_value *argv);
184
+
185
+ /* -- promises / async ----------------------------------------------------- */
186
+ xt_value xt_promise_resolve(xt_value value);
187
+ xt_value xt_promise_reject(xt_value value);
188
+ xt_value xt_promise_ctor(int32_t argc, xt_value *argv);
189
+ xt_value xt_promise_static(xt_value name, int32_t argc, xt_value *argv);
190
+ /** Unwrap an awaited value: promises yield their value, everything else is itself. */
191
+ xt_value xt_await(xt_value value);
192
+ /** Run queued promise reactions; called once the program body finishes. */
193
+ void xt_drain_microtasks(void);
154
194
 
155
195
  /* -- global functions ------------------------------------------------------ */
156
196
  xt_value xt_parse_int(int32_t argc, xt_value *argv);
@@ -167,6 +207,12 @@ xt_value xt_delete(xt_value obj, xt_value key);
167
207
  /** Collect `argv[start..argc)` into a new array (rest parameters). */
168
208
  xt_value xt_rest_args(int32_t argc, xt_value *argv, int32_t start);
169
209
 
210
+ /* -- program arguments ---------------------------------------------------- */
211
+ /* Captured from `main` so host extensions can expose `process.argv`. */
212
+ void xt_set_program_args(int32_t argc, char **argv);
213
+ extern int32_t xt_program_argc;
214
+ extern char **xt_program_argv;
215
+
170
216
  /* -- arrays --------------------------------------------------------------- */
171
217
  xt_value xt_array_new(int32_t count, xt_value *items);
172
218
  xt_value xt_array_get(xt_value arr, xt_value index);
@@ -195,6 +241,17 @@ void xt_console_log(int32_t argc, xt_value *argv);
195
241
  void xt_console_info(int32_t argc, xt_value *argv);
196
242
  void xt_console_warn(int32_t argc, xt_value *argv);
197
243
  void xt_console_error(int32_t argc, xt_value *argv);
244
+ xt_value xt_console_dir(int32_t argc, xt_value *argv);
245
+ xt_value xt_console_trace(int32_t argc, xt_value *argv);
246
+ xt_value xt_console_assert(int32_t argc, xt_value *argv);
247
+ xt_value xt_console_count(int32_t argc, xt_value *argv);
248
+ xt_value xt_console_count_reset(int32_t argc, xt_value *argv);
249
+ xt_value xt_console_group(int32_t argc, xt_value *argv);
250
+ xt_value xt_console_group_end(int32_t argc, xt_value *argv);
251
+ xt_value xt_console_table(int32_t argc, xt_value *argv);
252
+ xt_value xt_console_time(int32_t argc, xt_value *argv);
253
+ xt_value xt_console_time_end(int32_t argc, xt_value *argv);
254
+ xt_value xt_console_time_log(int32_t argc, xt_value *argv);
198
255
  void xt_print(xt_value v);
199
256
  void xt_println(xt_value v);
200
257
 
@@ -40,6 +40,12 @@
40
40
  #define XT_OBJECT_KIND_OBJECT 2
41
41
  #define XT_OBJECT_KIND_ARRAY 3
42
42
  #define XT_OBJECT_KIND_FUNCTION 4
43
+ #define XT_OBJECT_KIND_PROMISE 5
44
+ #define XT_OBJECT_KIND_MAP 6
45
+ #define XT_OBJECT_KIND_SET 7
46
+ #define XT_OBJECT_KIND_DATE 8
47
+ #define XT_OBJECT_KIND_REGEXP 9
48
+ #define XT_OBJECT_KIND_SYMBOL 10
43
49
 
44
50
  /* Common header for every heap object. */
45
51
  typedef struct xt_header {
@@ -67,6 +73,10 @@ typedef struct {
67
73
  uint32_t count;
68
74
  uint32_t capacity;
69
75
  xt_property *properties;
76
+ xt_value prototype;
77
+ uint8_t frozen;
78
+ uint8_t is_array_base;
79
+ uint16_t reserved2;
70
80
  } xt_object;
71
81
 
72
82
  typedef struct {
@@ -84,6 +94,7 @@ typedef struct {
84
94
  int32_t arity;
85
95
  xt_string *name;
86
96
  xt_object *properties;
97
+ xt_value prototype;
87
98
  } xt_function;
88
99
 
89
100
  /* Allocation (xt_alloc.c). */
@@ -99,6 +110,58 @@ int32_t xt_to_int32(xt_value v);
99
110
  /* Container helper (xt_containers.c). */
100
111
  void xt_array_reserve(xt_array *array, uint32_t needed);
101
112
 
113
+ /* Object helpers used by the standard library. */
114
+ xt_object *xt_as_object(xt_value value);
115
+ xt_property *xt_object_find_property(xt_object *obj, xt_string *key);
116
+
117
+ /* Map / Set / Promise / Date / RegExp live in xt_stdlib.c and xt_promise.c. */
118
+ int xt_is_promise(xt_value value);
119
+ int xt_is_map(xt_value value);
120
+ int xt_is_set(xt_value value);
121
+ int xt_is_date(xt_value value);
122
+ int xt_is_regexp(xt_value value);
123
+ int32_t xt_map_size(xt_value value);
124
+ int32_t xt_set_size(xt_value value);
125
+
126
+ /* -- collection / date / regexp representations --------------------------- */
127
+ typedef struct {
128
+ xt_header header;
129
+ xt_value *keys;
130
+ xt_value *values;
131
+ uint32_t count;
132
+ uint32_t capacity;
133
+ } xt_map;
134
+
135
+ typedef struct {
136
+ xt_header header;
137
+ xt_value *values;
138
+ uint32_t count;
139
+ uint32_t capacity;
140
+ } xt_set_object;
141
+
142
+ typedef struct {
143
+ xt_header header;
144
+ double time;
145
+ } xt_date;
146
+
147
+ typedef struct {
148
+ xt_header header;
149
+ xt_value source;
150
+ xt_value flags;
151
+ } xt_regexp;
152
+
153
+ /* Extended method dispatch (xt_stdlib2.c). `*handled` is set when the method
154
+ * was recognised, allowing an intentional `undefined` result to be returned. */
155
+ xt_value xt_ext_array_method(xt_value target, const char *method, int32_t argc, xt_value *argv, int *handled);
156
+ xt_value xt_ext_string_method(xt_value target, const char *method, int32_t argc, xt_value *argv, int *handled);
157
+ xt_value xt_ext_number_method(xt_value target, const char *method, int32_t argc, xt_value *argv, int *handled);
158
+ xt_value xt_ext_object_method(xt_value target, const char *method, int32_t argc, xt_value *argv, int *handled);
159
+ xt_value xt_ext_container_method(xt_value target, const char *method, int32_t argc, xt_value *argv, int *handled);
160
+ xt_value xt_promise_method(xt_value target, const char *method, int32_t argc, xt_value *argv, int *handled);
161
+
162
+ /* JSON helpers used by Promise / Map immutability checks. */
163
+ int xt_value_equals(xt_value a, xt_value b);
164
+
102
165
  /* Standard-library helpers (xt_stdlib.c). */
103
166
  xt_array *xt_as_array(xt_value value);
104
167
  xt_value xt_arg_at(int32_t argc, xt_value *argv, int32_t index);