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.
- package/LICENSE +21 -0
- package/README.md +191 -0
- package/bin/xbintsc.js +26 -0
- package/dist/src/ast/factory.d.ts +11 -0
- package/dist/src/ast/factory.js +36 -0
- package/dist/src/ast/factory.js.map +1 -0
- package/dist/src/ast/nodes.d.ts +848 -0
- package/dist/src/ast/nodes.js +247 -0
- package/dist/src/ast/nodes.js.map +1 -0
- package/dist/src/ast/visitor.d.ts +18 -0
- package/dist/src/ast/visitor.js +52 -0
- package/dist/src/ast/visitor.js.map +1 -0
- package/dist/src/binder/binder.d.ts +82 -0
- package/dist/src/binder/binder.js +443 -0
- package/dist/src/binder/binder.js.map +1 -0
- package/dist/src/cli/main.d.ts +16 -0
- package/dist/src/cli/main.js +191 -0
- package/dist/src/cli/main.js.map +1 -0
- package/dist/src/codegen/llvm.d.ts +31 -0
- package/dist/src/codegen/llvm.js +1178 -0
- package/dist/src/codegen/llvm.js.map +1 -0
- package/dist/src/codegen/values.d.ts +23 -0
- package/dist/src/codegen/values.js +32 -0
- package/dist/src/codegen/values.js.map +1 -0
- package/dist/src/diagnostics/diagnostic.d.ts +69 -0
- package/dist/src/diagnostics/diagnostic.js +104 -0
- package/dist/src/diagnostics/diagnostic.js.map +1 -0
- package/dist/src/diagnostics/source.d.ts +43 -0
- package/dist/src/diagnostics/source.js +73 -0
- package/dist/src/diagnostics/source.js.map +1 -0
- package/dist/src/driver/cache.d.ts +37 -0
- package/dist/src/driver/cache.js +82 -0
- package/dist/src/driver/cache.js.map +1 -0
- package/dist/src/driver/compiler.d.ts +41 -0
- package/dist/src/driver/compiler.js +128 -0
- package/dist/src/driver/compiler.js.map +1 -0
- package/dist/src/driver/index.d.ts +4 -0
- package/dist/src/driver/index.js +5 -0
- package/dist/src/driver/index.js.map +1 -0
- package/dist/src/driver/paths.d.ts +4 -0
- package/dist/src/driver/paths.js +22 -0
- package/dist/src/driver/paths.js.map +1 -0
- package/dist/src/driver/toolchain.d.ts +43 -0
- package/dist/src/driver/toolchain.js +76 -0
- package/dist/src/driver/toolchain.js.map +1 -0
- package/dist/src/extensions/node.d.ts +9 -0
- package/dist/src/extensions/node.js +20 -0
- package/dist/src/extensions/node.js.map +1 -0
- package/dist/src/extensions/registry.d.ts +45 -0
- package/dist/src/extensions/registry.js +76 -0
- package/dist/src/extensions/registry.js.map +1 -0
- package/dist/src/index.d.ts +18 -0
- package/dist/src/index.js +19 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lexer/scanner.d.ts +48 -0
- package/dist/src/lexer/scanner.js +650 -0
- package/dist/src/lexer/scanner.js.map +1 -0
- package/dist/src/lexer/token.d.ts +170 -0
- package/dist/src/lexer/token.js +250 -0
- package/dist/src/lexer/token.js.map +1 -0
- package/dist/src/parser/parser.d.ts +127 -0
- package/dist/src/parser/parser.js +2334 -0
- package/dist/src/parser/parser.js.map +1 -0
- package/dist/tests/binder/binder.test.d.ts +1 -0
- package/dist/tests/binder/binder.test.js +89 -0
- package/dist/tests/binder/binder.test.js.map +1 -0
- package/dist/tests/cli/main.test.d.ts +1 -0
- package/dist/tests/cli/main.test.js +68 -0
- package/dist/tests/cli/main.test.js.map +1 -0
- package/dist/tests/cli/process.test.d.ts +9 -0
- package/dist/tests/cli/process.test.js +57 -0
- package/dist/tests/cli/process.test.js.map +1 -0
- package/dist/tests/codegen/llvm.test.d.ts +1 -0
- package/dist/tests/codegen/llvm.test.js +93 -0
- package/dist/tests/codegen/llvm.test.js.map +1 -0
- package/dist/tests/driver/cache.test.d.ts +1 -0
- package/dist/tests/driver/cache.test.js +66 -0
- package/dist/tests/driver/cache.test.js.map +1 -0
- package/dist/tests/driver/compiler.test.d.ts +1 -0
- package/dist/tests/driver/compiler.test.js +80 -0
- package/dist/tests/driver/compiler.test.js.map +1 -0
- package/dist/tests/driver/toolchain.test.d.ts +1 -0
- package/dist/tests/driver/toolchain.test.js +60 -0
- package/dist/tests/driver/toolchain.test.js.map +1 -0
- package/dist/tests/e2e/compile.test.d.ts +5 -0
- package/dist/tests/e2e/compile.test.js +93 -0
- package/dist/tests/e2e/compile.test.js.map +1 -0
- package/dist/tests/extensions/registry.test.d.ts +1 -0
- package/dist/tests/extensions/registry.test.js +47 -0
- package/dist/tests/extensions/registry.test.js.map +1 -0
- package/dist/tests/helpers.d.ts +23 -0
- package/dist/tests/helpers.js +41 -0
- package/dist/tests/helpers.js.map +1 -0
- package/dist/tests/lexer/scanner.test.d.ts +1 -0
- package/dist/tests/lexer/scanner.test.js +95 -0
- package/dist/tests/lexer/scanner.test.js.map +1 -0
- package/dist/tests/parser/parser.test.d.ts +1 -0
- package/dist/tests/parser/parser.test.js +137 -0
- package/dist/tests/parser/parser.test.js.map +1 -0
- package/package.json +49 -0
- package/runtime/ext_node.c +42 -0
- package/runtime/rt.h +177 -0
- package/runtime/xt_runtime.c +682 -0
- package/scripts/build-runtime.mjs +34 -0
- package/src/ast/factory.ts +37 -0
- package/src/ast/nodes.ts +1111 -0
- package/src/ast/visitor.ts +60 -0
- package/src/binder/binder.ts +549 -0
- package/src/cli/main.ts +210 -0
- package/src/codegen/llvm.ts +1324 -0
- package/src/codegen/values.ts +36 -0
- package/src/diagnostics/diagnostic.ts +132 -0
- package/src/diagnostics/source.ts +97 -0
- package/src/driver/cache.ts +96 -0
- package/src/driver/compiler.ts +197 -0
- package/src/driver/index.ts +4 -0
- package/src/driver/paths.ts +24 -0
- package/src/driver/toolchain.ts +103 -0
- package/src/extensions/node.ts +23 -0
- package/src/extensions/registry.ts +101 -0
- package/src/index.ts +33 -0
- package/src/lexer/scanner.ts +650 -0
- package/src/lexer/token.ts +266 -0
- package/src/parser/parser.ts +2396 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Zy
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# xbintsc
|
|
2
|
+
|
|
3
|
+
`xbintsc` compiles a practical subset of **TypeScript directly to native binaries**.
|
|
4
|
+
It parses TypeScript itself, binds names, lowers the program to **LLVM IR text**,
|
|
5
|
+
and hands the IR to **clang**, which produces a standalone executable linked
|
|
6
|
+
against a small C runtime.
|
|
7
|
+
|
|
8
|
+
The design goals are:
|
|
9
|
+
|
|
10
|
+
1. **Incremental compilation** — builds are content-addressed and skipped when nothing changed.
|
|
11
|
+
2. **Well-factored modules** — lexer, parser, binder, codegen, driver, extensions each live in their own directory with their own tests.
|
|
12
|
+
3. **Extensive tests** — per-module unit tests plus end-to-end tests that compile and run real binaries.
|
|
13
|
+
4. **Pluggable extensions** — Node `fs`, Bun APIs, … are optional compile modules, not core code.
|
|
14
|
+
5. **Self-hosting ready** — the compiler is written in TypeScript and emits IR text, so a TypeScript rewrite can eventually compile itself.
|
|
15
|
+
6. **Multi-platform** — macOS, Linux and Windows on multiple CPUs, validated by GitHub Actions.
|
|
16
|
+
|
|
17
|
+
## How it works
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
source.ts
|
|
21
|
+
│ lexer src/lexer
|
|
22
|
+
▼
|
|
23
|
+
tokens
|
|
24
|
+
│ parser src/parser → AST (src/ast)
|
|
25
|
+
▼
|
|
26
|
+
AST
|
|
27
|
+
│ binder src/binder → scopes, symbols, closures
|
|
28
|
+
▼
|
|
29
|
+
bound AST
|
|
30
|
+
│ codegen src/codegen → LLVM IR text (src/codegen/llvm.ts)
|
|
31
|
+
▼
|
|
32
|
+
module.ll ──clang──► module.o ──link──► executable
|
|
33
|
+
▲
|
|
34
|
+
runtime/ (C runtime, NaN-boxed values)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Value model
|
|
38
|
+
|
|
39
|
+
JavaScript values are a single 64-bit word (`xt_value`). Doubles are stored
|
|
40
|
+
unboxed; everything else is a tagged pointer: a 16-bit tag in the high bits
|
|
41
|
+
plus a 48-bit payload. The representation is defined once in
|
|
42
|
+
`src/codegen/values.ts` and `runtime/rt.h`.
|
|
43
|
+
|
|
44
|
+
### Calling convention
|
|
45
|
+
|
|
46
|
+
Every compiled function uses the same ABI:
|
|
47
|
+
|
|
48
|
+
```c
|
|
49
|
+
xt_value fn(xt_value env, int32_t argc, xt_value *argv);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`env` threads captured variables (by reference, through boxes), so direct calls
|
|
53
|
+
and closure calls share one code path. JavaScript semantics that are awkward to
|
|
54
|
+
inline (`+` coercion, relational comparison, property access, inspection) are
|
|
55
|
+
delegated to `@xt_*` runtime calls.
|
|
56
|
+
|
|
57
|
+
### Runtime
|
|
58
|
+
|
|
59
|
+
`runtime/xt_runtime.c` implements strings, objects, arrays, closures, arithmetic,
|
|
60
|
+
comparison, exceptions and Node-like `console.log` inspection. It uses a bump
|
|
61
|
+
arena and never frees — garbage collection is deliberately deferred and isolated
|
|
62
|
+
behind `xt_alloc`, so it can be replaced without touching the compiler.
|
|
63
|
+
|
|
64
|
+
## Usage
|
|
65
|
+
|
|
66
|
+
There are two ways to invoke the CLI:
|
|
67
|
+
|
|
68
|
+
- **As a user** — the package is installed and the `xbintsc` command is available
|
|
69
|
+
(via the `bin` entry `./bin/xbintsc.js`).
|
|
70
|
+
- **As a developer** — running directly from a source checkout, before building.
|
|
71
|
+
|
|
72
|
+
### As a user
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# Install globally
|
|
76
|
+
npm install -g xbintsc
|
|
77
|
+
|
|
78
|
+
# ...or use it on demand without installing
|
|
79
|
+
npx xbintsc version
|
|
80
|
+
|
|
81
|
+
# Compile and run a program
|
|
82
|
+
xbintsc run examples/hello.ts
|
|
83
|
+
|
|
84
|
+
# Produce a native binary
|
|
85
|
+
xbintsc build examples/hello.ts --out build/examples
|
|
86
|
+
./build/examples/hello
|
|
87
|
+
|
|
88
|
+
# Inspect the generated LLVM IR
|
|
89
|
+
xbintsc emit examples/hello.ts | head
|
|
90
|
+
|
|
91
|
+
# Use an optional extension (here, Node's readFileSync)
|
|
92
|
+
xbintsc run examples/read-file.ts --ext node
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### As a developer (from source)
|
|
96
|
+
|
|
97
|
+
In a source checkout, run the TypeScript sources directly through `tsx` (or use
|
|
98
|
+
`npm run xbintsc`). The `bin` launcher also works here: without a `dist/` build it
|
|
99
|
+
falls back to `tsx` automatically.
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Install dependencies
|
|
103
|
+
npm install
|
|
104
|
+
|
|
105
|
+
# Compile and run a program
|
|
106
|
+
npm run xbintsc -- run examples/hello.ts
|
|
107
|
+
# equivalently
|
|
108
|
+
npx tsx src/cli/main.ts run examples/hello.ts
|
|
109
|
+
|
|
110
|
+
# Produce a native binary
|
|
111
|
+
npx tsx src/cli/main.ts build examples/hello.ts --out build/examples
|
|
112
|
+
./build/examples/hello
|
|
113
|
+
|
|
114
|
+
# Inspect the generated LLVM IR
|
|
115
|
+
npx tsx src/cli/main.ts emit examples/hello.ts | head
|
|
116
|
+
|
|
117
|
+
# Use an optional extension (here, Node's readFileSync)
|
|
118
|
+
npx tsx src/cli/main.ts run examples/read-file.ts --ext node
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
CLI options:
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
-o, --output <path> Output path
|
|
125
|
+
--out <dir> Output directory (default: build/)
|
|
126
|
+
--emit <kind> exe | obj | ir (default: exe)
|
|
127
|
+
-O0..-O3 Optimization level (default: -O2)
|
|
128
|
+
--ext <names> Comma separated extensions (e.g. node)
|
|
129
|
+
--force Ignore the incremental cache
|
|
130
|
+
--verbose Print progress information
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Programmatic API
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
import { build, compileString } from "xbintsc";
|
|
137
|
+
|
|
138
|
+
const { ir } = compileString("console.log(1 + 1);");
|
|
139
|
+
const result = build("program.ts", { emit: "exe", outDir: "build" });
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Incremental compilation
|
|
143
|
+
|
|
144
|
+
The driver keys each build on the entry source hash, compiler version, options,
|
|
145
|
+
platform and the active extension set (`src/driver/cache.ts`). If every recorded
|
|
146
|
+
output still exists, the build returns immediately. The C runtime and extension
|
|
147
|
+
sources are compiled once and cached on the same principle.
|
|
148
|
+
|
|
149
|
+
## Extensions
|
|
150
|
+
|
|
151
|
+
An extension is a plain object (`src/extensions/registry.ts`):
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
export const nodeExtension: Extension = {
|
|
155
|
+
name: "node",
|
|
156
|
+
runtimeSources: () => ["runtime/ext_node.c"],
|
|
157
|
+
builtins: () => ({ readFileSync: { symbol: "xt_node_read_text_file" } }),
|
|
158
|
+
};
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Registering it links the extra C source and makes `readFileSync(...)` resolve to
|
|
162
|
+
the C symbol with the uniform `(argc, argv)` calling convention. Builtins can be
|
|
163
|
+
added without changing the core compiler.
|
|
164
|
+
|
|
165
|
+
## Tests
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
npm run typecheck # tsc --noEmit
|
|
169
|
+
npm test # unit + end-to-end (runs real binaries when clang is present)
|
|
170
|
+
npm run test:e2e # only the compile-and-run tests
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Tests are organised by module under `tests/` (`lexer`, `parser`, `binder`,
|
|
174
|
+
`codegen`, `driver`, `extensions`, `cli`, `e2e`).
|
|
175
|
+
|
|
176
|
+
## Requirements
|
|
177
|
+
|
|
178
|
+
- Node.js 20+
|
|
179
|
+
- A `clang`-compatible C compiler on `PATH` (override with `xbintsc_CLANG`)
|
|
180
|
+
|
|
181
|
+
## Language subset
|
|
182
|
+
|
|
183
|
+
Implemented today: functions, arrow functions and closures, `let`/`const`/`var`,
|
|
184
|
+
all common operators, `if`/`while`/`do`/`for`/`for…of`/`for…in`, `break`/
|
|
185
|
+
`continue`/`return`/`throw`, objects, arrays, member/element access, assignments,
|
|
186
|
+
template literals, `console.log`, extension builtins, and the TypeScript type
|
|
187
|
+
syntax is parsed and ignored (types are erased).
|
|
188
|
+
|
|
189
|
+
Not yet implemented: classes, enums, `switch`, `try`/`catch`, `new`, `this`,
|
|
190
|
+
object spread, `async`/generators, and most standard library methods (`Array`
|
|
191
|
+
methods other than `push`, `Math`, etc.).
|
package/bin/xbintsc.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* xbintsc launcher.
|
|
4
|
+
*
|
|
5
|
+
* Prefers the compiled CLI in `dist/` (production installs run `npm run build`
|
|
6
|
+
* first). In a checkout, falls back to running the TypeScript sources through
|
|
7
|
+
* `tsx` so `npx xbintsc` works without a build step.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { existsSync } from "node:fs";
|
|
11
|
+
import { dirname, join, resolve } from "node:path";
|
|
12
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
13
|
+
import { spawnSync } from "node:child_process";
|
|
14
|
+
|
|
15
|
+
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
16
|
+
const compiled = join(root, "dist", "src", "cli", "main.js");
|
|
17
|
+
|
|
18
|
+
if (existsSync(compiled)) {
|
|
19
|
+
const { run } = await import(pathToFileURL(compiled).href);
|
|
20
|
+
process.exit(run(process.argv.slice(2)));
|
|
21
|
+
} else {
|
|
22
|
+
const tsx = join(root, "node_modules", ".bin", process.platform === "win32" ? "tsx.cmd" : "tsx");
|
|
23
|
+
const entry = join(root, "src", "cli", "main.ts");
|
|
24
|
+
const result = spawnSync(tsx, [entry, ...process.argv.slice(2)], { stdio: "inherit" });
|
|
25
|
+
process.exit(result.status ?? 1);
|
|
26
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Node, type Range } from "./nodes.js";
|
|
2
|
+
/**
|
|
3
|
+
* Small helpers used by the parser and by the code generators to build AST
|
|
4
|
+
* nodes. Keeping construction in one place means the shape of every node is
|
|
5
|
+
* defined exactly once and is easy to evolve.
|
|
6
|
+
*/
|
|
7
|
+
export declare function node<T extends Node>(value: T): T;
|
|
8
|
+
export declare function range(start: number, end: number): Range;
|
|
9
|
+
/** Concatenate the ranges of several nodes into one span. */
|
|
10
|
+
export declare function span(...nodes: (Node | Range | number | undefined)[]): Range;
|
|
11
|
+
export declare function isIdentifier(node: Node): node is import("./nodes.js").Identifier;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { SyntaxKind } from "./nodes.js";
|
|
2
|
+
/**
|
|
3
|
+
* Small helpers used by the parser and by the code generators to build AST
|
|
4
|
+
* nodes. Keeping construction in one place means the shape of every node is
|
|
5
|
+
* defined exactly once and is easy to evolve.
|
|
6
|
+
*/
|
|
7
|
+
export function node(value) {
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
export function range(start, end) {
|
|
11
|
+
return { start, end };
|
|
12
|
+
}
|
|
13
|
+
/** Concatenate the ranges of several nodes into one span. */
|
|
14
|
+
export function span(...nodes) {
|
|
15
|
+
let start = Number.POSITIVE_INFINITY;
|
|
16
|
+
let end = Number.NEGATIVE_INFINITY;
|
|
17
|
+
for (const item of nodes) {
|
|
18
|
+
if (item === undefined)
|
|
19
|
+
continue;
|
|
20
|
+
if (typeof item === "number") {
|
|
21
|
+
start = Math.min(start, item);
|
|
22
|
+
end = Math.max(end, item);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
start = Math.min(start, item.start);
|
|
26
|
+
end = Math.max(end, item.end);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (!Number.isFinite(start))
|
|
30
|
+
return { start: 0, end: 0 };
|
|
31
|
+
return { start, end };
|
|
32
|
+
}
|
|
33
|
+
export function isIdentifier(node) {
|
|
34
|
+
return node.kind === SyntaxKind.Identifier;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../../src/ast/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAyB,MAAM,YAAY,CAAC;AAE/D;;;;GAIG;AAEH,MAAM,UAAU,IAAI,CAAiB,KAAQ;IAC3C,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,KAAa,EAAE,GAAW;IAC9C,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AACxB,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,IAAI,CAAC,GAAG,KAA4C;IAClE,IAAI,KAAK,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACrC,IAAI,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACnC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QACjC,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAC9B,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YACpC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IACzD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAU;IACrC,OAAO,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,UAAU,CAAC;AAC7C,CAAC"}
|