xbintsc 0.2.9 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -2
- package/README.zh-CN.md +16 -2
- package/bin/xbintsc.js +49 -10
- package/dist/src/ast/expressions.d.ts +2 -0
- package/dist/src/binder/binder.d.ts +24 -98
- package/dist/src/binder/binder.js +13 -559
- package/dist/src/binder/binder.js.map +1 -1
- package/dist/src/binder/declarations.d.ts +16 -0
- package/dist/src/binder/declarations.js +168 -0
- package/dist/src/binder/declarations.js.map +1 -0
- package/dist/src/binder/helpers.d.ts +11 -0
- package/dist/src/binder/helpers.js +46 -0
- package/dist/src/binder/helpers.js.map +1 -0
- package/dist/src/binder/references.d.ts +21 -0
- package/dist/src/binder/references.js +349 -0
- package/dist/src/binder/references.js.map +1 -0
- package/dist/src/binder/types.d.ts +114 -0
- package/dist/src/binder/types.js +27 -0
- package/dist/src/binder/types.js.map +1 -0
- package/dist/src/cli/main.d.ts +1 -0
- package/dist/src/cli/main.js +40 -0
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/codegen/generator/calls/access.d.ts +13 -0
- package/dist/src/codegen/generator/calls/access.js +115 -0
- package/dist/src/codegen/generator/calls/access.js.map +1 -0
- package/dist/src/codegen/generator/calls/closures.d.ts +11 -0
- package/dist/src/codegen/generator/calls/closures.js +50 -0
- package/dist/src/codegen/generator/calls/closures.js.map +1 -0
- package/dist/src/codegen/generator/calls/invocation.d.ts +18 -0
- package/dist/src/codegen/generator/calls/invocation.js +242 -0
- package/dist/src/codegen/generator/calls/invocation.js.map +1 -0
- package/dist/src/codegen/generator/calls/literals.d.ts +10 -0
- package/dist/src/codegen/generator/calls/literals.js +69 -0
- package/dist/src/codegen/generator/calls/literals.js.map +1 -0
- package/dist/src/codegen/generator/calls/super.d.ts +10 -0
- package/dist/src/codegen/generator/calls/super.js +47 -0
- package/dist/src/codegen/generator/calls/super.js.map +1 -0
- package/dist/src/codegen/generator/calls.d.ts +15 -24
- package/dist/src/codegen/generator/calls.js +15 -482
- package/dist/src/codegen/generator/calls.js.map +1 -1
- package/dist/src/codegen/generator/context.d.ts +1 -1
- package/dist/src/codegen/generator/context.js +2 -2
- package/dist/src/codegen/generator/context.js.map +1 -1
- package/dist/src/codegen/generator/expressions/assignment.d.ts +13 -0
- package/dist/src/codegen/generator/expressions/assignment.js +203 -0
- package/dist/src/codegen/generator/expressions/assignment.js.map +1 -0
- package/dist/src/codegen/generator/expressions/operators.d.ts +14 -0
- package/dist/src/codegen/generator/expressions/operators.js +163 -0
- package/dist/src/codegen/generator/expressions/operators.js.map +1 -0
- package/dist/src/codegen/generator/expressions/primary.d.ts +17 -0
- package/dist/src/codegen/generator/expressions/primary.js +260 -0
- package/dist/src/codegen/generator/expressions/primary.js.map +1 -0
- package/dist/src/codegen/generator/expressions.d.ts +11 -21
- package/dist/src/codegen/generator/expressions.js +11 -494
- package/dist/src/codegen/generator/expressions.js.map +1 -1
- package/dist/src/codegen/generator/module.js +16 -4
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/state.js +8 -0
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/statements/control-flow.d.ts +14 -0
- package/dist/src/codegen/generator/statements/control-flow.js +199 -0
- package/dist/src/codegen/generator/statements/control-flow.js.map +1 -0
- package/dist/src/codegen/generator/statements/dispatch.d.ts +12 -0
- package/dist/src/codegen/generator/statements/dispatch.js +100 -0
- package/dist/src/codegen/generator/statements/dispatch.js.map +1 -0
- package/dist/src/codegen/generator/statements/loops.d.ts +13 -0
- package/dist/src/codegen/generator/statements/loops.js +152 -0
- package/dist/src/codegen/generator/statements/loops.js.map +1 -0
- package/dist/src/codegen/generator/statements/variables.d.ts +13 -0
- package/dist/src/codegen/generator/statements/variables.js +146 -0
- package/dist/src/codegen/generator/statements/variables.js.map +1 -0
- package/dist/src/codegen/generator/statements.d.ts +13 -21
- package/dist/src/codegen/generator/statements.js +13 -568
- package/dist/src/codegen/generator/statements.js.map +1 -1
- package/dist/src/codegen/generator/tables.js +7 -0
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/codegen/values.d.ts +17 -17
- package/dist/src/codegen/values.js +21 -57
- package/dist/src/codegen/values.js.map +1 -1
- package/dist/src/diagnostics/diagnostic.d.ts +1 -0
- package/dist/src/diagnostics/diagnostic.js +1 -0
- package/dist/src/diagnostics/diagnostic.js.map +1 -1
- package/dist/src/diagnostics/source.d.ts +1 -1
- package/dist/src/diagnostics/source.js +7 -12
- package/dist/src/diagnostics/source.js.map +1 -1
- package/dist/src/driver/compiler.d.ts +4 -0
- package/dist/src/driver/compiler.js +51 -16
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/index.d.ts +5 -2
- package/dist/src/driver/index.js +5 -2
- package/dist/src/driver/index.js.map +1 -1
- package/dist/src/driver/paths.d.ts +20 -0
- package/dist/src/driver/paths.js +49 -0
- package/dist/src/driver/paths.js.map +1 -1
- package/dist/src/driver/runtime-lib.d.ts +18 -0
- package/dist/src/driver/runtime-lib.js +31 -0
- package/dist/src/driver/runtime-lib.js.map +1 -0
- package/dist/src/driver/toolchain-download.d.ts +50 -0
- package/dist/src/driver/toolchain-download.js +76 -0
- package/dist/src/driver/toolchain-download.js.map +1 -0
- package/dist/src/driver/toolchain-provider.d.ts +33 -0
- package/dist/src/driver/toolchain-provider.js +71 -0
- package/dist/src/driver/toolchain-provider.js.map +1 -0
- package/dist/src/driver/toolchain.d.ts +9 -4
- package/dist/src/driver/toolchain.js +6 -10
- package/dist/src/driver/toolchain.js.map +1 -1
- package/dist/src/extensions/node/child_process/index.d.ts +4 -2
- package/dist/src/extensions/node/child_process/index.js +4 -2
- package/dist/src/extensions/node/child_process/index.js.map +1 -1
- package/dist/src/extensions/node/events/index.d.ts +10 -0
- package/dist/src/extensions/node/events/index.js +22 -0
- package/dist/src/extensions/node/events/index.js.map +1 -0
- package/dist/src/extensions/node/index.js +6 -0
- package/dist/src/extensions/node/index.js.map +1 -1
- package/dist/src/extensions/node/querystring/index.d.ts +10 -0
- package/dist/src/extensions/node/querystring/index.js +25 -0
- package/dist/src/extensions/node/querystring/index.js.map +1 -0
- package/dist/src/extensions/node/util/index.d.ts +11 -0
- package/dist/src/extensions/node/util/index.js +41 -0
- package/dist/src/extensions/node/util/index.js.map +1 -0
- package/dist/src/extensions/registry.d.ts +6 -0
- package/dist/src/extensions/registry.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/lexer/scanner/identifiers.d.ts +9 -0
- package/dist/src/lexer/scanner/identifiers.js +33 -0
- package/dist/src/lexer/scanner/identifiers.js.map +1 -0
- package/dist/src/lexer/scanner/numbers.d.ts +10 -0
- package/dist/src/lexer/scanner/numbers.js +89 -0
- package/dist/src/lexer/scanner/numbers.js.map +1 -0
- package/dist/src/lexer/scanner/punctuation.d.ts +9 -0
- package/dist/src/lexer/scanner/punctuation.js +151 -0
- package/dist/src/lexer/scanner/punctuation.js.map +1 -0
- package/dist/src/lexer/scanner/regex.d.ts +11 -0
- package/dist/src/lexer/scanner/regex.js +69 -0
- package/dist/src/lexer/scanner/regex.js.map +1 -0
- package/dist/src/lexer/scanner/strings.d.ts +13 -0
- package/dist/src/lexer/scanner/strings.js +118 -0
- package/dist/src/lexer/scanner/strings.js.map +1 -0
- package/dist/src/lexer/scanner.d.ts +20 -27
- package/dist/src/lexer/scanner.js +11 -415
- package/dist/src/lexer/scanner.js.map +1 -1
- package/dist/src/parser/declarations/classes.d.ts +14 -0
- package/dist/src/parser/declarations/classes.js +191 -0
- package/dist/src/parser/declarations/classes.js.map +1 -0
- package/dist/src/parser/declarations/functions.d.ts +17 -0
- package/dist/src/parser/declarations/functions.js +241 -0
- package/dist/src/parser/declarations/functions.js.map +1 -0
- package/dist/src/parser/declarations/type-members.d.ts +16 -0
- package/dist/src/parser/declarations/type-members.js +156 -0
- package/dist/src/parser/declarations/type-members.js.map +1 -0
- package/dist/src/parser/declarations.d.ts +13 -24
- package/dist/src/parser/declarations.js +13 -571
- package/dist/src/parser/declarations.js.map +1 -1
- package/dist/src/parser/helpers.js +13 -4
- package/dist/src/parser/helpers.js.map +1 -1
- package/dist/src/parser/literals.js +10 -1
- package/dist/src/parser/literals.js.map +1 -1
- package/dist/tests/codegen/llvm.test.js +24 -0
- package/dist/tests/codegen/llvm.test.js.map +1 -1
- package/dist/tests/driver/compiler.test.js +3 -0
- package/dist/tests/driver/compiler.test.js.map +1 -1
- package/dist/tests/driver/paths.test.d.ts +1 -0
- package/dist/tests/driver/paths.test.js +26 -0
- package/dist/tests/driver/paths.test.js.map +1 -0
- package/dist/tests/driver/toolchain-download.test.d.ts +1 -0
- package/dist/tests/driver/toolchain-download.test.js +38 -0
- package/dist/tests/driver/toolchain-download.test.js.map +1 -0
- package/dist/tests/driver/toolchain-provider.test.d.ts +1 -0
- package/dist/tests/driver/toolchain-provider.test.js +37 -0
- package/dist/tests/driver/toolchain-provider.test.js.map +1 -0
- package/dist/tests/e2e/compile-node.test.d.ts +7 -0
- package/dist/tests/e2e/compile-node.test.js +123 -0
- package/dist/tests/e2e/compile-node.test.js.map +1 -0
- package/dist/tests/e2e/compile.test.d.ts +4 -1
- package/dist/tests/e2e/compile.test.js +78 -130
- package/dist/tests/e2e/compile.test.js.map +1 -1
- package/dist/tests/e2e/harness.d.ts +36 -0
- package/dist/tests/e2e/harness.js +64 -0
- package/dist/tests/e2e/harness.js.map +1 -0
- package/dist/tests/e2e/node-modules.test.js +60 -0
- package/dist/tests/e2e/node-modules.test.js.map +1 -1
- package/dist/tests/extensions/registry.test.js +4 -0
- package/dist/tests/extensions/registry.test.js.map +1 -1
- package/package.json +5 -3
- package/runtime/ext_node/buffer/buffer.c +12 -552
- package/runtime/ext_node/buffer/parts/byte-access.inc +35 -0
- package/runtime/ext_node/buffer/parts/construction.inc +60 -0
- package/runtime/ext_node/buffer/parts/integer-io.inc +119 -0
- package/runtime/ext_node/buffer/parts/methods.inc +135 -0
- package/runtime/ext_node/buffer/parts/prototype.inc +54 -0
- package/runtime/ext_node/buffer/parts/search.inc +86 -0
- package/runtime/ext_node/buffer/parts/static-api.inc +58 -0
- package/runtime/ext_node/child_process/child_process.c +37 -3
- package/runtime/ext_node/events/events.c +285 -0
- package/runtime/ext_node/http/http.c +11 -736
- package/runtime/ext_node/http/parts/client.inc +290 -0
- package/runtime/ext_node/http/parts/helpers.inc +45 -0
- package/runtime/ext_node/http/parts/prototypes.inc +57 -0
- package/runtime/ext_node/http/parts/response.inc +149 -0
- package/runtime/ext_node/http/parts/server.inc +133 -0
- package/runtime/ext_node/http/parts/string-builder.inc +58 -0
- package/runtime/ext_node/net/net.c +12 -504
- package/runtime/ext_node/net/parts/construction.inc +22 -0
- package/runtime/ext_node/net/parts/platform.inc +60 -0
- package/runtime/ext_node/net/parts/prototypes.inc +35 -0
- package/runtime/ext_node/net/parts/read-loop.inc +58 -0
- package/runtime/ext_node/net/parts/server.inc +131 -0
- package/runtime/ext_node/net/parts/socket-methods.inc +100 -0
- package/runtime/ext_node/net/parts/static-api.inc +93 -0
- package/runtime/ext_node/querystring/querystring.c +251 -0
- package/runtime/ext_node/util/util.c +456 -0
- package/runtime/rt.h +8 -2
- package/runtime/rt_internal.h +34 -0
- package/runtime/xt_bigint/arithmetic.inc +135 -0
- package/runtime/xt_bigint/bits.inc +98 -0
- package/runtime/xt_bigint/bitwise.inc +103 -0
- package/runtime/xt_bigint/compare.inc +30 -0
- package/runtime/xt_bigint/conversions.inc +51 -0
- package/runtime/xt_bigint/division.inc +85 -0
- package/runtime/xt_bigint/format.inc +145 -0
- package/runtime/xt_bigint/helpers.inc +92 -0
- package/runtime/xt_bigint/magnitude.inc +88 -0
- package/runtime/xt_bigint/public.inc +59 -0
- package/runtime/xt_bigint/small-arithmetic.inc +58 -0
- package/runtime/xt_bigint.c +42 -0
- package/runtime/xt_builtins.c +1 -0
- package/runtime/xt_io.c +7 -0
- package/runtime/xt_stdlib/arrays.inc +161 -0
- package/runtime/xt_stdlib/dispatch.inc +116 -0
- package/runtime/xt_stdlib/helpers.inc +23 -0
- package/runtime/xt_stdlib/math.inc +72 -0
- package/runtime/xt_stdlib/strings.inc +178 -0
- package/runtime/xt_stdlib.c +10 -549
- package/runtime/xt_stdlib2/array-statics.inc +37 -0
- package/runtime/xt_stdlib2/arrays.inc +189 -0
- package/runtime/xt_stdlib2/container.inc +23 -0
- package/runtime/xt_stdlib2/date.inc +72 -0
- package/runtime/xt_stdlib2/error.inc +22 -0
- package/runtime/xt_stdlib2/helpers.inc +43 -0
- package/runtime/xt_stdlib2/json.inc +213 -0
- package/runtime/xt_stdlib2/map.inc +95 -0
- package/runtime/xt_stdlib2/number-string-statics.inc +73 -0
- package/runtime/xt_stdlib2/numbers.inc +38 -0
- package/runtime/xt_stdlib2/objects.inc +41 -0
- package/runtime/xt_stdlib2/regexp-match.inc +204 -0
- package/runtime/xt_stdlib2/regexp.inc +20 -0
- package/runtime/xt_stdlib2/set.inc +105 -0
- package/runtime/xt_stdlib2/strings.inc +94 -0
- package/runtime/xt_stdlib2.c +19 -1278
- package/runtime/xt_values.c +155 -12
- package/scripts/build-runtime.ts +109 -0
- package/scripts/fetch-toolchain.ts +101 -0
- package/scripts/package-release.ts +192 -0
- package/src/ast/expressions.ts +2 -0
- package/src/binder/binder.ts +40 -725
- package/src/binder/declarations.ts +203 -0
- package/src/binder/helpers.ts +47 -0
- package/src/binder/references.ts +410 -0
- package/src/binder/types.ts +134 -0
- package/src/cli/main.ts +43 -0
- package/src/codegen/generator/calls/access.ts +139 -0
- package/src/codegen/generator/calls/closures.ts +60 -0
- package/src/codegen/generator/calls/invocation.ts +282 -0
- package/src/codegen/generator/calls/literals.ts +77 -0
- package/src/codegen/generator/calls/super.ts +61 -0
- package/src/codegen/generator/calls.ts +30 -552
- package/src/codegen/generator/context.ts +2 -2
- package/src/codegen/generator/expressions/assignment.ts +226 -0
- package/src/codegen/generator/expressions/operators.ts +182 -0
- package/src/codegen/generator/expressions/primary.ts +304 -0
- package/src/codegen/generator/expressions.ts +22 -553
- package/src/codegen/generator/module.ts +14 -4
- package/src/codegen/generator/state.ts +8 -0
- package/src/codegen/generator/statements/control-flow.ts +225 -0
- package/src/codegen/generator/statements/dispatch.ts +122 -0
- package/src/codegen/generator/statements/loops.ts +173 -0
- package/src/codegen/generator/statements/variables.ts +152 -0
- package/src/codegen/generator/statements.ts +26 -612
- package/src/codegen/generator/tables.ts +7 -0
- package/src/codegen/values.ts +22 -57
- package/src/diagnostics/diagnostic.ts +1 -0
- package/src/diagnostics/source.ts +7 -12
- package/src/driver/compiler.ts +61 -18
- package/src/driver/index.ts +17 -2
- package/src/driver/paths.ts +54 -0
- package/src/driver/runtime-lib.ts +32 -0
- package/src/driver/toolchain-download.ts +108 -0
- package/src/driver/toolchain-provider.ts +91 -0
- package/src/driver/toolchain.ts +29 -11
- package/src/extensions/node/child_process/index.ts +4 -2
- package/src/extensions/node/events/index.ts +27 -0
- package/src/extensions/node/index.ts +6 -0
- package/src/extensions/node/querystring/index.ts +29 -0
- package/src/extensions/node/util/index.ts +48 -0
- package/src/extensions/registry.ts +6 -0
- package/src/index.ts +1 -0
- package/src/lexer/scanner/identifiers.ts +37 -0
- package/src/lexer/scanner/numbers.ts +84 -0
- package/src/lexer/scanner/punctuation.ts +132 -0
- package/src/lexer/scanner/regex.ts +79 -0
- package/src/lexer/scanner/strings.ts +128 -0
- package/src/lexer/scanner.ts +35 -401
- package/src/parser/declarations/classes.ts +215 -0
- package/src/parser/declarations/functions.ts +254 -0
- package/src/parser/declarations/type-members.ts +181 -0
- package/src/parser/declarations.ts +32 -609
- package/src/parser/helpers.ts +13 -6
- package/src/parser/literals.ts +10 -1
- package/scripts/build-runtime.mjs +0 -55
|
@@ -1,556 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Expression lowering:
|
|
3
|
-
*
|
|
2
|
+
* Expression lowering: aggregates the primary, operator and assignment method
|
|
3
|
+
* groups into the `ExpressionMethods` mixin consumed by the generator.
|
|
4
|
+
*
|
|
5
|
+
* The implementation is split by functional area under `expressions/`:
|
|
6
|
+
* - `primary` — dispatcher, identifiers, `this`/`new`/`await`, templates
|
|
7
|
+
* - `operators` — binary/short-circuit/conditional/unary operators
|
|
8
|
+
* - `assignment` — assignments and destructuring targets
|
|
4
9
|
*/
|
|
5
10
|
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
type ObjectLiteralExpression,
|
|
22
|
-
type PostfixUnaryExpression,
|
|
23
|
-
type PrefixUnaryExpression,
|
|
24
|
-
type PropertyAccessExpression,
|
|
25
|
-
type TemplateLiteral,
|
|
26
|
-
} from "../../ast/nodes.js";
|
|
27
|
-
import {
|
|
28
|
-
AssignmentOperator,
|
|
29
|
-
BinaryOperator,
|
|
30
|
-
PrefixUnaryOperator,
|
|
31
|
-
PostfixUnaryOperator,
|
|
32
|
-
} from "../../ast/nodes.js";
|
|
33
|
-
import { SymbolKind, type SymbolInfo } from "../../binder/binder.js";
|
|
34
|
-
import { DiagnosticCode } from "../../diagnostics/diagnostic.js";
|
|
35
|
-
import { i64, numberLiteral, XT_FALSE, XT_NULL, XT_TRUE, XT_UNDEFINED } from "../values.js";
|
|
36
|
-
import { BINARY_RUNTIME, compoundToBinary, isAssignmentOperator, BUILTIN_FUNCTION_VALUES, CTOR_FUNCTIONS } from "./tables.js";
|
|
37
|
-
import type { Generator } from "./generator.js";
|
|
38
|
-
|
|
39
|
-
export interface ExpressionMethods {
|
|
40
|
-
emitExpression(this: Generator, node: Expression): string;
|
|
41
|
-
emitIdentifier(this: Generator, identifier: Identifier): string;
|
|
42
|
-
emitFunctionValue(this: Generator, symbol: SymbolInfo): string;
|
|
43
|
-
emitTemplate(this: Generator, node: TemplateLiteral): string;
|
|
44
|
-
emitBinaryOrAssignment(this: Generator, node: BinaryExpression): string;
|
|
45
|
-
emitShortCircuit(this: Generator, node: BinaryExpression, kind: "and" | "or" | "nullish"): string;
|
|
46
|
-
emitConditional(this: Generator, node: ConditionalExpression): string;
|
|
47
|
-
emitPrefix(this: Generator, node: PrefixUnaryExpression): string;
|
|
48
|
-
emitPostfix(this: Generator, node: PostfixUnaryExpression): string;
|
|
49
|
-
emitAssignment(this: Generator, node: BinaryExpression): string;
|
|
50
|
-
emitLogicalAssignment(this: Generator, node: BinaryExpression): string;
|
|
51
|
-
emitAssignmentTarget(this: Generator, target: Expression, value: string): void;
|
|
52
|
-
emitThis(this: Generator): string;
|
|
53
|
-
emitNew(this: Generator, node: NewExpression): string;
|
|
54
|
-
emitAwait(this: Generator, node: AwaitExpression): string;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export const expressionMethods: ExpressionMethods = {
|
|
58
|
-
emitExpression(node: Expression): string {
|
|
59
|
-
switch (node.kind) {
|
|
60
|
-
case SyntaxKind.Identifier:
|
|
61
|
-
return this.emitIdentifier(node as Identifier);
|
|
62
|
-
case SyntaxKind.NumericLiteral: {
|
|
63
|
-
const value = (node as { value: number }).value;
|
|
64
|
-
return numberLiteral(value);
|
|
65
|
-
}
|
|
66
|
-
case SyntaxKind.BigIntLiteral:
|
|
67
|
-
return numberLiteral((node as { value: number }).value);
|
|
68
|
-
case SyntaxKind.StringLiteral:
|
|
69
|
-
return this.stringValue((node as { value: string }).value);
|
|
70
|
-
case SyntaxKind.NoSubstitutionTemplateLiteral:
|
|
71
|
-
return this.stringValue((node as { value: string }).value);
|
|
72
|
-
case SyntaxKind.RegularExpressionLiteral: {
|
|
73
|
-
const regex = node as { pattern: string; flags: string };
|
|
74
|
-
const pattern = this.stringValue(regex.pattern);
|
|
75
|
-
const flags = this.stringValue(regex.flags);
|
|
76
|
-
const ptr = `%regex${this.current.allocas.length}`;
|
|
77
|
-
this.current.allocas.push(`${ptr} = alloca i64, i32 2`);
|
|
78
|
-
const slot0 = this.reg();
|
|
79
|
-
this.emit(` ${slot0} = getelementptr i64, i64* ${ptr}, i32 0`);
|
|
80
|
-
this.emit(` store i64 ${pattern}, i64* ${slot0}`);
|
|
81
|
-
const slot1 = this.reg();
|
|
82
|
-
this.emit(` ${slot1} = getelementptr i64, i64* ${ptr}, i32 1`);
|
|
83
|
-
this.emit(` store i64 ${flags}, i64* ${slot1}`);
|
|
84
|
-
const result = this.reg();
|
|
85
|
-
this.emit(` ${result} = call i64 @xt_regexp_ctor(i32 2, i64* ${ptr})`);
|
|
86
|
-
return result;
|
|
87
|
-
}
|
|
88
|
-
case SyntaxKind.TemplateLiteral:
|
|
89
|
-
return this.emitTemplate(node as TemplateLiteral);
|
|
90
|
-
case SyntaxKind.TrueKeyword:
|
|
91
|
-
return i64(XT_TRUE);
|
|
92
|
-
case SyntaxKind.FalseKeyword:
|
|
93
|
-
return i64(XT_FALSE);
|
|
94
|
-
case SyntaxKind.NullKeyword:
|
|
95
|
-
return i64(XT_NULL);
|
|
96
|
-
case SyntaxKind.UndefinedKeyword:
|
|
97
|
-
return i64(XT_UNDEFINED);
|
|
98
|
-
case SyntaxKind.ParenthesizedExpression:
|
|
99
|
-
return this.emitExpression((node as { expression: Expression }).expression);
|
|
100
|
-
case SyntaxKind.AsExpression:
|
|
101
|
-
case SyntaxKind.SatisfiesExpression:
|
|
102
|
-
case SyntaxKind.NonNullExpression:
|
|
103
|
-
return this.emitExpression((node as { expression: Expression }).expression);
|
|
104
|
-
case SyntaxKind.DeleteExpression:
|
|
105
|
-
return this.emitDelete(node as DeleteExpression);
|
|
106
|
-
case SyntaxKind.TypeOfExpression: {
|
|
107
|
-
const operand = this.emitExpression((node as { expression: Expression }).expression);
|
|
108
|
-
const result = this.reg();
|
|
109
|
-
this.emit(` ${result} = call i64 @xt_typeof(i64 ${operand})`);
|
|
110
|
-
return result;
|
|
111
|
-
}
|
|
112
|
-
case SyntaxKind.VoidExpression:
|
|
113
|
-
this.emitExpression((node as { expression: Expression }).expression);
|
|
114
|
-
return i64(XT_UNDEFINED);
|
|
115
|
-
case SyntaxKind.ThisKeyword:
|
|
116
|
-
return this.emitThis();
|
|
117
|
-
case SyntaxKind.NewExpression:
|
|
118
|
-
return this.emitNew(node as NewExpression);
|
|
119
|
-
case SyntaxKind.AwaitExpression:
|
|
120
|
-
return this.emitAwait(node as AwaitExpression);
|
|
121
|
-
case SyntaxKind.ClassExpression: {
|
|
122
|
-
const info = this.binding.classOfNode.get(node);
|
|
123
|
-
if (!info) {
|
|
124
|
-
this.unsupported(node, "class expression");
|
|
125
|
-
return i64(XT_UNDEFINED);
|
|
126
|
-
}
|
|
127
|
-
this.emitClassSetup(info);
|
|
128
|
-
return this.emitClassReference(info);
|
|
129
|
-
}
|
|
130
|
-
case SyntaxKind.BinaryExpression:
|
|
131
|
-
return this.emitBinaryOrAssignment(node as BinaryExpression);
|
|
132
|
-
case SyntaxKind.PrefixUnaryExpression:
|
|
133
|
-
return this.emitPrefix(node as PrefixUnaryExpression);
|
|
134
|
-
case SyntaxKind.PostfixUnaryExpression:
|
|
135
|
-
return this.emitPostfix(node as PostfixUnaryExpression);
|
|
136
|
-
case SyntaxKind.ConditionalExpression:
|
|
137
|
-
return this.emitConditional(node as ConditionalExpression);
|
|
138
|
-
case SyntaxKind.CallExpression:
|
|
139
|
-
return this.emitCall(node as CallExpression);
|
|
140
|
-
case SyntaxKind.PropertyAccessExpression:
|
|
141
|
-
return this.emitPropertyAccess(node as PropertyAccessExpression);
|
|
142
|
-
case SyntaxKind.ElementAccessExpression:
|
|
143
|
-
return this.emitElementAccess(node as ElementAccessExpression);
|
|
144
|
-
case SyntaxKind.ArrayLiteralExpression:
|
|
145
|
-
return this.emitArrayLiteral(node as ArrayLiteralExpression);
|
|
146
|
-
case SyntaxKind.ObjectLiteralExpression:
|
|
147
|
-
return this.emitObjectLiteral(node as ObjectLiteralExpression);
|
|
148
|
-
case SyntaxKind.ArrowFunction:
|
|
149
|
-
case SyntaxKind.FunctionExpression:
|
|
150
|
-
return this.emitClosure(node as ArrowFunction | FunctionExpression);
|
|
151
|
-
default:
|
|
152
|
-
this.unsupported(node, "expression");
|
|
153
|
-
return i64(XT_UNDEFINED);
|
|
154
|
-
}
|
|
155
|
-
},
|
|
156
|
-
|
|
157
|
-
emitIdentifier(identifier: Identifier): string {
|
|
158
|
-
const symbol = this.binding.symbolOfIdentifier.get(identifier);
|
|
159
|
-
if (symbol) {
|
|
160
|
-
if (symbol.kind === SymbolKind.Class) {
|
|
161
|
-
const declaration = symbol.declarations[0];
|
|
162
|
-
const info = declaration ? this.binding.classOfNode.get(declaration) : undefined;
|
|
163
|
-
if (info) return this.emitClassReference(info);
|
|
164
|
-
}
|
|
165
|
-
if (symbol.kind === SymbolKind.Function && !this.current.slots.has(symbol.id)) {
|
|
166
|
-
return this.emitFunctionValue(symbol);
|
|
167
|
-
}
|
|
168
|
-
if (symbol.kind === SymbolKind.Import) {
|
|
169
|
-
// Imported runtime bindings have no first-class value: they are meant
|
|
170
|
-
// to be called (`readFileSync(...)`) or used as a namespace
|
|
171
|
-
// (`path.join(...)`), both handled before identifier lowering.
|
|
172
|
-
this.diagnostics.error(
|
|
173
|
-
DiagnosticCode.CodegenError,
|
|
174
|
-
`Imported binding '${identifier.text}' cannot be used as a value`,
|
|
175
|
-
identifier,
|
|
176
|
-
this.sourceFile.fileName,
|
|
177
|
-
);
|
|
178
|
-
return i64(XT_UNDEFINED);
|
|
179
|
-
}
|
|
180
|
-
return this.readSlot(symbol);
|
|
181
|
-
}
|
|
182
|
-
switch (identifier.text) {
|
|
183
|
-
case "undefined":
|
|
184
|
-
return i64(XT_UNDEFINED);
|
|
185
|
-
case "NaN":
|
|
186
|
-
return numberLiteral(NaN);
|
|
187
|
-
case "Infinity":
|
|
188
|
-
return numberLiteral(Infinity);
|
|
189
|
-
case "console":
|
|
190
|
-
return i64(XT_UNDEFINED);
|
|
191
|
-
case "arguments": {
|
|
192
|
-
const argc = this.reg();
|
|
193
|
-
this.emit(` ${argc} = load i32, i32* %saved.argc`);
|
|
194
|
-
const argv = this.reg();
|
|
195
|
-
this.emit(` ${argv} = load i64*, i64** %saved.argv`);
|
|
196
|
-
const rest = this.reg();
|
|
197
|
-
this.emit(` ${rest} = call i64 @xt_rest_args(i32 ${argc}, i64* ${argv}, i32 0)`);
|
|
198
|
-
return rest;
|
|
199
|
-
}
|
|
200
|
-
default: {
|
|
201
|
-
const builtinValue = BUILTIN_FUNCTION_VALUES[identifier.text];
|
|
202
|
-
if (builtinValue) {
|
|
203
|
-
// A global like `Boolean` used as a value (`arr.filter(Boolean)`):
|
|
204
|
-
// wrap its runtime trampoline in a closure object.
|
|
205
|
-
const cast = this.reg();
|
|
206
|
-
this.emit(` ${cast} = bitcast i64 (i64, i64, i32, i64*)* @${builtinValue} to i8*`);
|
|
207
|
-
const closure = this.reg();
|
|
208
|
-
this.emit(` ${closure} = call i64 @xt_closure_new(i8* ${cast}, i32 0, i64* null)`);
|
|
209
|
-
return closure;
|
|
210
|
-
}
|
|
211
|
-
this.diagnostics.error(
|
|
212
|
-
DiagnosticCode.CannotFindName,
|
|
213
|
-
`Cannot find name '${identifier.text}'`,
|
|
214
|
-
identifier,
|
|
215
|
-
this.sourceFile.fileName,
|
|
216
|
-
);
|
|
217
|
-
return i64(XT_UNDEFINED);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
},
|
|
221
|
-
|
|
222
|
-
emitFunctionValue(symbol: SymbolInfo): string {
|
|
223
|
-
const declaration = symbol.declarations[0];
|
|
224
|
-
const fn = declaration ? this.binding.functionOfNode.get(declaration) : undefined;
|
|
225
|
-
if (!fn) return i64(XT_UNDEFINED);
|
|
226
|
-
const cast = this.reg();
|
|
227
|
-
this.emit(` ${cast} = bitcast i64 (i64, i64, i32, i64*)* @${this.functionName(fn)} to i8*`);
|
|
228
|
-
const closure = this.reg();
|
|
229
|
-
this.emit(` ${closure} = call i64 @xt_closure_new(i8* ${cast}, i32 0, i64* null)`);
|
|
230
|
-
return closure;
|
|
231
|
-
},
|
|
232
|
-
|
|
233
|
-
emitThis(): string {
|
|
234
|
-
if (!this.current.thisPtr) return i64(XT_UNDEFINED);
|
|
235
|
-
const value = this.reg();
|
|
236
|
-
this.emit(` ${value} = load i64, i64* ${this.current.thisPtr}`);
|
|
237
|
-
return value;
|
|
238
|
-
},
|
|
239
|
-
|
|
240
|
-
emitAwait(node: AwaitExpression): string {
|
|
241
|
-
const value = this.emitExpression(node.expression);
|
|
242
|
-
const result = this.reg();
|
|
243
|
-
this.emit(` ${result} = call i64 @xt_await(i64 ${value})`);
|
|
244
|
-
return result;
|
|
245
|
-
},
|
|
246
|
-
|
|
247
|
-
emitNew(node: NewExpression): string {
|
|
248
|
-
const callee = node.expression;
|
|
249
|
-
if (callee.kind === SyntaxKind.Identifier) {
|
|
250
|
-
const identifier = callee as Identifier;
|
|
251
|
-
const symbol = this.binding.symbolOfIdentifier.get(identifier);
|
|
252
|
-
if (symbol && symbol.kind === SymbolKind.Class) {
|
|
253
|
-
const declaration = symbol.declarations[0];
|
|
254
|
-
const info = declaration ? this.binding.classOfNode.get(declaration) : undefined;
|
|
255
|
-
if (info) {
|
|
256
|
-
const ctor = this.emitClassReference(info);
|
|
257
|
-
const args = this.emitArguments(node.arguments);
|
|
258
|
-
const result = this.reg();
|
|
259
|
-
this.emit(` ${result} = call i64 @xt_new(i64 ${ctor}, i32 ${args.argc}, i64* ${args.ptr})`);
|
|
260
|
-
return result;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
if (!symbol) {
|
|
264
|
-
const ctor = CTOR_FUNCTIONS[identifier.text];
|
|
265
|
-
if (ctor) {
|
|
266
|
-
const args = this.emitArguments(node.arguments);
|
|
267
|
-
const result = this.reg();
|
|
268
|
-
this.emit(` ${result} = call i64 @${ctor}(i32 ${args.argc}, i64* ${args.ptr})`);
|
|
269
|
-
return result;
|
|
270
|
-
}
|
|
271
|
-
if (identifier.text === "Object") {
|
|
272
|
-
if (node.arguments.length > 0) return this.emitExpression(node.arguments[0]!);
|
|
273
|
-
return this.runtimeCall("xt_object_new", []);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
const ctorValue = this.emitExpression(callee);
|
|
278
|
-
const args = this.emitArguments(node.arguments);
|
|
279
|
-
const result = this.reg();
|
|
280
|
-
this.emit(` ${result} = call i64 @xt_new(i64 ${ctorValue}, i32 ${args.argc}, i64* ${args.ptr})`);
|
|
281
|
-
return result;
|
|
282
|
-
},
|
|
283
|
-
|
|
284
|
-
emitTemplate(node: TemplateLiteral): string {
|
|
285
|
-
let accumulator = this.stringValue(node.head);
|
|
286
|
-
for (const span of node.spans) {
|
|
287
|
-
const expression = this.emitExpression(span.expression);
|
|
288
|
-
const text = this.reg();
|
|
289
|
-
this.emit(` ${text} = call i64 @xt_to_string(i64 ${expression})`);
|
|
290
|
-
const joined = this.reg();
|
|
291
|
-
this.emit(` ${joined} = call i64 @xt_add(i64 ${accumulator}, i64 ${text})`);
|
|
292
|
-
accumulator = joined;
|
|
293
|
-
if (span.literal.length > 0) {
|
|
294
|
-
const literal = this.stringValue(span.literal);
|
|
295
|
-
const withLiteral = this.reg();
|
|
296
|
-
this.emit(` ${withLiteral} = call i64 @xt_add(i64 ${accumulator}, i64 ${literal})`);
|
|
297
|
-
accumulator = withLiteral;
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
return accumulator;
|
|
301
|
-
},
|
|
302
|
-
|
|
303
|
-
emitBinaryOrAssignment(node: BinaryExpression): string {
|
|
304
|
-
const operator = node.operator as string;
|
|
305
|
-
if (isAssignmentOperator(operator)) {
|
|
306
|
-
return this.emitAssignment(node);
|
|
307
|
-
}
|
|
308
|
-
switch (operator) {
|
|
309
|
-
case BinaryOperator.AmpersandAmpersand:
|
|
310
|
-
return this.emitShortCircuit(node, "and");
|
|
311
|
-
case BinaryOperator.BarBar:
|
|
312
|
-
return this.emitShortCircuit(node, "or");
|
|
313
|
-
case BinaryOperator.QuestionQuestion:
|
|
314
|
-
return this.emitShortCircuit(node, "nullish");
|
|
315
|
-
case BinaryOperator.Comma: {
|
|
316
|
-
this.emitExpression(node.left);
|
|
317
|
-
return this.emitExpression(node.right);
|
|
318
|
-
}
|
|
319
|
-
default:
|
|
320
|
-
break;
|
|
321
|
-
}
|
|
322
|
-
const left = this.emitExpression(node.left);
|
|
323
|
-
const right = this.emitExpression(node.right);
|
|
324
|
-
const runtime = BINARY_RUNTIME[operator];
|
|
325
|
-
if (!runtime) {
|
|
326
|
-
this.unsupported(node, `operator '${operator}'`);
|
|
327
|
-
return i64(XT_UNDEFINED);
|
|
328
|
-
}
|
|
329
|
-
const result = this.reg();
|
|
330
|
-
this.emit(` ${result} = call i64 @${runtime}(i64 ${left}, i64 ${right})`);
|
|
331
|
-
return result;
|
|
332
|
-
},
|
|
333
|
-
|
|
334
|
-
emitShortCircuit(node: BinaryExpression, kind: "and" | "or" | "nullish"): string {
|
|
335
|
-
const result = this.alloca();
|
|
336
|
-
const left = this.emitExpression(node.left);
|
|
337
|
-
this.emit(` store i64 ${left}, i64* ${result}`);
|
|
338
|
-
const rightLabel = this.label("sc.right");
|
|
339
|
-
const endLabel = this.label("sc.end");
|
|
340
|
-
let condition: string;
|
|
341
|
-
if (kind === "and") {
|
|
342
|
-
const truthy = this.reg();
|
|
343
|
-
this.emit(` ${truthy} = call i32 @xt_truthy(i64 ${left})`);
|
|
344
|
-
condition = this.reg();
|
|
345
|
-
this.emit(` ${condition} = icmp ne i32 ${truthy}, 0`);
|
|
346
|
-
} else if (kind === "or") {
|
|
347
|
-
const truthy = this.reg();
|
|
348
|
-
this.emit(` ${truthy} = call i32 @xt_truthy(i64 ${left})`);
|
|
349
|
-
const isTruthy = this.reg();
|
|
350
|
-
this.emit(` ${isTruthy} = icmp ne i32 ${truthy}, 0`);
|
|
351
|
-
condition = this.reg();
|
|
352
|
-
this.emit(` ${condition} = xor i1 ${isTruthy}, true`);
|
|
353
|
-
} else {
|
|
354
|
-
const nullish = this.reg();
|
|
355
|
-
this.emit(` ${nullish} = call i64 @xt_is_nullish(i64 ${left})`);
|
|
356
|
-
const truthy = this.reg();
|
|
357
|
-
this.emit(` ${truthy} = call i32 @xt_truthy(i64 ${nullish})`);
|
|
358
|
-
condition = this.reg();
|
|
359
|
-
this.emit(` ${condition} = icmp ne i32 ${truthy}, 0`);
|
|
360
|
-
}
|
|
361
|
-
this.terminate(`br i1 ${condition}, label %${rightLabel}, label %${endLabel}`);
|
|
362
|
-
this.startBlock(rightLabel);
|
|
363
|
-
const right = this.emitExpression(node.right);
|
|
364
|
-
this.emit(` store i64 ${right}, i64* ${result}`);
|
|
365
|
-
this.terminate(`br label %${endLabel}`);
|
|
366
|
-
this.startBlock(endLabel);
|
|
367
|
-
const value = this.reg();
|
|
368
|
-
this.emit(` ${value} = load i64, i64* ${result}`);
|
|
369
|
-
return value;
|
|
370
|
-
},
|
|
371
|
-
|
|
372
|
-
emitConditional(node: ConditionalExpression): string {
|
|
373
|
-
const result = this.alloca();
|
|
374
|
-
const condition = this.emitExpression(node.condition);
|
|
375
|
-
const truthy = this.reg();
|
|
376
|
-
this.emit(` ${truthy} = call i32 @xt_truthy(i64 ${condition})`);
|
|
377
|
-
const nonzero = this.reg();
|
|
378
|
-
this.emit(` ${nonzero} = icmp ne i32 ${truthy}, 0`);
|
|
379
|
-
const trueLabel = this.label("cond.true");
|
|
380
|
-
const falseLabel = this.label("cond.false");
|
|
381
|
-
const endLabel = this.label("cond.end");
|
|
382
|
-
this.terminate(`br i1 ${nonzero}, label %${trueLabel}, label %${falseLabel}`);
|
|
383
|
-
this.startBlock(trueLabel);
|
|
384
|
-
const whenTrue = this.emitExpression(node.whenTrue);
|
|
385
|
-
this.emit(` store i64 ${whenTrue}, i64* ${result}`);
|
|
386
|
-
this.terminate(`br label %${endLabel}`);
|
|
387
|
-
this.startBlock(falseLabel);
|
|
388
|
-
const whenFalse = this.emitExpression(node.whenFalse);
|
|
389
|
-
this.emit(` store i64 ${whenFalse}, i64* ${result}`);
|
|
390
|
-
this.terminate(`br label %${endLabel}`);
|
|
391
|
-
this.startBlock(endLabel);
|
|
392
|
-
const value = this.reg();
|
|
393
|
-
this.emit(` ${value} = load i64, i64* ${result}`);
|
|
394
|
-
return value;
|
|
395
|
-
},
|
|
396
|
-
|
|
397
|
-
emitPrefix(node: PrefixUnaryExpression): string {
|
|
398
|
-
switch (node.operator) {
|
|
399
|
-
case PrefixUnaryOperator.Minus: {
|
|
400
|
-
const operand = this.emitExpression(node.operand);
|
|
401
|
-
const result = this.reg();
|
|
402
|
-
this.emit(` ${result} = call i64 @xt_neg(i64 ${operand})`);
|
|
403
|
-
return result;
|
|
404
|
-
}
|
|
405
|
-
case PrefixUnaryOperator.Plus: {
|
|
406
|
-
const operand = this.emitExpression(node.operand);
|
|
407
|
-
const result = this.reg();
|
|
408
|
-
this.emit(` ${result} = call i64 @xt_pos(i64 ${operand})`);
|
|
409
|
-
return result;
|
|
410
|
-
}
|
|
411
|
-
case PrefixUnaryOperator.Exclamation: {
|
|
412
|
-
const operand = this.emitExpression(node.operand);
|
|
413
|
-
const result = this.reg();
|
|
414
|
-
this.emit(` ${result} = call i64 @xt_not(i64 ${operand})`);
|
|
415
|
-
return result;
|
|
416
|
-
}
|
|
417
|
-
case PrefixUnaryOperator.Tilde: {
|
|
418
|
-
const operand = this.emitExpression(node.operand);
|
|
419
|
-
const result = this.reg();
|
|
420
|
-
this.emit(` ${result} = call i64 @xt_bit_not(i64 ${operand})`);
|
|
421
|
-
return result;
|
|
422
|
-
}
|
|
423
|
-
case PrefixUnaryOperator.TypeOf: {
|
|
424
|
-
const operand = this.emitExpression(node.operand);
|
|
425
|
-
const result = this.reg();
|
|
426
|
-
this.emit(` ${result} = call i64 @xt_typeof(i64 ${operand})`);
|
|
427
|
-
return result;
|
|
428
|
-
}
|
|
429
|
-
case PrefixUnaryOperator.Void:
|
|
430
|
-
if (node.operand) this.emitExpression(node.operand);
|
|
431
|
-
return i64(XT_UNDEFINED);
|
|
432
|
-
case PrefixUnaryOperator.PlusPlus:
|
|
433
|
-
case PrefixUnaryOperator.MinusMinus: {
|
|
434
|
-
const one = numberLiteral(1);
|
|
435
|
-
const current = this.emitExpression(node.operand);
|
|
436
|
-
const fn = node.operator === PrefixUnaryOperator.PlusPlus ? "xt_add" : "xt_sub";
|
|
437
|
-
const next = this.reg();
|
|
438
|
-
this.emit(` ${next} = call i64 @${fn}(i64 ${current}, i64 ${one})`);
|
|
439
|
-
this.emitAssignmentTarget(node.operand, next);
|
|
440
|
-
return next;
|
|
441
|
-
}
|
|
442
|
-
default:
|
|
443
|
-
this.unsupported(node, `unary operator '${node.operator}'`);
|
|
444
|
-
return i64(XT_UNDEFINED);
|
|
445
|
-
}
|
|
446
|
-
},
|
|
447
|
-
|
|
448
|
-
emitPostfix(node: PostfixUnaryExpression): string {
|
|
449
|
-
const one = numberLiteral(1);
|
|
450
|
-
const current = this.emitExpression(node.operand);
|
|
451
|
-
const fn = node.operator === PostfixUnaryOperator.PlusPlus ? "xt_add" : "xt_sub";
|
|
452
|
-
const next = this.reg();
|
|
453
|
-
this.emit(` ${next} = call i64 @${fn}(i64 ${current}, i64 ${one})`);
|
|
454
|
-
this.emitAssignmentTarget(node.operand, next);
|
|
455
|
-
return current;
|
|
456
|
-
},
|
|
457
|
-
|
|
458
|
-
emitAssignment(node: BinaryExpression): string {
|
|
459
|
-
const operator = node.operator as unknown as AssignmentOperator;
|
|
460
|
-
const target = node.left;
|
|
461
|
-
let value: string;
|
|
462
|
-
if (operator === AssignmentOperator.Assign) {
|
|
463
|
-
value = this.emitExpression(node.right);
|
|
464
|
-
} else if (
|
|
465
|
-
operator === AssignmentOperator.AmpersandAmpersandAssign ||
|
|
466
|
-
operator === AssignmentOperator.BarBarAssign ||
|
|
467
|
-
operator === AssignmentOperator.QuestionQuestionAssign
|
|
468
|
-
) {
|
|
469
|
-
value = this.emitLogicalAssignment(node);
|
|
470
|
-
} else {
|
|
471
|
-
const current = this.emitExpression(target);
|
|
472
|
-
const right = this.emitExpression(node.right);
|
|
473
|
-
const binaryOperator = compoundToBinary(operator);
|
|
474
|
-
const runtime = BINARY_RUNTIME[binaryOperator];
|
|
475
|
-
if (!runtime) {
|
|
476
|
-
this.unsupported(node, `assignment operator '${operator}'`);
|
|
477
|
-
return i64(XT_UNDEFINED);
|
|
478
|
-
}
|
|
479
|
-
const result = this.reg();
|
|
480
|
-
this.emit(` ${result} = call i64 @${runtime}(i64 ${current}, i64 ${right})`);
|
|
481
|
-
value = result;
|
|
482
|
-
}
|
|
483
|
-
this.emitAssignmentTarget(target, value);
|
|
484
|
-
return value;
|
|
485
|
-
},
|
|
486
|
-
|
|
487
|
-
emitLogicalAssignment(node: BinaryExpression): string {
|
|
488
|
-
const operator = node.operator as unknown as AssignmentOperator;
|
|
489
|
-
const target = node.left;
|
|
490
|
-
const current = this.emitExpression(target);
|
|
491
|
-
const result = this.alloca();
|
|
492
|
-
this.emit(` store i64 ${current}, i64* ${result}`);
|
|
493
|
-
const rightLabel = this.label("assign.right");
|
|
494
|
-
const endLabel = this.label("assign.end");
|
|
495
|
-
let condition: string;
|
|
496
|
-
if (operator === AssignmentOperator.AmpersandAmpersandAssign) {
|
|
497
|
-
const truthy = this.reg();
|
|
498
|
-
this.emit(` ${truthy} = call i32 @xt_truthy(i64 ${current})`);
|
|
499
|
-
condition = this.reg();
|
|
500
|
-
this.emit(` ${condition} = icmp ne i32 ${truthy}, 0`);
|
|
501
|
-
} else if (operator === AssignmentOperator.BarBarAssign) {
|
|
502
|
-
const truthy = this.reg();
|
|
503
|
-
this.emit(` ${truthy} = call i32 @xt_truthy(i64 ${current})`);
|
|
504
|
-
const isTruthy = this.reg();
|
|
505
|
-
this.emit(` ${isTruthy} = icmp ne i32 ${truthy}, 0`);
|
|
506
|
-
condition = this.reg();
|
|
507
|
-
this.emit(` ${condition} = xor i1 ${isTruthy}, true`);
|
|
508
|
-
} else {
|
|
509
|
-
const nullish = this.reg();
|
|
510
|
-
this.emit(` ${nullish} = call i64 @xt_is_nullish(i64 ${current})`);
|
|
511
|
-
const truthy = this.reg();
|
|
512
|
-
this.emit(` ${truthy} = call i32 @xt_truthy(i64 ${nullish})`);
|
|
513
|
-
condition = this.reg();
|
|
514
|
-
this.emit(` ${condition} = icmp ne i32 ${truthy}, 0`);
|
|
515
|
-
}
|
|
516
|
-
this.terminate(`br i1 ${condition}, label %${rightLabel}, label %${endLabel}`);
|
|
517
|
-
this.startBlock(rightLabel);
|
|
518
|
-
const right = this.emitExpression(node.right);
|
|
519
|
-
this.emit(` store i64 ${right}, i64* ${result}`);
|
|
520
|
-
this.terminate(`br label %${endLabel}`);
|
|
521
|
-
this.startBlock(endLabel);
|
|
522
|
-
const value = this.reg();
|
|
523
|
-
this.emit(` ${value} = load i64, i64* ${result}`);
|
|
524
|
-
this.emitAssignmentTarget(target, value);
|
|
525
|
-
return value;
|
|
526
|
-
},
|
|
527
|
-
|
|
528
|
-
emitAssignmentTarget(target: Expression, value: string): void {
|
|
529
|
-
switch (target.kind) {
|
|
530
|
-
case SyntaxKind.Identifier: {
|
|
531
|
-
const symbol = this.binding.symbolOfIdentifier.get(target as Identifier);
|
|
532
|
-
if (symbol) this.writeSlot(symbol, value);
|
|
533
|
-
return;
|
|
534
|
-
}
|
|
535
|
-
case SyntaxKind.PropertyAccessExpression: {
|
|
536
|
-
const access = target as PropertyAccessExpression;
|
|
537
|
-
const object = this.emitExpression(access.expression);
|
|
538
|
-
const key = this.stringValue(access.name.text);
|
|
539
|
-
this.emit(` call i64 @xt_set(i64 ${object}, i64 ${key}, i64 ${value})`);
|
|
540
|
-
return;
|
|
541
|
-
}
|
|
542
|
-
case SyntaxKind.ElementAccessExpression: {
|
|
543
|
-
const access = target as ElementAccessExpression;
|
|
544
|
-
const object = this.emitExpression(access.expression);
|
|
545
|
-
const key = this.emitExpression(access.argumentExpression);
|
|
546
|
-
this.emit(` call i64 @xt_set(i64 ${object}, i64 ${key}, i64 ${value})`);
|
|
547
|
-
return;
|
|
548
|
-
}
|
|
549
|
-
case SyntaxKind.ParenthesizedExpression:
|
|
550
|
-
this.emitAssignmentTarget((target as { expression: Expression }).expression, value);
|
|
551
|
-
return;
|
|
552
|
-
default:
|
|
553
|
-
this.unsupported(target, "assignment target");
|
|
554
|
-
}
|
|
555
|
-
},
|
|
556
|
-
};
|
|
11
|
+
import { primaryExpressionMethods, type PrimaryExpressionMethods } from "./expressions/primary.js";
|
|
12
|
+
import { operatorExpressionMethods, type OperatorExpressionMethods } from "./expressions/operators.js";
|
|
13
|
+
import { assignmentExpressionMethods, type AssignmentExpressionMethods } from "./expressions/assignment.js";
|
|
14
|
+
|
|
15
|
+
export interface ExpressionMethods
|
|
16
|
+
extends PrimaryExpressionMethods,
|
|
17
|
+
OperatorExpressionMethods,
|
|
18
|
+
AssignmentExpressionMethods {}
|
|
19
|
+
|
|
20
|
+
export const expressionMethods: ExpressionMethods = Object.assign(
|
|
21
|
+
{},
|
|
22
|
+
primaryExpressionMethods,
|
|
23
|
+
operatorExpressionMethods,
|
|
24
|
+
assignmentExpressionMethods,
|
|
25
|
+
);
|
|
@@ -76,7 +76,9 @@ export const moduleMethods: ModuleMethods = {
|
|
|
76
76
|
"source_filename = \"" + sourceName + "\"",
|
|
77
77
|
"",
|
|
78
78
|
];
|
|
79
|
-
|
|
79
|
+
const runtimeDeclarations = new Set(RUNTIME_DECLARATIONS);
|
|
80
|
+
const extraDeclarations = [...this.extraDeclarations].filter((line) => !runtimeDeclarations.has(line));
|
|
81
|
+
return [...header, ...RUNTIME_DECLARATIONS, ...extraDeclarations, "", ...this.globals, "", ...this.functions, ""].join("\n");
|
|
80
82
|
},
|
|
81
83
|
|
|
82
84
|
// -- module level --------------------------------------------------------
|
|
@@ -114,16 +116,24 @@ export const moduleMethods: ModuleMethods = {
|
|
|
114
116
|
for (let index = 0; index < fn.params.length; index++) {
|
|
115
117
|
const symbol = fn.params[index]!;
|
|
116
118
|
const parameter = parameterNodes[index];
|
|
117
|
-
if (parameter
|
|
119
|
+
if (!parameter) continue;
|
|
120
|
+
if (parameter.dotDotDotToken) {
|
|
118
121
|
const rest = this.reg();
|
|
119
122
|
this.emit(` ${rest} = call i64 @xt_rest_args(i32 %argc, i64* %argv, i32 ${index})`);
|
|
120
123
|
this.declareSlot(symbol, rest);
|
|
121
124
|
continue;
|
|
122
125
|
}
|
|
123
|
-
|
|
126
|
+
let value = this.reg();
|
|
124
127
|
this.emit(` ${value} = call i64 @xt_arg(i32 %argc, i64* %argv, i32 ${index})`);
|
|
128
|
+
if (parameter.name.kind !== SyntaxKind.Identifier) {
|
|
129
|
+
// A destructuring parameter (`([a, b]) => ...` / `({ a }) => ...`) binds
|
|
130
|
+
// every name introduced by its pattern, not just the first one.
|
|
131
|
+
if (parameter.initializer) value = this.emitBindingDefault(value, parameter.initializer);
|
|
132
|
+
this.emitBindingPattern(parameter.name, value);
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
125
135
|
this.declareSlot(symbol, value);
|
|
126
|
-
if (parameter
|
|
136
|
+
if (parameter.initializer) this.emitDefaultParameter(symbol, value, parameter.initializer);
|
|
127
137
|
}
|
|
128
138
|
|
|
129
139
|
// Captures threaded through the environment.
|
|
@@ -97,6 +97,10 @@ export const RUNTIME_DECLARATIONS: readonly string[] = [
|
|
|
97
97
|
"declare i64 @xt_net_server_ctor(i32, i64*)",
|
|
98
98
|
"declare i64 @xt_dgram_static(i64, i32, i64*)",
|
|
99
99
|
"declare i64 @xt_http_static(i64, i32, i64*)",
|
|
100
|
+
"declare i64 @xt_event_emitter_ctor(i32, i64*)",
|
|
101
|
+
"declare i64 @xt_events_static(i64, i32, i64*)",
|
|
102
|
+
"declare i64 @xt_util_static(i64, i32, i64*)",
|
|
103
|
+
"declare i64 @xt_querystring_static(i64, i32, i64*)",
|
|
100
104
|
"declare i64 @xt_process_call(i64, i32, i64*)",
|
|
101
105
|
"declare i64 @xt_process_get(i64)",
|
|
102
106
|
"declare i64 @xt_map_ctor(i32, i64*)",
|
|
@@ -166,6 +170,9 @@ export const RUNTIME_DECLARATIONS: readonly string[] = [
|
|
|
166
170
|
"declare i64 @xt_is_nan(i32, i64*)",
|
|
167
171
|
"declare i64 @xt_is_finite(i32, i64*)",
|
|
168
172
|
"declare i64 @xt_number_ctor(i32, i64*)",
|
|
173
|
+
"declare i64 @xt_bigint_ctor(i32, i64*)",
|
|
174
|
+
"declare i64 @xt_bigint_static(i64, i32, i64*)",
|
|
175
|
+
"declare i64 @xt_bigint_from_string(i8*, i64)",
|
|
169
176
|
"declare i64 @xt_string_ctor(i32, i64*)",
|
|
170
177
|
"declare i64 @xt_boolean_ctor(i32, i64*)",
|
|
171
178
|
"declare i64 @xt_in(i64, i64)",
|
|
@@ -188,6 +195,7 @@ export const RUNTIME_DECLARATIONS: readonly string[] = [
|
|
|
188
195
|
"declare i64 @xt_builtin_value_number(i64, i64, i32, i64*)",
|
|
189
196
|
"declare i64 @xt_builtin_value_string(i64, i64, i32, i64*)",
|
|
190
197
|
"declare i64 @xt_builtin_value_boolean(i64, i64, i32, i64*)",
|
|
198
|
+
"declare i64 @xt_builtin_value_bigint(i64, i64, i32, i64*)",
|
|
191
199
|
"declare i64 @xt_get(i64, i64)",
|
|
192
200
|
"declare i64 @xt_set(i64, i64, i64)",
|
|
193
201
|
"declare i64 @xt_box_new(i64)",
|