xbintsc 0.2.9 → 0.3.3
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 +78 -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 +1 -0
- 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
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/* ------------------------------------------------------------------------- */
|
|
2
|
+
/* Public constructors and statics */
|
|
3
|
+
/* ------------------------------------------------------------------------- */
|
|
4
|
+
|
|
5
|
+
xt_value xt_bigint_ctor(int32_t argc, xt_value *argv) {
|
|
6
|
+
if (argc < 1) {
|
|
7
|
+
bi_throw_type("Cannot convert undefined to a BigInt");
|
|
8
|
+
return bi_wrap(bi_zero());
|
|
9
|
+
}
|
|
10
|
+
return bi_from_xt_value(argv[0]);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static xt_value bi_as_n(int32_t bits, xt_value value, int signedResult) {
|
|
14
|
+
if (!XT_IS_BIGINT(value)) value = bi_from_xt_value(value);
|
|
15
|
+
if (bits <= 0) return xt_bigint_from_i64(0);
|
|
16
|
+
uint32_t count = ((uint32_t)bits + 31u) / 32u;
|
|
17
|
+
uint32_t *tmp = (uint32_t *)calloc(count ? count : 1, sizeof(uint32_t));
|
|
18
|
+
if (!tmp) abort();
|
|
19
|
+
bi_to_twos(BI(value), tmp, count);
|
|
20
|
+
uint32_t rem = (uint32_t)bits & 31u;
|
|
21
|
+
if (rem) {
|
|
22
|
+
uint32_t mask = (1u << rem) - 1u;
|
|
23
|
+
tmp[count - 1] &= mask;
|
|
24
|
+
if (signedResult && (tmp[count - 1] & (1u << (rem - 1)))) {
|
|
25
|
+
tmp[count - 1] |= ~mask;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
xt_bigint *r = signedResult ? bi_from_twos(tmp, count) : bi_from_unsigned(tmp, count);
|
|
29
|
+
free(tmp);
|
|
30
|
+
return bi_wrap(r);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
xt_value xt_bigint_static(xt_value name, int32_t argc, xt_value *argv) {
|
|
34
|
+
const char *fn = xt_string_data(name);
|
|
35
|
+
if (!fn) return XT_UNDEFINED;
|
|
36
|
+
if (strcmp(fn, "asIntN") == 0) {
|
|
37
|
+
int32_t bits = argc >= 1 ? xt_to_int32(argv[0]) : 0;
|
|
38
|
+
xt_value value = xt_arg_at(argc, argv, 1);
|
|
39
|
+
return bi_as_n(bits, value, 1);
|
|
40
|
+
}
|
|
41
|
+
if (strcmp(fn, "asUintN") == 0) {
|
|
42
|
+
int32_t bits = argc >= 1 ? xt_to_int32(argv[0]) : 0;
|
|
43
|
+
xt_value value = xt_arg_at(argc, argv, 1);
|
|
44
|
+
return bi_as_n(bits, value, 0);
|
|
45
|
+
}
|
|
46
|
+
return XT_UNDEFINED;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
xt_value xt_bigint_method(xt_value target, const char *method, int32_t argc, xt_value *argv, int *handled) {
|
|
50
|
+
*handled = 1;
|
|
51
|
+
if (strcmp(method, "toString") == 0) {
|
|
52
|
+
int radix = argc >= 1 && argv[0] != XT_UNDEFINED ? xt_to_int32(argv[0]) : 10;
|
|
53
|
+
return xt_bigint_to_string_radix(target, radix);
|
|
54
|
+
}
|
|
55
|
+
if (strcmp(method, "toLocaleString") == 0) return xt_bigint_to_decimal(target);
|
|
56
|
+
if (strcmp(method, "valueOf") == 0) return target;
|
|
57
|
+
*handled = 0;
|
|
58
|
+
return XT_UNDEFINED;
|
|
59
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/* -- small in-place arithmetic -------------------------------------------- */
|
|
2
|
+
|
|
3
|
+
static void bi_add_small(xt_bigint *b, uint32_t value) {
|
|
4
|
+
if (value == 0) return;
|
|
5
|
+
bi_reserve(b, b->length + 1);
|
|
6
|
+
uint64_t carry = value;
|
|
7
|
+
for (uint32_t i = 0; i < b->length && carry; i++) {
|
|
8
|
+
uint64_t sum = (uint64_t)b->limbs[i] + carry;
|
|
9
|
+
b->limbs[i] = (uint32_t)sum;
|
|
10
|
+
carry = sum >> 32;
|
|
11
|
+
}
|
|
12
|
+
if (carry) b->limbs[b->length++] = (uint32_t)carry;
|
|
13
|
+
b->sign = 1;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static void bi_sub_small(xt_bigint *b, uint32_t value) {
|
|
17
|
+
uint64_t borrow = value;
|
|
18
|
+
for (uint32_t i = 0; i < b->length && borrow; i++) {
|
|
19
|
+
uint64_t cur = b->limbs[i];
|
|
20
|
+
if (cur < borrow) {
|
|
21
|
+
b->limbs[i] = (uint32_t)(cur + 0x100000000ULL - borrow);
|
|
22
|
+
borrow = 1;
|
|
23
|
+
} else {
|
|
24
|
+
b->limbs[i] = (uint32_t)(cur - borrow);
|
|
25
|
+
borrow = 0;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
bi_normalize(b);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static void bi_mul_small(xt_bigint *b, uint32_t value) {
|
|
32
|
+
if (b->length == 0) return;
|
|
33
|
+
if (value == 0) {
|
|
34
|
+
b->length = 0;
|
|
35
|
+
b->sign = 0;
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
bi_reserve(b, b->length + 1);
|
|
39
|
+
uint64_t carry = 0;
|
|
40
|
+
for (uint32_t i = 0; i < b->length; i++) {
|
|
41
|
+
uint64_t product = (uint64_t)b->limbs[i] * value + carry;
|
|
42
|
+
b->limbs[i] = (uint32_t)product;
|
|
43
|
+
carry = product >> 32;
|
|
44
|
+
}
|
|
45
|
+
if (carry) b->limbs[b->length++] = (uint32_t)carry;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static uint32_t bi_divmod_small(xt_bigint *b, uint32_t divisor) {
|
|
49
|
+
uint64_t remainder = 0;
|
|
50
|
+
for (uint32_t i = b->length; i-- > 0;) {
|
|
51
|
+
uint64_t cur = (remainder << 32) | b->limbs[i];
|
|
52
|
+
b->limbs[i] = (uint32_t)(cur / divisor);
|
|
53
|
+
remainder = cur % divisor;
|
|
54
|
+
}
|
|
55
|
+
bi_normalize(b);
|
|
56
|
+
return (uint32_t)remainder;
|
|
57
|
+
}
|
|
58
|
+
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* xbintsc runtime — arbitrary-precision integers (BigInt).
|
|
3
|
+
*
|
|
4
|
+
* BigInt values are sign-magnitude integers stored as little-endian base 2^32
|
|
5
|
+
* limb arrays behind the `XT_TAG_BIGINT` NaN-box tag. The implementation is
|
|
6
|
+
* deliberately small and dependency free: it favours clarity over throughput
|
|
7
|
+
* and covers everything the language subset needs (literals, arithmetic,
|
|
8
|
+
* bitwise operators, shifts, comparisons, string conversion and the
|
|
9
|
+
* `BigInt.asIntN` / `BigInt.asUintN` statics).
|
|
10
|
+
*
|
|
11
|
+
* Division uses binary long division (shift/subtract). That is O(bits*limbs)
|
|
12
|
+
* rather than the O(n*m) of Knuth's algorithm D, but keeps the code compact and
|
|
13
|
+
* is more than fast enough for the fixed-width (64-bit) values the compiler
|
|
14
|
+
* itself relies on.
|
|
15
|
+
*
|
|
16
|
+
* The implementation is grouped by functional area under `xt_bigint/` and
|
|
17
|
+
* `#include`d here as a single translation unit, so the limb helpers stay
|
|
18
|
+
* `static` while each file stays focused on one area.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
#include "rt_internal.h"
|
|
22
|
+
|
|
23
|
+
#include <limits.h>
|
|
24
|
+
#include <math.h>
|
|
25
|
+
#include <stdio.h>
|
|
26
|
+
#include <stdlib.h>
|
|
27
|
+
#include <string.h>
|
|
28
|
+
|
|
29
|
+
#define BI_LIMB_BITS 32
|
|
30
|
+
#define BI_MAX_SHIFT 0x01000000u /* 16 Mi bits: guard against runaway shifts */
|
|
31
|
+
|
|
32
|
+
#include "xt_bigint/helpers.inc"
|
|
33
|
+
#include "xt_bigint/small-arithmetic.inc"
|
|
34
|
+
#include "xt_bigint/magnitude.inc"
|
|
35
|
+
#include "xt_bigint/bits.inc"
|
|
36
|
+
#include "xt_bigint/division.inc"
|
|
37
|
+
#include "xt_bigint/format.inc"
|
|
38
|
+
#include "xt_bigint/conversions.inc"
|
|
39
|
+
#include "xt_bigint/compare.inc"
|
|
40
|
+
#include "xt_bigint/arithmetic.inc"
|
|
41
|
+
#include "xt_bigint/bitwise.inc"
|
|
42
|
+
#include "xt_bigint/public.inc"
|
package/runtime/xt_builtins.c
CHANGED
|
@@ -151,6 +151,7 @@ xt_value xt_boolean_ctor(int32_t argc, xt_value *argv) {
|
|
|
151
151
|
|
|
152
152
|
XT_BUILTIN_TRAMPOLINE(xt_builtin_value_boolean, xt_boolean_ctor)
|
|
153
153
|
XT_BUILTIN_TRAMPOLINE(xt_builtin_value_number, xt_number_ctor)
|
|
154
|
+
XT_BUILTIN_TRAMPOLINE(xt_builtin_value_bigint, xt_bigint_ctor)
|
|
154
155
|
XT_BUILTIN_TRAMPOLINE(xt_builtin_value_string, xt_string_ctor)
|
|
155
156
|
XT_BUILTIN_TRAMPOLINE(xt_builtin_value_parseInt, xt_parse_int)
|
|
156
157
|
XT_BUILTIN_TRAMPOLINE(xt_builtin_value_parseFloat, xt_parse_float)
|
package/runtime/xt_io.c
CHANGED
|
@@ -174,6 +174,13 @@ void xt_println(xt_value v) {
|
|
|
174
174
|
* top level, arrays as `[ a, b ]` and objects as `{ key: value }`.
|
|
175
175
|
*/
|
|
176
176
|
static void xt_inspect(xt_value v, FILE *out) {
|
|
177
|
+
if (XT_IS_BIGINT(v)) {
|
|
178
|
+
xt_value text = xt_bigint_to_decimal(v);
|
|
179
|
+
xt_string *s = xt_as_string(text);
|
|
180
|
+
fwrite(s->data, 1, s->length, out);
|
|
181
|
+
fputc('n', out);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
177
184
|
if (XT_IS_ARRAY(v)) {
|
|
178
185
|
xt_array *array = (xt_array *)XT_GET_PTR(v);
|
|
179
186
|
fputc('[', out);
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/* -- array methods -------------------------------------------------------- */
|
|
2
|
+
|
|
3
|
+
static xt_value xt_array_pop(xt_value value) {
|
|
4
|
+
xt_array *array = xt_as_array(value);
|
|
5
|
+
if (!array || array->length == 0) return XT_UNDEFINED;
|
|
6
|
+
return array->items[--array->length];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
static xt_value xt_array_shift(xt_value value) {
|
|
10
|
+
xt_array *array = xt_as_array(value);
|
|
11
|
+
if (!array || array->length == 0) return XT_UNDEFINED;
|
|
12
|
+
xt_value first = array->items[0];
|
|
13
|
+
for (uint32_t i = 1; i < array->length; i++) array->items[i - 1] = array->items[i];
|
|
14
|
+
array->length--;
|
|
15
|
+
return first;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static xt_value xt_array_unshift(xt_value value, int32_t argc, xt_value *argv) {
|
|
19
|
+
xt_array *array = xt_as_array(value);
|
|
20
|
+
if (!array) return XT_UNDEFINED;
|
|
21
|
+
if (argc <= 0) return xt_number((double)array->length);
|
|
22
|
+
xt_array_reserve(array, array->length + (uint32_t)argc);
|
|
23
|
+
for (uint32_t i = array->length; i-- > 0;) array->items[i + argc] = array->items[i];
|
|
24
|
+
for (int32_t i = 0; i < argc; i++) array->items[i] = argv[i];
|
|
25
|
+
array->length += (uint32_t)argc;
|
|
26
|
+
return xt_number((double)array->length);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static void xt_buffer_append(char **out, size_t *length, size_t *capacity, const char *data, size_t size) {
|
|
30
|
+
if (*length + size + 1 > *capacity) {
|
|
31
|
+
while (*length + size + 1 > *capacity) *capacity = (*capacity) * 2;
|
|
32
|
+
*out = (char *)realloc(*out, *capacity);
|
|
33
|
+
if (!*out) abort();
|
|
34
|
+
}
|
|
35
|
+
memcpy(*out + *length, data, size);
|
|
36
|
+
*length += size;
|
|
37
|
+
(*out)[*length] = '\0';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static xt_value xt_array_join(xt_value value, xt_value separator) {
|
|
41
|
+
xt_array *array = xt_as_array(value);
|
|
42
|
+
if (!array) return xt_string_from_cstr("");
|
|
43
|
+
xt_string *sep = xt_as_string(xt_to_string(separator == XT_UNDEFINED ? xt_string_from_cstr(",") : separator));
|
|
44
|
+
size_t capacity = 32;
|
|
45
|
+
size_t length = 0;
|
|
46
|
+
char *out = (char *)malloc(capacity);
|
|
47
|
+
if (!out) abort();
|
|
48
|
+
out[0] = '\0';
|
|
49
|
+
for (uint32_t i = 0; i < array->length; i++) {
|
|
50
|
+
if (i > 0) xt_buffer_append(&out, &length, &capacity, sep->data, sep->length);
|
|
51
|
+
xt_value item = array->items[i];
|
|
52
|
+
if (item == XT_UNDEFINED || item == XT_NULL) continue;
|
|
53
|
+
xt_string *str = xt_as_string(xt_to_string(item));
|
|
54
|
+
xt_buffer_append(&out, &length, &capacity, str->data, str->length);
|
|
55
|
+
}
|
|
56
|
+
xt_value result = xt_string_new(out, length);
|
|
57
|
+
free(out);
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static void xt_normalize_slice(int32_t len, int32_t *start, int32_t *end) {
|
|
62
|
+
if (*start < 0) *start += len;
|
|
63
|
+
if (*start < 0) *start = 0;
|
|
64
|
+
if (*start > len) *start = len;
|
|
65
|
+
if (*end < 0) *end += len;
|
|
66
|
+
if (*end < 0) *end = 0;
|
|
67
|
+
if (*end > len) *end = len;
|
|
68
|
+
if (*end < *start) *end = *start;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static xt_value xt_array_slice(xt_value value, xt_value startValue, xt_value endValue) {
|
|
72
|
+
xt_array *array = xt_as_array(value);
|
|
73
|
+
if (!array) return XT_UNDEFINED;
|
|
74
|
+
int32_t len = (int32_t)array->length;
|
|
75
|
+
int32_t start = startValue == XT_UNDEFINED ? 0 : xt_to_int32(startValue);
|
|
76
|
+
int32_t end = endValue == XT_UNDEFINED ? len : xt_to_int32(endValue);
|
|
77
|
+
xt_normalize_slice(len, &start, &end);
|
|
78
|
+
return xt_array_new(end - start, array->items + start);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
static xt_value xt_array_index_of(xt_value value, xt_value needle, xt_value fromValue, int sameValueZero) {
|
|
82
|
+
xt_array *array = xt_as_array(value);
|
|
83
|
+
if (!array) return xt_number(-1);
|
|
84
|
+
int32_t from = fromValue == XT_UNDEFINED ? 0 : xt_to_int32(fromValue);
|
|
85
|
+
if (from < 0) from += (int32_t)array->length;
|
|
86
|
+
if (from < 0) from = 0;
|
|
87
|
+
for (uint32_t i = (uint32_t)from; i < array->length; i++) {
|
|
88
|
+
int equal = sameValueZero ? xt_same_value_zero(array->items[i], needle) : xt_truthy(xt_seq(array->items[i], needle));
|
|
89
|
+
if (equal) return xt_number((double)i);
|
|
90
|
+
}
|
|
91
|
+
return xt_number(-1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
static xt_value xt_array_concat(xt_value value, int32_t argc, xt_value *argv) {
|
|
95
|
+
xt_array *array = xt_as_array(value);
|
|
96
|
+
xt_value result = xt_array_new(0, NULL);
|
|
97
|
+
if (!array) return result;
|
|
98
|
+
for (uint32_t i = 0; i < array->length; i++) xt_array_push(result, array->items[i]);
|
|
99
|
+
for (int32_t i = 0; i < argc; i++) {
|
|
100
|
+
if (XT_IS_ARRAY(argv[i])) {
|
|
101
|
+
xt_array *other = xt_as_array(argv[i]);
|
|
102
|
+
for (uint32_t j = 0; j < other->length; j++) xt_array_push(result, other->items[j]);
|
|
103
|
+
} else {
|
|
104
|
+
xt_array_push(result, argv[i]);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
static xt_value xt_array_for_each(xt_value value, xt_value fn) {
|
|
111
|
+
xt_array *array = xt_as_array(value);
|
|
112
|
+
if (!array) return XT_UNDEFINED;
|
|
113
|
+
for (uint32_t i = 0; i < array->length; i++) {
|
|
114
|
+
xt_value args[3] = {array->items[i], xt_number((double)i), value};
|
|
115
|
+
xt_closure_call(fn, 3, args);
|
|
116
|
+
}
|
|
117
|
+
return XT_UNDEFINED;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
static xt_value xt_array_map(xt_value value, xt_value fn) {
|
|
121
|
+
xt_array *array = xt_as_array(value);
|
|
122
|
+
xt_value result = xt_array_new(0, NULL);
|
|
123
|
+
if (!array) return result;
|
|
124
|
+
for (uint32_t i = 0; i < array->length; i++) {
|
|
125
|
+
xt_value args[3] = {array->items[i], xt_number((double)i), value};
|
|
126
|
+
xt_array_push(result, xt_closure_call(fn, 3, args));
|
|
127
|
+
}
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
static xt_value xt_array_filter(xt_value value, xt_value fn) {
|
|
132
|
+
xt_array *array = xt_as_array(value);
|
|
133
|
+
xt_value result = xt_array_new(0, NULL);
|
|
134
|
+
if (!array) return result;
|
|
135
|
+
for (uint32_t i = 0; i < array->length; i++) {
|
|
136
|
+
xt_value args[3] = {array->items[i], xt_number((double)i), value};
|
|
137
|
+
if (xt_truthy(xt_closure_call(fn, 3, args))) xt_array_push(result, array->items[i]);
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
static xt_value xt_array_reduce(xt_value value, xt_value fn, int32_t hasInitial, xt_value initial) {
|
|
143
|
+
xt_array *array = xt_as_array(value);
|
|
144
|
+
if (!array) return XT_UNDEFINED;
|
|
145
|
+
uint32_t i = 0;
|
|
146
|
+
xt_value accumulator;
|
|
147
|
+
if (hasInitial) {
|
|
148
|
+
accumulator = initial;
|
|
149
|
+
} else if (array->length > 0) {
|
|
150
|
+
accumulator = array->items[0];
|
|
151
|
+
i = 1;
|
|
152
|
+
} else {
|
|
153
|
+
xt_throw(xt_string_from_cstr("TypeError: Reduce of empty array with no initial value"));
|
|
154
|
+
return XT_UNDEFINED;
|
|
155
|
+
}
|
|
156
|
+
for (; i < array->length; i++) {
|
|
157
|
+
xt_value args[4] = {accumulator, array->items[i], xt_number((double)i), value};
|
|
158
|
+
accumulator = xt_closure_call(fn, 4, args);
|
|
159
|
+
}
|
|
160
|
+
return accumulator;
|
|
161
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/* -- method dispatch ------------------------------------------------------ */
|
|
2
|
+
|
|
3
|
+
static xt_value xt_array_method(xt_value target, const char *method, int32_t argc, xt_value *argv, int *handled) {
|
|
4
|
+
*handled = 1;
|
|
5
|
+
if (strcmp(method, "push") == 0) {
|
|
6
|
+
xt_value result = xt_number(0);
|
|
7
|
+
for (int32_t i = 0; i < argc; i++) result = xt_array_push(target, argv[i]);
|
|
8
|
+
if (argc == 0) result = xt_number((double)xt_as_array(target)->length);
|
|
9
|
+
return result;
|
|
10
|
+
}
|
|
11
|
+
if (strcmp(method, "pop") == 0) return xt_array_pop(target);
|
|
12
|
+
if (strcmp(method, "shift") == 0) return xt_array_shift(target);
|
|
13
|
+
if (strcmp(method, "unshift") == 0) return xt_array_unshift(target, argc, argv);
|
|
14
|
+
if (strcmp(method, "join") == 0) return xt_array_join(target, xt_arg_at(argc, argv, 0));
|
|
15
|
+
if (strcmp(method, "slice") == 0) return xt_array_slice(target, xt_arg_at(argc, argv, 0), xt_arg_at(argc, argv, 1));
|
|
16
|
+
if (strcmp(method, "indexOf") == 0) return xt_array_index_of(target, xt_arg_at(argc, argv, 0), xt_arg_at(argc, argv, 1), 0);
|
|
17
|
+
if (strcmp(method, "includes") == 0) return xt_bool(xt_truthy(xt_ne(xt_array_index_of(target, xt_arg_at(argc, argv, 0), xt_arg_at(argc, argv, 1), 1), xt_number(-1))));
|
|
18
|
+
if (strcmp(method, "concat") == 0) return xt_array_concat(target, argc, argv);
|
|
19
|
+
if (strcmp(method, "forEach") == 0) return xt_array_for_each(target, xt_arg_at(argc, argv, 0));
|
|
20
|
+
if (strcmp(method, "map") == 0) return xt_array_map(target, xt_arg_at(argc, argv, 0));
|
|
21
|
+
if (strcmp(method, "filter") == 0) return xt_array_filter(target, xt_arg_at(argc, argv, 0));
|
|
22
|
+
if (strcmp(method, "reduce") == 0) {
|
|
23
|
+
int32_t hasInitial = argc >= 2 ? 1 : 0;
|
|
24
|
+
return xt_array_reduce(target, xt_arg_at(argc, argv, 0), hasInitial, xt_arg_at(argc, argv, 1));
|
|
25
|
+
}
|
|
26
|
+
if (strcmp(method, "reverse") == 0) {
|
|
27
|
+
xt_array *array = xt_as_array(target);
|
|
28
|
+
for (uint32_t i = 0; i + 1 < array->length; i++, array->length--) {
|
|
29
|
+
xt_value tmp = array->items[i];
|
|
30
|
+
array->items[i] = array->items[array->length - 1];
|
|
31
|
+
array->items[array->length - 1] = tmp;
|
|
32
|
+
}
|
|
33
|
+
return target;
|
|
34
|
+
}
|
|
35
|
+
*handled = 0;
|
|
36
|
+
return XT_UNDEFINED;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static xt_value xt_string_method(xt_value target, const char *method, int32_t argc, xt_value *argv, int *handled) {
|
|
40
|
+
*handled = 1;
|
|
41
|
+
if (strcmp(method, "charAt") == 0) return xt_string_char_at(target, xt_arg_at(argc, argv, 0));
|
|
42
|
+
if (strcmp(method, "charCodeAt") == 0) return xt_string_char_code_at(target, xt_arg_at(argc, argv, 0));
|
|
43
|
+
if (strcmp(method, "indexOf") == 0) return xt_string_index_of(target, xt_arg_at(argc, argv, 0), xt_arg_at(argc, argv, 1));
|
|
44
|
+
if (strcmp(method, "includes") == 0) return xt_bool(xt_truthy(xt_ne(xt_string_index_of(target, xt_arg_at(argc, argv, 0), xt_arg_at(argc, argv, 1)), xt_number(-1))));
|
|
45
|
+
if (strcmp(method, "slice") == 0) return xt_string_slice(target, xt_arg_at(argc, argv, 0), xt_arg_at(argc, argv, 1));
|
|
46
|
+
if (strcmp(method, "substring") == 0) return xt_string_substring(target, xt_arg_at(argc, argv, 0), xt_arg_at(argc, argv, 1));
|
|
47
|
+
if (strcmp(method, "substr") == 0) return xt_string_substr(target, xt_arg_at(argc, argv, 0), xt_arg_at(argc, argv, 1));
|
|
48
|
+
if (strcmp(method, "split") == 0) return xt_string_split(target, xt_arg_at(argc, argv, 0));
|
|
49
|
+
if (strcmp(method, "toUpperCase") == 0) return xt_string_case(target, 1);
|
|
50
|
+
if (strcmp(method, "toLowerCase") == 0) return xt_string_case(target, 0);
|
|
51
|
+
if (strcmp(method, "trim") == 0) return xt_string_trim(target);
|
|
52
|
+
if (strcmp(method, "replace") == 0) return xt_string_replace(target, xt_arg_at(argc, argv, 0), xt_arg_at(argc, argv, 1));
|
|
53
|
+
if (strcmp(method, "repeat") == 0) return xt_string_repeat(target, xt_arg_at(argc, argv, 0));
|
|
54
|
+
if (strcmp(method, "startsWith") == 0) return xt_string_starts_with(target, xt_arg_at(argc, argv, 0));
|
|
55
|
+
if (strcmp(method, "endsWith") == 0) return xt_string_ends_with(target, xt_arg_at(argc, argv, 0));
|
|
56
|
+
if (strcmp(method, "concat") == 0) return xt_string_concat_args(target, argc, argv);
|
|
57
|
+
*handled = 0;
|
|
58
|
+
return XT_UNDEFINED;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
xt_value xt_call_method(xt_value target, xt_value name, int32_t argc, xt_value *argv) {
|
|
62
|
+
const char *method = xt_string_data(name);
|
|
63
|
+
if (!method) return XT_UNDEFINED;
|
|
64
|
+
int handled = 0;
|
|
65
|
+
if (XT_IS_OBJECT(target)) {
|
|
66
|
+
xt_object *obj = (xt_object *)XT_GET_PTR(target);
|
|
67
|
+
int kind = obj->header.kind;
|
|
68
|
+
if (kind == XT_OBJECT_KIND_PROMISE) {
|
|
69
|
+
xt_value result = xt_promise_method(target, method, argc, argv, &handled);
|
|
70
|
+
if (handled) return result;
|
|
71
|
+
}
|
|
72
|
+
if (kind != XT_OBJECT_KIND_OBJECT && kind != XT_OBJECT_KIND_FUNCTION) {
|
|
73
|
+
xt_value result = xt_ext_container_method(target, method, argc, argv, &handled);
|
|
74
|
+
if (handled) return result;
|
|
75
|
+
}
|
|
76
|
+
xt_value fn = xt_object_get(target, name);
|
|
77
|
+
if (XT_IS_FUNCTION(fn)) return xt_call_with_this(fn, target, argc, argv);
|
|
78
|
+
xt_value result = xt_ext_object_method(target, method, argc, argv, &handled);
|
|
79
|
+
if (handled) return result;
|
|
80
|
+
{
|
|
81
|
+
char message[256];
|
|
82
|
+
snprintf(message, sizeof(message), "TypeError: object has no callable method '%s'", method);
|
|
83
|
+
xt_throw(xt_string_from_cstr(message));
|
|
84
|
+
}
|
|
85
|
+
return XT_UNDEFINED;
|
|
86
|
+
}
|
|
87
|
+
if (XT_IS_FUNCTION(target)) {
|
|
88
|
+
xt_value fn = xt_object_get(target, name);
|
|
89
|
+
if (XT_IS_FUNCTION(fn)) return xt_call_with_this(fn, target, argc, argv);
|
|
90
|
+
{
|
|
91
|
+
char message[256];
|
|
92
|
+
snprintf(message, sizeof(message), "TypeError: function has no callable method '%s'", method);
|
|
93
|
+
xt_throw(xt_string_from_cstr(message));
|
|
94
|
+
}
|
|
95
|
+
return XT_UNDEFINED;
|
|
96
|
+
}
|
|
97
|
+
if (XT_IS_ARRAY(target)) {
|
|
98
|
+
xt_value result = xt_ext_array_method(target, method, argc, argv, &handled);
|
|
99
|
+
if (handled) return result;
|
|
100
|
+
return xt_array_method(target, method, argc, argv, &handled);
|
|
101
|
+
}
|
|
102
|
+
if (XT_IS_STRING(target)) {
|
|
103
|
+
xt_value result = xt_ext_string_method(target, method, argc, argv, &handled);
|
|
104
|
+
if (handled) return result;
|
|
105
|
+
return xt_string_method(target, method, argc, argv, &handled);
|
|
106
|
+
}
|
|
107
|
+
if (XT_IS_BIGINT(target)) {
|
|
108
|
+
xt_value result = xt_bigint_method(target, method, argc, argv, &handled);
|
|
109
|
+
if (handled) return result;
|
|
110
|
+
}
|
|
111
|
+
if (XT_IS_NUMBER(target)) {
|
|
112
|
+
xt_value result = xt_ext_number_method(target, method, argc, argv, &handled);
|
|
113
|
+
if (handled) return result;
|
|
114
|
+
}
|
|
115
|
+
return XT_UNDEFINED;
|
|
116
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/* ------------------------------------------------------------------------- */
|
|
2
|
+
/* Standard library: Array / String methods */
|
|
3
|
+
/* ------------------------------------------------------------------------- */
|
|
4
|
+
|
|
5
|
+
xt_value xt_arg_at(int32_t argc, xt_value *argv, int32_t index) {
|
|
6
|
+
if (!argv || index < 0 || index >= argc) return XT_UNDEFINED;
|
|
7
|
+
return argv[index];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
static int xt_same_value_zero(xt_value a, xt_value b) {
|
|
11
|
+
if (XT_IS_NUMBER(a) && XT_IS_NUMBER(b)) {
|
|
12
|
+
double x = xt_to_double(a);
|
|
13
|
+
double y = xt_to_double(b);
|
|
14
|
+
if (isnan(x) && isnan(y)) return 1;
|
|
15
|
+
return x == y;
|
|
16
|
+
}
|
|
17
|
+
return xt_truthy(xt_seq(a, b));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
xt_array *xt_as_array(xt_value value) {
|
|
21
|
+
if (XT_IS_ARRAY(value)) return (xt_array *)XT_GET_PTR(value);
|
|
22
|
+
return NULL;
|
|
23
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/* ------------------------------------------------------------------------- */
|
|
2
|
+
/* Math */
|
|
3
|
+
/* ------------------------------------------------------------------------- */
|
|
4
|
+
|
|
5
|
+
xt_value xt_math_call(xt_value name, int32_t argc, xt_value *argv) {
|
|
6
|
+
const char *fn = xt_string_data(name);
|
|
7
|
+
double a = xt_to_number(xt_arg_at(argc, argv, 0));
|
|
8
|
+
double b = xt_to_number(xt_arg_at(argc, argv, 1));
|
|
9
|
+
if (!fn) return xt_number(NAN);
|
|
10
|
+
if (strcmp(fn, "abs") == 0) return xt_number(fabs(a));
|
|
11
|
+
if (strcmp(fn, "floor") == 0) return xt_number(floor(a));
|
|
12
|
+
if (strcmp(fn, "ceil") == 0) return xt_number(ceil(a));
|
|
13
|
+
if (strcmp(fn, "round") == 0) return xt_number(floor(a + 0.5));
|
|
14
|
+
if (strcmp(fn, "trunc") == 0) return xt_number(trunc(a));
|
|
15
|
+
if (strcmp(fn, "sqrt") == 0) return xt_number(sqrt(a));
|
|
16
|
+
if (strcmp(fn, "cbrt") == 0) return xt_number(cbrt(a));
|
|
17
|
+
if (strcmp(fn, "pow") == 0) return xt_number(pow(a, b));
|
|
18
|
+
if (strcmp(fn, "exp") == 0) return xt_number(exp(a));
|
|
19
|
+
if (strcmp(fn, "log") == 0) return xt_number(log(a));
|
|
20
|
+
if (strcmp(fn, "log2") == 0) return xt_number(log2(a));
|
|
21
|
+
if (strcmp(fn, "log10") == 0) return xt_number(log10(a));
|
|
22
|
+
if (strcmp(fn, "log1p") == 0) return xt_number(log1p(a));
|
|
23
|
+
if (strcmp(fn, "expm1") == 0) return xt_number(expm1(a));
|
|
24
|
+
if (strcmp(fn, "sinh") == 0) return xt_number(sinh(a));
|
|
25
|
+
if (strcmp(fn, "cosh") == 0) return xt_number(cosh(a));
|
|
26
|
+
if (strcmp(fn, "tanh") == 0) return xt_number(tanh(a));
|
|
27
|
+
if (strcmp(fn, "asinh") == 0) return xt_number(asinh(a));
|
|
28
|
+
if (strcmp(fn, "acosh") == 0) return xt_number(acosh(a));
|
|
29
|
+
if (strcmp(fn, "atanh") == 0) return xt_number(atanh(a));
|
|
30
|
+
if (strcmp(fn, "fround") == 0) return xt_number((double)(float)a);
|
|
31
|
+
if (strcmp(fn, "imul") == 0) return xt_number((double)((int32_t)xt_to_int32(xt_arg_at(argc, argv, 0)) * (int32_t)xt_to_int32(xt_arg_at(argc, argv, 1))));
|
|
32
|
+
if (strcmp(fn, "clz32") == 0) {
|
|
33
|
+
uint32_t v = (uint32_t)xt_to_int32(xt_arg_at(argc, argv, 0));
|
|
34
|
+
int count = 0;
|
|
35
|
+
if (v == 0) count = 32;
|
|
36
|
+
else { while (!(v & 0x80000000u)) { v <<= 1; count++; } }
|
|
37
|
+
return xt_number((double)count);
|
|
38
|
+
}
|
|
39
|
+
if (strcmp(fn, "sin") == 0) return xt_number(sin(a));
|
|
40
|
+
if (strcmp(fn, "cos") == 0) return xt_number(cos(a));
|
|
41
|
+
if (strcmp(fn, "tan") == 0) return xt_number(tan(a));
|
|
42
|
+
if (strcmp(fn, "asin") == 0) return xt_number(asin(a));
|
|
43
|
+
if (strcmp(fn, "acos") == 0) return xt_number(acos(a));
|
|
44
|
+
if (strcmp(fn, "atan") == 0) return xt_number(atan(a));
|
|
45
|
+
if (strcmp(fn, "atan2") == 0) return xt_number(atan2(a, b));
|
|
46
|
+
if (strcmp(fn, "hypot") == 0) return xt_number(hypot(a, b));
|
|
47
|
+
if (strcmp(fn, "sign") == 0) {
|
|
48
|
+
if (isnan(a)) return xt_number(NAN);
|
|
49
|
+
return xt_number(a > 0 ? 1.0 : a < 0 ? -1.0 : a);
|
|
50
|
+
}
|
|
51
|
+
if (strcmp(fn, "random") == 0) return xt_number((double)rand() / ((double)RAND_MAX + 1.0));
|
|
52
|
+
if (strcmp(fn, "min") == 0) {
|
|
53
|
+
double result = INFINITY;
|
|
54
|
+
for (int32_t i = 0; i < argc; i++) {
|
|
55
|
+
double v = xt_to_number(argv[i]);
|
|
56
|
+
if (isnan(v)) return xt_number(NAN);
|
|
57
|
+
if (v < result) result = v;
|
|
58
|
+
}
|
|
59
|
+
return xt_number(result);
|
|
60
|
+
}
|
|
61
|
+
if (strcmp(fn, "max") == 0) {
|
|
62
|
+
double result = -INFINITY;
|
|
63
|
+
for (int32_t i = 0; i < argc; i++) {
|
|
64
|
+
double v = xt_to_number(argv[i]);
|
|
65
|
+
if (isnan(v)) return xt_number(NAN);
|
|
66
|
+
if (v > result) result = v;
|
|
67
|
+
}
|
|
68
|
+
return xt_number(result);
|
|
69
|
+
}
|
|
70
|
+
return xt_number(NAN);
|
|
71
|
+
}
|
|
72
|
+
|