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
@@ -1,615 +1,29 @@
1
1
  /**
2
- * Statement lowering: control flow, loops, switch and try/catch/finally.
2
+ * Statement lowering: aggregates the dispatch, variable, control-flow and loop
3
+ * method groups into the `StatementMethods` mixin consumed by the generator.
4
+ *
5
+ * The implementation is split by functional area under `statements/`:
6
+ * - `dispatch` — statement-list walking and kind routing
7
+ * - `variables` — declarations, bindings, defaults and enums
8
+ * - `control-flow` — `if`, `switch`, `try`/`catch`/`finally`, `return`
9
+ * - `loops` — `while`, `do`, `for`, `for`/`of`, `for`/`in`
3
10
  */
4
11
 
5
- import {
6
- SyntaxKind,
7
- type ArrayBindingPattern,
8
- type BindingName,
9
- type Block,
10
- type CaseClause,
11
- type DoStatement,
12
- type EnumDeclaration,
13
- type Expression,
14
- type ForInStatement,
15
- type ForOfStatement,
16
- type ForStatement,
17
- type Identifier,
18
- type IfStatement,
19
- type ObjectBindingPattern,
20
- type ReturnStatement,
21
- type Statement,
22
- type SwitchStatement,
23
- type ThrowStatement,
24
- type TryStatement,
25
- type VariableDeclarationList,
26
- type VariableStatement,
27
- type WhileStatement,
28
- } from "../../ast/nodes.js";
29
- import { i64, numberLiteral, XT_UNDEFINED } from "../values.js";
30
- import { propertyNameText } from "./tables.js";
31
- import type { Generator } from "./generator.js";
32
-
33
- export interface StatementMethods {
34
- emitStatements(this: Generator, statements: readonly Statement[]): void;
35
- emitStatement(this: Generator, statement: Statement): void;
36
- emitVariableStatement(this: Generator, statement: VariableStatement): void;
37
- emitBindingPattern(this: Generator, name: BindingName, value: string): void;
38
- emitBindingDefault(this: Generator, value: string, initializer: Expression): string;
39
- emitEnum(this: Generator, statement: EnumDeclaration): void;
40
- emitIf(this: Generator, statement: IfStatement): void;
41
- emitWhile(this: Generator, statement: WhileStatement): void;
42
- emitDo(this: Generator, statement: DoStatement): void;
43
- emitFor(this: Generator, statement: ForStatement): void;
44
- emitForOf(this: Generator, statement: ForOfStatement | ForInStatement): void;
45
- bindLoopVariable(this: Generator, initializer: VariableDeclarationList | Expression, value: string): void;
46
- emitSwitch(this: Generator, statement: SwitchStatement): void;
47
- emitTry(this: Generator, statement: TryStatement): void;
48
- bindCatchVariable(this: Generator, variable: Identifier | undefined, value: string): void;
49
- emitReturn(this: Generator, statement: ReturnStatement): void;
50
- popTryFramesTo(this: Generator, depth: number): void;
51
- }
52
-
53
- export const statementMethods: StatementMethods = {
54
- emitStatements(statements: readonly Statement[]): void {
55
- for (const statement of statements) {
56
- if (this.current.terminated) break;
57
- this.emitStatement(statement);
58
- }
59
- },
60
-
61
- emitStatement(statement: Statement): void {
62
- switch (statement.kind) {
63
- case SyntaxKind.ExpressionStatement:
64
- this.emitExpression((statement as { expression: Expression }).expression);
65
- return;
66
- case SyntaxKind.VariableStatement:
67
- this.emitVariableStatement(statement as VariableStatement);
68
- return;
69
- case SyntaxKind.Block:
70
- this.emitStatements((statement as Block).statements);
71
- return;
72
- case SyntaxKind.EmptyStatement:
73
- case SyntaxKind.DebuggerStatement:
74
- case SyntaxKind.FunctionDeclaration:
75
- case SyntaxKind.InterfaceDeclaration:
76
- case SyntaxKind.TypeAliasDeclaration:
77
- case SyntaxKind.ImportDeclaration:
78
- return; // functions are emitted at module scope; imports are resolved at call sites
79
- case SyntaxKind.ClassDeclaration: {
80
- const info = this.binding.classOfNode.get(statement);
81
- if (info) this.emitClassSetup(info);
82
- return;
83
- }
84
- case SyntaxKind.IfStatement:
85
- this.emitIf(statement as IfStatement);
86
- return;
87
- case SyntaxKind.WhileStatement:
88
- this.emitWhile(statement as WhileStatement);
89
- return;
90
- case SyntaxKind.DoStatement:
91
- this.emitDo(statement as DoStatement);
92
- return;
93
- case SyntaxKind.ForStatement:
94
- this.emitFor(statement as ForStatement);
95
- return;
96
- case SyntaxKind.ForOfStatement:
97
- case SyntaxKind.ForInStatement:
98
- this.emitForOf(statement as ForOfStatement | ForInStatement);
99
- return;
100
- case SyntaxKind.SwitchStatement:
101
- this.emitSwitch(statement as SwitchStatement);
102
- return;
103
- case SyntaxKind.TryStatement:
104
- this.emitTry(statement as TryStatement);
105
- return;
106
- case SyntaxKind.ReturnStatement:
107
- this.emitReturn(statement as ReturnStatement);
108
- return;
109
- case SyntaxKind.BreakStatement: {
110
- const loop = this.current.loops[this.current.loops.length - 1];
111
- if (loop) {
112
- this.popTryFramesTo(loop.tryDepth ?? 0);
113
- this.terminate(`br label %${loop.breakLabel}`);
114
- }
115
- return;
116
- }
117
- case SyntaxKind.ContinueStatement: {
118
- const loop = this.current.loops[this.current.loops.length - 1];
119
- if (loop) {
120
- this.popTryFramesTo(loop.tryDepth ?? 0);
121
- this.terminate(`br label %${loop.continueLabel}`);
122
- }
123
- return;
124
- }
125
- case SyntaxKind.ThrowStatement: {
126
- const value = this.emitExpression((statement as ThrowStatement).expression);
127
- this.emit(` call void @xt_throw(i64 ${value})`);
128
- this.terminate("unreachable");
129
- return;
130
- }
131
- case SyntaxKind.ExportDeclaration: {
132
- const declaration = (statement as { declaration?: Statement }).declaration;
133
- if (declaration) this.emitStatement(declaration);
134
- return;
135
- }
136
- case SyntaxKind.EnumDeclaration:
137
- this.emitEnum(statement as EnumDeclaration);
138
- return;
139
- default:
140
- this.unsupported(statement, "statement");
141
- }
142
- },
143
-
144
- emitVariableStatement(statement: VariableStatement): void {
145
- for (const declaration of statement.declarationList.declarations) {
146
- if (declaration.name.kind === SyntaxKind.Identifier) {
147
- const symbol = this.binding.symbolOfDeclaration.get(declaration);
148
- if (!symbol) {
149
- if (declaration.initializer) this.emitExpression(declaration.initializer);
150
- continue;
151
- }
152
- if (this.current.slots.has(symbol.id)) {
153
- // Hoisted `var` (or an already-declared slot): keep evaluating the
154
- // initializer for its side effects, but do not redeclare the slot.
155
- if (declaration.initializer) this.emitExpression(declaration.initializer);
156
- continue;
157
- }
158
- if (symbol.boxed) {
159
- // A captured binding lives in a box. Create the box *before*
160
- // evaluating the initializer so a self-referencing closure
161
- // (`const f = () => f()`) captures the box, not a copy of the
162
- // still-uninitialised value.
163
- this.declareSlot(symbol, i64(XT_UNDEFINED));
164
- if (declaration.initializer) this.writeSlot(symbol, this.emitExpression(declaration.initializer));
165
- continue;
166
- }
167
- const initial = declaration.initializer ? this.emitExpression(declaration.initializer) : i64(XT_UNDEFINED);
168
- this.declareSlot(symbol, initial);
169
- } else {
170
- const initial = declaration.initializer ? this.emitExpression(declaration.initializer) : i64(XT_UNDEFINED);
171
- this.emitBindingPattern(declaration.name, initial);
172
- }
173
- }
174
- },
175
-
176
- /** Lower a destructuring binding pattern, declaring each bound identifier. */
177
- emitBindingPattern(name: BindingName, value: string): void {
178
- if (name.kind === SyntaxKind.Identifier) {
179
- const symbol = this.binding.symbolOfDeclaration.get(name);
180
- if (!symbol) return;
181
- if (this.current.slots.has(symbol.id)) this.writeSlot(symbol, value);
182
- else this.declareSlot(symbol, value);
183
- return;
184
- }
185
- if (name.kind === SyntaxKind.ArrayBindingPattern) {
186
- const pattern = name as ArrayBindingPattern;
187
- for (let index = 0; index < pattern.elements.length; index++) {
188
- const element = pattern.elements[index];
189
- if (!element) continue;
190
- let elementValue: string;
191
- if (element.dotDotDotToken) {
192
- const startPtr = this.alloca();
193
- this.emit(` store i64 ${numberLiteral(index)}, i64* ${startPtr}`);
194
- const sliceName = this.stringValue("slice");
195
- elementValue = this.reg();
196
- this.emit(` ${elementValue} = call i64 @xt_call_method(i64 ${value}, i64 ${sliceName}, i32 1, i64* ${startPtr})`);
197
- } else {
198
- elementValue = this.reg();
199
- this.emit(` ${elementValue} = call i64 @xt_get(i64 ${value}, i64 ${numberLiteral(index)})`);
200
- }
201
- if (element.initializer) elementValue = this.emitBindingDefault(elementValue, element.initializer);
202
- this.emitBindingPattern(element.name, elementValue);
203
- }
204
- return;
205
- }
206
- const pattern = name as ObjectBindingPattern;
207
- for (const element of pattern.elements) {
208
- const key = element.propertyName ?? (element.name.kind === SyntaxKind.Identifier ? element.name : undefined);
209
- if (element.dotDotDotToken) {
210
- this.unsupported(element, "object rest destructuring");
211
- continue;
212
- }
213
- const keyValue = this.stringValue(key ? propertyNameText(key) : "undefined");
214
- let elementValue = this.reg();
215
- this.emit(` ${elementValue} = call i64 @xt_get(i64 ${value}, i64 ${keyValue})`);
216
- if (element.initializer) elementValue = this.emitBindingDefault(elementValue, element.initializer);
217
- this.emitBindingPattern(element.name, elementValue);
218
- }
219
- },
220
-
221
- /** `x = fallback` in a binding pattern: only apply when `x` is `undefined`. */
222
- emitBindingDefault(value: string, initializer: Expression): string {
223
- const fallback = this.emitExpression(initializer);
224
- const isUndefined = this.reg();
225
- this.emit(` ${isUndefined} = call i64 @xt_seq(i64 ${value}, i64 ${i64(XT_UNDEFINED)})`);
226
- const truthy = this.reg();
227
- this.emit(` ${truthy} = call i32 @xt_truthy(i64 ${isUndefined})`);
228
- const condition = this.reg();
229
- this.emit(` ${condition} = icmp ne i32 ${truthy}, 0`);
230
- const result = this.reg();
231
- this.emit(` ${result} = select i1 ${condition}, i64 ${fallback}, i64 ${value}`);
232
- return result;
233
- },
234
-
235
- /**
236
- * `enum E { A, B }` (and `const enum`) lowers to a runtime object with both
237
- * forward (`E.A`) and reverse (`E[0] === "A"`) numeric mappings.
238
- */
239
- emitEnum(statement: EnumDeclaration): void {
240
- const symbol = this.binding.symbolOfDeclaration.get(statement);
241
- const object = this.reg();
242
- this.emit(` ${object} = call i64 @xt_object_new()`);
243
- let next = 0;
244
- for (const member of statement.members) {
245
- const name = propertyNameText(member.name);
246
- const key = this.stringValue(name);
247
- let value: string;
248
- if (member.initializer) {
249
- value = this.emitExpression(member.initializer);
250
- if (member.initializer.kind === SyntaxKind.NumericLiteral) {
251
- const numeric = (member.initializer as { value?: number }).value ?? 0;
252
- next = numeric + 1;
253
- } else {
254
- next++;
255
- }
256
- } else {
257
- value = numberLiteral(next);
258
- next++;
259
- }
260
- this.emit(` call i64 @xt_set(i64 ${object}, i64 ${key}, i64 ${value})`);
261
- // Reverse mapping (only meaningful for numeric members).
262
- if (!member.initializer || member.initializer.kind === SyntaxKind.NumericLiteral) {
263
- const reverseKey = this.stringValue(name);
264
- this.emit(` call i64 @xt_set(i64 ${object}, i64 ${value}, i64 ${reverseKey})`);
265
- }
266
- }
267
- if (symbol) this.declareSlot(symbol, object);
268
- },
269
-
270
- emitIf(statement: IfStatement): void {
271
- const thenLabel = this.label("if.then");
272
- const elseLabel = statement.elseStatement ? this.label("if.else") : undefined;
273
- const endLabel = this.label("if.end");
274
- const condition = this.emitExpression(statement.condition);
275
- const truthy = this.reg();
276
- this.emit(` ${truthy} = call i32 @xt_truthy(i64 ${condition})`);
277
- const nonzero = this.reg();
278
- this.emit(` ${nonzero} = icmp ne i32 ${truthy}, 0`);
279
- this.terminate(`br i1 ${nonzero}, label %${thenLabel}, label %${elseLabel ?? endLabel}`);
280
-
281
- this.startBlock(thenLabel);
282
- this.emitStatement(statement.thenStatement);
283
- if (!this.current.terminated) this.terminate(`br label %${endLabel}`);
284
-
285
- if (elseLabel) {
286
- this.startBlock(elseLabel);
287
- this.emitStatement(statement.elseStatement!);
288
- if (!this.current.terminated) this.terminate(`br label %${endLabel}`);
289
- }
290
-
291
- this.startBlock(endLabel);
292
- },
293
-
294
- emitWhile(statement: WhileStatement): void {
295
- const condLabel = this.label("while.cond");
296
- const bodyLabel = this.label("while.body");
297
- const endLabel = this.label("while.end");
298
- this.terminate(`br label %${condLabel}`);
299
- this.startBlock(condLabel);
300
- const condition = this.emitExpression(statement.condition);
301
- const truthy = this.reg();
302
- this.emit(` ${truthy} = call i32 @xt_truthy(i64 ${condition})`);
303
- const nonzero = this.reg();
304
- this.emit(` ${nonzero} = icmp ne i32 ${truthy}, 0`);
305
- this.terminate(`br i1 ${nonzero}, label %${bodyLabel}, label %${endLabel}`);
306
- this.startBlock(bodyLabel);
307
- this.current.loops.push({ breakLabel: endLabel, continueLabel: condLabel, tryDepth: this.current.tryFrames.length });
308
- this.emitStatement(statement.statement);
309
- this.current.loops.pop();
310
- if (!this.current.terminated) this.terminate(`br label %${condLabel}`);
311
- this.startBlock(endLabel);
312
- },
313
-
314
- emitDo(statement: DoStatement): void {
315
- const bodyLabel = this.label("do.body");
316
- const condLabel = this.label("do.cond");
317
- const endLabel = this.label("do.end");
318
- this.terminate(`br label %${bodyLabel}`);
319
- this.startBlock(bodyLabel);
320
- this.current.loops.push({ breakLabel: endLabel, continueLabel: condLabel, tryDepth: this.current.tryFrames.length });
321
- this.emitStatement(statement.statement);
322
- this.current.loops.pop();
323
- if (!this.current.terminated) this.terminate(`br label %${condLabel}`);
324
-
325
- this.startBlock(condLabel);
326
- const condition = this.emitExpression(statement.condition);
327
- const truthy = this.reg();
328
- this.emit(` ${truthy} = call i32 @xt_truthy(i64 ${condition})`);
329
- const nonzero = this.reg();
330
- this.emit(` ${nonzero} = icmp ne i32 ${truthy}, 0`);
331
- this.terminate(`br i1 ${nonzero}, label %${bodyLabel}, label %${endLabel}`);
332
- this.startBlock(endLabel);
333
- },
334
-
335
- emitFor(statement: ForStatement): void {
336
- if (statement.initializer && statement.initializer.kind === SyntaxKind.VariableDeclarationList) {
337
- this.emitVariableStatement({
338
- kind: SyntaxKind.VariableStatement,
339
- declarationList: statement.initializer as VariableDeclarationList,
340
- modifiers: [],
341
- start: statement.initializer.start,
342
- end: statement.initializer.end,
343
- });
344
- } else if (statement.initializer) {
345
- this.emitExpression(statement.initializer as Expression);
346
- }
347
- const condLabel = this.label("for.cond");
348
- const bodyLabel = this.label("for.body");
349
- const updateLabel = this.label("for.update");
350
- const endLabel = this.label("for.end");
351
- this.terminate(`br label %${condLabel}`);
352
-
353
- this.startBlock(condLabel);
354
- if (statement.condition) {
355
- const condition = this.emitExpression(statement.condition);
356
- const truthy = this.reg();
357
- this.emit(` ${truthy} = call i32 @xt_truthy(i64 ${condition})`);
358
- const nonzero = this.reg();
359
- this.emit(` ${nonzero} = icmp ne i32 ${truthy}, 0`);
360
- this.terminate(`br i1 ${nonzero}, label %${bodyLabel}, label %${endLabel}`);
361
- } else {
362
- this.terminate(`br label %${bodyLabel}`);
363
- }
364
-
365
- this.startBlock(bodyLabel);
366
- this.current.loops.push({ breakLabel: endLabel, continueLabel: updateLabel, tryDepth: this.current.tryFrames.length });
367
- this.emitStatement(statement.statement);
368
- this.current.loops.pop();
369
- if (!this.current.terminated) this.terminate(`br label %${updateLabel}`);
370
-
371
- this.startBlock(updateLabel);
372
- if (statement.incrementor) this.emitExpression(statement.incrementor);
373
- this.terminate(`br label %${condLabel}`);
374
- this.startBlock(endLabel);
375
- },
376
-
377
- /** `for (const x of xs)` / `for (const k in obj)` over arrays, strings and objects. */
378
- emitForOf(statement: ForOfStatement | ForInStatement): void {
379
- const source = this.emitExpression(statement.expression);
380
- const isForIn = statement.kind === SyntaxKind.ForInStatement;
381
- // `for...in` iterates the enumerable keys (indices become strings);
382
- // `for...of` iterates the values at each index.
383
- const iterable = isForIn ? this.runtimeCall("xt_object_keys", [source]) : source;
384
- const indexPtr = this.alloca();
385
- this.emit(` store i64 ${numberLiteral(0)}, i64* ${indexPtr}`);
386
- const lengthValue = this.reg();
387
- this.emit(` ${lengthValue} = call i64 @xt_iter_length(i64 ${iterable})`);
388
-
389
- const condLabel = this.label("forof.cond");
390
- const bodyLabel = this.label("forof.body");
391
- const updateLabel = this.label("forof.update");
392
- const endLabel = this.label("forof.end");
393
- this.terminate(`br label %${condLabel}`);
394
-
395
- this.startBlock(condLabel);
396
- const index = this.reg();
397
- this.emit(` ${index} = load i64, i64* ${indexPtr}`);
398
- const inRange = this.reg();
399
- this.emit(` ${inRange} = call i64 @xt_lt(i64 ${index}, i64 ${lengthValue})`);
400
- const truthy = this.reg();
401
- this.emit(` ${truthy} = call i32 @xt_truthy(i64 ${inRange})`);
402
- const nonzero = this.reg();
403
- this.emit(` ${nonzero} = icmp ne i32 ${truthy}, 0`);
404
- this.terminate(`br i1 ${nonzero}, label %${bodyLabel}, label %${endLabel}`);
405
-
406
- this.startBlock(bodyLabel);
407
- const element = this.reg();
408
- this.emit(` ${element} = call i64 @xt_iter_value(i64 ${iterable}, i64 ${index})`);
409
- this.bindLoopVariable(statement.initializer, element);
410
- this.current.loops.push({ breakLabel: endLabel, continueLabel: updateLabel, tryDepth: this.current.tryFrames.length });
411
- this.emitStatement(statement.statement);
412
- this.current.loops.pop();
413
- if (!this.current.terminated) this.terminate(`br label %${updateLabel}`);
414
-
415
- this.startBlock(updateLabel);
416
- const next = this.reg();
417
- this.emit(` ${next} = call i64 @xt_add(i64 ${index}, i64 ${numberLiteral(1)})`);
418
- this.emit(` store i64 ${next}, i64* ${indexPtr}`);
419
- this.terminate(`br label %${condLabel}`);
420
- this.startBlock(endLabel);
421
- },
422
-
423
- bindLoopVariable(initializer: VariableDeclarationList | Expression, value: string): void {
424
- if (initializer.kind === SyntaxKind.VariableDeclarationList) {
425
- const declaration = initializer.declarations[0];
426
- if (!declaration) return;
427
- if (declaration.name.kind !== SyntaxKind.Identifier) {
428
- this.emitBindingPattern(declaration.name, value);
429
- return;
430
- }
431
- const symbol = this.binding.symbolOfDeclaration.get(declaration) ?? this.binding.symbolOfDeclaration.get(declaration.name);
432
- if (symbol) {
433
- if (this.current.slots.has(symbol.id)) this.writeSlot(symbol, value);
434
- else this.declareSlot(symbol, value);
435
- }
436
- return;
437
- }
438
- this.emitAssignmentTarget(initializer as Expression, value);
439
- },
440
-
441
- /**
442
- * JavaScript `switch`: test each `case` with strict equality, then run the
443
- * matched clause and fall through into the following clauses until `break`.
444
- */
445
- emitSwitch(statement: SwitchStatement): void {
446
- const discriminant = this.emitExpression(statement.expression);
447
- const endLabel = this.label("switch.end");
448
- const clauses = statement.clauses;
449
- const labels = clauses.map(() => this.label("switch.case"));
450
- const testLabels = clauses.map((clause) =>
451
- clause.kind === SyntaxKind.CaseClause ? this.label("switch.test") : undefined,
452
- );
453
- const defaultIndex = clauses.findIndex((clause) => clause.kind === SyntaxKind.DefaultClause);
454
- const defaultLabel = defaultIndex >= 0 ? labels[defaultIndex]! : endLabel;
455
- const caseIndexes = clauses
456
- .map((clause, index) => ({ clause, index }))
457
- .filter((entry) => entry.clause.kind === SyntaxKind.CaseClause);
458
-
459
- this.terminate(`br label %${caseIndexes.length > 0 ? testLabels[caseIndexes[0]!.index]! : defaultLabel}`);
460
- for (let test = 0; test < caseIndexes.length; test++) {
461
- const entry = caseIndexes[test]!;
462
- this.startBlock(testLabels[entry.index]!);
463
- const caseValue = this.emitExpression((entry.clause as CaseClause).expression);
464
- const equals = this.reg();
465
- this.emit(` ${equals} = call i64 @xt_seq(i64 ${discriminant}, i64 ${caseValue})`);
466
- const truthy = this.reg();
467
- this.emit(` ${truthy} = call i32 @xt_truthy(i64 ${equals})`);
468
- const condition = this.reg();
469
- this.emit(` ${condition} = icmp ne i32 ${truthy}, 0`);
470
- const next = test + 1 < caseIndexes.length ? testLabels[caseIndexes[test + 1]!.index]! : defaultLabel;
471
- this.terminate(`br i1 ${condition}, label %${labels[entry.index]}, label %${next}`);
472
- }
473
-
474
- for (let index = 0; index < clauses.length; index++) {
475
- this.startBlock(labels[index]!);
476
- const enclosing = this.current.loops[this.current.loops.length - 1];
477
- this.current.loops.push({ breakLabel: endLabel, continueLabel: enclosing?.continueLabel ?? endLabel, tryDepth: this.current.tryFrames.length });
478
- for (const child of clauses[index]!.statements) {
479
- if (this.current.terminated) break;
480
- this.emitStatement(child);
481
- }
482
- this.current.loops.pop();
483
- if (!this.current.terminated) {
484
- const next = index + 1 < clauses.length ? labels[index + 1]! : endLabel;
485
- this.terminate(`br label %${next}`);
486
- }
487
- }
488
- this.startBlock(endLabel);
489
- },
490
-
491
- /**
492
- * `try`/`catch`/`finally` via a runtime setjmp frame. The runtime keeps a
493
- * stack of frames; `xt_throw` longjmps into the innermost one. A `return`
494
- * that exits the protected region skips `finally` (a known limitation).
495
- */
496
- emitTry(statement: TryStatement): void {
497
- this.current.usesTry = true;
498
- const frameSlot = this.alloca();
499
- const exceptionSlot = this.alloca();
500
- const flagSlot = this.alloca();
501
- const tryLabel = this.label("try.body");
502
- const catchLabel = this.label("try.catch");
503
- const exceptionLabel = this.label("try.exception");
504
- const rethrowLabel = this.label("try.rethrow");
505
- const finallyLabel = statement.finallyBlock ? this.label("try.finally") : undefined;
506
- const endLabel = this.label("try.end");
507
- const hasCatch = !!statement.catchClause;
508
-
509
- const frame = this.reg();
510
- this.emit(` ${frame} = call i8* @xt_try_enter()`);
511
- this.emit(` store i8* ${frame}, i8** ${frameSlot}`);
512
- this.emit(` store i64 0, i64* ${flagSlot}`);
513
- // MSVC's `_setjmp` takes the caller's frame address as a second argument
514
- // (`_JUMP_BUFFER.Frame`); `longjmp` uses it to run the unwind. clang lowers
515
- // a C call to `_setjmp` exactly like this. The extra argument is ignored by
516
- // the one-argument `_setjmp` on Linux/macOS.
517
- const frameAddress = this.reg();
518
- this.emit(` ${frameAddress} = call i8* @llvm.frameaddress(i32 0)`);
519
- const jump = this.reg();
520
- this.emit(` ${jump} = call i32 @_setjmp(i8* ${frame}, i8* ${frameAddress})`);
521
- const isThrow = this.reg();
522
- this.emit(` ${isThrow} = icmp ne i32 ${jump}, 0`);
523
- const exceptionTarget = hasCatch ? catchLabel : exceptionLabel;
524
- this.terminate(`br i1 ${isThrow}, label %${exceptionTarget}, label %${tryLabel}`);
525
-
526
- // Normal completion of the try block.
527
- this.startBlock(tryLabel);
528
- this.current.tryFrames.push(frameSlot);
529
- this.emitStatements(statement.tryBlock.statements);
530
- this.current.tryFrames.pop();
531
- if (!this.current.terminated) {
532
- const currentFrame = this.reg();
533
- this.emit(` ${currentFrame} = load i8*, i8** ${frameSlot}`);
534
- this.emit(` call void @xt_try_leave(i8* ${currentFrame})`);
535
- this.terminate(`br label %${finallyLabel ?? endLabel}`);
536
- }
537
-
538
- if (hasCatch) {
539
- this.startBlock(catchLabel);
540
- const currentFrame = this.reg();
541
- this.emit(` ${currentFrame} = load i8*, i8** ${frameSlot}`);
542
- const exception = this.reg();
543
- this.emit(` ${exception} = call i64 @xt_try_exception(i8* ${currentFrame})`);
544
- this.emit(` call void @xt_try_leave(i8* ${currentFrame})`);
545
- this.bindCatchVariable(statement.catchClause!.variable, exception);
546
- this.emitStatements(statement.catchClause!.block.statements);
547
- if (!this.current.terminated) this.terminate(`br label %${finallyLabel ?? endLabel}`);
548
- } else {
549
- // Without a catch clause the exception is remembered, then rethrown
550
- // after `finally` runs.
551
- this.startBlock(exceptionLabel);
552
- const currentFrame = this.reg();
553
- this.emit(` ${currentFrame} = load i8*, i8** ${frameSlot}`);
554
- const exception = this.reg();
555
- this.emit(` ${exception} = call i64 @xt_try_exception(i8* ${currentFrame})`);
556
- this.emit(` call void @xt_try_leave(i8* ${currentFrame})`);
557
- this.emit(` store i64 ${exception}, i64* ${exceptionSlot}`);
558
- this.emit(` store i64 1, i64* ${flagSlot}`);
559
- this.terminate(`br label %${finallyLabel ?? rethrowLabel}`);
560
- }
561
-
562
- if (finallyLabel) {
563
- this.startBlock(finallyLabel);
564
- this.emitStatements(statement.finallyBlock!.statements);
565
- if (!this.current.terminated) {
566
- if (hasCatch) {
567
- this.terminate(`br label %${endLabel}`);
568
- } else {
569
- const flag = this.reg();
570
- this.emit(` ${flag} = load i64, i64* ${flagSlot}`);
571
- const truthy = this.reg();
572
- this.emit(` ${truthy} = call i32 @xt_truthy(i64 ${flag})`);
573
- const shouldRethrow = this.reg();
574
- this.emit(` ${shouldRethrow} = icmp ne i32 ${truthy}, 0`);
575
- this.terminate(`br i1 ${shouldRethrow}, label %${rethrowLabel}, label %${endLabel}`);
576
- }
577
- }
578
- }
579
-
580
- if (!hasCatch) {
581
- this.startBlock(rethrowLabel);
582
- const exception = this.reg();
583
- this.emit(` ${exception} = load i64, i64* ${exceptionSlot}`);
584
- this.emit(` call void @xt_throw(i64 ${exception})`);
585
- this.terminate("unreachable");
586
- }
587
-
588
- this.startBlock(endLabel);
589
- },
590
-
591
- bindCatchVariable(variable: Identifier | undefined, value: string): void {
592
- if (!variable) return;
593
- const symbol = this.binding.symbolOfDeclaration.get(variable);
594
- if (!symbol) return;
595
- if (this.current.slots.has(symbol.id)) this.writeSlot(symbol, value);
596
- else this.declareSlot(symbol, value);
597
- },
598
-
599
- emitReturn(statement: ReturnStatement): void {
600
- let value = statement.expression ? this.emitExpression(statement.expression) : i64(XT_UNDEFINED);
601
- if (this.current.fn.isAsync) value = this.wrapAsync(value);
602
- this.popTryFramesTo(0);
603
- this.terminate(`ret i64 ${value}`);
604
- },
605
-
606
- /** Emit `xt_try_leave` for every active frame above `depth` (innermost first). */
607
- popTryFramesTo(depth: number): void {
608
- for (let index = this.current.tryFrames.length - 1; index >= depth; index--) {
609
- const slot = this.current.tryFrames[index]!;
610
- const frame = this.reg();
611
- this.emit(` ${frame} = load i8*, i8** ${slot}`);
612
- this.emit(` call void @xt_try_leave(i8* ${frame})`);
613
- }
614
- },
615
- };
12
+ import { statementDispatchMethods, type StatementDispatchMethods } from "./statements/dispatch.js";
13
+ import { variableStatementMethods, type VariableStatementMethods } from "./statements/variables.js";
14
+ import { controlFlowStatementMethods, type ControlFlowStatementMethods } from "./statements/control-flow.js";
15
+ import { loopStatementMethods, type LoopStatementMethods } from "./statements/loops.js";
16
+
17
+ export interface StatementMethods
18
+ extends StatementDispatchMethods,
19
+ VariableStatementMethods,
20
+ ControlFlowStatementMethods,
21
+ LoopStatementMethods {}
22
+
23
+ export const statementMethods: StatementMethods = Object.assign(
24
+ {},
25
+ statementDispatchMethods,
26
+ variableStatementMethods,
27
+ controlFlowStatementMethods,
28
+ loopStatementMethods,
29
+ );
@@ -77,6 +77,7 @@ export const GLOBAL_FUNCTIONS: Record<string, string> = {
77
77
  Number: "xt_number_ctor",
78
78
  String: "xt_string_ctor",
79
79
  Boolean: "xt_boolean_ctor",
80
+ BigInt: "xt_bigint_ctor",
80
81
  };
81
82
 
82
83
  /** Global functions that are also usable as first-class values, each mapped to
@@ -89,6 +90,7 @@ export const BUILTIN_FUNCTION_VALUES: Record<string, string> = {
89
90
  Number: "xt_builtin_value_number",
90
91
  String: "xt_builtin_value_string",
91
92
  Boolean: "xt_builtin_value_boolean",
93
+ BigInt: "xt_builtin_value_bigint",
92
94
  };
93
95
 
94
96
  /** Global namespaces whose static methods map to runtime dispatchers. */
@@ -99,6 +101,7 @@ export const NAMESPACE_STATICS: Record<string, string> = {
99
101
  Object: "xt_object_static",
100
102
  Number: "xt_number_static",
101
103
  String: "xt_string_static",
104
+ BigInt: "xt_bigint_static",
102
105
  Date: "xt_date_static",
103
106
  Promise: "xt_promise_static",
104
107
  path: "xt_path_static",
@@ -114,6 +117,9 @@ export const NAMESPACE_STATICS: Record<string, string> = {
114
117
  net: "xt_net_static",
115
118
  dgram: "xt_dgram_static",
116
119
  http: "xt_http_static",
120
+ events: "xt_events_static",
121
+ util: "xt_util_static",
122
+ querystring: "xt_querystring_static",
117
123
  };
118
124
 
119
125
  /** Namespace identifiers whose property access maps to a runtime getter. */
@@ -139,6 +145,7 @@ export const CTOR_FUNCTIONS: Record<string, string> = {
139
145
  PassThrough: "xt_pass_through_ctor",
140
146
  Socket: "xt_net_socket_ctor",
141
147
  Server: "xt_net_server_ctor",
148
+ EventEmitter: "xt_event_emitter_ctor",
142
149
  };
143
150
 
144
151
  export const BUILTIN_METHODS = new Set<string>([