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.
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 +78 -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 +1 -0
  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
@@ -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) { return xt_number(xt_to_number(a) - xt_to_number(b)); }
209
- xt_value xt_mul(xt_value a, xt_value b) { return xt_number(xt_to_number(a) * xt_to_number(b)); }
210
- xt_value xt_div(xt_value a, xt_value b) { return xt_number(xt_to_number(a) / xt_to_number(b)); }
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) { return xt_number(pow(xt_to_number(a), xt_to_number(b))); }
219
- xt_value xt_neg(xt_value a) { return xt_number(-xt_to_number(a)); }
220
- xt_value xt_pos(xt_value a) { return xt_number(xt_to_number(a)); }
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) { return xt_number((double)(xt_to_int32(a) & xt_to_int32(b))); }
229
- xt_value xt_bit_or(xt_value a, xt_value b) { return xt_number((double)(xt_to_int32(a) | xt_to_int32(b))); }
230
- xt_value xt_bit_xor(xt_value a, xt_value b) { return xt_number((double)(xt_to_int32(a) ^ xt_to_int32(b))); }
231
- xt_value xt_bit_not(xt_value a) { return xt_number((double)(~xt_to_int32(a))); }
232
- xt_value xt_shl(xt_value a, xt_value b) { return xt_number((double)(int32_t)((uint32_t)xt_to_int32(a) << (xt_to_int32(b) & 31))); }
233
- xt_value xt_shr(xt_value a, xt_value b) { return xt_number((double)(xt_to_int32(a) >> (xt_to_int32(b) & 31))); }
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}`);
@@ -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 {