xbintsc 0.5.6 → 0.5.21

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 (490) hide show
  1. package/AGENTS.md +20 -10
  2. package/README.md +8 -7
  3. package/README.zh-CN.md +6 -6
  4. package/dist/src/binder/declarations.js +14 -3
  5. package/dist/src/binder/declarations.js.map +1 -1
  6. package/dist/src/cli/hints.js +7 -1
  7. package/dist/src/cli/hints.js.map +1 -1
  8. package/dist/src/cli/main.js +115 -15
  9. package/dist/src/cli/main.js.map +1 -1
  10. package/dist/src/cli/watch.d.ts +25 -0
  11. package/dist/src/cli/watch.js +93 -0
  12. package/dist/src/cli/watch.js.map +1 -0
  13. package/dist/src/codegen/generator/calls/access.js +11 -2
  14. package/dist/src/codegen/generator/calls/access.js.map +1 -1
  15. package/dist/src/codegen/generator/calls/closures.js +12 -4
  16. package/dist/src/codegen/generator/calls/closures.js.map +1 -1
  17. package/dist/src/codegen/generator/context.d.ts +8 -0
  18. package/dist/src/codegen/generator/context.js +22 -3
  19. package/dist/src/codegen/generator/context.js.map +1 -1
  20. package/dist/src/codegen/generator/expressions/operators.js +17 -15
  21. package/dist/src/codegen/generator/expressions/operators.js.map +1 -1
  22. package/dist/src/codegen/generator/expressions/primary.js +5 -0
  23. package/dist/src/codegen/generator/expressions/primary.js.map +1 -1
  24. package/dist/src/codegen/generator/module.js +0 -7
  25. package/dist/src/codegen/generator/module.js.map +1 -1
  26. package/dist/src/codegen/generator/numeric.d.ts +6 -3
  27. package/dist/src/codegen/generator/numeric.js +54 -11
  28. package/dist/src/codegen/generator/numeric.js.map +1 -1
  29. package/dist/src/codegen/generator/state.js +23 -0
  30. package/dist/src/codegen/generator/state.js.map +1 -1
  31. package/dist/src/codegen/generator/statements/control-flow.js +1 -4
  32. package/dist/src/codegen/generator/statements/control-flow.js.map +1 -1
  33. package/dist/src/codegen/generator/statements/loops.js +48 -16
  34. package/dist/src/codegen/generator/statements/loops.js.map +1 -1
  35. package/dist/src/codegen/generator/tables.js +26 -1
  36. package/dist/src/codegen/generator/tables.js.map +1 -1
  37. package/dist/src/diagnostics/diagnostic.d.ts +3 -1
  38. package/dist/src/diagnostics/diagnostic.js +23 -3
  39. package/dist/src/diagnostics/diagnostic.js.map +1 -1
  40. package/dist/src/driver/app-artifacts.d.ts +42 -0
  41. package/dist/src/driver/app-artifacts.js +53 -0
  42. package/dist/src/driver/app-artifacts.js.map +1 -0
  43. package/dist/src/driver/build-key.d.ts +29 -0
  44. package/dist/src/driver/build-key.js +35 -0
  45. package/dist/src/driver/build-key.js.map +1 -0
  46. package/dist/src/driver/bundler/graph.js +61 -12
  47. package/dist/src/driver/bundler/graph.js.map +1 -1
  48. package/dist/src/driver/bundler/merge.js +7 -1
  49. package/dist/src/driver/bundler/merge.js.map +1 -1
  50. package/dist/src/driver/compiler.d.ts +10 -67
  51. package/dist/src/driver/compiler.js +95 -234
  52. package/dist/src/driver/compiler.js.map +1 -1
  53. package/dist/src/driver/config.d.ts +3 -0
  54. package/dist/src/driver/config.js +8 -0
  55. package/dist/src/driver/config.js.map +1 -1
  56. package/dist/src/driver/frontend.d.ts +37 -0
  57. package/dist/src/driver/frontend.js +92 -0
  58. package/dist/src/driver/frontend.js.map +1 -0
  59. package/dist/src/driver/index.d.ts +1 -1
  60. package/dist/src/driver/index.js.map +1 -1
  61. package/dist/src/driver/options.d.ts +64 -0
  62. package/dist/src/driver/options.js +9 -0
  63. package/dist/src/driver/options.js.map +1 -0
  64. package/dist/src/driver/runtime-objects.d.ts +38 -0
  65. package/dist/src/driver/runtime-objects.js +112 -0
  66. package/dist/src/driver/runtime-objects.js.map +1 -0
  67. package/dist/src/driver/toolchain-provider.d.ts +4 -0
  68. package/dist/src/driver/toolchain-provider.js +4 -0
  69. package/dist/src/driver/toolchain-provider.js.map +1 -1
  70. package/dist/src/driver/toolchain.d.ts +32 -1
  71. package/dist/src/driver/toolchain.js +115 -11
  72. package/dist/src/driver/toolchain.js.map +1 -1
  73. package/dist/src/driver/version.d.ts +12 -0
  74. package/dist/src/driver/version.js +13 -0
  75. package/dist/src/driver/version.js.map +1 -0
  76. package/dist/src/driver/win-icon.d.ts +7 -9
  77. package/dist/src/driver/win-icon.js +37 -35
  78. package/dist/src/driver/win-icon.js.map +1 -1
  79. package/dist/src/extensions/node/fs/index.d.ts +4 -3
  80. package/dist/src/extensions/node/fs/index.js +12 -3
  81. package/dist/src/extensions/node/fs/index.js.map +1 -1
  82. package/dist/src/extensions/node/fs-promises/index.d.ts +5 -5
  83. package/dist/src/extensions/node/fs-promises/index.js +15 -6
  84. package/dist/src/extensions/node/fs-promises/index.js.map +1 -1
  85. package/dist/src/parser/declarations/classes.js +5 -0
  86. package/dist/src/parser/declarations/classes.js.map +1 -1
  87. package/dist/src/parser/declarations/functions.js +13 -1
  88. package/dist/src/parser/declarations/functions.js.map +1 -1
  89. package/dist/src/parser/modules.js +8 -3
  90. package/dist/src/parser/modules.js.map +1 -1
  91. package/dist/src/parser/parser.d.ts +1 -0
  92. package/dist/src/parser/parser.js +23 -0
  93. package/dist/src/parser/parser.js.map +1 -1
  94. package/dist/tests/cli/check.test.d.ts +6 -0
  95. package/dist/tests/cli/check.test.js +68 -0
  96. package/dist/tests/cli/check.test.js.map +1 -0
  97. package/dist/tests/cli/main.test.js +19 -0
  98. package/dist/tests/cli/main.test.js.map +1 -1
  99. package/dist/tests/cli/watch.test.d.ts +6 -0
  100. package/dist/tests/cli/watch.test.js +72 -0
  101. package/dist/tests/cli/watch.test.js.map +1 -0
  102. package/dist/tests/codegen/expressions.test.js +15 -3
  103. package/dist/tests/codegen/expressions.test.js.map +1 -1
  104. package/dist/tests/codegen/llvm.test.js +16 -0
  105. package/dist/tests/codegen/llvm.test.js.map +1 -1
  106. package/dist/tests/diagnostics/diagnostic.test.js +8 -0
  107. package/dist/tests/diagnostics/diagnostic.test.js.map +1 -1
  108. package/dist/tests/docs/structure.test.d.ts +1 -0
  109. package/dist/tests/docs/structure.test.js +92 -0
  110. package/dist/tests/docs/structure.test.js.map +1 -0
  111. package/dist/tests/driver/compiler.test.js +6 -0
  112. package/dist/tests/driver/compiler.test.js.map +1 -1
  113. package/dist/tests/driver/config.test.js +9 -0
  114. package/dist/tests/driver/config.test.js.map +1 -1
  115. package/dist/tests/driver/icon.test.js +19 -32
  116. package/dist/tests/driver/icon.test.js.map +1 -1
  117. package/dist/tests/driver/invalid-input.test.d.ts +10 -0
  118. package/dist/tests/driver/invalid-input.test.js +29 -0
  119. package/dist/tests/driver/invalid-input.test.js.map +1 -0
  120. package/dist/tests/driver/modules.test.js +42 -3
  121. package/dist/tests/driver/modules.test.js.map +1 -1
  122. package/dist/tests/driver/toolchain-provider.test.js +27 -1
  123. package/dist/tests/driver/toolchain-provider.test.js.map +1 -1
  124. package/dist/tests/driver/toolchain.test.js +60 -2
  125. package/dist/tests/driver/toolchain.test.js.map +1 -1
  126. package/dist/tests/e2e/array-buffer.test.d.ts +5 -0
  127. package/dist/tests/e2e/array-buffer.test.js +38 -0
  128. package/dist/tests/e2e/array-buffer.test.js.map +1 -0
  129. package/dist/tests/e2e/array-from-iterables.test.d.ts +7 -0
  130. package/dist/tests/e2e/array-from-iterables.test.js +34 -0
  131. package/dist/tests/e2e/array-from-iterables.test.js.map +1 -0
  132. package/dist/tests/e2e/array-symbol-iterator.test.d.ts +8 -0
  133. package/dist/tests/e2e/array-symbol-iterator.test.js +42 -0
  134. package/dist/tests/e2e/array-symbol-iterator.test.js.map +1 -0
  135. package/dist/tests/e2e/async-await.test.js +1 -1
  136. package/dist/tests/e2e/async-fs.test.d.ts +9 -0
  137. package/dist/tests/e2e/async-fs.test.js +119 -0
  138. package/dist/tests/e2e/async-fs.test.js.map +1 -0
  139. package/dist/tests/e2e/async-generators.test.d.ts +1 -0
  140. package/dist/tests/e2e/async-generators.test.js +154 -0
  141. package/dist/tests/e2e/async-generators.test.js.map +1 -0
  142. package/dist/tests/e2e/await-ordering.test.d.ts +5 -0
  143. package/dist/tests/e2e/await-ordering.test.js +37 -0
  144. package/dist/tests/e2e/await-ordering.test.js.map +1 -0
  145. package/dist/tests/e2e/compile-builtins.test.js +1 -1
  146. package/dist/tests/e2e/compile-modules.test.js +7 -0
  147. package/dist/tests/e2e/compile-modules.test.js.map +1 -1
  148. package/dist/tests/e2e/date-parse.test.d.ts +8 -0
  149. package/dist/tests/e2e/date-parse.test.js +38 -0
  150. package/dist/tests/e2e/date-parse.test.js.map +1 -0
  151. package/dist/tests/e2e/default-anonymous-exports.test.d.ts +7 -0
  152. package/dist/tests/e2e/default-anonymous-exports.test.js +23 -0
  153. package/dist/tests/e2e/default-anonymous-exports.test.js.map +1 -0
  154. package/dist/tests/e2e/fetch.test.js +24 -0
  155. package/dist/tests/e2e/fetch.test.js.map +1 -1
  156. package/dist/tests/e2e/globals-microtask.test.d.ts +9 -0
  157. package/dist/tests/e2e/globals-microtask.test.js +37 -0
  158. package/dist/tests/e2e/globals-microtask.test.js.map +1 -0
  159. package/dist/tests/e2e/gui-inline-svg.test.d.ts +11 -0
  160. package/dist/tests/e2e/gui-inline-svg.test.js +160 -0
  161. package/dist/tests/e2e/gui-inline-svg.test.js.map +1 -0
  162. package/dist/tests/e2e/gui-media.test.js +8 -1
  163. package/dist/tests/e2e/gui-media.test.js.map +1 -1
  164. package/dist/tests/e2e/inspect-builtins.test.d.ts +10 -0
  165. package/dist/tests/e2e/inspect-builtins.test.js +43 -0
  166. package/dist/tests/e2e/inspect-builtins.test.js.map +1 -0
  167. package/dist/tests/e2e/json-builtin-objects.test.d.ts +9 -0
  168. package/dist/tests/e2e/json-builtin-objects.test.js +23 -0
  169. package/dist/tests/e2e/json-builtin-objects.test.js.map +1 -0
  170. package/dist/tests/e2e/json-circular.test.d.ts +6 -0
  171. package/dist/tests/e2e/json-circular.test.js +43 -0
  172. package/dist/tests/e2e/json-circular.test.js.map +1 -0
  173. package/dist/tests/e2e/json-parse-reviver.test.d.ts +6 -0
  174. package/dist/tests/e2e/json-parse-reviver.test.js +29 -0
  175. package/dist/tests/e2e/json-parse-reviver.test.js.map +1 -0
  176. package/dist/tests/e2e/json-stringify-replacer.test.d.ts +6 -0
  177. package/dist/tests/e2e/json-stringify-replacer.test.js +27 -0
  178. package/dist/tests/e2e/json-stringify-replacer.test.js.map +1 -0
  179. package/dist/tests/e2e/json-stringify-space.test.d.ts +6 -0
  180. package/dist/tests/e2e/json-stringify-space.test.js +23 -0
  181. package/dist/tests/e2e/json-stringify-space.test.js.map +1 -0
  182. package/dist/tests/e2e/method-dispatch-errors.test.d.ts +9 -0
  183. package/dist/tests/e2e/method-dispatch-errors.test.js +38 -0
  184. package/dist/tests/e2e/method-dispatch-errors.test.js.map +1 -0
  185. package/dist/tests/e2e/native-extensions.test.js +1 -1
  186. package/dist/tests/e2e/native-extensions.test.js.map +1 -1
  187. package/dist/tests/e2e/promise-with-resolvers.test.d.ts +5 -0
  188. package/dist/tests/e2e/promise-with-resolvers.test.js +20 -0
  189. package/dist/tests/e2e/promise-with-resolvers.test.js.map +1 -0
  190. package/dist/tests/e2e/property-descriptors.test.d.ts +5 -0
  191. package/dist/tests/e2e/property-descriptors.test.js +25 -0
  192. package/dist/tests/e2e/property-descriptors.test.js.map +1 -0
  193. package/dist/tests/e2e/property-ic.test.d.ts +1 -0
  194. package/dist/tests/e2e/property-ic.test.js +55 -0
  195. package/dist/tests/e2e/property-ic.test.js.map +1 -0
  196. package/dist/tests/e2e/runtime-errors.test.d.ts +10 -0
  197. package/dist/tests/e2e/runtime-errors.test.js +52 -0
  198. package/dist/tests/e2e/runtime-errors.test.js.map +1 -0
  199. package/dist/tests/e2e/structured-clone.test.d.ts +6 -0
  200. package/dist/tests/e2e/structured-clone.test.js +49 -0
  201. package/dist/tests/e2e/structured-clone.test.js.map +1 -0
  202. package/dist/tests/e2e/text-codec.test.d.ts +6 -0
  203. package/dist/tests/e2e/text-codec.test.js +24 -0
  204. package/dist/tests/e2e/text-codec.test.js.map +1 -0
  205. package/dist/tests/e2e/typed-array-views.test.d.ts +6 -0
  206. package/dist/tests/e2e/typed-array-views.test.js +39 -0
  207. package/dist/tests/e2e/typed-array-views.test.js.map +1 -0
  208. package/dist/tests/e2e/url-search-params.test.d.ts +5 -0
  209. package/dist/tests/e2e/url-search-params.test.js +30 -0
  210. package/dist/tests/e2e/url-search-params.test.js.map +1 -0
  211. package/dist/tests/e2e/weak-collections.test.d.ts +1 -0
  212. package/dist/tests/e2e/weak-collections.test.js +88 -0
  213. package/dist/tests/e2e/weak-collections.test.js.map +1 -0
  214. package/dist/tests/parser/declarations.test.js +12 -0
  215. package/dist/tests/parser/declarations.test.js.map +1 -1
  216. package/dist/tests/parser/module-syntax.test.js +9 -0
  217. package/dist/tests/parser/module-syntax.test.js.map +1 -1
  218. package/dist/tests/parser/parser.test.js +7 -0
  219. package/dist/tests/parser/parser.test.js.map +1 -1
  220. package/dist/tests/version.test.js +5 -1
  221. package/dist/tests/version.test.js.map +1 -1
  222. package/doc/ai/README.md +4 -3
  223. package/doc/ai/cli.md +41 -0
  224. package/doc/ai/contributing.md +20 -16
  225. package/doc/ai/extensions.md +13 -10
  226. package/doc/ai/language-support.md +19 -14
  227. package/doc/ai/troubleshooting.md +11 -9
  228. package/doc/ai/zh-CN/README.md +3 -2
  229. package/doc/ai/zh-CN/cli.md +35 -0
  230. package/doc/ai/zh-CN/contributing.md +16 -15
  231. package/doc/ai/zh-CN/extensions.md +12 -9
  232. package/doc/ai/zh-CN/language-support.md +19 -15
  233. package/doc/ai/zh-CN/troubleshooting.md +9 -8
  234. package/doc/gui/api.md +8 -0
  235. package/doc/gui/build.md +13 -4
  236. package/doc/gui/known-issues.md +19 -14
  237. package/doc/gui/media.md +32 -3
  238. package/doc/gui/rendering.md +3 -1
  239. package/doc/gui.md +28 -5
  240. package/doc/icon.md +5 -4
  241. package/doc/implemented/async.md +51 -0
  242. package/doc/implemented/binder.md +13 -0
  243. package/doc/implemented/cli.md +47 -0
  244. package/doc/implemented/codegen.md +33 -0
  245. package/doc/implemented/collections.md +26 -0
  246. package/doc/implemented/driver.md +19 -0
  247. package/doc/implemented/extensions.md +19 -0
  248. package/doc/implemented/fetch.md +44 -0
  249. package/doc/implemented/lexer.md +23 -0
  250. package/doc/implemented/modules.md +28 -0
  251. package/doc/implemented/node/assert.md +17 -0
  252. package/doc/implemented/node/buffer.md +29 -0
  253. package/doc/implemented/node/child-process.md +29 -0
  254. package/doc/implemented/node/crypto.md +9 -0
  255. package/doc/implemented/node/dgram.md +15 -0
  256. package/doc/implemented/node/events.md +37 -0
  257. package/doc/implemented/node/fs-promises.md +49 -0
  258. package/doc/implemented/node/fs.md +112 -0
  259. package/doc/implemented/node/http.md +21 -0
  260. package/doc/implemented/node/net.md +17 -0
  261. package/doc/implemented/node/os.md +22 -0
  262. package/doc/implemented/node/path.md +33 -0
  263. package/doc/implemented/node/process.md +23 -0
  264. package/doc/implemented/node/querystring.md +20 -0
  265. package/doc/implemented/node/stream-promises.md +8 -0
  266. package/doc/implemented/node/stream.md +19 -0
  267. package/doc/implemented/node/test.md +10 -0
  268. package/doc/implemented/node/url.md +8 -0
  269. package/doc/implemented/node/util.md +25 -0
  270. package/doc/implemented/node/worker-threads.md +10 -0
  271. package/doc/implemented/node/zlib.md +8 -0
  272. package/doc/implemented/node.md +48 -0
  273. package/doc/implemented/operators.md +38 -0
  274. package/doc/implemented/parser.md +58 -0
  275. package/doc/implemented/pipeline.md +28 -0
  276. package/doc/implemented/runtime-core.md +32 -0
  277. package/doc/implemented/stdlib.md +78 -0
  278. package/doc/implemented/strings.md +27 -0
  279. package/doc/implemented/tests.md +10 -0
  280. package/doc/implemented/typed-arrays.md +26 -0
  281. package/doc/implemented/value-model.md +18 -0
  282. package/doc/implemented.md +54 -355
  283. package/doc/node-implemented.md +3 -585
  284. package/doc/node-unimplemented.md +3 -164
  285. package/doc/requirements.md +23 -8
  286. package/doc/unimplemented/classes.md +22 -0
  287. package/doc/unimplemented/deviations.md +27 -0
  288. package/doc/unimplemented/expressions.md +26 -0
  289. package/doc/unimplemented/functions.md +21 -0
  290. package/doc/unimplemented/modules.md +22 -0
  291. package/doc/unimplemented/node/async.md +20 -0
  292. package/doc/unimplemented/node/bun.md +9 -0
  293. package/doc/unimplemented/node/fs-promises.md +20 -0
  294. package/doc/unimplemented/node/fs.md +30 -0
  295. package/doc/unimplemented/node/globals.md +23 -0
  296. package/doc/unimplemented/node/modules.md +21 -0
  297. package/doc/unimplemented/node.md +21 -0
  298. package/doc/unimplemented/statements.md +18 -0
  299. package/doc/unimplemented/stdlib.md +54 -0
  300. package/doc/unimplemented/toolchain.md +14 -0
  301. package/doc/unimplemented/types.md +12 -0
  302. package/doc/unimplemented.md +18 -275
  303. package/doc/xbintsc.config.schema.json +12 -0
  304. package/doc/zh-CN/gui/api.md +7 -0
  305. package/doc/zh-CN/gui/build.md +11 -3
  306. package/doc/zh-CN/gui/known-issues.md +17 -11
  307. package/doc/zh-CN/gui/media.md +26 -2
  308. package/doc/zh-CN/gui/rendering.md +2 -1
  309. package/doc/zh-CN/gui.md +21 -3
  310. package/doc/zh-CN/icon.md +5 -4
  311. package/doc/zh-CN/implemented/async.md +49 -0
  312. package/doc/zh-CN/implemented/binder.md +13 -0
  313. package/doc/zh-CN/implemented/cli.md +46 -0
  314. package/doc/zh-CN/implemented/codegen.md +33 -0
  315. package/doc/zh-CN/implemented/collections.md +26 -0
  316. package/doc/zh-CN/implemented/driver.md +19 -0
  317. package/doc/zh-CN/implemented/extensions.md +19 -0
  318. package/doc/zh-CN/implemented/fetch.md +31 -0
  319. package/doc/zh-CN/implemented/lexer.md +23 -0
  320. package/doc/zh-CN/implemented/modules.md +28 -0
  321. package/doc/zh-CN/implemented/node/assert.md +17 -0
  322. package/doc/zh-CN/implemented/node/buffer.md +25 -0
  323. package/doc/zh-CN/implemented/node/child-process.md +27 -0
  324. package/doc/zh-CN/implemented/node/crypto.md +9 -0
  325. package/doc/zh-CN/implemented/node/dgram.md +15 -0
  326. package/doc/zh-CN/implemented/node/events.md +36 -0
  327. package/doc/zh-CN/implemented/node/fs-promises.md +30 -0
  328. package/doc/zh-CN/implemented/node/fs.md +105 -0
  329. package/doc/zh-CN/implemented/node/http.md +17 -0
  330. package/doc/zh-CN/implemented/node/net.md +17 -0
  331. package/doc/zh-CN/implemented/node/os.md +21 -0
  332. package/doc/zh-CN/implemented/node/path.md +26 -0
  333. package/doc/zh-CN/implemented/node/process.md +23 -0
  334. package/doc/zh-CN/implemented/node/querystring.md +20 -0
  335. package/doc/zh-CN/implemented/node/stream-promises.md +8 -0
  336. package/doc/zh-CN/implemented/node/stream.md +15 -0
  337. package/doc/zh-CN/implemented/node/test.md +10 -0
  338. package/doc/zh-CN/implemented/node/url.md +8 -0
  339. package/doc/zh-CN/implemented/node/util.md +25 -0
  340. package/doc/zh-CN/implemented/node/worker-threads.md +9 -0
  341. package/doc/zh-CN/implemented/node/zlib.md +8 -0
  342. package/doc/zh-CN/implemented/node.md +45 -0
  343. package/doc/zh-CN/implemented/operators.md +38 -0
  344. package/doc/zh-CN/implemented/parser.md +58 -0
  345. package/doc/zh-CN/implemented/pipeline.md +25 -0
  346. package/doc/zh-CN/implemented/runtime-core.md +31 -0
  347. package/doc/zh-CN/implemented/stdlib.md +76 -0
  348. package/doc/zh-CN/implemented/strings.md +27 -0
  349. package/doc/zh-CN/implemented/tests.md +10 -0
  350. package/doc/zh-CN/implemented/typed-arrays.md +26 -0
  351. package/doc/zh-CN/implemented/value-model.md +18 -0
  352. package/doc/zh-CN/implemented.md +50 -350
  353. package/doc/zh-CN/node-implemented.md +4 -531
  354. package/doc/zh-CN/node-unimplemented.md +4 -139
  355. package/doc/zh-CN/plan-require-node-modules.md +4 -4
  356. package/doc/zh-CN/requirements.md +20 -6
  357. package/doc/zh-CN/unimplemented/classes.md +22 -0
  358. package/doc/zh-CN/unimplemented/deviations.md +24 -0
  359. package/doc/zh-CN/unimplemented/expressions.md +24 -0
  360. package/doc/zh-CN/unimplemented/functions.md +21 -0
  361. package/doc/zh-CN/unimplemented/modules.md +19 -0
  362. package/doc/zh-CN/unimplemented/node/async.md +20 -0
  363. package/doc/zh-CN/unimplemented/node/bun.md +8 -0
  364. package/doc/zh-CN/unimplemented/node/fs-promises.md +12 -0
  365. package/doc/zh-CN/unimplemented/node/fs.md +24 -0
  366. package/doc/zh-CN/unimplemented/node/globals.md +14 -0
  367. package/doc/zh-CN/unimplemented/node/modules.md +15 -0
  368. package/doc/zh-CN/unimplemented/node.md +18 -0
  369. package/doc/zh-CN/unimplemented/statements.md +15 -0
  370. package/doc/zh-CN/unimplemented/stdlib.md +54 -0
  371. package/doc/zh-CN/unimplemented/toolchain.md +14 -0
  372. package/doc/zh-CN/unimplemented/types.md +11 -0
  373. package/doc/zh-CN/unimplemented.md +14 -237
  374. package/llms.txt +32 -4
  375. package/package.json +1 -1
  376. package/runtime/ext_gui/inline_svg.cpp +219 -0
  377. package/runtime/ext_gui/inline_svg.h +41 -0
  378. package/runtime/ext_gui/layout.cpp +18 -0
  379. package/runtime/ext_gui/layout.h +7 -0
  380. package/runtime/ext_gui/layout_flow.cpp +4 -3
  381. package/runtime/ext_gui/paint.cpp +14 -0
  382. package/runtime/ext_gui/paint.h +5 -1
  383. package/runtime/ext_gui/renderer_image.cpp +53 -25
  384. package/runtime/ext_gui/renderer_shaders.h +2 -2
  385. package/runtime/ext_gui/stb_image.h +1 -17
  386. package/runtime/ext_gui/style_ua.cpp +3 -0
  387. package/runtime/ext_gui/svg.cpp +122 -39
  388. package/runtime/ext_gui/svg.h +14 -3
  389. package/runtime/ext_gui/window.cpp +28 -0
  390. package/runtime/ext_node/child_process/child_process.c +173 -73
  391. package/runtime/ext_node/fs/async_api.c +314 -0
  392. package/runtime/ext_node/fs/async_complete.c +99 -0
  393. package/runtime/ext_node/fs/async_fh.c +206 -0
  394. package/runtime/ext_node/fs/async_job.c +81 -0
  395. package/runtime/ext_node/fs/async_job.h +132 -0
  396. package/runtime/ext_node/fs/async_worker.c +534 -0
  397. package/runtime/ext_node/fs/async_worker_dir.c +439 -0
  398. package/runtime/ext_node/fs/async_worker_dir.h +33 -0
  399. package/runtime/ext_node/fs/async_worker_fd.c +74 -0
  400. package/runtime/ext_node/fs/dir.c +60 -15
  401. package/runtime/ext_node/fs/fs_common.h +9 -0
  402. package/runtime/ext_node/fs/fs_ops.c +18 -29
  403. package/runtime/ext_node/fs/parts/builtins.inc +34 -0
  404. package/runtime/ext_node/fs/parts/platform.inc +66 -0
  405. package/runtime/ext_node/fs/promises.c +44 -234
  406. package/runtime/rt.h +15 -0
  407. package/runtime/rt_internal.h +108 -0
  408. package/runtime/xt_alloc.c +43 -7
  409. package/runtime/xt_array_buffer.c +284 -0
  410. package/runtime/xt_async.c +46 -21
  411. package/runtime/xt_async_io.c +333 -0
  412. package/runtime/xt_async_io.h +47 -0
  413. package/runtime/xt_bigint/helpers.inc +3 -3
  414. package/runtime/xt_builtins.c +21 -17
  415. package/runtime/xt_constructors.c +12 -2
  416. package/runtime/xt_containers/access.inc +148 -3
  417. package/runtime/xt_containers/objects.inc +26 -2
  418. package/runtime/xt_containers/shapes.inc +71 -0
  419. package/runtime/xt_containers.c +1 -0
  420. package/runtime/xt_coroutine.c +17 -0
  421. package/runtime/xt_fetch/async.inc +295 -0
  422. package/runtime/xt_fetch/request.inc +6 -183
  423. package/runtime/xt_fetch/socket.inc +5 -4
  424. package/runtime/xt_fetch.c +6 -4
  425. package/runtime/xt_generator.c +299 -10
  426. package/runtime/xt_io/inspect.inc +112 -0
  427. package/runtime/xt_loop.c +79 -7
  428. package/runtime/xt_performance.c +37 -0
  429. package/runtime/xt_promise.c +63 -1
  430. package/runtime/xt_stdlib/arrays.inc +1 -1
  431. package/runtime/xt_stdlib/dispatch.inc +46 -11
  432. package/runtime/xt_stdlib/strings.inc +1 -1
  433. package/runtime/xt_stdlib2/array-statics.inc +25 -0
  434. package/runtime/xt_stdlib2/arrays.inc +5 -3
  435. package/runtime/xt_stdlib2/container.inc +5 -0
  436. package/runtime/xt_stdlib2/date.inc +111 -3
  437. package/runtime/xt_stdlib2/error.inc +24 -0
  438. package/runtime/xt_stdlib2/json.inc +310 -19
  439. package/runtime/xt_stdlib2/number-string-statics.inc +1 -1
  440. package/runtime/xt_stdlib2/objects.inc +122 -0
  441. package/runtime/xt_stdlib2/set.inc +1 -1
  442. package/runtime/xt_structured_clone.c +159 -0
  443. package/runtime/xt_symbol.c +2 -2
  444. package/runtime/xt_text_codec.c +69 -0
  445. package/runtime/xt_typed_array/construction.inc +35 -5
  446. package/runtime/xt_typed_array/elements.inc +159 -0
  447. package/runtime/xt_typed_array/methods.inc +21 -5
  448. package/runtime/xt_typed_array.c +7 -10
  449. package/runtime/xt_url.c +375 -0
  450. package/runtime/xt_values/arithmetic.inc +2 -2
  451. package/runtime/xt_values/conversions.inc +1 -1
  452. package/runtime/xt_weak.c +281 -0
  453. package/scripts/build-gui.ts +133 -60
  454. package/scripts/check-version.ts +3 -3
  455. package/src/binder/declarations.ts +14 -3
  456. package/src/cli/hints.ts +8 -1
  457. package/src/cli/main.ts +119 -18
  458. package/src/cli/watch.ts +101 -0
  459. package/src/codegen/generator/calls/access.ts +10 -2
  460. package/src/codegen/generator/calls/closures.ts +12 -4
  461. package/src/codegen/generator/context.ts +23 -3
  462. package/src/codegen/generator/expressions/operators.ts +27 -13
  463. package/src/codegen/generator/expressions/primary.ts +4 -0
  464. package/src/codegen/generator/module.ts +0 -7
  465. package/src/codegen/generator/numeric.ts +85 -11
  466. package/src/codegen/generator/state.ts +23 -0
  467. package/src/codegen/generator/statements/control-flow.ts +1 -4
  468. package/src/codegen/generator/statements/loops.ts +50 -16
  469. package/src/codegen/generator/tables.ts +26 -1
  470. package/src/diagnostics/diagnostic.ts +23 -3
  471. package/src/driver/app-artifacts.ts +77 -0
  472. package/src/driver/build-key.ts +55 -0
  473. package/src/driver/bundler/graph.ts +63 -13
  474. package/src/driver/bundler/merge.ts +4 -1
  475. package/src/driver/compiler.ts +94 -328
  476. package/src/driver/config.ts +11 -0
  477. package/src/driver/frontend.ts +120 -0
  478. package/src/driver/index.ts +0 -1
  479. package/src/driver/options.ts +70 -0
  480. package/src/driver/runtime-objects.ts +134 -0
  481. package/src/driver/toolchain-provider.ts +4 -0
  482. package/src/driver/toolchain.ts +154 -10
  483. package/src/driver/version.ts +12 -0
  484. package/src/driver/win-icon.ts +36 -36
  485. package/src/extensions/node/fs/index.ts +12 -3
  486. package/src/extensions/node/fs-promises/index.ts +15 -6
  487. package/src/parser/declarations/classes.ts +4 -0
  488. package/src/parser/declarations/functions.ts +12 -1
  489. package/src/parser/modules.ts +8 -4
  490. package/src/parser/parser.ts +28 -0
package/src/cli/main.ts CHANGED
@@ -30,7 +30,6 @@ import {
30
30
  thrownFailure,
31
31
  toolchainPointer,
32
32
  UNEXPECTED_FAILURE_HINT,
33
- type DocumentationPointer,
34
33
  } from "./hints.js";
35
34
  import { createDefaultRegistry, type ExtensionRegistry } from "../extensions/registry.js";
36
35
  import { bundledExtensions } from "../extensions/catalog.js";
@@ -44,6 +43,10 @@ import {
44
43
  type AppConfig,
45
44
  type ProjectConfig,
46
45
  } from "../driver/config.js";
46
+ import { fingerprintTree, startWatching } from "./watch.js";
47
+
48
+ /** Sentinel: watch mode keeps the process alive instead of exiting. */
49
+ const KEEP_RUNNING = -1;
47
50
 
48
51
  export interface CliIo {
49
52
  readonly stdout: (text: string) => void;
@@ -80,6 +83,8 @@ const VALUE_FLAGS = new Set([
80
83
  "icon",
81
84
  "app-id",
82
85
  "app-name",
86
+ "pgo-generate",
87
+ "pgo-use",
83
88
  ]);
84
89
 
85
90
  function parseArgs(argv: readonly string[]): ParsedArgs {
@@ -200,22 +205,29 @@ function emitHint(io: CliIo, line: string): void {
200
205
  * the question.
201
206
  */
202
207
  function reportThrown(error: unknown, io: CliIo): number {
203
- const message =
204
- error instanceof ToolchainError
205
- ? `xbintsc: ${error.message}`
206
- : `xbintsc: ${error instanceof Error ? error.message : String(error)}`;
207
- io.stderr(`${message.trimEnd()}\n`);
208
- const text = error instanceof ToolchainError ? error.message : message;
209
- const pointer = error instanceof ToolchainError ? toolchainPointer(text) : thrownPointer(text);
210
- emitHint(io, `hint: ${pointer.text} — see ${pointer.path}`);
208
+ if (error instanceof ToolchainError) {
209
+ io.stderr(`xbintsc: ${error.message.trimEnd()}\n`);
210
+ const pointer = toolchainPointer(error.message);
211
+ emitHint(io, `hint: ${pointer.text} — see ${pointer.path}`);
212
+ return 1;
213
+ }
214
+ const message = error instanceof Error ? error.message : String(error);
215
+ const failure = thrownFailure(message);
216
+ if (failure === undefined) {
217
+ /* An uncaught exception that is not a known toolchain/setup failure is a
218
+ * compiler bug: say so instead of blaming the user's source or toolchain. */
219
+ io.stderr(`xbintsc: internal error: ${message.trimEnd()}\n`);
220
+ emitHint(
221
+ io,
222
+ `hint: this is a bug in xbintsc, not in your program — please report it with the input that triggered it — see ${UNEXPECTED_FAILURE_HINT.path}`,
223
+ );
224
+ return 1;
225
+ }
226
+ io.stderr(`xbintsc: ${message.trimEnd()}\n`);
227
+ emitHint(io, `hint: ${failure.pointer.text} — see ${failure.pointer.path}`);
211
228
  return 1;
212
229
  }
213
230
 
214
- /** The document that explains a failure the CLI reports as a plain message. */
215
- function thrownPointer(message: string): DocumentationPointer {
216
- return thrownFailure(message)?.pointer ?? UNEXPECTED_FAILURE_HINT;
217
- }
218
-
219
231
  /** Report a project-config failure, which never becomes a diagnostic bag. */
220
232
  function reportConfigError(error: string, io: CliIo): number {
221
233
  io.stderr(`xbintsc: ${error}\n`);
@@ -231,6 +243,8 @@ const HELP = `xbintsc ${COMPILER_VERSION} - TypeScript binary compiler
231
243
  Usage:
232
244
  xbintsc build <file.ts> [options] Compile to a native binary
233
245
  xbintsc run <file.ts> [-- args] Compile and execute
246
+ xbintsc check <file.ts> Parse and bind without linking
247
+ xbintsc watch <file.ts> [options] Rebuild whenever the source tree changes
234
248
  xbintsc emit <file.ts> Print LLVM IR
235
249
  xbintsc doctor Report the resolved toolchain
236
250
  xbintsc version Print the version
@@ -255,11 +269,15 @@ Options:
255
269
  --verbose Print progress information
256
270
  --time Print per-phase build timings
257
271
  --debug Emit debug info (DWARF/CodeView) and keep frame pointers
272
+ --lto Compile program and runtime to LTO bitcode; link with lld
273
+ --pgo-generate [dir] Build an instrumented binary writing profiles to dir
274
+ --pgo-use [dir] Build with the profiles collected from --pgo-generate
275
+ --json Print diagnostics as a JSON array on stdout
258
276
  --no-hints Do not append the "hint: … see <doc>" line to failures
259
277
 
260
278
  xbintsc compiles a subset of TypeScript to a native binary. Types are erased
261
- (never checked), Node modules need --ext node, third-party npm imports are not
262
- supported, and clang 16+ is required to link.
279
+ (never checked), Node built-ins need --ext node, packages in node_modules are
280
+ bundled at build time, and clang 16+ is required to link.
263
281
 
264
282
  Docs: doc/ai/README.md (task guide) - doc/ai/language-support.md (subset) -
265
283
  doc/ai/troubleshooting.md (failures) - llms.txt (index of every document)
@@ -323,7 +341,7 @@ function doctor(io: CliIo): number {
323
341
  try {
324
342
  if (!toolchain) throw new Error("no toolchain");
325
343
  const resource = resolveResourceCompiler(realRunner, toolchain.clang);
326
- io.stdout(`icon res : ${resource ? `${resource.tool} (${resource.kind})` : "none (.exe icon disabled)"}\n`);
344
+ io.stdout(`icon res : ${resource ? resource.tool : "none (.exe icon disabled)"}\n`);
327
345
  } catch {
328
346
  io.stdout("icon res : unknown\n");
329
347
  }
@@ -414,6 +432,57 @@ function dispatch(argv: readonly string[], io: CliIo): number {
414
432
  return 0;
415
433
  }
416
434
 
435
+ if (command === "check") {
436
+ const cliEntry = args.positionals[0];
437
+ const resolved = resolveProjectConfig(args.flags, cliEntry);
438
+ if (!resolved.ok) return reportConfigError(resolved.error, io);
439
+ const entry = cliEntry ?? resolved.config.entry;
440
+ if (!entry) {
441
+ io.stderr(`xbintsc: check requires a source file (or 'entry' in ${CONFIG_FILE_NAME})\n`);
442
+ emitHint(io, `hint: pass the entry file, or set 'entry' in ${CONFIG_FILE_NAME} — see ${DOC_CLI}`);
443
+ return 1;
444
+ }
445
+ const extNames = listFlag(args.flags, "ext") ?? resolved.config.extensions ?? [];
446
+ const nativeManifests = listFlag(args.flags, "ext-native") ?? resolved.config.extNative ?? [];
447
+ const registry = buildRegistry(extNames, nativeManifests);
448
+ /* Front-end only: parse, bundle and lower far enough to report binder /
449
+ * unsupported-feature diagnostics, but never invoke clang or write output. */
450
+ const { diagnostics } = compileEntry(entry, registry);
451
+ const failed = diagnostics.some((diagnostic) => diagnostic.category === "error");
452
+ if (args.flags.has("json")) {
453
+ io.stdout(`${JSON.stringify(diagnostics)}\n`);
454
+ } else if (failed) {
455
+ printDiagnostics(diagnostics, entry, io);
456
+ }
457
+ return failed ? 1 : 0;
458
+ }
459
+
460
+ if (command === "watch") {
461
+ const cliEntry = args.positionals[0];
462
+ const resolved = resolveProjectConfig(args.flags, cliEntry);
463
+ if (!resolved.ok) return reportConfigError(resolved.error, io);
464
+ const entry = cliEntry ?? resolved.config.entry;
465
+ if (!entry) {
466
+ io.stderr(`xbintsc: watch requires a source file (or 'entry' in ${CONFIG_FILE_NAME})\n`);
467
+ emitHint(io, `hint: pass the entry file, or set 'entry' in ${CONFIG_FILE_NAME} — see ${DOC_CLI}`);
468
+ return 1;
469
+ }
470
+ /* Re-enter the normal build path with the same flags, exactly as if the
471
+ * user had typed `build`; the config is re-read on every rebuild too. */
472
+ const forwarded = ["build", ...argv.slice(1)];
473
+ run(forwarded, io);
474
+ const root = dirname(resolve(entry));
475
+ startWatching({
476
+ scan: () => fingerprintTree(root),
477
+ onRebuild: () => {
478
+ io.stdout("\n");
479
+ run(forwarded, io);
480
+ },
481
+ });
482
+ io.stdout(`xbintsc: watching ${root} for changes (Ctrl+C to stop)\n`);
483
+ return KEEP_RUNNING;
484
+ }
485
+
417
486
  if (command === "emit") {
418
487
  const cliEntry = args.positionals[0];
419
488
  const resolved = resolveProjectConfig(args.flags, cliEntry);
@@ -429,6 +498,10 @@ function dispatch(argv: readonly string[], io: CliIo): number {
429
498
  const registry = buildRegistry(extNames, nativeManifests);
430
499
  const { ir, diagnostics } = compileEntry(entry, registry, { debug: Boolean(args.flags.get("debug")) });
431
500
  if (diagnostics.some((d) => d.category === "error")) {
501
+ if (args.flags.has("json")) {
502
+ io.stdout(`${JSON.stringify(diagnostics)}\n`);
503
+ return 1;
504
+ }
432
505
  printDiagnostics(diagnostics, entry, io);
433
506
  return 1;
434
507
  }
@@ -452,6 +525,24 @@ function dispatch(argv: readonly string[], io: CliIo): number {
452
525
  const extNames = listFlag(args.flags, "ext") ?? config.extensions ?? [];
453
526
  const nativeManifests = listFlag(args.flags, "ext-native") ?? config.extNative ?? [];
454
527
  const registry = buildRegistry(extNames, nativeManifests);
528
+ const pgoGenerate = args.flags.get("pgo-generate");
529
+ const pgoUse = args.flags.get("pgo-use");
530
+ if (pgoGenerate !== undefined && pgoUse !== undefined) {
531
+ io.stderr("xbintsc: --pgo-generate and --pgo-use are mutually exclusive\n");
532
+ return 1;
533
+ }
534
+ const pgo =
535
+ pgoGenerate !== undefined
536
+ ? ("generate" as const)
537
+ : pgoUse !== undefined
538
+ ? ("use" as const)
539
+ : config.pgo;
540
+ const pgoDir =
541
+ typeof pgoGenerate === "string"
542
+ ? pgoGenerate
543
+ : typeof pgoUse === "string"
544
+ ? pgoUse
545
+ : config.pgoDir;
455
546
 
456
547
  const result = build(entry, {
457
548
  output: typeof args.flags.get("output") === "string" ? (args.flags.get("output") as string) : config.output,
@@ -463,9 +554,16 @@ function dispatch(argv: readonly string[], io: CliIo): number {
463
554
  extensions: registry,
464
555
  app: mergeAppConfig(args.flags, config),
465
556
  debug: Boolean(args.flags.get("debug")),
557
+ lto: Boolean(args.flags.get("lto")) || config.lto === true,
558
+ ...(pgo ? { pgo } : {}),
559
+ ...(pgoDir ? { pgoDir } : {}),
466
560
  });
467
561
 
468
562
  if (result.diagnostics.some((d) => d.category === "error")) {
563
+ if (args.flags.has("json")) {
564
+ io.stdout(`${JSON.stringify(result.diagnostics)}\n`);
565
+ return 1;
566
+ }
469
567
  printDiagnostics(result.diagnostics, entry, io);
470
568
  return 1;
471
569
  }
@@ -493,5 +591,8 @@ function dispatch(argv: readonly string[], io: CliIo): number {
493
591
  const isMain =
494
592
  process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href;
495
593
  if (isMain) {
496
- process.exit(run(process.argv.slice(2)));
594
+ const status = run(process.argv.slice(2));
595
+ /* Watch mode returns KEEP_RUNNING; the polling interval keeps the process
596
+ * alive, so calling process.exit here would stop it immediately. */
597
+ if (status !== KEEP_RUNNING) process.exit(status);
497
598
  }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * `xbintsc watch` support: fingerprint a source tree and rebuild when it
3
+ * changes.
4
+ *
5
+ * The scan is deliberately polling-based. A self-hosted xbintsc binary has no
6
+ * `fs.watch` backend in the Node extension, and polling works identically on
7
+ * every platform. The tree is the entry file's directory, with build outputs
8
+ * and dependency directories excluded; package sources inside `node_modules`
9
+ * are not watched (run the build once after installing a dependency).
10
+ */
11
+
12
+ import { readFileSync, readdirSync, statSync, type Dirent } from "node:fs";
13
+ import { extname, join, resolve } from "node:path";
14
+
15
+ const WATCHED_EXTENSIONS = new Set([
16
+ ".ts",
17
+ ".tsx",
18
+ ".js",
19
+ ".mjs",
20
+ ".cjs",
21
+ ".json",
22
+ ".html",
23
+ ".css",
24
+ ]);
25
+
26
+ const IGNORED_DIRECTORIES = new Set([
27
+ "node_modules",
28
+ ".git",
29
+ ".github",
30
+ ".xbintsc",
31
+ ".xbintsc-cache",
32
+ "build",
33
+ "dist",
34
+ "coverage",
35
+ "scratch",
36
+ "target",
37
+ "vendor",
38
+ ]);
39
+
40
+ /** One string that changes whenever a watched file changes. */
41
+ export function fingerprintTree(root: string): string {
42
+ const entries: string[] = [];
43
+ collect(resolve(root), entries);
44
+ entries.sort();
45
+ return entries.join("|");
46
+ }
47
+
48
+ function collect(directory: string, out: string[]): void {
49
+ let entries: Dirent[];
50
+ try {
51
+ entries = readdirSync(directory, { withFileTypes: true });
52
+ } catch {
53
+ return; // the directory disappeared between scans
54
+ }
55
+ for (const entry of entries) {
56
+ const path = join(directory, entry.name);
57
+ if (entry.isDirectory()) {
58
+ if (!IGNORED_DIRECTORIES.has(entry.name)) collect(path, out);
59
+ continue;
60
+ }
61
+ if (!entry.isFile()) continue;
62
+ if (!WATCHED_EXTENSIONS.has(extname(entry.name).toLowerCase())) continue;
63
+ try {
64
+ const stat = statSync(path);
65
+ /* mtime resolution is coarse on some filesystems (and on Windows two
66
+ * same-size writes can share a timestamp), so hash the bytes as well. */
67
+ let hash = 2166136261;
68
+ const contents = readFileSync(path);
69
+ for (let i = 0; i < contents.length; i++) {
70
+ hash = Math.imul(hash ^ (contents[i] ?? 0), 16777619);
71
+ }
72
+ out.push(`${path}:${stat.mtimeMs}:${stat.size}:${hash >>> 0}`);
73
+ } catch {
74
+ // A file removed during the scan is picked up by the next iteration.
75
+ }
76
+ }
77
+ }
78
+
79
+ export interface WatchOptions {
80
+ /** Current fingerprint of everything that should trigger a rebuild. */
81
+ readonly scan: () => string;
82
+ /** Called after the fingerprint changes. Must be synchronous. */
83
+ readonly onRebuild: () => void;
84
+ /** Poll interval; defaults to 300 ms. */
85
+ readonly intervalMs?: number;
86
+ }
87
+
88
+ /**
89
+ * Start polling. Returns a stop function. The caller performs the initial
90
+ * build, so this never fires `onRebuild` for the state it starts in.
91
+ */
92
+ export function startWatching(options: WatchOptions): () => void {
93
+ let previous = options.scan();
94
+ const timer = setInterval(() => {
95
+ const next = options.scan();
96
+ if (next === previous) return;
97
+ previous = next;
98
+ options.onRebuild();
99
+ }, options.intervalMs ?? 300);
100
+ return () => clearInterval(timer);
101
+ }
@@ -143,7 +143,14 @@ export const accessCallMethods: AccessCallMethods = {
143
143
  const access = (): string => {
144
144
  const key = this.emitExpression(node.argumentExpression);
145
145
  const result = this.reg();
146
- this.emit(` ${result} = call i64 @xt_get(i64 ${object}, i64 ${key})`);
146
+ /* Array-index reads are not object property layouts, so skip the IC for
147
+ * a numeric literal; every other key may benefit from it. */
148
+ if (node.argumentExpression.kind === SyntaxKind.NumericLiteral) {
149
+ this.emit(` ${result} = call i64 @xt_get(i64 ${object}, i64 ${key})`);
150
+ } else {
151
+ const cache = this.icCachePointer();
152
+ this.emit(` ${result} = call i64 @xt_get_ic(i64 ${object}, i64 ${key}, i64* ${cache})`);
153
+ }
147
154
  return result;
148
155
  };
149
156
  return node.optional ? this.emitOptional(object, access) : access();
@@ -158,8 +165,9 @@ export const accessCallMethods: AccessCallMethods = {
158
165
  return result;
159
166
  }
160
167
  const key = this.stringValue(name);
168
+ const cache = this.icCachePointer();
161
169
  const result = this.reg();
162
- this.emit(` ${result} = call i64 @xt_get(i64 ${object}, i64 ${key})`);
170
+ this.emit(` ${result} = call i64 @xt_get_ic(i64 ${object}, i64 ${key}, i64* ${cache})`);
163
171
  return result;
164
172
  },
165
173
 
@@ -79,9 +79,17 @@ export const closureCallMethods: ClosureCallMethods = {
79
79
  if (fn.isConstructor && fn.classInfo) name = fn.classInfo.name;
80
80
  const nameValue = this.stringValue(name);
81
81
  this.emit(` call i64 @xt_function_set_metadata(i64 ${closure}, i64 ${nameValue}, i32 ${arity})`);
82
- if (fn.isGenerator) this.emit(` call i64 @xt_function_set_generator(i64 ${closure})`);
83
- /* `async` functions run on a coroutine: the runtime must know at call time
84
- * so it can return a promise and suspend at `await`. */
85
- if (fn.isAsync) this.emit(` call i64 @xt_function_set_async(i64 ${closure})`);
82
+ if (fn.isAsync && fn.isGenerator) {
83
+ /* `async function*`: a generator whose `.next()` returns promises. The
84
+ * runtime needs both flags, so use the combined marker instead of the
85
+ * two separate setters. */
86
+ this.emit(` call i64 @xt_function_set_async_generator(i64 ${closure})`);
87
+ } else if (fn.isGenerator) {
88
+ this.emit(` call i64 @xt_function_set_generator(i64 ${closure})`);
89
+ } else if (fn.isAsync) {
90
+ /* `async` functions run on a coroutine: the runtime must know at call
91
+ * time so it can return a promise and suspend at `await`. */
92
+ this.emit(` call i64 @xt_function_set_async(i64 ${closure})`);
93
+ }
86
94
  },
87
95
  };
@@ -64,6 +64,8 @@ export class GeneratorContext {
64
64
  readonly lineStartsByFile = new Map<string, number[]>();
65
65
  stringCounter = 0;
66
66
  staticCounter = 0;
67
+ /** Monotonic id for per-property-access inline-cache globals. */
68
+ icCounter = 0;
67
69
  /**
68
70
  * How many `UnsupportedFeature` diagnostics the function currently being
69
71
  * emitted produced. Unsupported constructs can leave the generator with a
@@ -187,8 +189,8 @@ export class GeneratorContext {
187
189
  if (!symbols.some((symbol) => this.usedAsValue(symbol))) return;
188
190
  this.diagnostics.error(
189
191
  DiagnosticCode.ModuleNotFound,
190
- `module '${specifier}' is not supported: xbintsc can import built-in platform modules, ` +
191
- "relative '.ts' files and ESM packages under node_modules; CommonJS packages are not supported",
192
+ `module '${specifier}' is not supported: expected a Node built-in ` +
193
+ "(with --ext node), a relative .ts/.js file, or a package in node_modules",
192
194
  declaration.moduleSpecifier,
193
195
  this.fileNameOf(declaration.moduleSpecifier),
194
196
  );
@@ -309,6 +311,19 @@ export class GeneratorContext {
309
311
  return ptr;
310
312
  }
311
313
 
314
+ /**
315
+ * Allocate a two-word inline cache for one property-access site and return
316
+ * the `i64*` the runtime fills with (shape, property index). The global is
317
+ * zero-initialised, which the runtime treats as an empty cache.
318
+ */
319
+ icCachePointer(): string {
320
+ const name = `@ic.${this.icCounter++}`;
321
+ this.globals.push(`${name} = internal global [2 x i64] zeroinitializer`);
322
+ const ptr = this.reg();
323
+ this.emit(` ${ptr} = getelementptr [2 x i64], [2 x i64]* ${name}, i64 0, i64 0`);
324
+ return ptr;
325
+ }
326
+
312
327
  /** Lay already-computed values out as a contiguous `i64*` argument buffer. */
313
328
  emitValueArguments(values: readonly string[]): { argc: string; ptr: string } {
314
329
  if (values.length === 0) return { argc: "0", ptr: "null" };
@@ -517,10 +532,15 @@ export class GeneratorContext {
517
532
 
518
533
  unsupported(node: Node, what: string): void {
519
534
  const label = kindName(node.kind);
535
+ const hasName = label !== String(node.kind);
536
+ /* `unsupported(statement, "statement")` is the generic fallback; when the
537
+ * syntax kind has a human name, use it directly instead of appending a
538
+ * redundant "(statement)". */
539
+ const subject = what === "statement" && hasName ? `this ${label}` : `this ${what} (${label})`;
520
540
  this.unsupportedCount++;
521
541
  this.diagnostics.error(
522
542
  DiagnosticCode.UnsupportedFeature,
523
- `xbintsc does not yet support this ${what} (${label})`,
543
+ `xbintsc does not yet support ${subject}`,
524
544
  node,
525
545
  this.fileNameOf(node),
526
546
  );
@@ -24,6 +24,15 @@ function isStringLike(node: Expression): boolean {
24
24
  return node.kind === SyntaxKind.StringLiteral || node.kind === SyntaxKind.NoSubstitutionTemplateLiteral;
25
25
  }
26
26
 
27
+ /** True for a numeric literal (optionally signed), whose tag check can be skipped. */
28
+ function isNumericLiteral(node: Expression): boolean {
29
+ if (node.kind === SyntaxKind.NumericLiteral) return true;
30
+ if (node.kind !== SyntaxKind.PrefixUnaryExpression) return false;
31
+ const prefix = node as PrefixUnaryExpression;
32
+ if (prefix.operator !== PrefixUnaryOperator.Minus && prefix.operator !== PrefixUnaryOperator.Plus) return false;
33
+ return prefix.operand.kind === SyntaxKind.NumericLiteral;
34
+ }
35
+
27
36
  /**
28
37
  * The built-in constructor a right-hand `instanceof` operand names, if any.
29
38
  * A user binding with the same name shadows it.
@@ -84,7 +93,15 @@ export const operatorExpressionMethods: OperatorExpressionMethods = {
84
93
  // `+` concatenates when either side is known to be a string; skip the
85
94
  // numeric tag checks for that shape and call the runtime directly.
86
95
  const knownStringConcat = operator === "+" && (isStringLike(node.left) || isStringLike(node.right));
87
- return this.emitBinaryOperation(left, right, operator, runtime, !knownStringConcat);
96
+ return this.emitBinaryOperation(
97
+ left,
98
+ right,
99
+ operator,
100
+ runtime,
101
+ !knownStringConcat,
102
+ isNumericLiteral(node.left),
103
+ isNumericLiteral(node.right),
104
+ );
88
105
  },
89
106
 
90
107
  emitShortCircuit(node: BinaryExpression, kind: "and" | "or" | "nullish"): string {
@@ -95,15 +112,9 @@ export const operatorExpressionMethods: OperatorExpressionMethods = {
95
112
  const endLabel = this.label("sc.end");
96
113
  let condition: string;
97
114
  if (kind === "and") {
98
- const truthy = this.reg();
99
- this.emit(` ${truthy} = call i32 @xt_truthy(i64 ${left})`);
100
- condition = this.reg();
101
- this.emit(` ${condition} = icmp ne i32 ${truthy}, 0`);
115
+ condition = this.emitTruthiness(left, node.left);
102
116
  } else if (kind === "or") {
103
- const truthy = this.reg();
104
- this.emit(` ${truthy} = call i32 @xt_truthy(i64 ${left})`);
105
- const isTruthy = this.reg();
106
- this.emit(` ${isTruthy} = icmp ne i32 ${truthy}, 0`);
117
+ const isTruthy = this.emitTruthiness(left, node.left);
107
118
  condition = this.reg();
108
119
  this.emit(` ${condition} = xor i1 ${isTruthy}, true`);
109
120
  } else {
@@ -128,10 +139,7 @@ export const operatorExpressionMethods: OperatorExpressionMethods = {
128
139
  emitConditional(node: ConditionalExpression): string {
129
140
  const result = this.alloca();
130
141
  const condition = this.emitExpression(node.condition);
131
- const truthy = this.reg();
132
- this.emit(` ${truthy} = call i32 @xt_truthy(i64 ${condition})`);
133
- const nonzero = this.reg();
134
- this.emit(` ${nonzero} = icmp ne i32 ${truthy}, 0`);
142
+ const nonzero = this.emitTruthiness(condition, node.condition);
135
143
  const trueLabel = this.label("cond.true");
136
144
  const falseLabel = this.label("cond.false");
137
145
  const endLabel = this.label("cond.end");
@@ -195,6 +203,9 @@ export const operatorExpressionMethods: OperatorExpressionMethods = {
195
203
  one,
196
204
  node.operator === PrefixUnaryOperator.PlusPlus ? "+" : "-",
197
205
  fn,
206
+ true,
207
+ false,
208
+ true,
198
209
  );
199
210
  this.emitAssignmentTarget(node.operand, next);
200
211
  return next;
@@ -214,6 +225,9 @@ export const operatorExpressionMethods: OperatorExpressionMethods = {
214
225
  one,
215
226
  node.operator === PostfixUnaryOperator.PlusPlus ? "+" : "-",
216
227
  fn,
228
+ true,
229
+ false,
230
+ true,
217
231
  );
218
232
  this.emitAssignmentTarget(node.operand, next);
219
233
  return current;
@@ -245,6 +245,10 @@ export const primaryExpressionMethods: PrimaryExpressionMethods = {
245
245
  this.reportRequireUse(identifier);
246
246
  return i64(XT_UNDEFINED);
247
247
  }
248
+ /* The parser's recovery node for a missing expression. The syntax
249
+ * error has already been reported; "Cannot find name '<error>'" is
250
+ * pure noise on top of it. */
251
+ if (identifier.text === "<error>") return i64(XT_UNDEFINED);
248
252
  this.diagnostics.error(
249
253
  DiagnosticCode.CannotFindName,
250
254
  `Cannot find name '${identifier.text}'`,
@@ -100,13 +100,6 @@ export const moduleMethods: ModuleMethods = {
100
100
 
101
101
  emitFunction(fn: FunctionInfo): void {
102
102
  this.unsupportedCount = 0;
103
- // `async function*` would need an async iterator and a promise-returning
104
- // `.next()`; the generator/async lowering below would silently produce a
105
- // synchronous generator instead, so reject it rather than miscompile.
106
- if (fn.isAsync && fn.isGenerator) {
107
- this.unsupported(fn.node, "async generator function");
108
- return;
109
- }
110
103
  const name = this.functionName(fn);
111
104
  const debugSubprogram = this.debugSubprogramFor(fn);
112
105
  const state: FunctionState = {