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.
Files changed (311) hide show
  1. package/README.md +17 -2
  2. package/README.zh-CN.md +16 -2
  3. package/bin/xbintsc.js +49 -10
  4. package/dist/src/ast/expressions.d.ts +2 -0
  5. package/dist/src/binder/binder.d.ts +24 -98
  6. package/dist/src/binder/binder.js +13 -559
  7. package/dist/src/binder/binder.js.map +1 -1
  8. package/dist/src/binder/declarations.d.ts +16 -0
  9. package/dist/src/binder/declarations.js +168 -0
  10. package/dist/src/binder/declarations.js.map +1 -0
  11. package/dist/src/binder/helpers.d.ts +11 -0
  12. package/dist/src/binder/helpers.js +46 -0
  13. package/dist/src/binder/helpers.js.map +1 -0
  14. package/dist/src/binder/references.d.ts +21 -0
  15. package/dist/src/binder/references.js +349 -0
  16. package/dist/src/binder/references.js.map +1 -0
  17. package/dist/src/binder/types.d.ts +114 -0
  18. package/dist/src/binder/types.js +27 -0
  19. package/dist/src/binder/types.js.map +1 -0
  20. package/dist/src/cli/main.d.ts +1 -0
  21. package/dist/src/cli/main.js +40 -0
  22. package/dist/src/cli/main.js.map +1 -1
  23. package/dist/src/codegen/generator/calls/access.d.ts +13 -0
  24. package/dist/src/codegen/generator/calls/access.js +115 -0
  25. package/dist/src/codegen/generator/calls/access.js.map +1 -0
  26. package/dist/src/codegen/generator/calls/closures.d.ts +11 -0
  27. package/dist/src/codegen/generator/calls/closures.js +50 -0
  28. package/dist/src/codegen/generator/calls/closures.js.map +1 -0
  29. package/dist/src/codegen/generator/calls/invocation.d.ts +18 -0
  30. package/dist/src/codegen/generator/calls/invocation.js +242 -0
  31. package/dist/src/codegen/generator/calls/invocation.js.map +1 -0
  32. package/dist/src/codegen/generator/calls/literals.d.ts +10 -0
  33. package/dist/src/codegen/generator/calls/literals.js +69 -0
  34. package/dist/src/codegen/generator/calls/literals.js.map +1 -0
  35. package/dist/src/codegen/generator/calls/super.d.ts +10 -0
  36. package/dist/src/codegen/generator/calls/super.js +47 -0
  37. package/dist/src/codegen/generator/calls/super.js.map +1 -0
  38. package/dist/src/codegen/generator/calls.d.ts +15 -24
  39. package/dist/src/codegen/generator/calls.js +15 -482
  40. package/dist/src/codegen/generator/calls.js.map +1 -1
  41. package/dist/src/codegen/generator/context.d.ts +1 -1
  42. package/dist/src/codegen/generator/context.js +2 -2
  43. package/dist/src/codegen/generator/context.js.map +1 -1
  44. package/dist/src/codegen/generator/expressions/assignment.d.ts +13 -0
  45. package/dist/src/codegen/generator/expressions/assignment.js +203 -0
  46. package/dist/src/codegen/generator/expressions/assignment.js.map +1 -0
  47. package/dist/src/codegen/generator/expressions/operators.d.ts +14 -0
  48. package/dist/src/codegen/generator/expressions/operators.js +163 -0
  49. package/dist/src/codegen/generator/expressions/operators.js.map +1 -0
  50. package/dist/src/codegen/generator/expressions/primary.d.ts +17 -0
  51. package/dist/src/codegen/generator/expressions/primary.js +260 -0
  52. package/dist/src/codegen/generator/expressions/primary.js.map +1 -0
  53. package/dist/src/codegen/generator/expressions.d.ts +11 -21
  54. package/dist/src/codegen/generator/expressions.js +11 -494
  55. package/dist/src/codegen/generator/expressions.js.map +1 -1
  56. package/dist/src/codegen/generator/module.js +16 -4
  57. package/dist/src/codegen/generator/module.js.map +1 -1
  58. package/dist/src/codegen/generator/state.js +8 -0
  59. package/dist/src/codegen/generator/state.js.map +1 -1
  60. package/dist/src/codegen/generator/statements/control-flow.d.ts +14 -0
  61. package/dist/src/codegen/generator/statements/control-flow.js +199 -0
  62. package/dist/src/codegen/generator/statements/control-flow.js.map +1 -0
  63. package/dist/src/codegen/generator/statements/dispatch.d.ts +12 -0
  64. package/dist/src/codegen/generator/statements/dispatch.js +100 -0
  65. package/dist/src/codegen/generator/statements/dispatch.js.map +1 -0
  66. package/dist/src/codegen/generator/statements/loops.d.ts +13 -0
  67. package/dist/src/codegen/generator/statements/loops.js +152 -0
  68. package/dist/src/codegen/generator/statements/loops.js.map +1 -0
  69. package/dist/src/codegen/generator/statements/variables.d.ts +13 -0
  70. package/dist/src/codegen/generator/statements/variables.js +146 -0
  71. package/dist/src/codegen/generator/statements/variables.js.map +1 -0
  72. package/dist/src/codegen/generator/statements.d.ts +13 -21
  73. package/dist/src/codegen/generator/statements.js +13 -568
  74. package/dist/src/codegen/generator/statements.js.map +1 -1
  75. package/dist/src/codegen/generator/tables.js +7 -0
  76. package/dist/src/codegen/generator/tables.js.map +1 -1
  77. package/dist/src/codegen/values.d.ts +17 -17
  78. package/dist/src/codegen/values.js +21 -57
  79. package/dist/src/codegen/values.js.map +1 -1
  80. package/dist/src/diagnostics/diagnostic.d.ts +1 -0
  81. package/dist/src/diagnostics/diagnostic.js +1 -0
  82. package/dist/src/diagnostics/diagnostic.js.map +1 -1
  83. package/dist/src/diagnostics/source.d.ts +1 -1
  84. package/dist/src/diagnostics/source.js +7 -12
  85. package/dist/src/diagnostics/source.js.map +1 -1
  86. package/dist/src/driver/compiler.d.ts +4 -0
  87. package/dist/src/driver/compiler.js +51 -16
  88. package/dist/src/driver/compiler.js.map +1 -1
  89. package/dist/src/driver/index.d.ts +5 -2
  90. package/dist/src/driver/index.js +5 -2
  91. package/dist/src/driver/index.js.map +1 -1
  92. package/dist/src/driver/paths.d.ts +20 -0
  93. package/dist/src/driver/paths.js +49 -0
  94. package/dist/src/driver/paths.js.map +1 -1
  95. package/dist/src/driver/runtime-lib.d.ts +18 -0
  96. package/dist/src/driver/runtime-lib.js +31 -0
  97. package/dist/src/driver/runtime-lib.js.map +1 -0
  98. package/dist/src/driver/toolchain-download.d.ts +50 -0
  99. package/dist/src/driver/toolchain-download.js +76 -0
  100. package/dist/src/driver/toolchain-download.js.map +1 -0
  101. package/dist/src/driver/toolchain-provider.d.ts +33 -0
  102. package/dist/src/driver/toolchain-provider.js +71 -0
  103. package/dist/src/driver/toolchain-provider.js.map +1 -0
  104. package/dist/src/driver/toolchain.d.ts +9 -4
  105. package/dist/src/driver/toolchain.js +6 -10
  106. package/dist/src/driver/toolchain.js.map +1 -1
  107. package/dist/src/extensions/node/child_process/index.d.ts +4 -2
  108. package/dist/src/extensions/node/child_process/index.js +4 -2
  109. package/dist/src/extensions/node/child_process/index.js.map +1 -1
  110. package/dist/src/extensions/node/events/index.d.ts +10 -0
  111. package/dist/src/extensions/node/events/index.js +22 -0
  112. package/dist/src/extensions/node/events/index.js.map +1 -0
  113. package/dist/src/extensions/node/index.js +6 -0
  114. package/dist/src/extensions/node/index.js.map +1 -1
  115. package/dist/src/extensions/node/querystring/index.d.ts +10 -0
  116. package/dist/src/extensions/node/querystring/index.js +25 -0
  117. package/dist/src/extensions/node/querystring/index.js.map +1 -0
  118. package/dist/src/extensions/node/util/index.d.ts +11 -0
  119. package/dist/src/extensions/node/util/index.js +41 -0
  120. package/dist/src/extensions/node/util/index.js.map +1 -0
  121. package/dist/src/extensions/registry.d.ts +6 -0
  122. package/dist/src/extensions/registry.js.map +1 -1
  123. package/dist/src/index.d.ts +1 -1
  124. package/dist/src/index.js +1 -1
  125. package/dist/src/index.js.map +1 -1
  126. package/dist/src/lexer/scanner/identifiers.d.ts +9 -0
  127. package/dist/src/lexer/scanner/identifiers.js +33 -0
  128. package/dist/src/lexer/scanner/identifiers.js.map +1 -0
  129. package/dist/src/lexer/scanner/numbers.d.ts +10 -0
  130. package/dist/src/lexer/scanner/numbers.js +89 -0
  131. package/dist/src/lexer/scanner/numbers.js.map +1 -0
  132. package/dist/src/lexer/scanner/punctuation.d.ts +9 -0
  133. package/dist/src/lexer/scanner/punctuation.js +151 -0
  134. package/dist/src/lexer/scanner/punctuation.js.map +1 -0
  135. package/dist/src/lexer/scanner/regex.d.ts +11 -0
  136. package/dist/src/lexer/scanner/regex.js +69 -0
  137. package/dist/src/lexer/scanner/regex.js.map +1 -0
  138. package/dist/src/lexer/scanner/strings.d.ts +13 -0
  139. package/dist/src/lexer/scanner/strings.js +118 -0
  140. package/dist/src/lexer/scanner/strings.js.map +1 -0
  141. package/dist/src/lexer/scanner.d.ts +20 -27
  142. package/dist/src/lexer/scanner.js +11 -415
  143. package/dist/src/lexer/scanner.js.map +1 -1
  144. package/dist/src/parser/declarations/classes.d.ts +14 -0
  145. package/dist/src/parser/declarations/classes.js +191 -0
  146. package/dist/src/parser/declarations/classes.js.map +1 -0
  147. package/dist/src/parser/declarations/functions.d.ts +17 -0
  148. package/dist/src/parser/declarations/functions.js +241 -0
  149. package/dist/src/parser/declarations/functions.js.map +1 -0
  150. package/dist/src/parser/declarations/type-members.d.ts +16 -0
  151. package/dist/src/parser/declarations/type-members.js +156 -0
  152. package/dist/src/parser/declarations/type-members.js.map +1 -0
  153. package/dist/src/parser/declarations.d.ts +13 -24
  154. package/dist/src/parser/declarations.js +13 -571
  155. package/dist/src/parser/declarations.js.map +1 -1
  156. package/dist/src/parser/helpers.js +13 -4
  157. package/dist/src/parser/helpers.js.map +1 -1
  158. package/dist/src/parser/literals.js +10 -1
  159. package/dist/src/parser/literals.js.map +1 -1
  160. package/dist/tests/codegen/llvm.test.js +24 -0
  161. package/dist/tests/codegen/llvm.test.js.map +1 -1
  162. package/dist/tests/driver/compiler.test.js +3 -0
  163. package/dist/tests/driver/compiler.test.js.map +1 -1
  164. package/dist/tests/driver/paths.test.d.ts +1 -0
  165. package/dist/tests/driver/paths.test.js +26 -0
  166. package/dist/tests/driver/paths.test.js.map +1 -0
  167. package/dist/tests/driver/toolchain-download.test.d.ts +1 -0
  168. package/dist/tests/driver/toolchain-download.test.js +38 -0
  169. package/dist/tests/driver/toolchain-download.test.js.map +1 -0
  170. package/dist/tests/driver/toolchain-provider.test.d.ts +1 -0
  171. package/dist/tests/driver/toolchain-provider.test.js +37 -0
  172. package/dist/tests/driver/toolchain-provider.test.js.map +1 -0
  173. package/dist/tests/e2e/compile-node.test.d.ts +7 -0
  174. package/dist/tests/e2e/compile-node.test.js +123 -0
  175. package/dist/tests/e2e/compile-node.test.js.map +1 -0
  176. package/dist/tests/e2e/compile.test.d.ts +4 -1
  177. package/dist/tests/e2e/compile.test.js +90 -130
  178. package/dist/tests/e2e/compile.test.js.map +1 -1
  179. package/dist/tests/e2e/harness.d.ts +36 -0
  180. package/dist/tests/e2e/harness.js +64 -0
  181. package/dist/tests/e2e/harness.js.map +1 -0
  182. package/dist/tests/e2e/node-modules.test.js +60 -0
  183. package/dist/tests/e2e/node-modules.test.js.map +1 -1
  184. package/dist/tests/extensions/registry.test.js +4 -0
  185. package/dist/tests/extensions/registry.test.js.map +1 -1
  186. package/package.json +5 -3
  187. package/runtime/ext_node/buffer/buffer.c +12 -552
  188. package/runtime/ext_node/buffer/parts/byte-access.inc +35 -0
  189. package/runtime/ext_node/buffer/parts/construction.inc +60 -0
  190. package/runtime/ext_node/buffer/parts/integer-io.inc +119 -0
  191. package/runtime/ext_node/buffer/parts/methods.inc +135 -0
  192. package/runtime/ext_node/buffer/parts/prototype.inc +54 -0
  193. package/runtime/ext_node/buffer/parts/search.inc +86 -0
  194. package/runtime/ext_node/buffer/parts/static-api.inc +58 -0
  195. package/runtime/ext_node/child_process/child_process.c +37 -3
  196. package/runtime/ext_node/events/events.c +285 -0
  197. package/runtime/ext_node/http/http.c +11 -736
  198. package/runtime/ext_node/http/parts/client.inc +290 -0
  199. package/runtime/ext_node/http/parts/helpers.inc +45 -0
  200. package/runtime/ext_node/http/parts/prototypes.inc +57 -0
  201. package/runtime/ext_node/http/parts/response.inc +149 -0
  202. package/runtime/ext_node/http/parts/server.inc +133 -0
  203. package/runtime/ext_node/http/parts/string-builder.inc +58 -0
  204. package/runtime/ext_node/net/net.c +12 -504
  205. package/runtime/ext_node/net/parts/construction.inc +22 -0
  206. package/runtime/ext_node/net/parts/platform.inc +60 -0
  207. package/runtime/ext_node/net/parts/prototypes.inc +35 -0
  208. package/runtime/ext_node/net/parts/read-loop.inc +58 -0
  209. package/runtime/ext_node/net/parts/server.inc +131 -0
  210. package/runtime/ext_node/net/parts/socket-methods.inc +100 -0
  211. package/runtime/ext_node/net/parts/static-api.inc +93 -0
  212. package/runtime/ext_node/querystring/querystring.c +251 -0
  213. package/runtime/ext_node/util/util.c +456 -0
  214. package/runtime/rt.h +8 -2
  215. package/runtime/rt_internal.h +34 -0
  216. package/runtime/xt_bigint/arithmetic.inc +135 -0
  217. package/runtime/xt_bigint/bits.inc +98 -0
  218. package/runtime/xt_bigint/bitwise.inc +103 -0
  219. package/runtime/xt_bigint/compare.inc +30 -0
  220. package/runtime/xt_bigint/conversions.inc +51 -0
  221. package/runtime/xt_bigint/division.inc +85 -0
  222. package/runtime/xt_bigint/format.inc +145 -0
  223. package/runtime/xt_bigint/helpers.inc +92 -0
  224. package/runtime/xt_bigint/magnitude.inc +88 -0
  225. package/runtime/xt_bigint/public.inc +59 -0
  226. package/runtime/xt_bigint/small-arithmetic.inc +58 -0
  227. package/runtime/xt_bigint.c +42 -0
  228. package/runtime/xt_builtins.c +40 -5
  229. package/runtime/xt_io.c +7 -0
  230. package/runtime/xt_stdlib/arrays.inc +161 -0
  231. package/runtime/xt_stdlib/dispatch.inc +116 -0
  232. package/runtime/xt_stdlib/helpers.inc +23 -0
  233. package/runtime/xt_stdlib/math.inc +72 -0
  234. package/runtime/xt_stdlib/strings.inc +178 -0
  235. package/runtime/xt_stdlib.c +10 -549
  236. package/runtime/xt_stdlib2/array-statics.inc +37 -0
  237. package/runtime/xt_stdlib2/arrays.inc +189 -0
  238. package/runtime/xt_stdlib2/container.inc +23 -0
  239. package/runtime/xt_stdlib2/date.inc +72 -0
  240. package/runtime/xt_stdlib2/error.inc +22 -0
  241. package/runtime/xt_stdlib2/helpers.inc +43 -0
  242. package/runtime/xt_stdlib2/json.inc +213 -0
  243. package/runtime/xt_stdlib2/map.inc +95 -0
  244. package/runtime/xt_stdlib2/number-string-statics.inc +73 -0
  245. package/runtime/xt_stdlib2/numbers.inc +38 -0
  246. package/runtime/xt_stdlib2/objects.inc +41 -0
  247. package/runtime/xt_stdlib2/regexp-match.inc +204 -0
  248. package/runtime/xt_stdlib2/regexp.inc +20 -0
  249. package/runtime/xt_stdlib2/set.inc +105 -0
  250. package/runtime/xt_stdlib2/strings.inc +94 -0
  251. package/runtime/xt_stdlib2.c +19 -1278
  252. package/runtime/xt_values.c +155 -12
  253. package/scripts/build-runtime.ts +109 -0
  254. package/scripts/fetch-toolchain.ts +101 -0
  255. package/scripts/package-release.ts +192 -0
  256. package/src/ast/expressions.ts +2 -0
  257. package/src/binder/binder.ts +40 -725
  258. package/src/binder/declarations.ts +203 -0
  259. package/src/binder/helpers.ts +47 -0
  260. package/src/binder/references.ts +410 -0
  261. package/src/binder/types.ts +134 -0
  262. package/src/cli/main.ts +43 -0
  263. package/src/codegen/generator/calls/access.ts +139 -0
  264. package/src/codegen/generator/calls/closures.ts +60 -0
  265. package/src/codegen/generator/calls/invocation.ts +282 -0
  266. package/src/codegen/generator/calls/literals.ts +77 -0
  267. package/src/codegen/generator/calls/super.ts +61 -0
  268. package/src/codegen/generator/calls.ts +30 -552
  269. package/src/codegen/generator/context.ts +2 -2
  270. package/src/codegen/generator/expressions/assignment.ts +226 -0
  271. package/src/codegen/generator/expressions/operators.ts +182 -0
  272. package/src/codegen/generator/expressions/primary.ts +304 -0
  273. package/src/codegen/generator/expressions.ts +22 -553
  274. package/src/codegen/generator/module.ts +14 -4
  275. package/src/codegen/generator/state.ts +8 -0
  276. package/src/codegen/generator/statements/control-flow.ts +225 -0
  277. package/src/codegen/generator/statements/dispatch.ts +122 -0
  278. package/src/codegen/generator/statements/loops.ts +173 -0
  279. package/src/codegen/generator/statements/variables.ts +152 -0
  280. package/src/codegen/generator/statements.ts +26 -612
  281. package/src/codegen/generator/tables.ts +7 -0
  282. package/src/codegen/values.ts +22 -57
  283. package/src/diagnostics/diagnostic.ts +1 -0
  284. package/src/diagnostics/source.ts +7 -12
  285. package/src/driver/compiler.ts +61 -18
  286. package/src/driver/index.ts +17 -2
  287. package/src/driver/paths.ts +54 -0
  288. package/src/driver/runtime-lib.ts +32 -0
  289. package/src/driver/toolchain-download.ts +108 -0
  290. package/src/driver/toolchain-provider.ts +91 -0
  291. package/src/driver/toolchain.ts +29 -11
  292. package/src/extensions/node/child_process/index.ts +4 -2
  293. package/src/extensions/node/events/index.ts +27 -0
  294. package/src/extensions/node/index.ts +6 -0
  295. package/src/extensions/node/querystring/index.ts +29 -0
  296. package/src/extensions/node/util/index.ts +48 -0
  297. package/src/extensions/registry.ts +6 -0
  298. package/src/index.ts +1 -0
  299. package/src/lexer/scanner/identifiers.ts +37 -0
  300. package/src/lexer/scanner/numbers.ts +84 -0
  301. package/src/lexer/scanner/punctuation.ts +132 -0
  302. package/src/lexer/scanner/regex.ts +79 -0
  303. package/src/lexer/scanner/strings.ts +128 -0
  304. package/src/lexer/scanner.ts +35 -401
  305. package/src/parser/declarations/classes.ts +215 -0
  306. package/src/parser/declarations/functions.ts +254 -0
  307. package/src/parser/declarations/type-members.ts +181 -0
  308. package/src/parser/declarations.ts +32 -609
  309. package/src/parser/helpers.ts +13 -6
  310. package/src/parser/literals.ts +10 -1
  311. package/scripts/build-runtime.mjs +0 -55
@@ -0,0 +1,456 @@
1
+ /*
2
+ * Node.js `util` module for xbintsc.
3
+ *
4
+ * Implements the pieces of `util` that are useful without a real event loop:
5
+ * `format` (printf-style placeholders), `inspect` (a recursive pretty printer),
6
+ * `isDeepStrictEqual`, `inherits`, `deprecate`, `promisify` and the small set
7
+ * of `isX` type predicates.
8
+ *
9
+ * `promisify` builds a real promise through `xt_promise_ctor`: the returned
10
+ * function calls the wrapped function with a trailing `(err, value)` callback
11
+ * that resolves or rejects the promise.
12
+ */
13
+
14
+ #include "../node_common.h"
15
+
16
+ #include <stdio.h>
17
+
18
+ int xt_node_is_buffer(xt_value value);
19
+
20
+ /* -- growable string buffer ---------------------------------------------- */
21
+
22
+ typedef struct {
23
+ char *data;
24
+ size_t length;
25
+ size_t capacity;
26
+ } util_buf;
27
+
28
+ static void util_buf_init(util_buf *buf) {
29
+ buf->capacity = 64;
30
+ buf->length = 0;
31
+ buf->data = (char *)malloc(buf->capacity);
32
+ if (buf->data) buf->data[0] = '\0';
33
+ }
34
+
35
+ static void util_buf_reserve(util_buf *buf, size_t extra) {
36
+ if (!buf->data) return;
37
+ if (buf->length + extra + 1 <= buf->capacity) return;
38
+ while (buf->length + extra + 1 > buf->capacity) buf->capacity *= 2;
39
+ buf->data = (char *)realloc(buf->data, buf->capacity);
40
+ }
41
+
42
+ static void util_buf_putc(util_buf *buf, char c) {
43
+ util_buf_reserve(buf, 1);
44
+ if (!buf->data) return;
45
+ buf->data[buf->length++] = c;
46
+ buf->data[buf->length] = '\0';
47
+ }
48
+
49
+ static void util_buf_puts(util_buf *buf, const char *text, size_t length) {
50
+ if (!text) return;
51
+ util_buf_reserve(buf, length);
52
+ if (!buf->data) return;
53
+ memcpy(buf->data + buf->length, text, length);
54
+ buf->length += length;
55
+ buf->data[buf->length] = '\0';
56
+ }
57
+
58
+ static void util_buf_put_cstr(util_buf *buf, const char *text) {
59
+ if (text) util_buf_puts(buf, text, strlen(text));
60
+ }
61
+
62
+ static void util_buf_put_value(util_buf *buf, xt_value value) {
63
+ xt_value text = xt_to_string(value);
64
+ const char *data = xt_string_data(text);
65
+ int32_t length = xt_string_length_value(text);
66
+ if (data) util_buf_puts(buf, data, (size_t)length);
67
+ }
68
+
69
+ static xt_value util_buf_finish(util_buf *buf) {
70
+ xt_value result = buf->data ? xt_string_new(buf->data, buf->length) : xt_string_from_cstr("");
71
+ free(buf->data);
72
+ buf->data = NULL;
73
+ return result;
74
+ }
75
+
76
+ /* -- inspect -------------------------------------------------------------- */
77
+
78
+ static void util_inspect_into(util_buf *buf, xt_value value, int depth);
79
+
80
+ static void util_inspect_string(util_buf *buf, xt_value value) {
81
+ const char *data = xt_string_data(value);
82
+ int32_t length = xt_string_length_value(value);
83
+ util_buf_putc(buf, '\'');
84
+ for (int32_t i = 0; i < length; i++) {
85
+ char c = data[i];
86
+ if (c == '\'') util_buf_put_cstr(buf, "\\'");
87
+ else if (c == '\\') util_buf_put_cstr(buf, "\\\\");
88
+ else if (c == '\n') util_buf_put_cstr(buf, "\\n");
89
+ else if (c == '\r') util_buf_put_cstr(buf, "\\r");
90
+ else if (c == '\t') util_buf_put_cstr(buf, "\\t");
91
+ else util_buf_putc(buf, c);
92
+ }
93
+ util_buf_putc(buf, '\'');
94
+ }
95
+
96
+ static void util_inspect_into(util_buf *buf, xt_value value, int depth) {
97
+ if (value == XT_UNDEFINED) {
98
+ util_buf_put_cstr(buf, "undefined");
99
+ return;
100
+ }
101
+ if (value == XT_NULL) {
102
+ util_buf_put_cstr(buf, "null");
103
+ return;
104
+ }
105
+ if (value == XT_TRUE) {
106
+ util_buf_put_cstr(buf, "true");
107
+ return;
108
+ }
109
+ if (value == XT_FALSE) {
110
+ util_buf_put_cstr(buf, "false");
111
+ return;
112
+ }
113
+ if (XT_IS_NUMBER(value)) {
114
+ util_buf_put_value(buf, value);
115
+ return;
116
+ }
117
+ if (XT_IS_BIGINT(value)) {
118
+ util_buf_put_value(buf, value);
119
+ util_buf_putc(buf, 'n');
120
+ return;
121
+ }
122
+ if (XT_IS_STRING(value)) {
123
+ util_inspect_string(buf, value);
124
+ return;
125
+ }
126
+ if (XT_IS_FUNCTION(value)) {
127
+ util_buf_put_cstr(buf, "[Function]");
128
+ return;
129
+ }
130
+ if (xt_is_date(value)) {
131
+ util_buf_put_value(buf, xt_to_string(value));
132
+ return;
133
+ }
134
+ if (xt_is_regexp(value)) {
135
+ util_buf_put_value(buf, xt_to_string(value));
136
+ return;
137
+ }
138
+ if (depth >= 2) {
139
+ if (XT_IS_ARRAY(value)) util_buf_put_cstr(buf, "[Array]");
140
+ else util_buf_put_cstr(buf, "[Object]");
141
+ return;
142
+ }
143
+ if (XT_IS_ARRAY(value)) {
144
+ int32_t count = (int32_t)xt_to_number(xt_array_length(value));
145
+ util_buf_put_cstr(buf, "[ ");
146
+ for (int32_t i = 0; i < count; i++) {
147
+ if (i > 0) util_buf_put_cstr(buf, ", ");
148
+ util_inspect_into(buf, xt_array_get(value, xt_number((double)i)), depth + 1);
149
+ }
150
+ if (count > 0) util_buf_putc(buf, ' ');
151
+ util_buf_putc(buf, ']');
152
+ return;
153
+ }
154
+ if (XT_IS_OBJECT(value)) {
155
+ xt_value keys = xt_object_keys(value);
156
+ int32_t count = (int32_t)xt_to_number(xt_array_length(keys));
157
+ util_buf_put_cstr(buf, "{ ");
158
+ for (int32_t i = 0; i < count; i++) {
159
+ if (i > 0) util_buf_put_cstr(buf, ", ");
160
+ xt_value key = xt_array_get(keys, xt_number((double)i));
161
+ util_buf_put_value(buf, key);
162
+ util_buf_put_cstr(buf, ": ");
163
+ util_inspect_into(buf, xt_object_get(value, key), depth + 1);
164
+ }
165
+ if (count > 0) util_buf_putc(buf, ' ');
166
+ util_buf_putc(buf, '}');
167
+ return;
168
+ }
169
+ util_buf_put_value(buf, value);
170
+ }
171
+
172
+ static xt_value util_inspect_value(xt_value value) {
173
+ util_buf buf;
174
+ util_buf_init(&buf);
175
+ util_inspect_into(&buf, value, 0);
176
+ return util_buf_finish(&buf);
177
+ }
178
+
179
+ xt_value xt_util_inspect(int32_t argc, xt_value *argv) {
180
+ return util_inspect_value(xt_arg(argc, argv, 0));
181
+ }
182
+
183
+ /* -- format --------------------------------------------------------------- */
184
+
185
+ /* Convert one `%s`/`%d`/... argument for `format`. */
186
+ static void util_format_arg(util_buf *buf, char specifier, xt_value value) {
187
+ switch (specifier) {
188
+ case 's':
189
+ if (XT_IS_STRING(value)) {
190
+ const char *data = xt_string_data(value);
191
+ util_buf_puts(buf, data, (size_t)xt_string_length_value(value));
192
+ } else if (XT_IS_OBJECT(value) || XT_IS_ARRAY(value)) {
193
+ util_inspect_into(buf, value, 0);
194
+ } else {
195
+ util_buf_put_value(buf, value);
196
+ }
197
+ break;
198
+ case 'd':
199
+ case 'i': {
200
+ if (XT_IS_BIGINT(value)) {
201
+ util_buf_put_value(buf, value);
202
+ } else {
203
+ char buffer[32];
204
+ snprintf(buffer, sizeof(buffer), "%lld", (long long)xt_to_number(value));
205
+ util_buf_put_cstr(buf, buffer);
206
+ }
207
+ break;
208
+ }
209
+ case 'f':
210
+ if (XT_IS_BIGINT(value)) {
211
+ util_buf_put_value(buf, value);
212
+ } else {
213
+ char buffer[64];
214
+ snprintf(buffer, sizeof(buffer), "%f", xt_to_number(value));
215
+ util_buf_put_cstr(buf, buffer);
216
+ }
217
+ break;
218
+ case 'j':
219
+ util_buf_put_value(buf, xt_json_stringify(1, &value));
220
+ break;
221
+ case 'o':
222
+ case 'O':
223
+ util_inspect_into(buf, value, 0);
224
+ break;
225
+ default:
226
+ util_buf_put_value(buf, value);
227
+ break;
228
+ }
229
+ }
230
+
231
+ xt_value xt_util_format(int32_t argc, xt_value *argv) {
232
+ util_buf buf;
233
+ util_buf_init(&buf);
234
+ if (argc == 0) return util_buf_finish(&buf);
235
+
236
+ xt_value first = argv[0];
237
+ if (!XT_IS_STRING(first)) {
238
+ for (int32_t i = 0; i < argc; i++) {
239
+ if (i > 0) util_buf_putc(&buf, ' ');
240
+ util_inspect_into(&buf, argv[i], 0);
241
+ }
242
+ return util_buf_finish(&buf);
243
+ }
244
+
245
+ const char *text = xt_string_data(first);
246
+ int32_t length = xt_string_length_value(first);
247
+ int32_t next = 1;
248
+ for (int32_t i = 0; i < length; i++) {
249
+ char c = text[i];
250
+ if (c != '%' || i + 1 >= length) {
251
+ util_buf_putc(&buf, c);
252
+ continue;
253
+ }
254
+ char specifier = text[++i];
255
+ if (specifier == '%') {
256
+ util_buf_putc(&buf, '%');
257
+ continue;
258
+ }
259
+ if (specifier == 'c') continue; /* CSS directive: ignored */
260
+ if (next < argc) {
261
+ util_format_arg(&buf, specifier, argv[next++]);
262
+ } else {
263
+ util_buf_putc(&buf, '%');
264
+ util_buf_putc(&buf, specifier);
265
+ }
266
+ }
267
+ for (int32_t i = next; i < argc; i++) {
268
+ util_buf_putc(&buf, ' ');
269
+ util_inspect_into(&buf, argv[i], 0);
270
+ }
271
+ return util_buf_finish(&buf);
272
+ }
273
+
274
+ xt_value xt_util_format_with_options(int32_t argc, xt_value *argv) {
275
+ /* The inspect options are accepted and ignored; only the format string and
276
+ its arguments are used. */
277
+ if (argc <= 1) return xt_string_from_cstr("");
278
+ return xt_util_format(argc - 1, argv + 1);
279
+ }
280
+
281
+ /* -- isDeepStrictEqual ---------------------------------------------------- */
282
+
283
+ static int util_deep_equal(xt_value a, xt_value b, int depth) {
284
+ if (depth > 32) return 1;
285
+ if (a == b) return 1;
286
+ /* NaN === NaN under `isDeepStrictEqual`. */
287
+ if (XT_IS_NUMBER(a) && XT_IS_NUMBER(b)) {
288
+ double x = xt_to_number(a), y = xt_to_number(b);
289
+ return (x == y) || (x != x && y != y);
290
+ }
291
+ if (XT_IS_ARRAY(a) && XT_IS_ARRAY(b)) {
292
+ int32_t na = (int32_t)xt_to_number(xt_array_length(a));
293
+ int32_t nb = (int32_t)xt_to_number(xt_array_length(b));
294
+ if (na != nb) return 0;
295
+ for (int32_t i = 0; i < na; i++) {
296
+ if (!util_deep_equal(xt_array_get(a, xt_number((double)i)), xt_array_get(b, xt_number((double)i)), depth + 1))
297
+ return 0;
298
+ }
299
+ return 1;
300
+ }
301
+ if (XT_IS_OBJECT(a) && XT_IS_OBJECT(b)) {
302
+ xt_value keysA = xt_object_keys(a);
303
+ xt_value keysB = xt_object_keys(b);
304
+ int32_t na = (int32_t)xt_to_number(xt_array_length(keysA));
305
+ int32_t nb = (int32_t)xt_to_number(xt_array_length(keysB));
306
+ if (na != nb) return 0;
307
+ for (int32_t i = 0; i < na; i++) {
308
+ xt_value key = xt_array_get(keysA, xt_number((double)i));
309
+ if (!xt_truthy(xt_object_has_own(b, key))) return 0;
310
+ if (!util_deep_equal(xt_object_get(a, key), xt_object_get(b, key), depth + 1)) return 0;
311
+ }
312
+ return 1;
313
+ }
314
+ return 0;
315
+ }
316
+
317
+ xt_value xt_util_is_deep_strict_equal(int32_t argc, xt_value *argv) {
318
+ return xt_bool(util_deep_equal(xt_arg(argc, argv, 0), xt_arg(argc, argv, 1), 0));
319
+ }
320
+
321
+ /* -- inherits ------------------------------------------------------------- */
322
+
323
+ xt_value xt_util_inherits(int32_t argc, xt_value *argv) {
324
+ xt_value ctor = xt_arg(argc, argv, 0);
325
+ xt_value superCtor = xt_arg(argc, argv, 1);
326
+ if (XT_IS_FUNCTION(ctor) && XT_IS_FUNCTION(superCtor)) {
327
+ xt_value superProto = xt_function_get_prototype(superCtor);
328
+ xt_value proto = xt_object_new_with_proto(superProto);
329
+ xt_object_set(proto, xt_string_from_cstr("constructor"), ctor);
330
+ xt_function_set_prototype(ctor, proto);
331
+ xt_node_set(ctor, "super_", superCtor);
332
+ }
333
+ return xt_undefined();
334
+ }
335
+
336
+ /* -- deprecate ------------------------------------------------------------ */
337
+
338
+ xt_value xt_util_deprecate(int32_t argc, xt_value *argv) {
339
+ /* No process event loop to emit warnings into: hand back the function. */
340
+ return xt_arg(argc, argv, 0);
341
+ }
342
+
343
+ /* -- promisify ------------------------------------------------------------ */
344
+
345
+ static xt_value util_promisify_callback(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
346
+ (void)thisValue;
347
+ xt_value resolve = xt_closure_env(env, 0);
348
+ xt_value reject = xt_closure_env(env, 1);
349
+ xt_value error = xt_arg(argc, argv, 0);
350
+ if (!xt_truthy(xt_is_nullish(error))) {
351
+ if (XT_IS_FUNCTION(reject)) xt_closure_call(reject, 1, &error);
352
+ return xt_undefined();
353
+ }
354
+ xt_value value = argc > 1 ? argv[1] : xt_undefined();
355
+ if (XT_IS_FUNCTION(resolve)) xt_closure_call(resolve, 1, &value);
356
+ return xt_undefined();
357
+ }
358
+
359
+ static xt_value util_promisify_executor(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
360
+ (void)thisValue;
361
+ xt_value fn = xt_closure_env(env, 0);
362
+ xt_value args = xt_closure_env(env, 1);
363
+ xt_value resolve = xt_arg(argc, argv, 0);
364
+ xt_value reject = xt_arg(argc, argv, 1);
365
+ int32_t count = (int32_t)xt_to_number(xt_array_length(args));
366
+ xt_value *callArgs = (xt_value *)malloc(sizeof(xt_value) * (size_t)(count + 1));
367
+ if (!callArgs) return xt_undefined();
368
+ for (int32_t i = 0; i < count; i++) callArgs[i] = xt_array_get(args, xt_number((double)i));
369
+ xt_value callbackEnv[2] = {resolve, reject};
370
+ callArgs[count] = xt_closure_new((void *)util_promisify_callback, 2, callbackEnv);
371
+ if (XT_IS_FUNCTION(fn)) xt_closure_call(fn, count + 1, callArgs);
372
+ free(callArgs);
373
+ return xt_undefined();
374
+ }
375
+
376
+ static xt_value util_promisify_wrapper(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
377
+ (void)thisValue;
378
+ xt_value fn = xt_closure_env(env, 0);
379
+ xt_value args = xt_array_new(argc, argv);
380
+ xt_value executorEnv[2] = {fn, args};
381
+ xt_value executor = xt_closure_new((void *)util_promisify_executor, 2, executorEnv);
382
+ xt_value ctorArgs[1] = {executor};
383
+ return xt_promise_ctor(1, ctorArgs);
384
+ }
385
+
386
+ xt_value xt_util_promisify(int32_t argc, xt_value *argv) {
387
+ xt_value fn = xt_arg(argc, argv, 0);
388
+ xt_value env[1] = {fn};
389
+ return xt_closure_new((void *)util_promisify_wrapper, 1, env);
390
+ }
391
+
392
+ /* -- type predicates ------------------------------------------------------ */
393
+
394
+ xt_value xt_util_is_string(int32_t argc, xt_value *argv) { return xt_bool(XT_IS_STRING(xt_arg(argc, argv, 0))); }
395
+ xt_value xt_util_is_number(int32_t argc, xt_value *argv) { return xt_bool(XT_IS_NUMBER(xt_arg(argc, argv, 0))); }
396
+ xt_value xt_util_is_boolean(int32_t argc, xt_value *argv) {
397
+ xt_value value = xt_arg(argc, argv, 0);
398
+ return xt_bool(value == XT_TRUE || value == XT_FALSE);
399
+ }
400
+ xt_value xt_util_is_undefined(int32_t argc, xt_value *argv) { return xt_bool(xt_arg(argc, argv, 0) == XT_UNDEFINED); }
401
+ xt_value xt_util_is_null(int32_t argc, xt_value *argv) { return xt_bool(xt_arg(argc, argv, 0) == XT_NULL); }
402
+ xt_value xt_util_is_function(int32_t argc, xt_value *argv) { return xt_bool(XT_IS_FUNCTION(xt_arg(argc, argv, 0))); }
403
+ xt_value xt_util_is_array(int32_t argc, xt_value *argv) { return xt_bool(XT_IS_ARRAY(xt_arg(argc, argv, 0))); }
404
+ xt_value xt_util_is_object(int32_t argc, xt_value *argv) {
405
+ xt_value value = xt_arg(argc, argv, 0);
406
+ return xt_bool(XT_IS_OBJECT(value) && !XT_IS_ARRAY(value));
407
+ }
408
+ xt_value xt_util_is_buffer(int32_t argc, xt_value *argv) { return xt_bool(xt_node_is_buffer(xt_arg(argc, argv, 0))); }
409
+ xt_value xt_util_is_date(int32_t argc, xt_value *argv) { return xt_bool(xt_is_date(xt_arg(argc, argv, 0))); }
410
+ xt_value xt_util_is_regexp(int32_t argc, xt_value *argv) { return xt_bool(xt_is_regexp(xt_arg(argc, argv, 0))); }
411
+ xt_value xt_util_is_promise(int32_t argc, xt_value *argv) { return xt_bool(xt_is_promise(xt_arg(argc, argv, 0))); }
412
+
413
+ /* Best-effort `Error` detection: error objects carry own `name`/`message`. */
414
+ xt_value xt_util_is_error(int32_t argc, xt_value *argv) {
415
+ xt_value value = xt_arg(argc, argv, 0);
416
+ if (!XT_IS_OBJECT(value)) return xt_bool(0);
417
+ return xt_bool(xt_truthy(xt_object_has_own(value, xt_string_from_cstr("message"))) &&
418
+ xt_truthy(xt_object_has_own(value, xt_string_from_cstr("name"))));
419
+ }
420
+
421
+ /* -- namespace dispatcher ------------------------------------------------- */
422
+
423
+ static const struct {
424
+ const char *name;
425
+ xt_value (*fn)(int32_t, xt_value *);
426
+ } util_functions[] = {
427
+ {"format", xt_util_format},
428
+ {"formatWithOptions", xt_util_format_with_options},
429
+ {"inspect", xt_util_inspect},
430
+ {"isDeepStrictEqual", xt_util_is_deep_strict_equal},
431
+ {"inherits", xt_util_inherits},
432
+ {"deprecate", xt_util_deprecate},
433
+ {"promisify", xt_util_promisify},
434
+ {"isString", xt_util_is_string},
435
+ {"isNumber", xt_util_is_number},
436
+ {"isBoolean", xt_util_is_boolean},
437
+ {"isUndefined", xt_util_is_undefined},
438
+ {"isNull", xt_util_is_null},
439
+ {"isFunction", xt_util_is_function},
440
+ {"isArray", xt_util_is_array},
441
+ {"isObject", xt_util_is_object},
442
+ {"isBuffer", xt_util_is_buffer},
443
+ {"isDate", xt_util_is_date},
444
+ {"isRegExp", xt_util_is_regexp},
445
+ {"isPromise", xt_util_is_promise},
446
+ {"isError", xt_util_is_error},
447
+ };
448
+
449
+ xt_value xt_util_static(xt_value name, int32_t argc, xt_value *argv) {
450
+ const char *fn = xt_string_data(name);
451
+ if (!fn) return xt_undefined();
452
+ for (size_t i = 0; i < sizeof(util_functions) / sizeof(util_functions[0]); i++) {
453
+ if (strcmp(fn, util_functions[i].name) == 0) return util_functions[i].fn(argc, argv);
454
+ }
455
+ return xt_undefined();
456
+ }
package/runtime/rt.h CHANGED
@@ -31,7 +31,7 @@ typedef uint64_t xt_value;
31
31
  #define XT_TAG_UNDEFINED 0xFFF8000000000000ULL
32
32
  #define XT_TAG_NULL 0xFFF9000000000000ULL
33
33
  #define XT_TAG_FALSE 0xFFFA000000000000ULL
34
- #define XT_TAG_TRUE 0xFFFB000000000000ULL
34
+ #define XT_TAG_BIGINT 0xFFFB000000000000ULL
35
35
  #define XT_TAG_STRING 0xFFFC000000000000ULL
36
36
  #define XT_TAG_OBJECT 0xFFFD000000000000ULL
37
37
  #define XT_TAG_ARRAY 0xFFFE000000000000ULL
@@ -44,6 +44,7 @@ typedef uint64_t xt_value;
44
44
  #define XT_IS_UNDEFINED(v) ((v) == XT_TAG_UNDEFINED)
45
45
  #define XT_IS_NULL(v) ((v) == XT_TAG_NULL)
46
46
  #define XT_IS_BOOL(v) (((v) & ~0x1ULL) == XT_TAG_FALSE)
47
+ #define XT_IS_BIGINT(v) XT_IS_TAGGED(v, XT_TAG_BIGINT)
47
48
  #define XT_IS_STRING(v) XT_IS_TAGGED(v, XT_TAG_STRING)
48
49
  #define XT_IS_OBJECT(v) XT_IS_TAGGED(v, XT_TAG_OBJECT)
49
50
  #define XT_IS_ARRAY(v) XT_IS_TAGGED(v, XT_TAG_ARRAY)
@@ -56,7 +57,7 @@ typedef uint64_t xt_value;
56
57
  #define XT_UNDEFINED XT_TAG_UNDEFINED
57
58
  #define XT_NULL XT_TAG_NULL
58
59
  #define XT_FALSE XT_TAG_FALSE
59
- #define XT_TRUE XT_TAG_TRUE
60
+ #define XT_TRUE (XT_TAG_FALSE | 0x1ULL)
60
61
 
61
62
  /* Double <-> value helpers. */
62
63
  static inline xt_value xt_from_double(double d) {
@@ -87,6 +88,11 @@ xt_value xt_string_from_cstr(const char *data);
87
88
  const char *xt_string_data(xt_value value);
88
89
  int32_t xt_string_length_value(xt_value value);
89
90
 
91
+ /* -- bigint -------------------------------------------------------------- */
92
+ xt_value xt_bigint_from_string(const char *data, size_t len);
93
+ xt_value xt_bigint_ctor(int32_t argc, xt_value *argv);
94
+ xt_value xt_bigint_static(xt_value name, int32_t argc, xt_value *argv);
95
+
90
96
  /* -- function calling convention ----------------------------------------- */
91
97
  /* Every compiled function has the signature:
92
98
  * xt_value fn(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv);
@@ -46,6 +46,7 @@
46
46
  #define XT_OBJECT_KIND_DATE 8
47
47
  #define XT_OBJECT_KIND_REGEXP 9
48
48
  #define XT_OBJECT_KIND_SYMBOL 10
49
+ #define XT_OBJECT_KIND_BIGINT 11
49
50
 
50
51
  /* Common header for every heap object. */
51
52
  typedef struct xt_header {
@@ -63,6 +64,15 @@ typedef struct {
63
64
  char *data;
64
65
  } xt_string;
65
66
 
67
+ /* Sign-magnitude arbitrary-precision integer; see xt_bigint.c. */
68
+ typedef struct {
69
+ xt_header header;
70
+ int32_t sign; /* -1, 0 or 1 */
71
+ uint32_t length;
72
+ uint32_t capacity;
73
+ uint32_t *limbs;
74
+ } xt_bigint;
75
+
66
76
  typedef struct {
67
77
  xt_string *key;
68
78
  xt_value value;
@@ -111,6 +121,30 @@ int32_t xt_string_length(xt_string *s);
111
121
  int xt_string_equals(xt_string *a, xt_string *b);
112
122
  int32_t xt_to_int32(xt_value v);
113
123
 
124
+ /* BigInt runtime (xt_bigint.c). */
125
+ int xt_is_bigint(xt_value value);
126
+ double xt_bigint_to_double_value(xt_value value);
127
+ xt_value xt_bigint_to_string_radix(xt_value value, int radix);
128
+ xt_value xt_bigint_to_decimal(xt_value value);
129
+ xt_value xt_bigint_from_i64(int64_t value);
130
+ xt_value xt_bigint_from_double(double value);
131
+ xt_value xt_bigint_neg(xt_value value);
132
+ xt_value xt_bigint_add(xt_value a, xt_value b);
133
+ xt_value xt_bigint_sub(xt_value a, xt_value b);
134
+ xt_value xt_bigint_mul(xt_value a, xt_value b);
135
+ xt_value xt_bigint_div(xt_value a, xt_value b);
136
+ xt_value xt_bigint_mod(xt_value a, xt_value b);
137
+ xt_value xt_bigint_pow(xt_value a, xt_value b);
138
+ xt_value xt_bigint_bit_and(xt_value a, xt_value b);
139
+ xt_value xt_bigint_bit_or(xt_value a, xt_value b);
140
+ xt_value xt_bigint_bit_xor(xt_value a, xt_value b);
141
+ xt_value xt_bigint_bit_not(xt_value a);
142
+ xt_value xt_bigint_shl(xt_value a, xt_value b);
143
+ xt_value xt_bigint_shr(xt_value a, xt_value b);
144
+ int xt_bigint_compare(xt_value a, xt_value b);
145
+ int xt_bigint_compare_double(xt_value a, double b);
146
+ xt_value xt_bigint_method(xt_value target, const char *method, int32_t argc, xt_value *argv, int *handled);
147
+
114
148
  /* Container helper (xt_containers.c). */
115
149
  void xt_array_reserve(xt_array *array, uint32_t needed);
116
150
 
@@ -0,0 +1,135 @@
1
+ /* ------------------------------------------------------------------------- */
2
+ /* Arithmetic */
3
+ /* ------------------------------------------------------------------------- */
4
+
5
+ xt_value xt_bigint_neg(xt_value value) {
6
+ xt_bigint *r = bi_copy(BI(value));
7
+ r->sign = -r->sign;
8
+ return bi_wrap(r);
9
+ }
10
+
11
+ xt_value xt_bigint_add(xt_value av, xt_value bv) {
12
+ const xt_bigint *a = BI(av);
13
+ const xt_bigint *b = BI(bv);
14
+ if (a->sign == 0) return bv;
15
+ if (b->sign == 0) return av;
16
+ if (a->sign == b->sign) {
17
+ xt_bigint *r = bi_add_mag(a, b);
18
+ r->sign = a->sign;
19
+ return bi_wrap(r);
20
+ }
21
+ int cmp = bi_cmp_mag(a, b);
22
+ if (cmp == 0) return bi_wrap(bi_zero());
23
+ if (cmp > 0) {
24
+ xt_bigint *r = bi_sub_mag(a, b);
25
+ r->sign = a->sign;
26
+ return bi_wrap(r);
27
+ }
28
+ xt_bigint *r = bi_sub_mag(b, a);
29
+ r->sign = b->sign;
30
+ return bi_wrap(r);
31
+ }
32
+
33
+ xt_value xt_bigint_sub(xt_value av, xt_value bv) {
34
+ const xt_bigint *a = BI(av);
35
+ const xt_bigint *b = BI(bv);
36
+ if (b->sign == 0) return av;
37
+ if (a->sign == 0) return xt_bigint_neg(bv);
38
+ if (a->sign != b->sign) {
39
+ xt_bigint *r = bi_add_mag(a, b);
40
+ r->sign = a->sign;
41
+ return bi_wrap(r);
42
+ }
43
+ int cmp = bi_cmp_mag(a, b);
44
+ if (cmp == 0) return bi_wrap(bi_zero());
45
+ if (cmp > 0) {
46
+ xt_bigint *r = bi_sub_mag(a, b);
47
+ r->sign = a->sign;
48
+ return bi_wrap(r);
49
+ }
50
+ xt_bigint *r = bi_sub_mag(b, a);
51
+ r->sign = -a->sign;
52
+ return bi_wrap(r);
53
+ }
54
+
55
+ xt_value xt_bigint_mul(xt_value av, xt_value bv) {
56
+ const xt_bigint *a = BI(av);
57
+ const xt_bigint *b = BI(bv);
58
+ if (a->sign == 0 || b->sign == 0) return bi_wrap(bi_zero());
59
+ xt_bigint *r = bi_mul_mag(a, b);
60
+ r->sign = a->sign * b->sign;
61
+ return bi_wrap(r);
62
+ }
63
+
64
+ xt_value xt_bigint_div(xt_value av, xt_value bv) {
65
+ const xt_bigint *a = BI(av);
66
+ const xt_bigint *b = BI(bv);
67
+ if (b->sign == 0) {
68
+ bi_throw_range("Division by zero");
69
+ return bi_wrap(bi_zero());
70
+ }
71
+ if (a->sign == 0) return bi_wrap(bi_zero());
72
+ xt_bigint *q = NULL;
73
+ xt_bigint *r = NULL;
74
+ bi_divmod_mag(a, b, &q, &r);
75
+ q->sign = q->length ? a->sign * b->sign : 0;
76
+ return bi_wrap(q);
77
+ }
78
+
79
+ xt_value xt_bigint_mod(xt_value av, xt_value bv) {
80
+ const xt_bigint *a = BI(av);
81
+ const xt_bigint *b = BI(bv);
82
+ if (b->sign == 0) {
83
+ bi_throw_range("Division by zero");
84
+ return bi_wrap(bi_zero());
85
+ }
86
+ if (a->sign == 0) return bi_wrap(bi_zero());
87
+ xt_bigint *q = NULL;
88
+ xt_bigint *r = NULL;
89
+ bi_divmod_mag(a, b, &q, &r);
90
+ r->sign = r->length ? a->sign : 0;
91
+ return bi_wrap(r);
92
+ }
93
+
94
+ xt_value xt_bigint_pow(xt_value av, xt_value bv) {
95
+ const xt_bigint *a = BI(av);
96
+ const xt_bigint *b = BI(bv);
97
+ if (b->sign < 0) {
98
+ bi_throw_range("Exponent must be non-negative");
99
+ return bi_wrap(bi_zero());
100
+ }
101
+ if (b->sign == 0) return xt_bigint_from_i64(1);
102
+ if (a->sign == 0) return bi_wrap(bi_zero());
103
+ if (b->length > 2) {
104
+ bi_throw_range("Maximum BigInt size exceeded");
105
+ return bi_wrap(bi_zero());
106
+ }
107
+ uint64_t exponent = b->limbs[0];
108
+ if (b->length == 2) exponent |= (uint64_t)b->limbs[1] << 32;
109
+ if (exponent > 0xffffffffULL) {
110
+ bi_throw_range("Maximum BigInt size exceeded");
111
+ return bi_wrap(bi_zero());
112
+ }
113
+
114
+ xt_bigint *result = bi_from_u64(1, 1);
115
+ xt_bigint *base = bi_copy(a);
116
+ base->sign = 1;
117
+ uint32_t exp = (uint32_t)exponent;
118
+ while (exp > 0) {
119
+ if (exp & 1) {
120
+ xt_bigint *next = bi_mul_mag(result, base);
121
+ next->sign = 1;
122
+ result = next;
123
+ }
124
+ exp >>= 1;
125
+ if (exp) {
126
+ xt_bigint *next = bi_mul_mag(base, base);
127
+ next->sign = 1;
128
+ base = next;
129
+ }
130
+ }
131
+ result->sign = (a->sign < 0 && (exponent & 1)) ? -1 : 1;
132
+ if (result->length == 0) result->sign = 0;
133
+ return bi_wrap(result);
134
+ }
135
+