xbintsc 0.2.8 → 0.3.1
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 +17 -2
- package/README.zh-CN.md +16 -2
- package/bin/xbintsc.js +49 -10
- package/dist/src/ast/expressions.d.ts +2 -0
- package/dist/src/binder/binder.d.ts +24 -98
- package/dist/src/binder/binder.js +13 -559
- package/dist/src/binder/binder.js.map +1 -1
- package/dist/src/binder/declarations.d.ts +16 -0
- package/dist/src/binder/declarations.js +168 -0
- package/dist/src/binder/declarations.js.map +1 -0
- package/dist/src/binder/helpers.d.ts +11 -0
- package/dist/src/binder/helpers.js +46 -0
- package/dist/src/binder/helpers.js.map +1 -0
- package/dist/src/binder/references.d.ts +21 -0
- package/dist/src/binder/references.js +349 -0
- package/dist/src/binder/references.js.map +1 -0
- package/dist/src/binder/types.d.ts +114 -0
- package/dist/src/binder/types.js +27 -0
- package/dist/src/binder/types.js.map +1 -0
- package/dist/src/cli/main.d.ts +1 -0
- package/dist/src/cli/main.js +40 -0
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/codegen/generator/calls/access.d.ts +13 -0
- package/dist/src/codegen/generator/calls/access.js +115 -0
- package/dist/src/codegen/generator/calls/access.js.map +1 -0
- package/dist/src/codegen/generator/calls/closures.d.ts +11 -0
- package/dist/src/codegen/generator/calls/closures.js +50 -0
- package/dist/src/codegen/generator/calls/closures.js.map +1 -0
- package/dist/src/codegen/generator/calls/invocation.d.ts +18 -0
- package/dist/src/codegen/generator/calls/invocation.js +242 -0
- package/dist/src/codegen/generator/calls/invocation.js.map +1 -0
- package/dist/src/codegen/generator/calls/literals.d.ts +10 -0
- package/dist/src/codegen/generator/calls/literals.js +69 -0
- package/dist/src/codegen/generator/calls/literals.js.map +1 -0
- package/dist/src/codegen/generator/calls/super.d.ts +10 -0
- package/dist/src/codegen/generator/calls/super.js +47 -0
- package/dist/src/codegen/generator/calls/super.js.map +1 -0
- package/dist/src/codegen/generator/calls.d.ts +15 -24
- package/dist/src/codegen/generator/calls.js +15 -482
- package/dist/src/codegen/generator/calls.js.map +1 -1
- package/dist/src/codegen/generator/context.d.ts +1 -1
- package/dist/src/codegen/generator/context.js +2 -2
- package/dist/src/codegen/generator/context.js.map +1 -1
- package/dist/src/codegen/generator/expressions/assignment.d.ts +13 -0
- package/dist/src/codegen/generator/expressions/assignment.js +203 -0
- package/dist/src/codegen/generator/expressions/assignment.js.map +1 -0
- package/dist/src/codegen/generator/expressions/operators.d.ts +14 -0
- package/dist/src/codegen/generator/expressions/operators.js +163 -0
- package/dist/src/codegen/generator/expressions/operators.js.map +1 -0
- package/dist/src/codegen/generator/expressions/primary.d.ts +17 -0
- package/dist/src/codegen/generator/expressions/primary.js +260 -0
- package/dist/src/codegen/generator/expressions/primary.js.map +1 -0
- package/dist/src/codegen/generator/expressions.d.ts +11 -21
- package/dist/src/codegen/generator/expressions.js +11 -494
- package/dist/src/codegen/generator/expressions.js.map +1 -1
- package/dist/src/codegen/generator/module.js +16 -4
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/state.js +8 -0
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/statements/control-flow.d.ts +14 -0
- package/dist/src/codegen/generator/statements/control-flow.js +199 -0
- package/dist/src/codegen/generator/statements/control-flow.js.map +1 -0
- package/dist/src/codegen/generator/statements/dispatch.d.ts +12 -0
- package/dist/src/codegen/generator/statements/dispatch.js +100 -0
- package/dist/src/codegen/generator/statements/dispatch.js.map +1 -0
- package/dist/src/codegen/generator/statements/loops.d.ts +13 -0
- package/dist/src/codegen/generator/statements/loops.js +152 -0
- package/dist/src/codegen/generator/statements/loops.js.map +1 -0
- package/dist/src/codegen/generator/statements/variables.d.ts +13 -0
- package/dist/src/codegen/generator/statements/variables.js +146 -0
- package/dist/src/codegen/generator/statements/variables.js.map +1 -0
- package/dist/src/codegen/generator/statements.d.ts +13 -21
- package/dist/src/codegen/generator/statements.js +13 -568
- package/dist/src/codegen/generator/statements.js.map +1 -1
- package/dist/src/codegen/generator/tables.js +7 -0
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/codegen/values.d.ts +17 -17
- package/dist/src/codegen/values.js +21 -57
- package/dist/src/codegen/values.js.map +1 -1
- package/dist/src/diagnostics/diagnostic.d.ts +1 -0
- package/dist/src/diagnostics/diagnostic.js +1 -0
- package/dist/src/diagnostics/diagnostic.js.map +1 -1
- package/dist/src/diagnostics/source.d.ts +1 -1
- package/dist/src/diagnostics/source.js +7 -12
- package/dist/src/diagnostics/source.js.map +1 -1
- package/dist/src/driver/compiler.d.ts +4 -0
- package/dist/src/driver/compiler.js +51 -16
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/index.d.ts +5 -2
- package/dist/src/driver/index.js +5 -2
- package/dist/src/driver/index.js.map +1 -1
- package/dist/src/driver/paths.d.ts +20 -0
- package/dist/src/driver/paths.js +49 -0
- package/dist/src/driver/paths.js.map +1 -1
- package/dist/src/driver/runtime-lib.d.ts +18 -0
- package/dist/src/driver/runtime-lib.js +31 -0
- package/dist/src/driver/runtime-lib.js.map +1 -0
- package/dist/src/driver/toolchain-download.d.ts +50 -0
- package/dist/src/driver/toolchain-download.js +76 -0
- package/dist/src/driver/toolchain-download.js.map +1 -0
- package/dist/src/driver/toolchain-provider.d.ts +33 -0
- package/dist/src/driver/toolchain-provider.js +71 -0
- package/dist/src/driver/toolchain-provider.js.map +1 -0
- package/dist/src/driver/toolchain.d.ts +9 -4
- package/dist/src/driver/toolchain.js +6 -10
- package/dist/src/driver/toolchain.js.map +1 -1
- package/dist/src/extensions/node/child_process/index.d.ts +4 -2
- package/dist/src/extensions/node/child_process/index.js +4 -2
- package/dist/src/extensions/node/child_process/index.js.map +1 -1
- package/dist/src/extensions/node/events/index.d.ts +10 -0
- package/dist/src/extensions/node/events/index.js +22 -0
- package/dist/src/extensions/node/events/index.js.map +1 -0
- package/dist/src/extensions/node/index.js +6 -0
- package/dist/src/extensions/node/index.js.map +1 -1
- package/dist/src/extensions/node/querystring/index.d.ts +10 -0
- package/dist/src/extensions/node/querystring/index.js +25 -0
- package/dist/src/extensions/node/querystring/index.js.map +1 -0
- package/dist/src/extensions/node/util/index.d.ts +11 -0
- package/dist/src/extensions/node/util/index.js +41 -0
- package/dist/src/extensions/node/util/index.js.map +1 -0
- package/dist/src/extensions/registry.d.ts +6 -0
- package/dist/src/extensions/registry.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/lexer/scanner/identifiers.d.ts +9 -0
- package/dist/src/lexer/scanner/identifiers.js +33 -0
- package/dist/src/lexer/scanner/identifiers.js.map +1 -0
- package/dist/src/lexer/scanner/numbers.d.ts +10 -0
- package/dist/src/lexer/scanner/numbers.js +89 -0
- package/dist/src/lexer/scanner/numbers.js.map +1 -0
- package/dist/src/lexer/scanner/punctuation.d.ts +9 -0
- package/dist/src/lexer/scanner/punctuation.js +151 -0
- package/dist/src/lexer/scanner/punctuation.js.map +1 -0
- package/dist/src/lexer/scanner/regex.d.ts +11 -0
- package/dist/src/lexer/scanner/regex.js +69 -0
- package/dist/src/lexer/scanner/regex.js.map +1 -0
- package/dist/src/lexer/scanner/strings.d.ts +13 -0
- package/dist/src/lexer/scanner/strings.js +118 -0
- package/dist/src/lexer/scanner/strings.js.map +1 -0
- package/dist/src/lexer/scanner.d.ts +20 -27
- package/dist/src/lexer/scanner.js +11 -415
- package/dist/src/lexer/scanner.js.map +1 -1
- package/dist/src/parser/declarations/classes.d.ts +14 -0
- package/dist/src/parser/declarations/classes.js +191 -0
- package/dist/src/parser/declarations/classes.js.map +1 -0
- package/dist/src/parser/declarations/functions.d.ts +17 -0
- package/dist/src/parser/declarations/functions.js +241 -0
- package/dist/src/parser/declarations/functions.js.map +1 -0
- package/dist/src/parser/declarations/type-members.d.ts +16 -0
- package/dist/src/parser/declarations/type-members.js +156 -0
- package/dist/src/parser/declarations/type-members.js.map +1 -0
- package/dist/src/parser/declarations.d.ts +13 -24
- package/dist/src/parser/declarations.js +13 -571
- package/dist/src/parser/declarations.js.map +1 -1
- package/dist/src/parser/helpers.js +13 -4
- package/dist/src/parser/helpers.js.map +1 -1
- package/dist/src/parser/literals.js +10 -1
- package/dist/src/parser/literals.js.map +1 -1
- package/dist/tests/codegen/llvm.test.js +24 -0
- package/dist/tests/codegen/llvm.test.js.map +1 -1
- package/dist/tests/driver/compiler.test.js +3 -0
- package/dist/tests/driver/compiler.test.js.map +1 -1
- package/dist/tests/driver/paths.test.d.ts +1 -0
- package/dist/tests/driver/paths.test.js +26 -0
- package/dist/tests/driver/paths.test.js.map +1 -0
- package/dist/tests/driver/toolchain-download.test.d.ts +1 -0
- package/dist/tests/driver/toolchain-download.test.js +38 -0
- package/dist/tests/driver/toolchain-download.test.js.map +1 -0
- package/dist/tests/driver/toolchain-provider.test.d.ts +1 -0
- package/dist/tests/driver/toolchain-provider.test.js +37 -0
- package/dist/tests/driver/toolchain-provider.test.js.map +1 -0
- package/dist/tests/e2e/compile-node.test.d.ts +7 -0
- package/dist/tests/e2e/compile-node.test.js +123 -0
- package/dist/tests/e2e/compile-node.test.js.map +1 -0
- package/dist/tests/e2e/compile.test.d.ts +4 -1
- package/dist/tests/e2e/compile.test.js +90 -130
- package/dist/tests/e2e/compile.test.js.map +1 -1
- package/dist/tests/e2e/harness.d.ts +36 -0
- package/dist/tests/e2e/harness.js +64 -0
- package/dist/tests/e2e/harness.js.map +1 -0
- package/dist/tests/e2e/node-modules.test.js +60 -0
- package/dist/tests/e2e/node-modules.test.js.map +1 -1
- package/dist/tests/extensions/registry.test.js +4 -0
- package/dist/tests/extensions/registry.test.js.map +1 -1
- package/package.json +5 -3
- package/runtime/ext_node/buffer/buffer.c +12 -552
- package/runtime/ext_node/buffer/parts/byte-access.inc +35 -0
- package/runtime/ext_node/buffer/parts/construction.inc +60 -0
- package/runtime/ext_node/buffer/parts/integer-io.inc +119 -0
- package/runtime/ext_node/buffer/parts/methods.inc +135 -0
- package/runtime/ext_node/buffer/parts/prototype.inc +54 -0
- package/runtime/ext_node/buffer/parts/search.inc +86 -0
- package/runtime/ext_node/buffer/parts/static-api.inc +58 -0
- package/runtime/ext_node/child_process/child_process.c +37 -3
- package/runtime/ext_node/events/events.c +285 -0
- package/runtime/ext_node/http/http.c +11 -736
- package/runtime/ext_node/http/parts/client.inc +290 -0
- package/runtime/ext_node/http/parts/helpers.inc +45 -0
- package/runtime/ext_node/http/parts/prototypes.inc +57 -0
- package/runtime/ext_node/http/parts/response.inc +149 -0
- package/runtime/ext_node/http/parts/server.inc +133 -0
- package/runtime/ext_node/http/parts/string-builder.inc +58 -0
- package/runtime/ext_node/net/net.c +12 -504
- package/runtime/ext_node/net/parts/construction.inc +22 -0
- package/runtime/ext_node/net/parts/platform.inc +60 -0
- package/runtime/ext_node/net/parts/prototypes.inc +35 -0
- package/runtime/ext_node/net/parts/read-loop.inc +58 -0
- package/runtime/ext_node/net/parts/server.inc +131 -0
- package/runtime/ext_node/net/parts/socket-methods.inc +100 -0
- package/runtime/ext_node/net/parts/static-api.inc +93 -0
- package/runtime/ext_node/querystring/querystring.c +251 -0
- package/runtime/ext_node/util/util.c +456 -0
- package/runtime/rt.h +8 -2
- package/runtime/rt_internal.h +34 -0
- package/runtime/xt_bigint/arithmetic.inc +135 -0
- package/runtime/xt_bigint/bits.inc +98 -0
- package/runtime/xt_bigint/bitwise.inc +103 -0
- package/runtime/xt_bigint/compare.inc +30 -0
- package/runtime/xt_bigint/conversions.inc +51 -0
- package/runtime/xt_bigint/division.inc +85 -0
- package/runtime/xt_bigint/format.inc +145 -0
- package/runtime/xt_bigint/helpers.inc +92 -0
- package/runtime/xt_bigint/magnitude.inc +88 -0
- package/runtime/xt_bigint/public.inc +59 -0
- package/runtime/xt_bigint/small-arithmetic.inc +58 -0
- package/runtime/xt_bigint.c +42 -0
- package/runtime/xt_builtins.c +40 -5
- package/runtime/xt_io.c +7 -0
- package/runtime/xt_stdlib/arrays.inc +161 -0
- package/runtime/xt_stdlib/dispatch.inc +116 -0
- package/runtime/xt_stdlib/helpers.inc +23 -0
- package/runtime/xt_stdlib/math.inc +72 -0
- package/runtime/xt_stdlib/strings.inc +178 -0
- package/runtime/xt_stdlib.c +10 -549
- package/runtime/xt_stdlib2/array-statics.inc +37 -0
- package/runtime/xt_stdlib2/arrays.inc +189 -0
- package/runtime/xt_stdlib2/container.inc +23 -0
- package/runtime/xt_stdlib2/date.inc +72 -0
- package/runtime/xt_stdlib2/error.inc +22 -0
- package/runtime/xt_stdlib2/helpers.inc +43 -0
- package/runtime/xt_stdlib2/json.inc +213 -0
- package/runtime/xt_stdlib2/map.inc +95 -0
- package/runtime/xt_stdlib2/number-string-statics.inc +73 -0
- package/runtime/xt_stdlib2/numbers.inc +38 -0
- package/runtime/xt_stdlib2/objects.inc +41 -0
- package/runtime/xt_stdlib2/regexp-match.inc +204 -0
- package/runtime/xt_stdlib2/regexp.inc +20 -0
- package/runtime/xt_stdlib2/set.inc +105 -0
- package/runtime/xt_stdlib2/strings.inc +94 -0
- package/runtime/xt_stdlib2.c +19 -1278
- package/runtime/xt_values.c +155 -12
- package/scripts/build-runtime.ts +109 -0
- package/scripts/fetch-toolchain.ts +101 -0
- package/scripts/package-release.ts +192 -0
- package/src/ast/expressions.ts +2 -0
- package/src/binder/binder.ts +40 -725
- package/src/binder/declarations.ts +203 -0
- package/src/binder/helpers.ts +47 -0
- package/src/binder/references.ts +410 -0
- package/src/binder/types.ts +134 -0
- package/src/cli/main.ts +43 -0
- package/src/codegen/generator/calls/access.ts +139 -0
- package/src/codegen/generator/calls/closures.ts +60 -0
- package/src/codegen/generator/calls/invocation.ts +282 -0
- package/src/codegen/generator/calls/literals.ts +77 -0
- package/src/codegen/generator/calls/super.ts +61 -0
- package/src/codegen/generator/calls.ts +30 -552
- package/src/codegen/generator/context.ts +2 -2
- package/src/codegen/generator/expressions/assignment.ts +226 -0
- package/src/codegen/generator/expressions/operators.ts +182 -0
- package/src/codegen/generator/expressions/primary.ts +304 -0
- package/src/codegen/generator/expressions.ts +22 -553
- package/src/codegen/generator/module.ts +14 -4
- package/src/codegen/generator/state.ts +8 -0
- package/src/codegen/generator/statements/control-flow.ts +225 -0
- package/src/codegen/generator/statements/dispatch.ts +122 -0
- package/src/codegen/generator/statements/loops.ts +173 -0
- package/src/codegen/generator/statements/variables.ts +152 -0
- package/src/codegen/generator/statements.ts +26 -612
- package/src/codegen/generator/tables.ts +7 -0
- package/src/codegen/values.ts +22 -57
- package/src/diagnostics/diagnostic.ts +1 -0
- package/src/diagnostics/source.ts +7 -12
- package/src/driver/compiler.ts +61 -18
- package/src/driver/index.ts +17 -2
- package/src/driver/paths.ts +54 -0
- package/src/driver/runtime-lib.ts +32 -0
- package/src/driver/toolchain-download.ts +108 -0
- package/src/driver/toolchain-provider.ts +91 -0
- package/src/driver/toolchain.ts +29 -11
- package/src/extensions/node/child_process/index.ts +4 -2
- package/src/extensions/node/events/index.ts +27 -0
- package/src/extensions/node/index.ts +6 -0
- package/src/extensions/node/querystring/index.ts +29 -0
- package/src/extensions/node/util/index.ts +48 -0
- package/src/extensions/registry.ts +6 -0
- package/src/index.ts +1 -0
- package/src/lexer/scanner/identifiers.ts +37 -0
- package/src/lexer/scanner/numbers.ts +84 -0
- package/src/lexer/scanner/punctuation.ts +132 -0
- package/src/lexer/scanner/regex.ts +79 -0
- package/src/lexer/scanner/strings.ts +128 -0
- package/src/lexer/scanner.ts +35 -401
- package/src/parser/declarations/classes.ts +215 -0
- package/src/parser/declarations/functions.ts +254 -0
- package/src/parser/declarations/type-members.ts +181 -0
- package/src/parser/declarations.ts +32 -609
- package/src/parser/helpers.ts +13 -6
- package/src/parser/literals.ts +10 -1
- package/scripts/build-runtime.mjs +0 -55
package/runtime/xt_values.c
CHANGED
|
@@ -117,6 +117,7 @@ int xt_truthy(xt_value v) {
|
|
|
117
117
|
if (v == XT_UNDEFINED || v == XT_NULL) return 0;
|
|
118
118
|
if (v == XT_FALSE) return 0;
|
|
119
119
|
if (v == XT_TRUE) return 1;
|
|
120
|
+
if (XT_IS_BIGINT(v)) return XT_GET_PTR(v) != NULL && ((xt_bigint *)XT_GET_PTR(v))->sign != 0;
|
|
120
121
|
if (XT_IS_STRING(v)) return xt_as_string(v)->length != 0;
|
|
121
122
|
return 1; /* objects, arrays and functions are truthy */
|
|
122
123
|
}
|
|
@@ -127,6 +128,7 @@ double xt_to_number(xt_value v) {
|
|
|
127
128
|
if (v == XT_FALSE) return 0.0;
|
|
128
129
|
if (v == XT_UNDEFINED) return NAN;
|
|
129
130
|
if (v == XT_NULL) return 0.0;
|
|
131
|
+
if (XT_IS_BIGINT(v)) return xt_bigint_to_double_value(v);
|
|
130
132
|
if (XT_IS_STRING(v)) {
|
|
131
133
|
xt_string *s = xt_as_string(v);
|
|
132
134
|
if (s->length == 0) return 0.0;
|
|
@@ -151,6 +153,7 @@ xt_value xt_to_string(xt_value v) {
|
|
|
151
153
|
if (v == XT_NULL) return xt_string_from_cstr("null");
|
|
152
154
|
if (v == XT_TRUE) return xt_string_from_cstr("true");
|
|
153
155
|
if (v == XT_FALSE) return xt_string_from_cstr("false");
|
|
156
|
+
if (XT_IS_BIGINT(v)) return xt_bigint_to_decimal(v);
|
|
154
157
|
if (XT_IS_ARRAY(v)) {
|
|
155
158
|
xt_array *a = (xt_array *)XT_GET_PTR(v);
|
|
156
159
|
/* Join elements with commas, like Array.prototype.toString. */
|
|
@@ -182,6 +185,7 @@ xt_value xt_typeof(xt_value v) {
|
|
|
182
185
|
if (XT_IS_NUMBER(v)) return xt_string_from_cstr("number");
|
|
183
186
|
if (XT_IS_STRING(v)) return xt_string_from_cstr("string");
|
|
184
187
|
if (v == XT_TRUE || v == XT_FALSE) return xt_string_from_cstr("boolean");
|
|
188
|
+
if (XT_IS_BIGINT(v)) return xt_string_from_cstr("bigint");
|
|
185
189
|
if (v == XT_UNDEFINED) return xt_string_from_cstr("undefined");
|
|
186
190
|
if (XT_IS_FUNCTION(v)) return xt_string_from_cstr("function");
|
|
187
191
|
if (v == XT_NULL) return xt_string_from_cstr("object");
|
|
@@ -192,32 +196,80 @@ xt_value xt_typeof(xt_value v) {
|
|
|
192
196
|
/* Arithmetic */
|
|
193
197
|
/* ------------------------------------------------------------------------- */
|
|
194
198
|
|
|
199
|
+
static void xt_throw_mixed_bigint(void) {
|
|
200
|
+
xt_throw(xt_string_from_cstr("TypeError: Cannot mix BigInt and other types, use explicit conversions"));
|
|
201
|
+
}
|
|
202
|
+
|
|
195
203
|
xt_value xt_add(xt_value a, xt_value b) {
|
|
196
204
|
if (XT_IS_NUMBER(a) && XT_IS_NUMBER(b)) {
|
|
197
205
|
return xt_number(xt_to_double(a) + xt_to_double(b));
|
|
198
206
|
}
|
|
207
|
+
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_add(a, b);
|
|
199
208
|
/* JavaScript's `+` concatenates when either operand is a string. */
|
|
200
209
|
if (XT_IS_STRING(a) || XT_IS_STRING(b)) {
|
|
201
210
|
xt_value sa = xt_to_string(a);
|
|
202
211
|
xt_value sb = xt_to_string(b);
|
|
203
212
|
return xt_string_concat(xt_as_string(sa), xt_as_string(sb));
|
|
204
213
|
}
|
|
214
|
+
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
215
|
+
xt_throw_mixed_bigint();
|
|
216
|
+
return XT_UNDEFINED;
|
|
217
|
+
}
|
|
205
218
|
return xt_number(xt_to_number(a) + xt_to_number(b));
|
|
206
219
|
}
|
|
207
220
|
|
|
208
|
-
xt_value xt_sub(xt_value a, xt_value b) {
|
|
209
|
-
|
|
210
|
-
|
|
221
|
+
xt_value xt_sub(xt_value a, xt_value b) {
|
|
222
|
+
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_sub(a, b);
|
|
223
|
+
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
224
|
+
xt_throw_mixed_bigint();
|
|
225
|
+
return XT_UNDEFINED;
|
|
226
|
+
}
|
|
227
|
+
return xt_number(xt_to_number(a) - xt_to_number(b));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
xt_value xt_mul(xt_value a, xt_value b) {
|
|
231
|
+
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_mul(a, b);
|
|
232
|
+
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
233
|
+
xt_throw_mixed_bigint();
|
|
234
|
+
return XT_UNDEFINED;
|
|
235
|
+
}
|
|
236
|
+
return xt_number(xt_to_number(a) * xt_to_number(b));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
xt_value xt_div(xt_value a, xt_value b) {
|
|
240
|
+
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_div(a, b);
|
|
241
|
+
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
242
|
+
xt_throw_mixed_bigint();
|
|
243
|
+
return XT_UNDEFINED;
|
|
244
|
+
}
|
|
245
|
+
return xt_number(xt_to_number(a) / xt_to_number(b));
|
|
246
|
+
}
|
|
211
247
|
|
|
212
248
|
xt_value xt_mod(xt_value a, xt_value b) {
|
|
249
|
+
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_mod(a, b);
|
|
250
|
+
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
251
|
+
xt_throw_mixed_bigint();
|
|
252
|
+
return XT_UNDEFINED;
|
|
253
|
+
}
|
|
213
254
|
double x = xt_to_number(a);
|
|
214
255
|
double y = xt_to_number(b);
|
|
215
256
|
return xt_number(fmod(x, y));
|
|
216
257
|
}
|
|
217
258
|
|
|
218
|
-
xt_value xt_pow(xt_value a, xt_value b) {
|
|
219
|
-
|
|
220
|
-
|
|
259
|
+
xt_value xt_pow(xt_value a, xt_value b) {
|
|
260
|
+
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_pow(a, b);
|
|
261
|
+
return xt_number(pow(xt_to_number(a), xt_to_number(b)));
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
xt_value xt_neg(xt_value a) {
|
|
265
|
+
if (XT_IS_BIGINT(a)) return xt_bigint_neg(a);
|
|
266
|
+
return xt_number(-xt_to_number(a));
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
xt_value xt_pos(xt_value a) {
|
|
270
|
+
if (XT_IS_BIGINT(a)) return a;
|
|
271
|
+
return xt_number(xt_to_number(a));
|
|
272
|
+
}
|
|
221
273
|
|
|
222
274
|
int32_t xt_to_int32(xt_value v) {
|
|
223
275
|
double d = xt_to_number(v);
|
|
@@ -225,13 +277,61 @@ int32_t xt_to_int32(xt_value v) {
|
|
|
225
277
|
return (int32_t)(uint32_t)(int64_t)d;
|
|
226
278
|
}
|
|
227
279
|
|
|
228
|
-
xt_value xt_bit_and(xt_value a, xt_value b) {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
280
|
+
xt_value xt_bit_and(xt_value a, xt_value b) {
|
|
281
|
+
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_bit_and(a, b);
|
|
282
|
+
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
283
|
+
xt_throw_mixed_bigint();
|
|
284
|
+
return XT_UNDEFINED;
|
|
285
|
+
}
|
|
286
|
+
return xt_number((double)(xt_to_int32(a) & xt_to_int32(b)));
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
xt_value xt_bit_or(xt_value a, xt_value b) {
|
|
290
|
+
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_bit_or(a, b);
|
|
291
|
+
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
292
|
+
xt_throw_mixed_bigint();
|
|
293
|
+
return XT_UNDEFINED;
|
|
294
|
+
}
|
|
295
|
+
return xt_number((double)(xt_to_int32(a) | xt_to_int32(b)));
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
xt_value xt_bit_xor(xt_value a, xt_value b) {
|
|
299
|
+
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_bit_xor(a, b);
|
|
300
|
+
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
301
|
+
xt_throw_mixed_bigint();
|
|
302
|
+
return XT_UNDEFINED;
|
|
303
|
+
}
|
|
304
|
+
return xt_number((double)(xt_to_int32(a) ^ xt_to_int32(b)));
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
xt_value xt_bit_not(xt_value a) {
|
|
308
|
+
if (XT_IS_BIGINT(a)) return xt_bigint_bit_not(a);
|
|
309
|
+
return xt_number((double)(~xt_to_int32(a)));
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
xt_value xt_shl(xt_value a, xt_value b) {
|
|
313
|
+
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_shl(a, b);
|
|
314
|
+
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
315
|
+
xt_throw_mixed_bigint();
|
|
316
|
+
return XT_UNDEFINED;
|
|
317
|
+
}
|
|
318
|
+
return xt_number((double)(int32_t)((uint32_t)xt_to_int32(a) << (xt_to_int32(b) & 31)));
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
xt_value xt_shr(xt_value a, xt_value b) {
|
|
322
|
+
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_shr(a, b);
|
|
323
|
+
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
324
|
+
xt_throw_mixed_bigint();
|
|
325
|
+
return XT_UNDEFINED;
|
|
326
|
+
}
|
|
327
|
+
return xt_number((double)(xt_to_int32(a) >> (xt_to_int32(b) & 31)));
|
|
328
|
+
}
|
|
329
|
+
|
|
234
330
|
xt_value xt_ushr(xt_value a, xt_value b) {
|
|
331
|
+
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
332
|
+
xt_throw(xt_string_from_cstr("TypeError: BigInts have no unsigned right shift, use >> instead"));
|
|
333
|
+
return XT_UNDEFINED;
|
|
334
|
+
}
|
|
235
335
|
return xt_number((double)(uint32_t)((uint32_t)xt_to_int32(a) >> (xt_to_int32(b) & 31)));
|
|
236
336
|
}
|
|
237
337
|
|
|
@@ -239,6 +339,30 @@ xt_value xt_ushr(xt_value a, xt_value b) {
|
|
|
239
339
|
/* Comparison */
|
|
240
340
|
/* ------------------------------------------------------------------------- */
|
|
241
341
|
|
|
342
|
+
/** Mixed numeric/bigint comparison; returns -1/0/1, or 2 for unordered. */
|
|
343
|
+
static int xt_compare_numeric(xt_value a, xt_value b) {
|
|
344
|
+
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bigint_compare(a, b);
|
|
345
|
+
if (XT_IS_BIGINT(a)) {
|
|
346
|
+
if (XT_IS_NUMBER(b)) return xt_bigint_compare_double(a, xt_to_double(b));
|
|
347
|
+
if (XT_IS_STRING(b)) {
|
|
348
|
+
double n = xt_to_number(b);
|
|
349
|
+
if (isnan(n)) return 2;
|
|
350
|
+
return xt_bigint_compare_double(a, n);
|
|
351
|
+
}
|
|
352
|
+
if (b == XT_TRUE) return xt_bigint_compare_double(a, 1.0);
|
|
353
|
+
if (b == XT_FALSE) return xt_bigint_compare_double(a, 0.0);
|
|
354
|
+
return 2;
|
|
355
|
+
}
|
|
356
|
+
if (XT_IS_BIGINT(b)) {
|
|
357
|
+
int cmp = xt_compare_numeric(b, a);
|
|
358
|
+
return cmp == 2 ? 2 : -cmp;
|
|
359
|
+
}
|
|
360
|
+
double x = xt_to_number(a);
|
|
361
|
+
double y = xt_to_number(b);
|
|
362
|
+
if (isnan(x) || isnan(y)) return 2;
|
|
363
|
+
return x < y ? -1 : (x > y ? 1 : 0);
|
|
364
|
+
}
|
|
365
|
+
|
|
242
366
|
xt_value xt_lt(xt_value a, xt_value b) {
|
|
243
367
|
if (XT_IS_STRING(a) && XT_IS_STRING(b)) {
|
|
244
368
|
xt_string *x = xt_as_string(a);
|
|
@@ -248,6 +372,7 @@ xt_value xt_lt(xt_value a, xt_value b) {
|
|
|
248
372
|
if (cmp == 0) return xt_bool(x->length < y->length);
|
|
249
373
|
return xt_bool(cmp < 0);
|
|
250
374
|
}
|
|
375
|
+
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) return xt_bool(xt_compare_numeric(a, b) == -1);
|
|
251
376
|
return xt_bool(xt_to_number(a) < xt_to_number(b));
|
|
252
377
|
}
|
|
253
378
|
|
|
@@ -260,6 +385,10 @@ xt_value xt_le(xt_value a, xt_value b) {
|
|
|
260
385
|
if (cmp == 0) return xt_bool(x->length <= y->length);
|
|
261
386
|
return xt_bool(cmp < 0);
|
|
262
387
|
}
|
|
388
|
+
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
389
|
+
int cmp = xt_compare_numeric(a, b);
|
|
390
|
+
return xt_bool(cmp != 2 && cmp <= 0);
|
|
391
|
+
}
|
|
263
392
|
return xt_bool(xt_to_number(a) <= xt_to_number(b));
|
|
264
393
|
}
|
|
265
394
|
|
|
@@ -271,6 +400,19 @@ static int xt_loose_equals(xt_value a, xt_value b) {
|
|
|
271
400
|
if (XT_IS_STRING(a) && XT_IS_STRING(b)) return xt_string_equals(xt_as_string(a), xt_as_string(b));
|
|
272
401
|
if (a == b) return 1;
|
|
273
402
|
if ((a == XT_NULL && b == XT_UNDEFINED) || (a == XT_UNDEFINED && b == XT_NULL)) return 1;
|
|
403
|
+
if (XT_IS_BIGINT(a) || XT_IS_BIGINT(b)) {
|
|
404
|
+
xt_value big = XT_IS_BIGINT(a) ? a : b;
|
|
405
|
+
xt_value other = XT_IS_BIGINT(a) ? b : a;
|
|
406
|
+
if (XT_IS_BIGINT(other)) return xt_bigint_compare(big, other) == 0;
|
|
407
|
+
if (XT_IS_NUMBER(other)) return xt_bigint_compare_double(big, xt_to_double(other)) == 0;
|
|
408
|
+
if (XT_IS_STRING(other)) {
|
|
409
|
+
int cmp = xt_compare_numeric(big, other);
|
|
410
|
+
return cmp == 0;
|
|
411
|
+
}
|
|
412
|
+
if (other == XT_TRUE) return xt_bigint_compare_double(big, 1.0) == 0;
|
|
413
|
+
if (other == XT_FALSE) return xt_bigint_compare_double(big, 0.0) == 0;
|
|
414
|
+
return 0;
|
|
415
|
+
}
|
|
274
416
|
if (XT_IS_BOOL(a)) return xt_loose_equals(xt_number(xt_to_number(a)), b);
|
|
275
417
|
if (XT_IS_BOOL(b)) return xt_loose_equals(a, xt_number(xt_to_number(b)));
|
|
276
418
|
if (XT_IS_STRING(a) && XT_IS_NUMBER(b)) return xt_to_number(a) == xt_to_double(b);
|
|
@@ -284,6 +426,7 @@ xt_value xt_ne(xt_value a, xt_value b) { return xt_bool(!xt_loose_equals(a, b));
|
|
|
284
426
|
xt_value xt_seq(xt_value a, xt_value b) {
|
|
285
427
|
if (XT_IS_NUMBER(a) && XT_IS_NUMBER(b)) return xt_bool(xt_to_double(a) == xt_to_double(b));
|
|
286
428
|
if (XT_IS_STRING(a) && XT_IS_STRING(b)) return xt_bool(xt_string_equals(xt_as_string(a), xt_as_string(b)));
|
|
429
|
+
if (XT_IS_BIGINT(a) && XT_IS_BIGINT(b)) return xt_bool(xt_bigint_compare(a, b) == 0);
|
|
287
430
|
return xt_bool(a == b);
|
|
288
431
|
}
|
|
289
432
|
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Build the prebuilt runtime archives shipped with xbintsc:
|
|
4
|
+
*
|
|
5
|
+
* runtime/lib/<os>-<arch>/core.a compiled from RUNTIME_SOURCES
|
|
6
|
+
* runtime/lib/<os>-<arch>/ext_node.a compiled from nodeExtension.runtimeSources()
|
|
7
|
+
*
|
|
8
|
+
* The driver prefers these archives (see `src/driver/runtime-lib.ts`) and falls
|
|
9
|
+
* back to compiling the C sources on demand when they are missing. Run this in
|
|
10
|
+
* CI (or locally) after the runtime sources change.
|
|
11
|
+
*
|
|
12
|
+
* Environment:
|
|
13
|
+
* xbintsc_CLANG C compiler override (otherwise the resolved toolchain is used)
|
|
14
|
+
* xbintsc_AR archiver override (otherwise `llvm-ar`, then `ar`)
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { mkdirSync, rmSync } from "node:fs";
|
|
18
|
+
import { spawnSync } from "node:child_process";
|
|
19
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
20
|
+
import { fileURLToPath } from "node:url";
|
|
21
|
+
import { RUNTIME_SOURCES } from "../src/driver/compiler.js";
|
|
22
|
+
import { platformSlug } from "../src/driver/paths.js";
|
|
23
|
+
import { resolveToolchain } from "../src/driver/toolchain-provider.js";
|
|
24
|
+
import { nodeExtension } from "../src/extensions/node/index.js";
|
|
25
|
+
|
|
26
|
+
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
27
|
+
const runtimeDir = join(root, "runtime");
|
|
28
|
+
const outDir = join(runtimeDir, "lib", platformSlug());
|
|
29
|
+
const objDir = join(root, "build", "runtime-obj");
|
|
30
|
+
|
|
31
|
+
if (process.platform === "win32") {
|
|
32
|
+
// The Windows release ships no prebuilt archives yet: the current MSVC CI
|
|
33
|
+
// cannot produce MinGW-compatible objects, so the driver compiles the C
|
|
34
|
+
// sources on demand. Revisit once the bundled MinGW-w64 ABI lands.
|
|
35
|
+
// See doc/self-contained-roadmap.md.
|
|
36
|
+
console.log("xbintsc: skipped runtime archives on Windows until the MinGW-w64 toolchain lands");
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Use the same toolchain the driver will: a bundled clang when present, with its
|
|
41
|
+
// `LD_LIBRARY_PATH` (the legacy `libtinfo.so.5` on Linux) threaded through.
|
|
42
|
+
const toolchain = resolveToolchain();
|
|
43
|
+
const clang = toolchain.clang;
|
|
44
|
+
const childEnv = Object.assign({}, process.env, toolchain.env);
|
|
45
|
+
|
|
46
|
+
function isRunnable(candidate: string): boolean {
|
|
47
|
+
// An existing tool may still exit non-zero for `--version` (Apple `ar` does);
|
|
48
|
+
// we only care that spawning it did not fail with ENOENT.
|
|
49
|
+
return !spawnSync(candidate, [], { encoding: "utf8" }).error;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function findArchiver(clangPath: string): string {
|
|
53
|
+
const dir = dirname(clangPath);
|
|
54
|
+
const exe = process.platform === "win32" ? ".exe" : "";
|
|
55
|
+
const candidates = [
|
|
56
|
+
process.env.xbintsc_AR,
|
|
57
|
+
// A bundled toolchain ships `llvm-ar` next to clang.
|
|
58
|
+
dir === "." ? undefined : join(dir, `llvm-ar${exe}`),
|
|
59
|
+
"llvm-ar",
|
|
60
|
+
"ar",
|
|
61
|
+
].filter((candidate): candidate is string => Boolean(candidate));
|
|
62
|
+
for (const candidate of candidates) {
|
|
63
|
+
if (isRunnable(candidate)) return candidate;
|
|
64
|
+
}
|
|
65
|
+
console.error("xbintsc: no archiver found; set xbintsc_AR to llvm-ar or ar");
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function compile(sources: readonly string[], extension: string): string[] {
|
|
70
|
+
mkdirSync(objDir, { recursive: true });
|
|
71
|
+
const objects: string[] = [];
|
|
72
|
+
sources.forEach((source, index) => {
|
|
73
|
+
const object = join(objDir, `${extension}_${index}_${basename(source, ".c")}.o`);
|
|
74
|
+
const result = spawnSync(
|
|
75
|
+
clang,
|
|
76
|
+
["-O2", "-D_CRT_SECURE_NO_WARNINGS", "-c", source, "-o", object, `-I${runtimeDir}`],
|
|
77
|
+
{ stdio: "inherit", env: childEnv },
|
|
78
|
+
);
|
|
79
|
+
if (result.status !== 0) {
|
|
80
|
+
console.error(`xbintsc: failed to compile ${source}`);
|
|
81
|
+
process.exit(result.status ?? 1);
|
|
82
|
+
}
|
|
83
|
+
objects.push(object);
|
|
84
|
+
});
|
|
85
|
+
return objects;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function archive(name: string, objects: string[], ar: string): void {
|
|
89
|
+
mkdirSync(outDir, { recursive: true });
|
|
90
|
+
const output = join(outDir, name);
|
|
91
|
+
rmSync(output, { force: true });
|
|
92
|
+
const result = spawnSync(ar, ["rcs", output, ...objects], { stdio: "inherit", env: childEnv });
|
|
93
|
+
if (result.status !== 0) {
|
|
94
|
+
console.error(`xbintsc: failed to archive ${name}`);
|
|
95
|
+
process.exit(result.status ?? 1);
|
|
96
|
+
}
|
|
97
|
+
console.log(`xbintsc: wrote ${output}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
console.log(`xbintsc: runtime toolchain ${clang} (${toolchain.source})`);
|
|
101
|
+
const coreObjects = compile(RUNTIME_SOURCES.map((source) => join(runtimeDir, source)), "core");
|
|
102
|
+
|
|
103
|
+
const ar = findArchiver(clang);
|
|
104
|
+
archive("core.a", coreObjects, ar);
|
|
105
|
+
|
|
106
|
+
const nodeSources = nodeExtension.runtimeSources?.() ?? [];
|
|
107
|
+
if (nodeSources.length > 0) {
|
|
108
|
+
archive("ext_node.a", compile(nodeSources, "node"), ar);
|
|
109
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Download the pinned toolchain that xbintsc bundles for this host into
|
|
4
|
+
* `vendor/<os>-<arch>/`, so `build` needs no user-installed compiler:
|
|
5
|
+
*
|
|
6
|
+
* Linux -> official LLVM release (clang + lld + llvm-ar) plus the legacy
|
|
7
|
+
* `libtinfo.so.5` shared library the official build still needs
|
|
8
|
+
* Windows -> llvm-mingw (clang + lld + MinGW-w64 CRT/import libraries)
|
|
9
|
+
* macOS -> nothing; the Xcode Command Line Tools are the prerequisite
|
|
10
|
+
*
|
|
11
|
+
* Requires `curl`, `tar` and (on Linux) `ar` on PATH; all are present on
|
|
12
|
+
* GitHub-hosted runners. Pass `--force` to refetch an existing toolchain.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { copyFileSync, existsSync, mkdirSync, rmSync } from "node:fs";
|
|
16
|
+
import { spawnSync } from "node:child_process";
|
|
17
|
+
import { join } from "node:path";
|
|
18
|
+
import { tmpdir } from "node:os";
|
|
19
|
+
import { platformSlug, vendorRootDir } from "../src/driver/paths.js";
|
|
20
|
+
import { toolchainDownload, toolchainSupportLibraries } from "../src/driver/toolchain-download.js";
|
|
21
|
+
|
|
22
|
+
const force = process.argv.includes("--force");
|
|
23
|
+
const target = toolchainDownload();
|
|
24
|
+
|
|
25
|
+
if (!target) {
|
|
26
|
+
console.log(
|
|
27
|
+
`xbintsc: no bundled toolchain for ${platformSlug()}; using the system SDK (macOS: Xcode Command Line Tools)`,
|
|
28
|
+
);
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const vendorDir = join(vendorRootDir(), platformSlug());
|
|
33
|
+
const clangName = process.platform === "win32" ? "clang.exe" : "clang";
|
|
34
|
+
const clangPath = join(vendorDir, "bin", clangName);
|
|
35
|
+
|
|
36
|
+
function run(command: string, args: readonly string[], cwd?: string): void {
|
|
37
|
+
const result = spawnSync(command, [...args], { stdio: "inherit", cwd });
|
|
38
|
+
if (result.status !== 0) {
|
|
39
|
+
console.error(`xbintsc: command failed: ${command} ${args.join(" ")}`);
|
|
40
|
+
process.exit(result.status ?? 1);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Download the first reachable URL to `dest`, failing after the last one. */
|
|
45
|
+
function download(urls: readonly string[], dest: string): void {
|
|
46
|
+
for (const url of urls) {
|
|
47
|
+
console.log(`xbintsc: downloading ${url}`);
|
|
48
|
+
const result = spawnSync("curl", ["-fL", "--retry", "3", "-o", dest, url], { stdio: "inherit" });
|
|
49
|
+
if (result.status === 0) return;
|
|
50
|
+
console.log("xbintsc: download failed, trying the next mirror");
|
|
51
|
+
}
|
|
52
|
+
console.error(`xbintsc: could not download ${dest}`);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const workDir = join(tmpdir(), `xbintsc-toolchain-${process.pid}`);
|
|
57
|
+
rmSync(workDir, { recursive: true, force: true });
|
|
58
|
+
mkdirSync(workDir, { recursive: true });
|
|
59
|
+
|
|
60
|
+
if (existsSync(clangPath) && !force) {
|
|
61
|
+
console.log(`xbintsc: toolchain already present at ${vendorDir}`);
|
|
62
|
+
} else {
|
|
63
|
+
const archivePath = join(workDir, target.archive);
|
|
64
|
+
download([target.url], archivePath);
|
|
65
|
+
console.log(`xbintsc: extracting into ${vendorDir}`);
|
|
66
|
+
mkdirSync(vendorDir, { recursive: true });
|
|
67
|
+
// `tar` here is bsdtar on macOS/Windows and GNU tar on Linux; both accept
|
|
68
|
+
// `--strip-components`, and bsdtar also unpacks the `.zip` used on Windows.
|
|
69
|
+
run("tar", ["-xf", archivePath, "-C", vendorDir, `--strip-components=${target.stripComponents}`]);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Shared libraries the bundled toolchain needs but the OS does not provide.
|
|
73
|
+
const supportLibraries = toolchainSupportLibraries();
|
|
74
|
+
if (supportLibraries.length > 0) {
|
|
75
|
+
const libDir = join(vendorDir, "lib");
|
|
76
|
+
mkdirSync(libDir, { recursive: true });
|
|
77
|
+
for (const library of supportLibraries) {
|
|
78
|
+
const dest = join(libDir, library.dest);
|
|
79
|
+
if (existsSync(dest) && !force) {
|
|
80
|
+
console.log(`xbintsc: already bundled ${library.dest}`);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const debPath = join(workDir, library.archive);
|
|
84
|
+
download(library.urls, debPath);
|
|
85
|
+
const debDir = join(workDir, `deb-${library.dest}`);
|
|
86
|
+
mkdirSync(debDir, { recursive: true });
|
|
87
|
+
// A `.deb` is an `ar` archive whose `data.tar.*` member holds the files.
|
|
88
|
+
run("ar", ["x", debPath], debDir);
|
|
89
|
+
run("tar", ["-xf", join(debDir, "data.tar.xz"), "-C", debDir]);
|
|
90
|
+
copyFileSync(join(debDir, library.member), dest);
|
|
91
|
+
console.log(`xbintsc: bundled ${library.dest}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
rmSync(workDir, { recursive: true, force: true });
|
|
96
|
+
|
|
97
|
+
if (!existsSync(clangPath)) {
|
|
98
|
+
console.error(`xbintsc: expected ${clangPath} after extraction`);
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
console.log(`xbintsc: done -> ${clangPath}`);
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Assemble a self-contained release archive for the current platform:
|
|
4
|
+
*
|
|
5
|
+
* dist/release/xbintsc-<os>-<arch>.tar.gz (or .tar.zst)
|
|
6
|
+
* dist/release/xbintsc-<os>-<arch>.tar.gz.sha256
|
|
7
|
+
*
|
|
8
|
+
* The unpacked staging tree is built under `build/release-stage/`, never under
|
|
9
|
+
* `dist/release/`, so an upload glob over `dist/release/*` cannot accidentally
|
|
10
|
+
* ship the (multi-GB) tree alongside the archive.
|
|
11
|
+
*
|
|
12
|
+
* Layout inside the archive:
|
|
13
|
+
*
|
|
14
|
+
* xbintsc-<os>-<arch>/
|
|
15
|
+
* bin/xbintsc[.exe] the self-hosted compiler
|
|
16
|
+
* runtime/ C runtime sources + prebuilt runtime/lib/<slug>
|
|
17
|
+
* vendor/<slug>/ the bundled clang+lld toolchain (Linux/Windows)
|
|
18
|
+
* README.md
|
|
19
|
+
*
|
|
20
|
+
* The compiler locates `runtime/` and `vendor/` relative to its own executable
|
|
21
|
+
* (see `findRuntimeDir`/`findVendorDir`), so this tree runs with no system
|
|
22
|
+
* toolchain installed.
|
|
23
|
+
*
|
|
24
|
+
* Inputs:
|
|
25
|
+
* - the self-hosted binary staged at `dist/xbintsc[.exe]` (CI copies it there)
|
|
26
|
+
* - `vendor/<slug>/`, fetched by `scripts/fetch-toolchain.ts`
|
|
27
|
+
* - `runtime/lib/<slug>/`, built by `scripts/build-runtime.ts`
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import { createHash } from "node:crypto";
|
|
31
|
+
import {
|
|
32
|
+
copyFileSync,
|
|
33
|
+
cpSync,
|
|
34
|
+
chmodSync,
|
|
35
|
+
existsSync,
|
|
36
|
+
mkdirSync,
|
|
37
|
+
readdirSync,
|
|
38
|
+
readFileSync,
|
|
39
|
+
realpathSync,
|
|
40
|
+
rmSync,
|
|
41
|
+
statSync,
|
|
42
|
+
writeFileSync,
|
|
43
|
+
} from "node:fs";
|
|
44
|
+
import { spawnSync } from "node:child_process";
|
|
45
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
46
|
+
import { fileURLToPath } from "node:url";
|
|
47
|
+
import {
|
|
48
|
+
findRuntimeDir,
|
|
49
|
+
platformSlug,
|
|
50
|
+
releaseArchiveBase,
|
|
51
|
+
releaseArchiveExtension,
|
|
52
|
+
} from "../src/driver/paths.js";
|
|
53
|
+
|
|
54
|
+
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
55
|
+
const slug = platformSlug();
|
|
56
|
+
const base = releaseArchiveBase();
|
|
57
|
+
const exeSuffix = process.platform === "win32" ? ".exe" : "";
|
|
58
|
+
|
|
59
|
+
function fail(message: string): never {
|
|
60
|
+
console.error(`xbintsc: ${message}`);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** First existing path from a list of candidates. */
|
|
65
|
+
function firstExisting(candidates: readonly string[]): string | undefined {
|
|
66
|
+
for (const candidate of candidates) {
|
|
67
|
+
if (existsSync(candidate)) return candidate;
|
|
68
|
+
}
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Copy only the parts of the fetched toolchain that xbintsc actually runs.
|
|
74
|
+
*
|
|
75
|
+
* The official LLVM release unpacks to ~7 GB: every MLIR/Flang/lldb tool, the
|
|
76
|
+
* static archives and the full C++ headers. The compiler only shells out to the
|
|
77
|
+
* clang driver, the lld linker and llvm-ar, and clang additionally needs its own
|
|
78
|
+
* resource directory (`lib/clang/<version>`, the builtin headers and
|
|
79
|
+
* compiler-rt). Copying just those keeps the archive ~100x smaller.
|
|
80
|
+
*/
|
|
81
|
+
function stageToolchain(vendor: string, dest: string): void {
|
|
82
|
+
const exe = process.platform === "win32" ? ".exe" : "";
|
|
83
|
+
mkdirSync(join(dest, "bin"), { recursive: true });
|
|
84
|
+
|
|
85
|
+
const real = (...candidates: readonly string[]): string | undefined => {
|
|
86
|
+
const found = firstExisting(candidates.map((candidate) => join(vendor, candidate)));
|
|
87
|
+
return found ? realpathSync(found) : undefined;
|
|
88
|
+
};
|
|
89
|
+
const copyAs = (source: string | undefined, name: string): void => {
|
|
90
|
+
if (!source) return;
|
|
91
|
+
const target = join(dest, "bin", name);
|
|
92
|
+
copyFileSync(source, target);
|
|
93
|
+
if (process.platform !== "win32") chmodSync(target, 0o755);
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// In the official release `clang`/`ld.lld` are symlinks into the bin/ dir;
|
|
97
|
+
// copy the resolved targets under the names the toolchain provider (and
|
|
98
|
+
// clang's `-fuse-ld=lld`) expect next to `bin/clang`.
|
|
99
|
+
copyAs(real(`bin/clang${exe}`, `bin/clang-18${exe}`), `clang${exe}`);
|
|
100
|
+
copyAs(real(`bin/ld.lld${exe}`, `bin/lld${exe}`), `ld.lld${exe}`);
|
|
101
|
+
copyAs(real(`bin/llvm-ar${exe}`, "bin/llvm-ar"), `llvm-ar${exe}`);
|
|
102
|
+
|
|
103
|
+
// clang's resource directory: builtin headers + compiler-rt archives.
|
|
104
|
+
const resourceDir = join(vendor, "lib", "clang");
|
|
105
|
+
if (existsSync(resourceDir)) {
|
|
106
|
+
cpSync(resourceDir, join(dest, "lib", "clang"), { recursive: true });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Shared libraries the fetch placed next to the toolchain (on Linux that is
|
|
110
|
+
// the legacy `libtinfo.so.5` the official build still links).
|
|
111
|
+
const libDir = join(vendor, "lib");
|
|
112
|
+
if (existsSync(libDir)) {
|
|
113
|
+
for (const entry of readdirSync(libDir, { withFileTypes: true })) {
|
|
114
|
+
if (/^(.*\.so(\.\d+)*|.*\.dylib|.*\.dll)$/.test(entry.name)) {
|
|
115
|
+
cpSync(join(libDir, entry.name), join(dest, "lib", entry.name), { recursive: true });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const distDir = join(root, "dist");
|
|
122
|
+
const binary = firstExisting([
|
|
123
|
+
join(distDir, `xbintsc${exeSuffix}`),
|
|
124
|
+
join(distDir, "main" + exeSuffix),
|
|
125
|
+
join(root, "scratch", "self", `main${exeSuffix}`),
|
|
126
|
+
]);
|
|
127
|
+
if (!binary) {
|
|
128
|
+
fail(`no self-hosted binary found under ${distDir} (expected dist/xbintsc${exeSuffix})`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Archives go to `dist/release/`; the unpacked staging tree goes to
|
|
132
|
+
// `build/release-stage/` so the upload glob over `dist/release/*` cannot pick up
|
|
133
|
+
// the raw tree (which would ship the toolchain twice, and uncompressed).
|
|
134
|
+
const releaseRoot = join(distDir, "release");
|
|
135
|
+
const stageRoot = join(root, "build", "release-stage");
|
|
136
|
+
const stage = join(stageRoot, base);
|
|
137
|
+
rmSync(stage, { recursive: true, force: true });
|
|
138
|
+
mkdirSync(join(stage, "bin"), { recursive: true });
|
|
139
|
+
mkdirSync(releaseRoot, { recursive: true });
|
|
140
|
+
|
|
141
|
+
// 1. The compiler binary.
|
|
142
|
+
const stagedBinary = join(stage, "bin", `xbintsc${exeSuffix}`);
|
|
143
|
+
copyFileSync(binary, stagedBinary);
|
|
144
|
+
if (process.platform !== "win32") chmodSync(stagedBinary, 0o755);
|
|
145
|
+
console.log(`xbintsc: packaged binary ${basename(binary)} (${statSync(binary).size} bytes)`);
|
|
146
|
+
|
|
147
|
+
// 2. The C runtime (sources fallback + prebuilt archives) next to the binary.
|
|
148
|
+
cpSync(findRuntimeDir(), join(stage, "runtime"), { recursive: true });
|
|
149
|
+
console.log("xbintsc: packaged runtime/");
|
|
150
|
+
|
|
151
|
+
// 3. The bundled toolchain, when one was fetched for this platform.
|
|
152
|
+
const vendor = join(root, "vendor", slug);
|
|
153
|
+
if (existsSync(join(vendor, "bin"))) {
|
|
154
|
+
if (process.platform === "win32") {
|
|
155
|
+
// llvm-mingw spreads its MinGW-w64 CRT/import libraries across the tree, so
|
|
156
|
+
// bundling it whole is the safe default there for now.
|
|
157
|
+
cpSync(vendor, join(stage, "vendor", slug), { recursive: true });
|
|
158
|
+
} else {
|
|
159
|
+
stageToolchain(vendor, join(stage, "vendor", slug));
|
|
160
|
+
}
|
|
161
|
+
console.log(`xbintsc: packaged vendor/${slug}/`);
|
|
162
|
+
} else if (process.platform === "linux" || process.platform === "win32") {
|
|
163
|
+
console.warn(
|
|
164
|
+
`xbintsc: warning: no vendor/${slug}/ found; the release will rely on a system toolchain. ` +
|
|
165
|
+
"Run `npm run fetch-toolchain` first for a self-contained archive.",
|
|
166
|
+
);
|
|
167
|
+
} else {
|
|
168
|
+
console.log(`xbintsc: no bundled toolchain for ${slug}; relying on the system SDK (macOS)`);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// 4. Human-facing notes.
|
|
172
|
+
for (const name of ["README.md", "LICENSE"]) {
|
|
173
|
+
const source = join(root, name);
|
|
174
|
+
if (existsSync(source)) copyFileSync(source, join(stage, name));
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// 5. Archive it. Prefer zstd when available, otherwise gzip.
|
|
178
|
+
const hasZstd = !spawnSync("zstd", ["--version"], { stdio: "ignore" }).error;
|
|
179
|
+
const extension = releaseArchiveExtension(hasZstd);
|
|
180
|
+
const archive = join(releaseRoot, `${base}${extension}`);
|
|
181
|
+
rmSync(archive, { force: true });
|
|
182
|
+
const tarArgs = ["-c", hasZstd ? "--zstd" : "-z", "-f", archive, "-C", stageRoot, base];
|
|
183
|
+
const tar = spawnSync("tar", tarArgs, { stdio: "inherit" });
|
|
184
|
+
if (tar.error) fail(`failed to run tar: ${tar.error.message}`);
|
|
185
|
+
if (tar.status !== 0) fail(`tar exited with ${tar.status}`);
|
|
186
|
+
|
|
187
|
+
// 6. Checksum, so users can verify the download.
|
|
188
|
+
const digest = createHash("sha256").update(readFileSync(archive)).digest("hex");
|
|
189
|
+
writeFileSync(`${archive}.sha256`, `${digest} ${basename(archive)}\n`);
|
|
190
|
+
|
|
191
|
+
console.log(`xbintsc: wrote ${archive} (${statSync(archive).size} bytes)`);
|
|
192
|
+
console.log(`xbintsc: sha256 ${digest}`);
|
package/src/ast/expressions.ts
CHANGED
|
@@ -113,6 +113,8 @@ export interface PropertyAssignment extends Node {
|
|
|
113
113
|
export interface ShorthandPropertyAssignment extends Node {
|
|
114
114
|
readonly kind: SyntaxKind.ShorthandPropertyAssignment;
|
|
115
115
|
readonly name: Identifier;
|
|
116
|
+
/** Present for `{ a = default }` when used as a destructuring target. */
|
|
117
|
+
readonly initializer?: Expression;
|
|
116
118
|
}
|
|
117
119
|
|
|
118
120
|
export interface SpreadElement extends Node {
|