xbintsc 0.1.0

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 (124) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +191 -0
  3. package/bin/xbintsc.js +26 -0
  4. package/dist/src/ast/factory.d.ts +11 -0
  5. package/dist/src/ast/factory.js +36 -0
  6. package/dist/src/ast/factory.js.map +1 -0
  7. package/dist/src/ast/nodes.d.ts +848 -0
  8. package/dist/src/ast/nodes.js +247 -0
  9. package/dist/src/ast/nodes.js.map +1 -0
  10. package/dist/src/ast/visitor.d.ts +18 -0
  11. package/dist/src/ast/visitor.js +52 -0
  12. package/dist/src/ast/visitor.js.map +1 -0
  13. package/dist/src/binder/binder.d.ts +82 -0
  14. package/dist/src/binder/binder.js +443 -0
  15. package/dist/src/binder/binder.js.map +1 -0
  16. package/dist/src/cli/main.d.ts +16 -0
  17. package/dist/src/cli/main.js +191 -0
  18. package/dist/src/cli/main.js.map +1 -0
  19. package/dist/src/codegen/llvm.d.ts +31 -0
  20. package/dist/src/codegen/llvm.js +1178 -0
  21. package/dist/src/codegen/llvm.js.map +1 -0
  22. package/dist/src/codegen/values.d.ts +23 -0
  23. package/dist/src/codegen/values.js +32 -0
  24. package/dist/src/codegen/values.js.map +1 -0
  25. package/dist/src/diagnostics/diagnostic.d.ts +69 -0
  26. package/dist/src/diagnostics/diagnostic.js +104 -0
  27. package/dist/src/diagnostics/diagnostic.js.map +1 -0
  28. package/dist/src/diagnostics/source.d.ts +43 -0
  29. package/dist/src/diagnostics/source.js +73 -0
  30. package/dist/src/diagnostics/source.js.map +1 -0
  31. package/dist/src/driver/cache.d.ts +37 -0
  32. package/dist/src/driver/cache.js +82 -0
  33. package/dist/src/driver/cache.js.map +1 -0
  34. package/dist/src/driver/compiler.d.ts +41 -0
  35. package/dist/src/driver/compiler.js +128 -0
  36. package/dist/src/driver/compiler.js.map +1 -0
  37. package/dist/src/driver/index.d.ts +4 -0
  38. package/dist/src/driver/index.js +5 -0
  39. package/dist/src/driver/index.js.map +1 -0
  40. package/dist/src/driver/paths.d.ts +4 -0
  41. package/dist/src/driver/paths.js +22 -0
  42. package/dist/src/driver/paths.js.map +1 -0
  43. package/dist/src/driver/toolchain.d.ts +43 -0
  44. package/dist/src/driver/toolchain.js +76 -0
  45. package/dist/src/driver/toolchain.js.map +1 -0
  46. package/dist/src/extensions/node.d.ts +9 -0
  47. package/dist/src/extensions/node.js +20 -0
  48. package/dist/src/extensions/node.js.map +1 -0
  49. package/dist/src/extensions/registry.d.ts +45 -0
  50. package/dist/src/extensions/registry.js +76 -0
  51. package/dist/src/extensions/registry.js.map +1 -0
  52. package/dist/src/index.d.ts +18 -0
  53. package/dist/src/index.js +19 -0
  54. package/dist/src/index.js.map +1 -0
  55. package/dist/src/lexer/scanner.d.ts +48 -0
  56. package/dist/src/lexer/scanner.js +650 -0
  57. package/dist/src/lexer/scanner.js.map +1 -0
  58. package/dist/src/lexer/token.d.ts +170 -0
  59. package/dist/src/lexer/token.js +250 -0
  60. package/dist/src/lexer/token.js.map +1 -0
  61. package/dist/src/parser/parser.d.ts +127 -0
  62. package/dist/src/parser/parser.js +2334 -0
  63. package/dist/src/parser/parser.js.map +1 -0
  64. package/dist/tests/binder/binder.test.d.ts +1 -0
  65. package/dist/tests/binder/binder.test.js +89 -0
  66. package/dist/tests/binder/binder.test.js.map +1 -0
  67. package/dist/tests/cli/main.test.d.ts +1 -0
  68. package/dist/tests/cli/main.test.js +68 -0
  69. package/dist/tests/cli/main.test.js.map +1 -0
  70. package/dist/tests/cli/process.test.d.ts +9 -0
  71. package/dist/tests/cli/process.test.js +57 -0
  72. package/dist/tests/cli/process.test.js.map +1 -0
  73. package/dist/tests/codegen/llvm.test.d.ts +1 -0
  74. package/dist/tests/codegen/llvm.test.js +93 -0
  75. package/dist/tests/codegen/llvm.test.js.map +1 -0
  76. package/dist/tests/driver/cache.test.d.ts +1 -0
  77. package/dist/tests/driver/cache.test.js +66 -0
  78. package/dist/tests/driver/cache.test.js.map +1 -0
  79. package/dist/tests/driver/compiler.test.d.ts +1 -0
  80. package/dist/tests/driver/compiler.test.js +80 -0
  81. package/dist/tests/driver/compiler.test.js.map +1 -0
  82. package/dist/tests/driver/toolchain.test.d.ts +1 -0
  83. package/dist/tests/driver/toolchain.test.js +60 -0
  84. package/dist/tests/driver/toolchain.test.js.map +1 -0
  85. package/dist/tests/e2e/compile.test.d.ts +5 -0
  86. package/dist/tests/e2e/compile.test.js +93 -0
  87. package/dist/tests/e2e/compile.test.js.map +1 -0
  88. package/dist/tests/extensions/registry.test.d.ts +1 -0
  89. package/dist/tests/extensions/registry.test.js +47 -0
  90. package/dist/tests/extensions/registry.test.js.map +1 -0
  91. package/dist/tests/helpers.d.ts +23 -0
  92. package/dist/tests/helpers.js +41 -0
  93. package/dist/tests/helpers.js.map +1 -0
  94. package/dist/tests/lexer/scanner.test.d.ts +1 -0
  95. package/dist/tests/lexer/scanner.test.js +95 -0
  96. package/dist/tests/lexer/scanner.test.js.map +1 -0
  97. package/dist/tests/parser/parser.test.d.ts +1 -0
  98. package/dist/tests/parser/parser.test.js +137 -0
  99. package/dist/tests/parser/parser.test.js.map +1 -0
  100. package/package.json +49 -0
  101. package/runtime/ext_node.c +42 -0
  102. package/runtime/rt.h +177 -0
  103. package/runtime/xt_runtime.c +682 -0
  104. package/scripts/build-runtime.mjs +34 -0
  105. package/src/ast/factory.ts +37 -0
  106. package/src/ast/nodes.ts +1111 -0
  107. package/src/ast/visitor.ts +60 -0
  108. package/src/binder/binder.ts +549 -0
  109. package/src/cli/main.ts +210 -0
  110. package/src/codegen/llvm.ts +1324 -0
  111. package/src/codegen/values.ts +36 -0
  112. package/src/diagnostics/diagnostic.ts +132 -0
  113. package/src/diagnostics/source.ts +97 -0
  114. package/src/driver/cache.ts +96 -0
  115. package/src/driver/compiler.ts +197 -0
  116. package/src/driver/index.ts +4 -0
  117. package/src/driver/paths.ts +24 -0
  118. package/src/driver/toolchain.ts +103 -0
  119. package/src/extensions/node.ts +23 -0
  120. package/src/extensions/registry.ts +101 -0
  121. package/src/index.ts +33 -0
  122. package/src/lexer/scanner.ts +650 -0
  123. package/src/lexer/token.ts +266 -0
  124. package/src/parser/parser.ts +2396 -0
@@ -0,0 +1,128 @@
1
+ /**
2
+ * The build driver: source file in, native binary out.
3
+ *
4
+ * Pipeline: read -> parse -> bind/check -> LLVM IR -> object -> link.
5
+ * The runtime (and any registered extension sources) are compiled once and
6
+ * cached, and the whole build is skipped when the incremental cache says
7
+ * nothing relevant changed.
8
+ */
9
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
10
+ import { basename, extname, join, resolve } from "node:path";
11
+ import { DiagnosticBag } from "../diagnostics/diagnostic.js";
12
+ import { SourceFile } from "../diagnostics/source.js";
13
+ import { Parser } from "../parser/parser.js";
14
+ import { generate } from "../codegen/llvm.js";
15
+ import { createDefaultRegistry } from "../extensions/registry.js";
16
+ import { BuildCache, hashParts } from "./cache.js";
17
+ import { findRuntimeDir } from "./paths.js";
18
+ import { compileC, compileIr, findClang, link, realRunner, } from "./toolchain.js";
19
+ export const COMPILER_VERSION = "0.1.0";
20
+ /** Compile TypeScript source text to LLVM IR without touching the toolchain. */
21
+ export function compileString(source, fileName = "input.ts", extensions) {
22
+ const file = new SourceFile(fileName, source);
23
+ const diagnostics = new DiagnosticBag();
24
+ const parser = new Parser(file, diagnostics);
25
+ const sourceFile = parser.parseSourceFile();
26
+ const registry = extensions ?? createDefaultRegistry();
27
+ const { ir } = generate(sourceFile, diagnostics, { builtins: registry.builtins() });
28
+ return { ir, diagnostics: diagnostics.diagnostics };
29
+ }
30
+ function executableName(entry, outDir, explicit) {
31
+ if (explicit)
32
+ return resolve(explicit);
33
+ const base = basename(entry, extname(entry));
34
+ const suffix = process.platform === "win32" ? ".exe" : "";
35
+ return resolve(outDir, base + suffix);
36
+ }
37
+ export function build(entryPath, options = {}) {
38
+ const runner = options.runner ?? realRunner;
39
+ const registry = options.extensions ?? createDefaultRegistry();
40
+ const outDir = resolve(options.outDir ?? join(process.cwd(), "build"));
41
+ const cacheDir = resolve(options.cacheDir ?? join(process.cwd(), ".xbintsc"));
42
+ const emit = options.emit ?? "exe";
43
+ const optimize = options.optimize ?? "2";
44
+ const absoluteEntry = resolve(entryPath);
45
+ const sourceText = readFileSync(absoluteEntry, "utf8");
46
+ const baseName = basename(absoluteEntry, extname(absoluteEntry));
47
+ const outputPath = emit === "ir"
48
+ ? resolve(options.output ?? join(outDir, baseName + ".ll"))
49
+ : emit === "obj"
50
+ ? resolve(options.output ?? join(outDir, baseName + ".o"))
51
+ : executableName(absoluteEntry, outDir, options.output);
52
+ const cacheKey = hashParts([
53
+ COMPILER_VERSION,
54
+ sourceText,
55
+ emit,
56
+ optimize,
57
+ process.platform,
58
+ registry.all().map((e) => e.name).join(","),
59
+ ]);
60
+ const cache = new BuildCache(cacheDir);
61
+ const outputs = [outputPath];
62
+ if (!options.force && cache.isFresh(cacheKey, outputs)) {
63
+ return { outputPath, cached: true, diagnostics: [] };
64
+ }
65
+ // -- front end -----------------------------------------------------------
66
+ const file = new SourceFile(absoluteEntry, sourceText);
67
+ const diagnostics = new DiagnosticBag();
68
+ const parser = new Parser(file, diagnostics);
69
+ const sourceFile = parser.parseSourceFile();
70
+ const { ir } = generate(sourceFile, diagnostics, { builtins: registry.builtins() });
71
+ if (options.verbose) {
72
+ process.stderr.write(`xbintsc: generated ${ir.length} bytes of LLVM IR\n`);
73
+ }
74
+ if (diagnostics.hasErrors) {
75
+ return { outputPath, cached: false, diagnostics: diagnostics.diagnostics, ir };
76
+ }
77
+ mkdirSync(outDir, { recursive: true });
78
+ const irPath = resolve(outDir, basename(absoluteEntry, extname(absoluteEntry)) + ".ll");
79
+ writeFileSync(irPath, ir);
80
+ if (emit === "ir") {
81
+ cache.record(cacheKey, outputs);
82
+ cache.save();
83
+ return { outputPath, irPath, cached: false, diagnostics: [], ir };
84
+ }
85
+ // -- toolchain -----------------------------------------------------------
86
+ const clang = options.clang ?? findClang(runner);
87
+ const runtimeDir = findRuntimeDir();
88
+ mkdirSync(cacheDir, { recursive: true });
89
+ const { runtimeObject, extensionObjects } = ensureRuntimeObjects(runner, clang, runtimeDir, cacheDir, registry);
90
+ const objectPath = emit === "obj" ? outputPath : resolve(outDir, baseName + ".o");
91
+ compileIr(runner, { clang, irPath, objectPath, optimize });
92
+ if (emit === "obj") {
93
+ cache.record(cacheKey, outputs);
94
+ cache.save();
95
+ return { outputPath, irPath, cached: false, diagnostics: [], ir };
96
+ }
97
+ link(runner, {
98
+ clang,
99
+ objectPaths: [objectPath, runtimeObject, ...extensionObjects],
100
+ outputPath,
101
+ linkerFlags: [...(process.platform === "win32" ? [] : ["-lm"]), ...registry.linkerFlags()],
102
+ optimize,
103
+ });
104
+ cache.record(cacheKey, outputs);
105
+ cache.save();
106
+ return { outputPath, irPath, cached: false, diagnostics: [], ir };
107
+ }
108
+ /**
109
+ * Compile the core runtime and every extension source, reusing cached object
110
+ * files keyed on the C source hash. Returns the object paths to link.
111
+ */
112
+ function ensureRuntimeObjects(runner, clang, runtimeDir, cacheDir, registry) {
113
+ const compileOne = (sourcePath, tag) => {
114
+ const body = readFileSync(sourcePath, "utf8");
115
+ const key = hashParts(["runtime", COMPILER_VERSION, tag, body, clang, process.platform]);
116
+ const objectPath = join(cacheDir, `${tag}-${key}.o`);
117
+ if (!existsSync(objectPath)) {
118
+ compileC(runner, clang, sourcePath, objectPath, runtimeDir);
119
+ }
120
+ return objectPath;
121
+ };
122
+ const runtimeObject = compileOne(join(runtimeDir, "xt_runtime.c"), "xt_runtime");
123
+ const extensionObjects = registry
124
+ .runtimeSources()
125
+ .map((sourcePath, index) => compileOne(sourcePath, `ext_${index}_${basename(sourcePath, ".c")}`));
126
+ return { runtimeObject, extensionObjects };
127
+ }
128
+ //# sourceMappingURL=compiler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler.js","sourceRoot":"","sources":["../../../src/driver/compiler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { build, compileString, COMPILER_VERSION, type BuildOptions, type BuildResult, type EmitKind } from "./compiler.js";
2
+ export { BuildCache, hashParts, hashString } from "./cache.js";
3
+ export { findRuntimeDir, findPackageRoot } from "./paths.js";
4
+ export { findClang, realRunner, ToolchainError, type Runner } from "./toolchain.js";
@@ -0,0 +1,5 @@
1
+ export { build, compileString, COMPILER_VERSION } from "./compiler.js";
2
+ export { BuildCache, hashParts, hashString } from "./cache.js";
3
+ export { findRuntimeDir, findPackageRoot } from "./paths.js";
4
+ export { findClang, realRunner, ToolchainError } from "./toolchain.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/driver/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAsD,MAAM,eAAe,CAAC;AAC3H,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAe,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,4 @@
1
+ /** Filesystem locations owned by the compiler package. */
2
+ /** Directory containing `rt.h` and the runtime/ext C sources. */
3
+ export declare function findRuntimeDir(): string;
4
+ export declare function findPackageRoot(): string;
@@ -0,0 +1,22 @@
1
+ /** Filesystem locations owned by the compiler package. */
2
+ import { existsSync } from "node:fs";
3
+ import { dirname, join, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ const here = dirname(fileURLToPath(import.meta.url));
6
+ /** Directory containing `rt.h` and the runtime/ext C sources. */
7
+ export function findRuntimeDir() {
8
+ const candidates = [
9
+ resolve(here, "../../runtime"),
10
+ resolve(here, "../../../runtime"),
11
+ resolve(process.cwd(), "runtime"),
12
+ ];
13
+ for (const candidate of candidates) {
14
+ if (existsSync(join(candidate, "rt.h")))
15
+ return candidate;
16
+ }
17
+ throw new Error("Unable to locate the xbintsc runtime directory (missing runtime/rt.h)");
18
+ }
19
+ export function findPackageRoot() {
20
+ return resolve(findRuntimeDir(), "..");
21
+ }
22
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/driver/paths.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAE1D,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAErD,iEAAiE;AACjE,MAAM,UAAU,cAAc;IAC5B,MAAM,UAAU,GAAG;QACjB,OAAO,CAAC,IAAI,EAAE,eAAe,CAAC;QAC9B,OAAO,CAAC,IAAI,EAAE,kBAAkB,CAAC;QACjC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC;KAClC,CAAC;IACF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAAE,OAAO,SAAS,CAAC;IAC5D,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;AAC3F,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,OAAO,CAAC,cAAc,EAAE,EAAE,IAAI,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Thin wrappers around the external toolchain (clang) and process execution.
3
+ *
4
+ * Everything that shells out lives here so the rest of the driver stays
5
+ * testable: unit tests can pass a fake `Runner` and never touch the host.
6
+ */
7
+ export interface CommandResult {
8
+ readonly status: number;
9
+ readonly stdout: string;
10
+ readonly stderr: string;
11
+ }
12
+ export interface Runner {
13
+ run(command: string, args: readonly string[], options?: {
14
+ cwd?: string;
15
+ }): CommandResult;
16
+ }
17
+ export declare const realRunner: Runner;
18
+ export declare class ToolchainError extends Error {
19
+ readonly command: string;
20
+ readonly status: number;
21
+ readonly stderr: string;
22
+ constructor(command: string, status: number, stderr: string);
23
+ }
24
+ /** Locate a clang-compatible C compiler, honouring `xbintsc_CLANG`. */
25
+ export declare function findClang(runner?: Runner): string;
26
+ export interface CompileIrOptions {
27
+ readonly clang: string;
28
+ readonly irPath: string;
29
+ readonly objectPath: string;
30
+ readonly optimize: string;
31
+ }
32
+ /** Compile an LLVM IR file to a native object file. */
33
+ export declare function compileIr(runner: Runner, options: CompileIrOptions): void;
34
+ export interface LinkOptions {
35
+ readonly clang: string;
36
+ readonly objectPaths: readonly string[];
37
+ readonly outputPath: string;
38
+ readonly linkerFlags: readonly string[];
39
+ readonly optimize: string;
40
+ }
41
+ export declare function link(runner: Runner, options: LinkOptions): void;
42
+ /** Compile a C source to an object file (used for the runtime and extensions). */
43
+ export declare function compileC(runner: Runner, clang: string, sourcePath: string, objectPath: string, includeDir: string): void;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Thin wrappers around the external toolchain (clang) and process execution.
3
+ *
4
+ * Everything that shells out lives here so the rest of the driver stays
5
+ * testable: unit tests can pass a fake `Runner` and never touch the host.
6
+ */
7
+ import { spawnSync } from "node:child_process";
8
+ export const realRunner = {
9
+ run(command, args, options = {}) {
10
+ const spawnOptions = {
11
+ cwd: options.cwd,
12
+ encoding: "utf8",
13
+ maxBuffer: 64 * 1024 * 1024,
14
+ };
15
+ const result = spawnSync(command, [...args], spawnOptions);
16
+ return {
17
+ status: result.status ?? (result.error ? 1 : 0),
18
+ stdout: result.stdout?.toString() ?? "",
19
+ stderr: result.stderr?.toString() ?? (result.error ? String(result.error.message) : ""),
20
+ };
21
+ },
22
+ };
23
+ export class ToolchainError extends Error {
24
+ command;
25
+ status;
26
+ stderr;
27
+ constructor(command, status, stderr) {
28
+ super(`Command failed (${status}): ${command}\n${stderr}`);
29
+ this.name = "ToolchainError";
30
+ this.command = command;
31
+ this.status = status;
32
+ this.stderr = stderr;
33
+ }
34
+ }
35
+ /** Locate a clang-compatible C compiler, honouring `xbintsc_CLANG`. */
36
+ export function findClang(runner = realRunner) {
37
+ const candidates = [
38
+ process.env.xbintsc_CLANG,
39
+ "clang",
40
+ "clang-18",
41
+ "clang-17",
42
+ "clang-16",
43
+ "cc",
44
+ ].filter((candidate) => Boolean(candidate));
45
+ for (const candidate of candidates) {
46
+ const result = runner.run(candidate, ["--version"]);
47
+ if (result.status === 0)
48
+ return candidate;
49
+ }
50
+ throw new ToolchainError("clang --version", 1, "No C compiler found. Set xbintsc_CLANG to a clang binary.");
51
+ }
52
+ /** Compile an LLVM IR file to a native object file. */
53
+ export function compileIr(runner, options) {
54
+ const result = runner.run(options.clang, [
55
+ `-O${options.optimize}`,
56
+ "-c",
57
+ options.irPath,
58
+ "-o",
59
+ options.objectPath,
60
+ ]);
61
+ if (result.status !== 0)
62
+ throw new ToolchainError(`${options.clang} ${options.irPath}`, result.status, result.stderr);
63
+ }
64
+ export function link(runner, options) {
65
+ const args = [`-O${options.optimize}`, ...options.objectPaths, "-o", options.outputPath, ...options.linkerFlags];
66
+ const result = runner.run(options.clang, args);
67
+ if (result.status !== 0)
68
+ throw new ToolchainError(`${options.clang} link`, result.status, result.stderr);
69
+ }
70
+ /** Compile a C source to an object file (used for the runtime and extensions). */
71
+ export function compileC(runner, clang, sourcePath, objectPath, includeDir) {
72
+ const result = runner.run(clang, ["-O2", "-c", sourcePath, "-o", objectPath, `-I${includeDir}`]);
73
+ if (result.status !== 0)
74
+ throw new ToolchainError(`${clang} ${sourcePath}`, result.status, result.stderr);
75
+ }
76
+ //# sourceMappingURL=toolchain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolchain.js","sourceRoot":"","sources":["../../../src/driver/toolchain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Node.js compatibility extension.
3
+ *
4
+ * Registering it links `runtime/ext_node.c` and exposes the builtins it
5
+ * implements, so `readFileSync("...")` in TypeScript resolves to the C
6
+ * implementation without the core compiler knowing anything about Node.
7
+ */
8
+ import type { Extension } from "./registry.js";
9
+ export declare const nodeExtension: Extension;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Node.js compatibility extension.
3
+ *
4
+ * Registering it links `runtime/ext_node.c` and exposes the builtins it
5
+ * implements, so `readFileSync("...")` in TypeScript resolves to the C
6
+ * implementation without the core compiler knowing anything about Node.
7
+ */
8
+ import { fileURLToPath } from "node:url";
9
+ import { dirname, resolve } from "node:path";
10
+ const here = dirname(fileURLToPath(import.meta.url));
11
+ export const nodeExtension = {
12
+ name: "node",
13
+ description: "Node.js host APIs (readFileSync, ...)",
14
+ runtimeSources: () => [resolve(here, "../../runtime/ext_node.c")],
15
+ builtins: () => ({
16
+ readFileSync: { symbol: "xt_node_read_text_file" },
17
+ readTextFile: { symbol: "xt_node_read_text_file" },
18
+ }),
19
+ };
20
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../../../src/extensions/node.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAG7C,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAErD,MAAM,CAAC,MAAM,aAAa,GAAc;IACtC,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,uCAAuC;IACpD,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,0BAA0B,CAAC,CAAC;IACjE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;QACf,YAAY,EAAE,EAAE,MAAM,EAAE,wBAAwB,EAAE;QAClD,YAAY,EAAE,EAAE,MAAM,EAAE,wBAAwB,EAAE;KACnD,CAAC;CACH,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Pluggable compile modules ("extensions").
3
+ *
4
+ * An extension teaches xbintsc about a host platform: additional C runtime
5
+ * sources to link, libraries to pass to the linker, and global functions that
6
+ * resolve to runtime symbols. Node's `fs`, Bun's `Bun.file`, ... all fit this
7
+ * shape, so the core compiler never has to grow platform specific branches.
8
+ *
9
+ * The default registry ships an empty baseline; callers register the
10
+ * extensions they need before invoking the driver.
11
+ */
12
+ export interface BuiltinFunction {
13
+ /** Exported C symbol, called as `xt_value symbol(int32_t argc, xt_value *argv)`. */
14
+ readonly symbol: string;
15
+ readonly returnVoid?: boolean;
16
+ }
17
+ export interface Extension {
18
+ readonly name: string;
19
+ /** Description shown by `xbintsc ext list`. */
20
+ readonly description?: string;
21
+ /** C/asm sources compiled and linked alongside the generated module. */
22
+ runtimeSources?(): readonly string[];
23
+ /** Extra linker flags (e.g. `["-lm"]`, `["-framework", "CoreFoundation"]`). */
24
+ linkerFlags?(): readonly string[];
25
+ /** Global identifiers that resolve to runtime symbols when called. */
26
+ builtins?(): Readonly<Record<string, BuiltinFunction>>;
27
+ }
28
+ export declare class ExtensionRegistry {
29
+ private readonly extensions;
30
+ register(extension: Extension): this;
31
+ unregister(name: string): boolean;
32
+ get(name: string): Extension | undefined;
33
+ has(name: string): boolean;
34
+ all(): readonly Extension[];
35
+ /** Flatten every registered builtin into one lookup table. */
36
+ builtins(): Readonly<Record<string, BuiltinFunction>>;
37
+ runtimeSources(): readonly string[];
38
+ linkerFlags(): readonly string[];
39
+ }
40
+ /**
41
+ * A built-in extension that exposes the runtime's own console/IO helpers. It is
42
+ * always present so `console.log` works even without a platform extension.
43
+ */
44
+ export declare const coreExtension: Extension;
45
+ export declare function createDefaultRegistry(): ExtensionRegistry;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Pluggable compile modules ("extensions").
3
+ *
4
+ * An extension teaches xbintsc about a host platform: additional C runtime
5
+ * sources to link, libraries to pass to the linker, and global functions that
6
+ * resolve to runtime symbols. Node's `fs`, Bun's `Bun.file`, ... all fit this
7
+ * shape, so the core compiler never has to grow platform specific branches.
8
+ *
9
+ * The default registry ships an empty baseline; callers register the
10
+ * extensions they need before invoking the driver.
11
+ */
12
+ export class ExtensionRegistry {
13
+ extensions = new Map();
14
+ register(extension) {
15
+ if (this.extensions.has(extension.name)) {
16
+ throw new Error(`Extension '${extension.name}' is already registered`);
17
+ }
18
+ this.extensions.set(extension.name, extension);
19
+ return this;
20
+ }
21
+ unregister(name) {
22
+ return this.extensions.delete(name);
23
+ }
24
+ get(name) {
25
+ return this.extensions.get(name);
26
+ }
27
+ has(name) {
28
+ return this.extensions.has(name);
29
+ }
30
+ all() {
31
+ return [...this.extensions.values()];
32
+ }
33
+ /** Flatten every registered builtin into one lookup table. */
34
+ builtins() {
35
+ const merged = {};
36
+ for (const extension of this.extensions.values()) {
37
+ const builtins = extension.builtins?.();
38
+ if (builtins)
39
+ Object.assign(merged, builtins);
40
+ }
41
+ return merged;
42
+ }
43
+ runtimeSources() {
44
+ const sources = [];
45
+ for (const extension of this.extensions.values()) {
46
+ const extra = extension.runtimeSources?.();
47
+ if (extra)
48
+ sources.push(...extra);
49
+ }
50
+ return sources;
51
+ }
52
+ linkerFlags() {
53
+ const flags = [];
54
+ for (const extension of this.extensions.values()) {
55
+ const extra = extension.linkerFlags?.();
56
+ if (extra)
57
+ flags.push(...extra);
58
+ }
59
+ return flags;
60
+ }
61
+ }
62
+ /**
63
+ * A built-in extension that exposes the runtime's own console/IO helpers. It is
64
+ * always present so `console.log` works even without a platform extension.
65
+ */
66
+ export const coreExtension = {
67
+ name: "core",
68
+ description: "Core runtime helpers (console, print)",
69
+ builtins: () => ({
70
+ print: { symbol: "xt_println" },
71
+ }),
72
+ };
73
+ export function createDefaultRegistry() {
74
+ return new ExtensionRegistry().register(coreExtension);
75
+ }
76
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/extensions/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAoBH,MAAM,OAAO,iBAAiB;IACX,UAAU,GAAG,IAAI,GAAG,EAAqB,CAAC;IAE3D,QAAQ,CAAC,SAAoB;QAC3B,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,cAAc,SAAS,CAAC,IAAI,yBAAyB,CAAC,CAAC;QACzE,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,UAAU,CAAC,IAAY;QACrB,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,GAAG;QACD,OAAO,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,8DAA8D;IAC9D,QAAQ;QACN,MAAM,MAAM,GAAoC,EAAE,CAAC;QACnD,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;YACjD,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,EAAE,EAAE,CAAC;YACxC,IAAI,QAAQ;gBAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAChD,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,cAAc;QACZ,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;YACjD,MAAM,KAAK,GAAG,SAAS,CAAC,cAAc,EAAE,EAAE,CAAC;YAC3C,IAAI,KAAK;gBAAE,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;QACpC,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,WAAW;QACT,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;YACjD,MAAM,KAAK,GAAG,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;YACxC,IAAI,KAAK;gBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;QAClC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAc;IACtC,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,uCAAuC;IACpD,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;QACf,KAAK,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE;KAChC,CAAC;CACH,CAAC;AAEF,MAAM,UAAU,qBAAqB;IACnC,OAAO,IAAI,iBAAiB,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;AACzD,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * xbintsc public API surface.
3
+ *
4
+ * Re-exports the compiler pipeline so the CLI, tests and embedding tools can
5
+ * compose stages (lex, parse, bind, generate) without depending on internals.
6
+ */
7
+ export { SourceFile, hashText, combineHashes } from "./diagnostics/source.js";
8
+ export { DiagnosticBag, DiagnosticCode, DiagnosticError, formatDiagnostic, formatDiagnostics, type Diagnostic, } from "./diagnostics/diagnostic.js";
9
+ export { Scanner } from "./lexer/scanner.js";
10
+ export { TokenKind, KEYWORDS, type Token } from "./lexer/token.js";
11
+ export * from "./ast/nodes.js";
12
+ export { Parser } from "./parser/parser.js";
13
+ export { bind, SymbolKind, ScopeKind, type BindResult, type FunctionInfo, type SymbolInfo } from "./binder/binder.js";
14
+ export { generate, type CodegenResult, type CodegenOptions } from "./codegen/llvm.js";
15
+ export { XT_UNDEFINED, XT_NULL, XT_TRUE, XT_FALSE, numberLiteral, booleanLiteral, } from "./codegen/values.js";
16
+ export { ExtensionRegistry, createDefaultRegistry, coreExtension, type Extension } from "./extensions/registry.js";
17
+ export { nodeExtension } from "./extensions/node.js";
18
+ export * from "./driver/index.js";
@@ -0,0 +1,19 @@
1
+ /**
2
+ * xbintsc public API surface.
3
+ *
4
+ * Re-exports the compiler pipeline so the CLI, tests and embedding tools can
5
+ * compose stages (lex, parse, bind, generate) without depending on internals.
6
+ */
7
+ export { SourceFile, hashText, combineHashes } from "./diagnostics/source.js";
8
+ export { DiagnosticBag, DiagnosticCode, DiagnosticError, formatDiagnostic, formatDiagnostics, } from "./diagnostics/diagnostic.js";
9
+ export { Scanner } from "./lexer/scanner.js";
10
+ export { TokenKind, KEYWORDS } from "./lexer/token.js";
11
+ export * from "./ast/nodes.js";
12
+ export { Parser } from "./parser/parser.js";
13
+ export { bind, SymbolKind, ScopeKind } from "./binder/binder.js";
14
+ export { generate } from "./codegen/llvm.js";
15
+ export { XT_UNDEFINED, XT_NULL, XT_TRUE, XT_FALSE, numberLiteral, booleanLiteral, } from "./codegen/values.js";
16
+ export { ExtensionRegistry, createDefaultRegistry, coreExtension } from "./extensions/registry.js";
17
+ export { nodeExtension } from "./extensions/node.js";
18
+ export * from "./driver/index.js";
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EACL,aAAa,EACb,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,iBAAiB,GAElB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAc,MAAM,kBAAkB,CAAC;AACnE,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAuD,MAAM,oBAAoB,CAAC;AACtH,OAAO,EAAE,QAAQ,EAA2C,MAAM,mBAAmB,CAAC;AACtF,OAAO,EACL,YAAY,EACZ,OAAO,EACP,OAAO,EACP,QAAQ,EACR,aAAa,EACb,cAAc,GACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,aAAa,EAAkB,MAAM,0BAA0B,CAAC;AACnH,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,48 @@
1
+ import { DiagnosticBag } from "../diagnostics/diagnostic.js";
2
+ import type { SourceFile } from "../diagnostics/source.js";
3
+ import { Token } from "./token.js";
4
+ /**
5
+ * Hand-written scanner for the TypeScript language. It produces a flat token
6
+ * stream consumed by the parser. Comments and trivia are skipped, but line
7
+ * breaks are tracked so the parser can implement ASI (automatic semicolon
8
+ * insertion) correctly.
9
+ */
10
+ export declare class Scanner {
11
+ private readonly text;
12
+ private pos;
13
+ private readonly diagnostics;
14
+ private readonly source;
15
+ private _token;
16
+ constructor(source: SourceFile, diagnostics: DiagnosticBag);
17
+ get token(): Token;
18
+ get position(): number;
19
+ /**
20
+ * Reset the scanner read head. Used by the parser to re-scan the `}` that
21
+ * terminates a template substitution as template text instead of a brace.
22
+ */
23
+ seek(offset: number): void;
24
+ /** Advance to the next token. */
25
+ nextToken(): Token;
26
+ /** Scan everything, useful for lexer tests. */
27
+ tokenize(): Token[];
28
+ private error;
29
+ private scan;
30
+ private makeToken;
31
+ private scanIdentifier;
32
+ private scanNumber;
33
+ private finishNumber;
34
+ private scanString;
35
+ private scanEscapeSequence;
36
+ /** Scans a template literal chunk starting at a backtick or after `}`. */
37
+ scanTemplate(start: number, precededByLineBreak: boolean, isHead: boolean): Token;
38
+ /** Called by the parser after a template substitution expression. */
39
+ continueTemplate(offset: number): Token;
40
+ /**
41
+ * True when a `/` in this position starts a regular expression rather than a
42
+ * division. The decision is made from the previous significant token.
43
+ */
44
+ private regexAllowed;
45
+ /** Scan a `/pattern/flags` literal, starting at the leading slash. */
46
+ private scanRegex;
47
+ private scanPunctuation;
48
+ }