xbintsc 0.2.9 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) hide show
  1. package/README.md +17 -2
  2. package/README.zh-CN.md +16 -2
  3. package/bin/xbintsc.js +49 -10
  4. package/dist/src/ast/expressions.d.ts +2 -0
  5. package/dist/src/binder/binder.d.ts +24 -98
  6. package/dist/src/binder/binder.js +13 -559
  7. package/dist/src/binder/binder.js.map +1 -1
  8. package/dist/src/binder/declarations.d.ts +16 -0
  9. package/dist/src/binder/declarations.js +168 -0
  10. package/dist/src/binder/declarations.js.map +1 -0
  11. package/dist/src/binder/helpers.d.ts +11 -0
  12. package/dist/src/binder/helpers.js +46 -0
  13. package/dist/src/binder/helpers.js.map +1 -0
  14. package/dist/src/binder/references.d.ts +21 -0
  15. package/dist/src/binder/references.js +349 -0
  16. package/dist/src/binder/references.js.map +1 -0
  17. package/dist/src/binder/types.d.ts +114 -0
  18. package/dist/src/binder/types.js +27 -0
  19. package/dist/src/binder/types.js.map +1 -0
  20. package/dist/src/cli/main.d.ts +1 -0
  21. package/dist/src/cli/main.js +40 -0
  22. package/dist/src/cli/main.js.map +1 -1
  23. package/dist/src/codegen/generator/calls/access.d.ts +13 -0
  24. package/dist/src/codegen/generator/calls/access.js +115 -0
  25. package/dist/src/codegen/generator/calls/access.js.map +1 -0
  26. package/dist/src/codegen/generator/calls/closures.d.ts +11 -0
  27. package/dist/src/codegen/generator/calls/closures.js +50 -0
  28. package/dist/src/codegen/generator/calls/closures.js.map +1 -0
  29. package/dist/src/codegen/generator/calls/invocation.d.ts +18 -0
  30. package/dist/src/codegen/generator/calls/invocation.js +242 -0
  31. package/dist/src/codegen/generator/calls/invocation.js.map +1 -0
  32. package/dist/src/codegen/generator/calls/literals.d.ts +10 -0
  33. package/dist/src/codegen/generator/calls/literals.js +69 -0
  34. package/dist/src/codegen/generator/calls/literals.js.map +1 -0
  35. package/dist/src/codegen/generator/calls/super.d.ts +10 -0
  36. package/dist/src/codegen/generator/calls/super.js +47 -0
  37. package/dist/src/codegen/generator/calls/super.js.map +1 -0
  38. package/dist/src/codegen/generator/calls.d.ts +15 -24
  39. package/dist/src/codegen/generator/calls.js +15 -482
  40. package/dist/src/codegen/generator/calls.js.map +1 -1
  41. package/dist/src/codegen/generator/context.d.ts +1 -1
  42. package/dist/src/codegen/generator/context.js +2 -2
  43. package/dist/src/codegen/generator/context.js.map +1 -1
  44. package/dist/src/codegen/generator/expressions/assignment.d.ts +13 -0
  45. package/dist/src/codegen/generator/expressions/assignment.js +203 -0
  46. package/dist/src/codegen/generator/expressions/assignment.js.map +1 -0
  47. package/dist/src/codegen/generator/expressions/operators.d.ts +14 -0
  48. package/dist/src/codegen/generator/expressions/operators.js +163 -0
  49. package/dist/src/codegen/generator/expressions/operators.js.map +1 -0
  50. package/dist/src/codegen/generator/expressions/primary.d.ts +17 -0
  51. package/dist/src/codegen/generator/expressions/primary.js +260 -0
  52. package/dist/src/codegen/generator/expressions/primary.js.map +1 -0
  53. package/dist/src/codegen/generator/expressions.d.ts +11 -21
  54. package/dist/src/codegen/generator/expressions.js +11 -494
  55. package/dist/src/codegen/generator/expressions.js.map +1 -1
  56. package/dist/src/codegen/generator/module.js +16 -4
  57. package/dist/src/codegen/generator/module.js.map +1 -1
  58. package/dist/src/codegen/generator/state.js +8 -0
  59. package/dist/src/codegen/generator/state.js.map +1 -1
  60. package/dist/src/codegen/generator/statements/control-flow.d.ts +14 -0
  61. package/dist/src/codegen/generator/statements/control-flow.js +199 -0
  62. package/dist/src/codegen/generator/statements/control-flow.js.map +1 -0
  63. package/dist/src/codegen/generator/statements/dispatch.d.ts +12 -0
  64. package/dist/src/codegen/generator/statements/dispatch.js +100 -0
  65. package/dist/src/codegen/generator/statements/dispatch.js.map +1 -0
  66. package/dist/src/codegen/generator/statements/loops.d.ts +13 -0
  67. package/dist/src/codegen/generator/statements/loops.js +152 -0
  68. package/dist/src/codegen/generator/statements/loops.js.map +1 -0
  69. package/dist/src/codegen/generator/statements/variables.d.ts +13 -0
  70. package/dist/src/codegen/generator/statements/variables.js +146 -0
  71. package/dist/src/codegen/generator/statements/variables.js.map +1 -0
  72. package/dist/src/codegen/generator/statements.d.ts +13 -21
  73. package/dist/src/codegen/generator/statements.js +13 -568
  74. package/dist/src/codegen/generator/statements.js.map +1 -1
  75. package/dist/src/codegen/generator/tables.js +7 -0
  76. package/dist/src/codegen/generator/tables.js.map +1 -1
  77. package/dist/src/codegen/values.d.ts +17 -17
  78. package/dist/src/codegen/values.js +21 -57
  79. package/dist/src/codegen/values.js.map +1 -1
  80. package/dist/src/diagnostics/diagnostic.d.ts +1 -0
  81. package/dist/src/diagnostics/diagnostic.js +1 -0
  82. package/dist/src/diagnostics/diagnostic.js.map +1 -1
  83. package/dist/src/diagnostics/source.d.ts +1 -1
  84. package/dist/src/diagnostics/source.js +7 -12
  85. package/dist/src/diagnostics/source.js.map +1 -1
  86. package/dist/src/driver/compiler.d.ts +4 -0
  87. package/dist/src/driver/compiler.js +51 -16
  88. package/dist/src/driver/compiler.js.map +1 -1
  89. package/dist/src/driver/index.d.ts +5 -2
  90. package/dist/src/driver/index.js +5 -2
  91. package/dist/src/driver/index.js.map +1 -1
  92. package/dist/src/driver/paths.d.ts +20 -0
  93. package/dist/src/driver/paths.js +49 -0
  94. package/dist/src/driver/paths.js.map +1 -1
  95. package/dist/src/driver/runtime-lib.d.ts +18 -0
  96. package/dist/src/driver/runtime-lib.js +31 -0
  97. package/dist/src/driver/runtime-lib.js.map +1 -0
  98. package/dist/src/driver/toolchain-download.d.ts +50 -0
  99. package/dist/src/driver/toolchain-download.js +76 -0
  100. package/dist/src/driver/toolchain-download.js.map +1 -0
  101. package/dist/src/driver/toolchain-provider.d.ts +33 -0
  102. package/dist/src/driver/toolchain-provider.js +71 -0
  103. package/dist/src/driver/toolchain-provider.js.map +1 -0
  104. package/dist/src/driver/toolchain.d.ts +9 -4
  105. package/dist/src/driver/toolchain.js +6 -10
  106. package/dist/src/driver/toolchain.js.map +1 -1
  107. package/dist/src/extensions/node/child_process/index.d.ts +4 -2
  108. package/dist/src/extensions/node/child_process/index.js +4 -2
  109. package/dist/src/extensions/node/child_process/index.js.map +1 -1
  110. package/dist/src/extensions/node/events/index.d.ts +10 -0
  111. package/dist/src/extensions/node/events/index.js +22 -0
  112. package/dist/src/extensions/node/events/index.js.map +1 -0
  113. package/dist/src/extensions/node/index.js +6 -0
  114. package/dist/src/extensions/node/index.js.map +1 -1
  115. package/dist/src/extensions/node/querystring/index.d.ts +10 -0
  116. package/dist/src/extensions/node/querystring/index.js +25 -0
  117. package/dist/src/extensions/node/querystring/index.js.map +1 -0
  118. package/dist/src/extensions/node/util/index.d.ts +11 -0
  119. package/dist/src/extensions/node/util/index.js +41 -0
  120. package/dist/src/extensions/node/util/index.js.map +1 -0
  121. package/dist/src/extensions/registry.d.ts +6 -0
  122. package/dist/src/extensions/registry.js.map +1 -1
  123. package/dist/src/index.d.ts +1 -1
  124. package/dist/src/index.js +1 -1
  125. package/dist/src/index.js.map +1 -1
  126. package/dist/src/lexer/scanner/identifiers.d.ts +9 -0
  127. package/dist/src/lexer/scanner/identifiers.js +33 -0
  128. package/dist/src/lexer/scanner/identifiers.js.map +1 -0
  129. package/dist/src/lexer/scanner/numbers.d.ts +10 -0
  130. package/dist/src/lexer/scanner/numbers.js +89 -0
  131. package/dist/src/lexer/scanner/numbers.js.map +1 -0
  132. package/dist/src/lexer/scanner/punctuation.d.ts +9 -0
  133. package/dist/src/lexer/scanner/punctuation.js +151 -0
  134. package/dist/src/lexer/scanner/punctuation.js.map +1 -0
  135. package/dist/src/lexer/scanner/regex.d.ts +11 -0
  136. package/dist/src/lexer/scanner/regex.js +69 -0
  137. package/dist/src/lexer/scanner/regex.js.map +1 -0
  138. package/dist/src/lexer/scanner/strings.d.ts +13 -0
  139. package/dist/src/lexer/scanner/strings.js +118 -0
  140. package/dist/src/lexer/scanner/strings.js.map +1 -0
  141. package/dist/src/lexer/scanner.d.ts +20 -27
  142. package/dist/src/lexer/scanner.js +11 -415
  143. package/dist/src/lexer/scanner.js.map +1 -1
  144. package/dist/src/parser/declarations/classes.d.ts +14 -0
  145. package/dist/src/parser/declarations/classes.js +191 -0
  146. package/dist/src/parser/declarations/classes.js.map +1 -0
  147. package/dist/src/parser/declarations/functions.d.ts +17 -0
  148. package/dist/src/parser/declarations/functions.js +241 -0
  149. package/dist/src/parser/declarations/functions.js.map +1 -0
  150. package/dist/src/parser/declarations/type-members.d.ts +16 -0
  151. package/dist/src/parser/declarations/type-members.js +156 -0
  152. package/dist/src/parser/declarations/type-members.js.map +1 -0
  153. package/dist/src/parser/declarations.d.ts +13 -24
  154. package/dist/src/parser/declarations.js +13 -571
  155. package/dist/src/parser/declarations.js.map +1 -1
  156. package/dist/src/parser/helpers.js +13 -4
  157. package/dist/src/parser/helpers.js.map +1 -1
  158. package/dist/src/parser/literals.js +10 -1
  159. package/dist/src/parser/literals.js.map +1 -1
  160. package/dist/tests/codegen/llvm.test.js +24 -0
  161. package/dist/tests/codegen/llvm.test.js.map +1 -1
  162. package/dist/tests/driver/compiler.test.js +3 -0
  163. package/dist/tests/driver/compiler.test.js.map +1 -1
  164. package/dist/tests/driver/paths.test.d.ts +1 -0
  165. package/dist/tests/driver/paths.test.js +26 -0
  166. package/dist/tests/driver/paths.test.js.map +1 -0
  167. package/dist/tests/driver/toolchain-download.test.d.ts +1 -0
  168. package/dist/tests/driver/toolchain-download.test.js +38 -0
  169. package/dist/tests/driver/toolchain-download.test.js.map +1 -0
  170. package/dist/tests/driver/toolchain-provider.test.d.ts +1 -0
  171. package/dist/tests/driver/toolchain-provider.test.js +37 -0
  172. package/dist/tests/driver/toolchain-provider.test.js.map +1 -0
  173. package/dist/tests/e2e/compile-node.test.d.ts +7 -0
  174. package/dist/tests/e2e/compile-node.test.js +123 -0
  175. package/dist/tests/e2e/compile-node.test.js.map +1 -0
  176. package/dist/tests/e2e/compile.test.d.ts +4 -1
  177. package/dist/tests/e2e/compile.test.js +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
@@ -13,8 +13,14 @@ export interface CommandResult {
13
13
  readonly stderr: string;
14
14
  }
15
15
 
16
+ export interface RunOptions {
17
+ readonly cwd?: string;
18
+ /** Extra environment variables, merged over `process.env`. */
19
+ readonly env?: Record<string, string>;
20
+ }
21
+
16
22
  export interface Runner {
17
- run(command: string, args: readonly string[], options?: { cwd?: string }): CommandResult;
23
+ run(command: string, args: readonly string[], options?: RunOptions): CommandResult;
18
24
  }
19
25
 
20
26
  export const realRunner: Runner = {
@@ -24,6 +30,7 @@ export const realRunner: Runner = {
24
30
  encoding: "utf8",
25
31
  maxBuffer: 64 * 1024 * 1024,
26
32
  };
33
+ if (options.env) spawnOptions.env = Object.assign({}, process.env, options.env);
27
34
  const result = spawnSync(command, [...args], spawnOptions);
28
35
  return {
29
36
  status: result.status ?? (result.error ? 1 : 0),
@@ -68,17 +75,16 @@ export interface CompileIrOptions {
68
75
  readonly irPath: string;
69
76
  readonly objectPath: string;
70
77
  readonly optimize: string;
78
+ readonly env?: Record<string, string>;
71
79
  }
72
80
 
73
81
  /** Compile an LLVM IR file to a native object file. */
74
82
  export function compileIr(runner: Runner, options: CompileIrOptions): void {
75
- const result = runner.run(options.clang, [
76
- `-O${options.optimize}`,
77
- "-c",
78
- options.irPath,
79
- "-o",
80
- options.objectPath,
81
- ]);
83
+ const result = runner.run(
84
+ options.clang,
85
+ [`-O${options.optimize}`, "-c", options.irPath, "-o", options.objectPath],
86
+ { env: options.env },
87
+ );
82
88
  if (result.status !== 0) throw new ToolchainError(`${options.clang} ${options.irPath}`, result.status, result.stderr);
83
89
  }
84
90
 
@@ -88,16 +94,28 @@ export interface LinkOptions {
88
94
  readonly outputPath: string;
89
95
  readonly linkerFlags: readonly string[];
90
96
  readonly optimize: string;
97
+ readonly env?: Record<string, string>;
91
98
  }
92
99
 
93
100
  export function link(runner: Runner, options: LinkOptions): void {
94
101
  const args = [`-O${options.optimize}`, ...options.objectPaths, "-o", options.outputPath, ...options.linkerFlags];
95
- const result = runner.run(options.clang, args);
102
+ const result = runner.run(options.clang, args, { env: options.env });
96
103
  if (result.status !== 0) throw new ToolchainError(`${options.clang} link`, result.status, result.stderr);
97
104
  }
98
105
 
99
106
  /** Compile a C source to an object file (used for the runtime and extensions). */
100
- export function compileC(runner: Runner, clang: string, sourcePath: string, objectPath: string, includeDir: string): void {
101
- const result = runner.run(clang, ["-O2", "-D_CRT_SECURE_NO_WARNINGS", "-c", sourcePath, "-o", objectPath, `-I${includeDir}`]);
107
+ export function compileC(
108
+ runner: Runner,
109
+ clang: string,
110
+ sourcePath: string,
111
+ objectPath: string,
112
+ includeDir: string,
113
+ env?: Record<string, string>,
114
+ ): void {
115
+ const result = runner.run(
116
+ clang,
117
+ ["-O2", "-D_CRT_SECURE_NO_WARNINGS", "-c", sourcePath, "-o", objectPath, `-I${includeDir}`],
118
+ { env },
119
+ );
102
120
  if (result.status !== 0) throw new ToolchainError(`${clang} ${sourcePath}`, result.status, result.stderr);
103
121
  }
@@ -1,7 +1,9 @@
1
1
  /**
2
2
  * Node's `child_process` module: `spawnSync(command, args, options)`, backed by
3
- * `runtime/ext_node/child_process`. Captures stdout/stderr as UTF-8 strings and
4
- * honours `options.cwd`, which is all the compiler's toolchain wrapper needs.
3
+ * `runtime/ext_node/child_process`. Captures stdout/stderr as UTF-8 strings,
4
+ * honours `options.cwd`, and supports `options.stdio: "inherit"` (hand the
5
+ * child the parent's stdout/stderr) — which is all the compiler's toolchain
6
+ * wrapper and `xbintsc run` need.
5
7
  */
6
8
 
7
9
  import type { NodeModule } from "../module.js";
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Node's `events` module.
3
+ *
4
+ * Exposes the standalone `EventEmitter` class plus its statics. `EventEmitter`
5
+ * is provided both as a global constructor and as a named export, so
6
+ * `new EventEmitter()` and `import { EventEmitter } from "events"` both work.
7
+ * The implementation lives in `runtime/ext_node/events/events.c`.
8
+ */
9
+
10
+ import type { NodeModule } from "../module.js";
11
+ import { resolveFrom } from "../module.js";
12
+ import type { ModuleExports } from "../../registry.js";
13
+
14
+ const methods = ["listenerCount", "getEventListeners", "getMaxListeners", "setMaxListeners", "once"] as const;
15
+
16
+ const exports: ModuleExports = {
17
+ EventEmitter: { symbol: "xt_event_emitter_ctor", isConstructor: true },
18
+ ...Object.fromEntries(methods.map((method) => [method, { namespace: "events", method }])),
19
+ };
20
+
21
+ export const eventsModule: NodeModule = {
22
+ name: "events",
23
+ namespace: "events",
24
+ runtimeSources: () => [resolveFrom(import.meta.url, "../../../../runtime/ext_node/events/events.c")],
25
+ builtins: () => ({}),
26
+ exports: () => exports,
27
+ };
@@ -25,6 +25,9 @@ import { httpModule } from "./http/index.js";
25
25
  import { urlModule } from "./url/index.js";
26
26
  import { cryptoModule } from "./crypto/index.js";
27
27
  import { childProcessModule } from "./child_process/index.js";
28
+ import { eventsModule } from "./events/index.js";
29
+ import { utilModule } from "./util/index.js";
30
+ import { querystringModule } from "./querystring/index.js";
28
31
 
29
32
  /** Every Node module the extension currently provides. */
30
33
  const modules: readonly NodeModule[] = [
@@ -41,6 +44,9 @@ const modules: readonly NodeModule[] = [
41
44
  urlModule,
42
45
  cryptoModule,
43
46
  childProcessModule,
47
+ eventsModule,
48
+ utilModule,
49
+ querystringModule,
44
50
  ];
45
51
 
46
52
  export const nodeExtension: Extension = {
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Node's `querystring` module.
3
+ *
4
+ * `parse` / `decode` and `stringify` / `encode` are the same functions under
5
+ * two names, alongside `escape` / `unescape`. Both named imports and namespace
6
+ * calls (`import qs from "querystring"`) are supported; the implementation
7
+ * lives in `runtime/ext_node/querystring/querystring.c`.
8
+ */
9
+
10
+ import type { NodeModule } from "../module.js";
11
+ import { resolveFrom } from "../module.js";
12
+ import type { ModuleExports } from "../../registry.js";
13
+
14
+ const exports: ModuleExports = {
15
+ parse: { symbol: "xt_querystring_parse" },
16
+ decode: { symbol: "xt_querystring_parse" },
17
+ stringify: { symbol: "xt_querystring_stringify" },
18
+ encode: { symbol: "xt_querystring_stringify" },
19
+ escape: { symbol: "xt_querystring_escape" },
20
+ unescape: { symbol: "xt_querystring_unescape" },
21
+ };
22
+
23
+ export const querystringModule: NodeModule = {
24
+ name: "querystring",
25
+ namespace: "querystring",
26
+ runtimeSources: () => [resolveFrom(import.meta.url, "../../../../runtime/ext_node/querystring/querystring.c")],
27
+ builtins: () => ({}),
28
+ exports: () => exports,
29
+ };
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Node's `util` module.
3
+ *
4
+ * Exposes the commonly used helpers (`format`, `inspect`, `isDeepStrictEqual`,
5
+ * `inherits`, `deprecate`, `promisify`) and the `isX` type predicates. Both
6
+ * `import { format } from "util"` and `import util from "util"` (namespace
7
+ * calls) are supported; the implementation lives in
8
+ * `runtime/ext_node/util/util.c`.
9
+ */
10
+
11
+ import type { NodeModule } from "../module.js";
12
+ import { resolveFrom } from "../module.js";
13
+ import type { ModuleExports } from "../../registry.js";
14
+
15
+ const symbols: Record<string, string> = {
16
+ format: "xt_util_format",
17
+ formatWithOptions: "xt_util_format_with_options",
18
+ inspect: "xt_util_inspect",
19
+ isDeepStrictEqual: "xt_util_is_deep_strict_equal",
20
+ inherits: "xt_util_inherits",
21
+ deprecate: "xt_util_deprecate",
22
+ promisify: "xt_util_promisify",
23
+ isString: "xt_util_is_string",
24
+ isNumber: "xt_util_is_number",
25
+ isBoolean: "xt_util_is_boolean",
26
+ isUndefined: "xt_util_is_undefined",
27
+ isNull: "xt_util_is_null",
28
+ isFunction: "xt_util_is_function",
29
+ isArray: "xt_util_is_array",
30
+ isObject: "xt_util_is_object",
31
+ isBuffer: "xt_util_is_buffer",
32
+ isDate: "xt_util_is_date",
33
+ isRegExp: "xt_util_is_regexp",
34
+ isPromise: "xt_util_is_promise",
35
+ isError: "xt_util_is_error",
36
+ };
37
+
38
+ const exports: ModuleExports = Object.fromEntries(
39
+ Object.entries(symbols).map(([name, symbol]) => [name, { symbol }]),
40
+ );
41
+
42
+ export const utilModule: NodeModule = {
43
+ name: "util",
44
+ namespace: "util",
45
+ runtimeSources: () => [resolveFrom(import.meta.url, "../../../../runtime/ext_node/util/util.c")],
46
+ builtins: () => ({}),
47
+ exports: () => exports,
48
+ };
@@ -28,6 +28,12 @@ export interface ModuleExport {
28
28
  readonly returnVoid?: boolean;
29
29
  readonly namespace?: string;
30
30
  readonly method?: string;
31
+ /**
32
+ * Marks a runtime symbol as a constructor callable with `new` (it has the
33
+ * `(i32, i64*)` signature). Lets `import { EventEmitter } from "events"` be
34
+ * used as `new EventEmitter()`.
35
+ */
36
+ readonly isConstructor?: boolean;
31
37
  }
32
38
 
33
39
  export type ModuleExports = Readonly<Record<string, ModuleExport>>;
package/src/index.ts CHANGED
@@ -25,6 +25,7 @@ export {
25
25
  XT_NULL,
26
26
  XT_TRUE,
27
27
  XT_FALSE,
28
+ XT_BIGINT,
28
29
  numberLiteral,
29
30
  booleanLiteral,
30
31
  } from "./codegen/values.js";
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Identifier scanning (identifiers, keywords and private `#name`s).
3
+ */
4
+
5
+ import { DiagnosticCode } from "../../diagnostics/diagnostic.js";
6
+ import { KEYWORDS, Token, TokenKind } from "../token.js";
7
+ import { Char, isIdentifierPart } from "../char.js";
8
+ import type { Scanner } from "../scanner.js";
9
+
10
+ export interface IdentifierMethods {
11
+ scanIdentifier(this: Scanner, start: number, precededByLineBreak: boolean): Token;
12
+ }
13
+
14
+ export const identifierMethods: IdentifierMethods = {
15
+ scanIdentifier(this: Scanner, start: number, precededByLineBreak: boolean): Token {
16
+ this.pos++;
17
+ while (this.pos < this.text.length) {
18
+ const ch = this.text.charCodeAt(this.pos);
19
+ if (isIdentifierPart(ch)) {
20
+ this.pos++;
21
+ } else if (ch === Char.Backslash && this.text.charCodeAt(this.pos + 1) === Char.LowerU) {
22
+ this.pos += 2;
23
+ const hex = this.text.slice(this.pos, this.pos + 4);
24
+ this.pos += 4;
25
+ if (!/^[0-9a-fA-F]{4}$/.test(hex)) {
26
+ this.error(DiagnosticCode.InvalidEscape, "Invalid unicode escape in identifier", this.pos - 4, this.pos);
27
+ }
28
+ } else {
29
+ break;
30
+ }
31
+ }
32
+ const text = this.text.slice(start, this.pos);
33
+ const keyword = KEYWORDS.get(text);
34
+ const kind = keyword ?? TokenKind.Identifier;
35
+ return this.makeToken(kind, start, this.pos, text, precededByLineBreak);
36
+ },
37
+ };
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Numeric literal scanning: decimals, radix prefixes, exponents and BigInt.
3
+ */
4
+
5
+ import { DiagnosticCode } from "../../diagnostics/diagnostic.js";
6
+ import { Token, TokenKind } from "../token.js";
7
+ import { Char, isDigit, isHexDigit } from "../char.js";
8
+ import type { Scanner } from "../scanner.js";
9
+
10
+ export interface NumberMethods {
11
+ scanNumber(this: Scanner, start: number, precededByLineBreak: boolean): Token;
12
+ finishNumber(this: Scanner, start: number, precededByLineBreak: boolean, isBigInt: boolean): Token;
13
+ }
14
+
15
+ export const numberMethods: NumberMethods = {
16
+ scanNumber(this: Scanner, start: number, precededByLineBreak: boolean): Token {
17
+ const text = this.text;
18
+ let isBigInt = false;
19
+ // Radix prefixes.
20
+ if (text.charCodeAt(this.pos) === Char.Zero) {
21
+ const next = text.charCodeAt(this.pos + 1);
22
+ if (next === Char.LowerX || next === Char.UpperX) {
23
+ this.pos += 2;
24
+ while (isHexDigit(text.charCodeAt(this.pos)) || text.charCodeAt(this.pos) === Char.Underscore) this.pos++;
25
+ isBigInt = text.charCodeAt(this.pos) === Char.LowerN;
26
+ if (isBigInt) this.pos++;
27
+ return this.finishNumber(start, precededByLineBreak, isBigInt);
28
+ }
29
+ if (next === Char.LowerO || next === Char.UpperO || next === Char.LowerB || next === Char.UpperB) {
30
+ this.pos += 2;
31
+ while (isDigit(text.charCodeAt(this.pos)) || text.charCodeAt(this.pos) === Char.Underscore) this.pos++;
32
+ isBigInt = text.charCodeAt(this.pos) === Char.LowerN;
33
+ if (isBigInt) this.pos++;
34
+ return this.finishNumber(start, precededByLineBreak, isBigInt);
35
+ }
36
+ }
37
+
38
+ while (isDigit(text.charCodeAt(this.pos)) || text.charCodeAt(this.pos) === Char.Underscore) this.pos++;
39
+ if (text.charCodeAt(this.pos) === Char.Dot) {
40
+ this.pos++;
41
+ while (isDigit(text.charCodeAt(this.pos)) || text.charCodeAt(this.pos) === Char.Underscore) this.pos++;
42
+ }
43
+ const e = text.charCodeAt(this.pos);
44
+ if (e === Char.LowerE || e === Char.UpperE) {
45
+ const save = this.pos;
46
+ this.pos++;
47
+ const sign = text.charCodeAt(this.pos);
48
+ if (sign === Char.Plus || sign === Char.Minus) this.pos++;
49
+ if (isDigit(text.charCodeAt(this.pos))) {
50
+ while (isDigit(text.charCodeAt(this.pos)) || text.charCodeAt(this.pos) === Char.Underscore) this.pos++;
51
+ } else {
52
+ // Not an exponent, roll back.
53
+ this.pos = save;
54
+ }
55
+ }
56
+ isBigInt = text.charCodeAt(this.pos) === Char.LowerN;
57
+ if (isBigInt) this.pos++;
58
+ return this.finishNumber(start, precededByLineBreak, isBigInt);
59
+ },
60
+
61
+ finishNumber(this: Scanner, start: number, precededByLineBreak: boolean, isBigInt: boolean): Token {
62
+ let raw = this.text.slice(start, this.pos);
63
+ const cleaned = raw.replace(/_/g, "");
64
+ if (isBigInt) {
65
+ raw = raw.slice(0, -1).replace(/_/g, "");
66
+ const parsed = Number(raw);
67
+ if (parsed !== parsed) {
68
+ this.error(DiagnosticCode.InvalidNumber, `Invalid BigInt literal '${raw}'`, start, this.pos);
69
+ return this.makeToken(TokenKind.BigIntLiteral, start, this.pos, raw, precededByLineBreak, 0);
70
+ }
71
+ return this.makeToken(TokenKind.BigIntLiteral, start, this.pos, raw, precededByLineBreak, parsed);
72
+ }
73
+ let value: number;
74
+ if (/^0[xX]/.test(cleaned)) value = parseInt(cleaned.slice(2), 16);
75
+ else if (/^0[oO]/.test(cleaned)) value = parseInt(cleaned.slice(2), 8);
76
+ else if (/^0[bB]/.test(cleaned)) value = parseInt(cleaned.slice(2), 2);
77
+ else value = Number(cleaned);
78
+ if (Number.isNaN(value)) {
79
+ this.error(DiagnosticCode.InvalidNumber, `Invalid numeric literal '${raw}'`, start, this.pos);
80
+ value = 0;
81
+ }
82
+ return this.makeToken(TokenKind.NumericLiteral, start, this.pos, raw, precededByLineBreak, value);
83
+ },
84
+ };
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Punctuation and operator scanning (the operator dispatch table).
3
+ */
4
+
5
+ import { DiagnosticCode } from "../../diagnostics/diagnostic.js";
6
+ import { Token, TokenKind } from "../token.js";
7
+ import { Char, isDigit } from "../char.js";
8
+ import type { Scanner } from "../scanner.js";
9
+
10
+ export interface PunctuationMethods {
11
+ scanPunctuation(this: Scanner, start: number, precededByLineBreak: boolean): Token;
12
+ }
13
+
14
+ export const punctuationMethods: PunctuationMethods = {
15
+ scanPunctuation(this: Scanner, start: number, precededByLineBreak: boolean): Token {
16
+ const text = this.text;
17
+ const ch = text.charCodeAt(this.pos);
18
+ const next = text.charCodeAt(this.pos + 1);
19
+ const third = text.charCodeAt(this.pos + 2);
20
+ const fourth = text.charCodeAt(this.pos + 3);
21
+
22
+ const emit = (kind: TokenKind, length: number): Token => {
23
+ this.pos += length;
24
+ return this.makeToken(kind, start, this.pos, text.slice(start, this.pos), precededByLineBreak);
25
+ };
26
+
27
+ switch (ch) {
28
+ case Char.OpenBrace:
29
+ return emit(TokenKind.OpenBrace, 1);
30
+ case Char.CloseBrace:
31
+ return emit(TokenKind.CloseBrace, 1);
32
+ case Char.OpenParen:
33
+ return emit(TokenKind.OpenParen, 1);
34
+ case Char.CloseParen:
35
+ return emit(TokenKind.CloseParen, 1);
36
+ case Char.OpenBracket:
37
+ return emit(TokenKind.OpenBracket, 1);
38
+ case Char.CloseBracket:
39
+ return emit(TokenKind.CloseBracket, 1);
40
+ case Char.Semicolon:
41
+ return emit(TokenKind.Semicolon, 1);
42
+ case Char.Comma:
43
+ return emit(TokenKind.Comma, 1);
44
+ case Char.At:
45
+ return emit(TokenKind.At, 1);
46
+ case Char.Tilde:
47
+ return emit(TokenKind.Tilde, 1);
48
+ case Char.Colon:
49
+ return emit(TokenKind.Colon, 1);
50
+ case Char.Dot:
51
+ if (next === Char.Dot && third === Char.Dot) return emit(TokenKind.DotDotDot, 3);
52
+ return emit(TokenKind.Dot, 1);
53
+ case Char.Question:
54
+ if (next === Char.Question) {
55
+ if (third === Char.Equals) return emit(TokenKind.QuestionQuestionEquals, 3);
56
+ return emit(TokenKind.QuestionQuestion, 2);
57
+ }
58
+ if (next === Char.Dot && !isDigit(third)) return emit(TokenKind.QuestionDot, 2);
59
+ return emit(TokenKind.Question, 1);
60
+ case Char.Equals:
61
+ if (next === Char.Equals && third === Char.Equals) return emit(TokenKind.EqualsEqualsEquals, 3);
62
+ if (next === Char.Equals) return emit(TokenKind.EqualsEquals, 2);
63
+ if (next === Char.GreaterThan) return emit(TokenKind.EqualsGreaterThan, 2);
64
+ return emit(TokenKind.Equals, 1);
65
+ case Char.Exclamation:
66
+ if (next === Char.Equals && third === Char.Equals) return emit(TokenKind.ExclamationEqualsEquals, 3);
67
+ if (next === Char.Equals) return emit(TokenKind.ExclamationEquals, 2);
68
+ return emit(TokenKind.Exclamation, 1);
69
+ case Char.Plus:
70
+ if (next === Char.Plus) return emit(TokenKind.PlusPlus, 2);
71
+ if (next === Char.Equals) return emit(TokenKind.PlusEquals, 2);
72
+ return emit(TokenKind.Plus, 1);
73
+ case Char.Minus:
74
+ if (next === Char.Minus) return emit(TokenKind.MinusMinus, 2);
75
+ if (next === Char.Equals) return emit(TokenKind.MinusEquals, 2);
76
+ return emit(TokenKind.Minus, 1);
77
+ case Char.Asterisk:
78
+ if (next === Char.Asterisk) {
79
+ if (third === Char.Equals) return emit(TokenKind.AsteriskAsteriskEquals, 3);
80
+ return emit(TokenKind.AsteriskAsterisk, 2);
81
+ }
82
+ if (next === Char.Equals) return emit(TokenKind.AsteriskEquals, 2);
83
+ return emit(TokenKind.Asterisk, 1);
84
+ case Char.Slash:
85
+ if (next === Char.Equals) return emit(TokenKind.SlashEquals, 2);
86
+ if (this.regexAllowed()) return this.scanRegex(start, precededByLineBreak);
87
+ return emit(TokenKind.Slash, 1);
88
+ case Char.Percent:
89
+ if (next === Char.Equals) return emit(TokenKind.PercentEquals, 2);
90
+ return emit(TokenKind.Percent, 1);
91
+ case Char.LessThan:
92
+ if (next === Char.LessThan) {
93
+ if (third === Char.Equals) return emit(TokenKind.LessThanLessThanEquals, 3);
94
+ return emit(TokenKind.LessThanLessThan, 2);
95
+ }
96
+ if (next === Char.Equals) return emit(TokenKind.LessThanEquals, 2);
97
+ return emit(TokenKind.LessThan, 1);
98
+ case Char.GreaterThan:
99
+ if (next === Char.GreaterThan) {
100
+ if (third === Char.GreaterThan) {
101
+ if (fourth === Char.Equals) return emit(TokenKind.GreaterThanGreaterThanGreaterThanEquals, 4);
102
+ return emit(TokenKind.GreaterThanGreaterThanGreaterThan, 3);
103
+ }
104
+ if (third === Char.Equals) return emit(TokenKind.GreaterThanGreaterThanEquals, 3);
105
+ return emit(TokenKind.GreaterThanGreaterThan, 2);
106
+ }
107
+ if (next === Char.Equals) return emit(TokenKind.GreaterThanEquals, 2);
108
+ return emit(TokenKind.GreaterThan, 1);
109
+ case Char.Ampersand:
110
+ if (next === Char.Ampersand) {
111
+ if (third === Char.Equals) return emit(TokenKind.AmpersandAmpersandEquals, 3);
112
+ return emit(TokenKind.AmpersandAmpersand, 2);
113
+ }
114
+ if (next === Char.Equals) return emit(TokenKind.AmpersandEquals, 2);
115
+ return emit(TokenKind.Ampersand, 1);
116
+ case Char.Bar:
117
+ if (next === Char.Bar) {
118
+ if (third === Char.Equals) return emit(TokenKind.BarBarEquals, 3);
119
+ return emit(TokenKind.BarBar, 2);
120
+ }
121
+ if (next === Char.Equals) return emit(TokenKind.BarEquals, 2);
122
+ return emit(TokenKind.Bar, 1);
123
+ case Char.Caret:
124
+ if (next === Char.Equals) return emit(TokenKind.CaretEquals, 2);
125
+ return emit(TokenKind.Caret, 1);
126
+ default:
127
+ this.pos++;
128
+ this.error(DiagnosticCode.InvalidCharacter, `Invalid character '${text[start]}'`, start, this.pos);
129
+ return this.makeToken(TokenKind.Identifier, start, this.pos, text[start] ?? "", precededByLineBreak);
130
+ }
131
+ },
132
+ };
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Regular expression literal scanning and the disambiguation rule that decides
3
+ * whether a `/` is a regex or a division operator.
4
+ */
5
+
6
+ import { DiagnosticCode } from "../../diagnostics/diagnostic.js";
7
+ import { Token, TokenKind } from "../token.js";
8
+ import { Char, isIdentifierPart } from "../char.js";
9
+ import type { Scanner } from "../scanner.js";
10
+
11
+ export interface RegexMethods {
12
+ regexAllowed(this: Scanner): boolean;
13
+ scanRegex(this: Scanner, start: number, precededByLineBreak: boolean): Token;
14
+ }
15
+
16
+ export const regexMethods: RegexMethods = {
17
+ /**
18
+ * True when a `/` in this position starts a regular expression rather than a
19
+ * division. The decision is made from the previous significant token.
20
+ */
21
+ regexAllowed(this: Scanner): boolean {
22
+ switch (this._token.kind) {
23
+ case TokenKind.Identifier:
24
+ case TokenKind.PrivateIdentifier:
25
+ case TokenKind.NumericLiteral:
26
+ case TokenKind.BigIntLiteral:
27
+ case TokenKind.StringLiteral:
28
+ case TokenKind.NoSubstitutionTemplateLiteral:
29
+ case TokenKind.TemplateTail:
30
+ case TokenKind.RegularExpressionLiteral:
31
+ case TokenKind.CloseParen:
32
+ case TokenKind.CloseBracket:
33
+ case TokenKind.TrueKeyword:
34
+ case TokenKind.FalseKeyword:
35
+ case TokenKind.NullKeyword:
36
+ case TokenKind.UndefinedKeyword:
37
+ case TokenKind.ThisKeyword:
38
+ case TokenKind.PlusPlus:
39
+ case TokenKind.MinusMinus:
40
+ return false;
41
+ default:
42
+ return true;
43
+ }
44
+ },
45
+
46
+ /** Scan a `/pattern/flags` literal, starting at the leading slash. */
47
+ scanRegex(this: Scanner, start: number, precededByLineBreak: boolean): Token {
48
+ this.pos++; // opening slash
49
+ let inClass = false;
50
+ for (;;) {
51
+ if (this.pos >= this.text.length) {
52
+ this.error(DiagnosticCode.InvalidCharacter, "Unterminated regular expression", start);
53
+ break;
54
+ }
55
+ const ch = this.text.charCodeAt(this.pos);
56
+ if (ch === Char.Backslash) {
57
+ this.pos += 2;
58
+ continue;
59
+ }
60
+ if (ch === Char.LineFeed || ch === Char.CarriageReturn) break;
61
+ if (ch === 91 /* [ */) inClass = true;
62
+ else if (ch === 93 /* ] */) inClass = false;
63
+ else if (ch === Char.Slash && !inClass) {
64
+ this.pos++;
65
+ break;
66
+ }
67
+ this.pos++;
68
+ }
69
+ // Flags.
70
+ while (this.pos < this.text.length && isIdentifierPart(this.text.charCodeAt(this.pos))) this.pos++;
71
+ return this.makeToken(
72
+ TokenKind.RegularExpressionLiteral,
73
+ start,
74
+ this.pos,
75
+ this.text.slice(start, this.pos),
76
+ precededByLineBreak,
77
+ );
78
+ },
79
+ };