xbintsc 0.1.6 → 0.1.9
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 +7 -4
- package/dist/src/ast/common.d.ts +33 -0
- package/dist/src/ast/common.js +7 -0
- package/dist/src/ast/common.js.map +1 -0
- package/dist/src/ast/declarations.d.ts +110 -0
- package/dist/src/ast/declarations.js +5 -0
- package/dist/src/ast/declarations.js.map +1 -0
- package/dist/src/ast/expressions.d.ts +219 -0
- package/dist/src/ast/expressions.js +6 -0
- package/dist/src/ast/expressions.js.map +1 -0
- package/dist/src/ast/kinds.d.ts +160 -0
- package/dist/src/ast/kinds.js +171 -0
- package/dist/src/ast/kinds.js.map +1 -0
- package/dist/src/ast/modules.d.ts +61 -0
- package/dist/src/ast/modules.js +5 -0
- package/dist/src/ast/modules.js.map +1 -0
- package/dist/src/ast/nodes.d.ts +11 -839
- package/dist/src/ast/nodes.js +11 -237
- package/dist/src/ast/nodes.js.map +1 -1
- package/dist/src/ast/operators.d.ts +71 -0
- package/dist/src/ast/operators.js +77 -0
- package/dist/src/ast/operators.js.map +1 -0
- package/dist/src/ast/statements.d.ts +120 -0
- package/dist/src/ast/statements.js +5 -0
- package/dist/src/ast/statements.js.map +1 -0
- package/dist/src/ast/types.d.ts +123 -0
- package/dist/src/ast/types.js +6 -0
- package/dist/src/ast/types.js.map +1 -0
- package/dist/src/binder/binder.d.ts +35 -1
- package/dist/src/binder/binder.js +138 -0
- package/dist/src/binder/binder.js.map +1 -1
- package/dist/src/codegen/generator/calls.d.ts +26 -0
- package/dist/src/codegen/generator/calls.js +373 -0
- package/dist/src/codegen/generator/calls.js.map +1 -0
- package/dist/src/codegen/generator/context.d.ts +47 -0
- package/dist/src/codegen/generator/context.js +164 -0
- package/dist/src/codegen/generator/context.js.map +1 -0
- package/dist/src/codegen/generator/expressions.d.ts +25 -0
- package/dist/src/codegen/generator/expressions.js +454 -0
- package/dist/src/codegen/generator/expressions.js.map +1 -0
- package/dist/src/codegen/generator/generator.d.ts +22 -0
- package/dist/src/codegen/generator/generator.js +21 -0
- package/dist/src/codegen/generator/generator.js.map +1 -0
- package/dist/src/codegen/generator/module.d.ts +19 -0
- package/dist/src/codegen/generator/module.js +214 -0
- package/dist/src/codegen/generator/module.js.map +1 -0
- package/dist/src/codegen/generator/state.d.ts +42 -0
- package/dist/src/codegen/generator/state.js +125 -0
- package/dist/src/codegen/generator/state.js.map +1 -0
- package/dist/src/codegen/generator/statements.d.ts +22 -0
- package/dist/src/codegen/generator/statements.js +433 -0
- package/dist/src/codegen/generator/statements.js.map +1 -0
- package/dist/src/codegen/generator/tables.d.ts +23 -0
- package/dist/src/codegen/generator/tables.js +186 -0
- package/dist/src/codegen/generator/tables.js.map +1 -0
- package/dist/src/codegen/llvm.d.ts +4 -13
- package/dist/src/codegen/llvm.js +4 -1537
- package/dist/src/codegen/llvm.js.map +1 -1
- package/dist/src/driver/compiler.js +36 -11
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/modules.d.ts +24 -0
- package/dist/src/driver/modules.js +347 -0
- package/dist/src/driver/modules.js.map +1 -0
- package/dist/src/lexer/char.d.ts +78 -0
- package/dist/src/lexer/char.js +106 -0
- package/dist/src/lexer/char.js.map +1 -0
- package/dist/src/lexer/scanner.js +1 -98
- package/dist/src/lexer/scanner.js.map +1 -1
- package/dist/src/parser/context.d.ts +58 -0
- package/dist/src/parser/context.js +174 -0
- package/dist/src/parser/context.js.map +1 -0
- package/dist/src/parser/declarations.d.ts +26 -0
- package/dist/src/parser/declarations.js +461 -0
- package/dist/src/parser/declarations.js.map +1 -0
- package/dist/src/parser/expressions.d.ts +27 -0
- package/dist/src/parser/expressions.js +440 -0
- package/dist/src/parser/expressions.js.map +1 -0
- package/dist/src/parser/helpers.d.ts +7 -0
- package/dist/src/parser/helpers.js +36 -0
- package/dist/src/parser/helpers.js.map +1 -0
- package/dist/src/parser/literals.d.ts +16 -0
- package/dist/src/parser/literals.js +193 -0
- package/dist/src/parser/literals.js.map +1 -0
- package/dist/src/parser/modules.d.ts +12 -0
- package/dist/src/parser/modules.js +175 -0
- package/dist/src/parser/modules.js.map +1 -0
- package/dist/src/parser/operators.d.ts +12 -0
- package/dist/src/parser/operators.js +172 -0
- package/dist/src/parser/operators.js.map +1 -0
- package/dist/src/parser/parser.d.ts +17 -122
- package/dist/src/parser/parser.js +18 -2311
- package/dist/src/parser/parser.js.map +1 -1
- package/dist/src/parser/speculation.d.ts +6 -0
- package/dist/src/parser/speculation.js +10 -0
- package/dist/src/parser/speculation.js.map +1 -0
- package/dist/src/parser/statements.d.ts +28 -0
- package/dist/src/parser/statements.js +402 -0
- package/dist/src/parser/statements.js.map +1 -0
- package/dist/src/parser/types.d.ts +21 -0
- package/dist/src/parser/types.js +338 -0
- package/dist/src/parser/types.js.map +1 -0
- package/dist/tests/codegen/llvm.test.js +1 -1
- package/dist/tests/codegen/llvm.test.js.map +1 -1
- package/dist/tests/e2e/compile.test.js +86 -0
- package/dist/tests/e2e/compile.test.js.map +1 -1
- package/package.json +1 -1
- package/runtime/rt.h +55 -4
- package/runtime/rt_internal.h +169 -0
- package/runtime/xt_alloc.c +38 -0
- package/runtime/xt_builtins.c +238 -0
- package/runtime/xt_containers.c +312 -0
- package/runtime/xt_io.c +246 -0
- package/runtime/xt_promise.c +292 -0
- package/runtime/xt_stdlib.c +556 -0
- package/runtime/xt_stdlib2.c +1043 -0
- package/runtime/xt_values.c +291 -0
- package/scripts/build-runtime.mjs +8 -1
- package/src/ast/common.ts +210 -0
- package/src/ast/declarations.ts +130 -0
- package/src/ast/expressions.ts +275 -0
- package/src/ast/kinds.ts +176 -0
- package/src/ast/modules.ts +73 -0
- package/src/ast/nodes.ts +11 -1101
- package/src/ast/operators.ts +76 -0
- package/src/ast/statements.ts +148 -0
- package/src/ast/types.ts +173 -0
- package/src/binder/binder.ts +196 -0
- package/src/codegen/generator/calls.ts +433 -0
- package/src/codegen/generator/context.ts +190 -0
- package/src/codegen/generator/expressions.ts +508 -0
- package/src/codegen/generator/generator.ts +35 -0
- package/src/codegen/generator/module.ts +244 -0
- package/src/codegen/generator/state.ts +169 -0
- package/src/codegen/generator/statements.ts +480 -0
- package/src/codegen/generator/tables.ts +206 -0
- package/src/codegen/llvm.ts +4 -1720
- package/src/driver/compiler.ts +45 -12
- package/src/driver/modules.ts +377 -0
- package/src/lexer/char.ts +116 -0
- package/src/lexer/scanner.ts +9 -109
- package/src/parser/context.ts +196 -0
- package/src/parser/declarations.ts +502 -0
- package/src/parser/expressions.ts +468 -0
- package/src/parser/helpers.ts +42 -0
- package/src/parser/literals.ts +207 -0
- package/src/parser/modules.ts +194 -0
- package/src/parser/operators.ts +181 -0
- package/src/parser/parser.ts +35 -2373
- package/src/parser/speculation.ts +9 -0
- package/src/parser/statements.ts +457 -0
- package/src/parser/types.ts +365 -0
- package/runtime/xt_runtime.c +0 -1372
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Operator taxonomies shared by the parser and code generator.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export const enum PrefixUnaryOperator {
|
|
6
|
+
Plus = "+",
|
|
7
|
+
Minus = "-",
|
|
8
|
+
Tilde = "~",
|
|
9
|
+
Exclamation = "!",
|
|
10
|
+
TypeOf = "typeof",
|
|
11
|
+
Void = "void",
|
|
12
|
+
Delete = "delete",
|
|
13
|
+
PlusPlus = "++",
|
|
14
|
+
MinusMinus = "--",
|
|
15
|
+
Await = "await",
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const enum PostfixUnaryOperator {
|
|
19
|
+
PlusPlus = "++",
|
|
20
|
+
MinusMinus = "--",
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const enum BinaryOperator {
|
|
24
|
+
Add = "+",
|
|
25
|
+
Subtract = "-",
|
|
26
|
+
Multiply = "*",
|
|
27
|
+
Divide = "/",
|
|
28
|
+
Remainder = "%",
|
|
29
|
+
Exponent = "**",
|
|
30
|
+
LessThan = "<",
|
|
31
|
+
LessThanEquals = "<=",
|
|
32
|
+
GreaterThan = ">",
|
|
33
|
+
GreaterThanEquals = ">=",
|
|
34
|
+
EqualsEquals = "==",
|
|
35
|
+
ExclamationEquals = "!=",
|
|
36
|
+
EqualsEqualsEquals = "===",
|
|
37
|
+
ExclamationEqualsEquals = "!==",
|
|
38
|
+
AmpersandAmpersand = "&&",
|
|
39
|
+
BarBar = "||",
|
|
40
|
+
QuestionQuestion = "??",
|
|
41
|
+
Ampersand = "&",
|
|
42
|
+
Bar = "|",
|
|
43
|
+
Caret = "^",
|
|
44
|
+
LessThanLessThan = "<<",
|
|
45
|
+
GreaterThanGreaterThan = ">>",
|
|
46
|
+
GreaterThanGreaterThanGreaterThan = ">>>",
|
|
47
|
+
Comma = ",",
|
|
48
|
+
In = "in",
|
|
49
|
+
InstanceOf = "instanceof",
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Assignment operators, including the compound forms. */
|
|
53
|
+
export const enum AssignmentOperator {
|
|
54
|
+
Assign = "=",
|
|
55
|
+
AddAssign = "+=",
|
|
56
|
+
SubtractAssign = "-=",
|
|
57
|
+
MultiplyAssign = "*=",
|
|
58
|
+
DivideAssign = "/=",
|
|
59
|
+
RemainderAssign = "%=",
|
|
60
|
+
ExponentAssign = "**=",
|
|
61
|
+
LessThanLessThanAssign = "<<=",
|
|
62
|
+
GreaterThanGreaterThanAssign = ">>=",
|
|
63
|
+
GreaterThanGreaterThanGreaterThanAssign = ">>>=",
|
|
64
|
+
AmpersandAssign = "&=",
|
|
65
|
+
BarAssign = "|=",
|
|
66
|
+
CaretAssign = "^=",
|
|
67
|
+
AmpersandAmpersandAssign = "&&=",
|
|
68
|
+
BarBarAssign = "||=",
|
|
69
|
+
QuestionQuestionAssign = "??=",
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const enum TypeOperator {
|
|
73
|
+
KeyOf = "keyof",
|
|
74
|
+
Unique = "unique",
|
|
75
|
+
Readonly = "readonly",
|
|
76
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Statement nodes of the xbintsc AST.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { SyntaxKind } from "./kinds.js";
|
|
6
|
+
import type { Expression, Modifier, Node, Statement, TypeNode } from "./common.js";
|
|
7
|
+
import type { Identifier } from "./expressions.js";
|
|
8
|
+
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Statements
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
export interface ExpressionStatement extends Node {
|
|
14
|
+
readonly kind: SyntaxKind.ExpressionStatement;
|
|
15
|
+
readonly expression: Expression;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface Block extends Node {
|
|
19
|
+
readonly kind: SyntaxKind.Block;
|
|
20
|
+
readonly statements: Statement[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface EmptyStatement extends Node {
|
|
24
|
+
readonly kind: SyntaxKind.EmptyStatement;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface DebuggerStatement extends Node {
|
|
28
|
+
readonly kind: SyntaxKind.DebuggerStatement;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface VariableDeclaration extends Node {
|
|
32
|
+
readonly kind: SyntaxKind.VariableDeclaration;
|
|
33
|
+
readonly name: Identifier;
|
|
34
|
+
readonly exclamation: boolean;
|
|
35
|
+
readonly type?: TypeNode;
|
|
36
|
+
readonly initializer?: Expression;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface VariableDeclarationList extends Node {
|
|
40
|
+
readonly kind: SyntaxKind.VariableDeclarationList;
|
|
41
|
+
readonly declarations: VariableDeclaration[];
|
|
42
|
+
readonly declarationKind: "var" | "let" | "const" | "using";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface VariableStatement extends Node {
|
|
46
|
+
readonly kind: SyntaxKind.VariableStatement;
|
|
47
|
+
readonly declarationList: VariableDeclarationList;
|
|
48
|
+
readonly modifiers: Modifier[];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface IfStatement extends Node {
|
|
52
|
+
readonly kind: SyntaxKind.IfStatement;
|
|
53
|
+
readonly condition: Expression;
|
|
54
|
+
readonly thenStatement: Statement;
|
|
55
|
+
readonly elseStatement?: Statement;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface WhileStatement extends Node {
|
|
59
|
+
readonly kind: SyntaxKind.WhileStatement;
|
|
60
|
+
readonly condition: Expression;
|
|
61
|
+
readonly statement: Statement;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface DoStatement extends Node {
|
|
65
|
+
readonly kind: SyntaxKind.DoStatement;
|
|
66
|
+
readonly condition: Expression;
|
|
67
|
+
readonly statement: Statement;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface ForStatement extends Node {
|
|
71
|
+
readonly kind: SyntaxKind.ForStatement;
|
|
72
|
+
readonly initializer?: VariableDeclarationList | Expression;
|
|
73
|
+
readonly condition?: Expression;
|
|
74
|
+
readonly incrementor?: Expression;
|
|
75
|
+
readonly statement: Statement;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface ForOfStatement extends Node {
|
|
79
|
+
readonly kind: SyntaxKind.ForOfStatement;
|
|
80
|
+
readonly initializer: VariableDeclarationList | Expression;
|
|
81
|
+
readonly expression: Expression;
|
|
82
|
+
readonly statement: Statement;
|
|
83
|
+
readonly awaitModifier: boolean;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface ForInStatement extends Node {
|
|
87
|
+
readonly kind: SyntaxKind.ForInStatement;
|
|
88
|
+
readonly initializer: VariableDeclarationList | Expression;
|
|
89
|
+
readonly expression: Expression;
|
|
90
|
+
readonly statement: Statement;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface ReturnStatement extends Node {
|
|
94
|
+
readonly kind: SyntaxKind.ReturnStatement;
|
|
95
|
+
readonly expression?: Expression;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export interface BreakStatement extends Node {
|
|
99
|
+
readonly kind: SyntaxKind.BreakStatement;
|
|
100
|
+
readonly label?: Identifier;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface ContinueStatement extends Node {
|
|
104
|
+
readonly kind: SyntaxKind.ContinueStatement;
|
|
105
|
+
readonly label?: Identifier;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface ThrowStatement extends Node {
|
|
109
|
+
readonly kind: SyntaxKind.ThrowStatement;
|
|
110
|
+
readonly expression: Expression;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface CatchClause extends Node {
|
|
114
|
+
readonly kind: SyntaxKind.CatchClause;
|
|
115
|
+
readonly variable?: Identifier;
|
|
116
|
+
readonly type?: TypeNode;
|
|
117
|
+
readonly block: Block;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface TryStatement extends Node {
|
|
121
|
+
readonly kind: SyntaxKind.TryStatement;
|
|
122
|
+
readonly tryBlock: Block;
|
|
123
|
+
readonly catchClause?: CatchClause;
|
|
124
|
+
readonly finallyBlock?: Block;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export interface CaseClause extends Node {
|
|
128
|
+
readonly kind: SyntaxKind.CaseClause;
|
|
129
|
+
readonly expression: Expression;
|
|
130
|
+
readonly statements: Statement[];
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export interface DefaultClause extends Node {
|
|
134
|
+
readonly kind: SyntaxKind.DefaultClause;
|
|
135
|
+
readonly statements: Statement[];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface SwitchStatement extends Node {
|
|
139
|
+
readonly kind: SyntaxKind.SwitchStatement;
|
|
140
|
+
readonly expression: Expression;
|
|
141
|
+
readonly clauses: (CaseClause | DefaultClause)[];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface LabeledStatement extends Node {
|
|
145
|
+
readonly kind: SyntaxKind.LabeledStatement;
|
|
146
|
+
readonly label: Identifier;
|
|
147
|
+
readonly statement: Statement;
|
|
148
|
+
}
|
package/src/ast/types.ts
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type nodes of the xbintsc AST. The parser records type syntax so diagnostics
|
|
3
|
+
* and tooling can see it, but the code generator erases types before lowering.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { SyntaxKind } from "./kinds.js";
|
|
7
|
+
import type { TypeOperator } from "./operators.js";
|
|
8
|
+
import type { Node, TypeNode } from "./common.js";
|
|
9
|
+
import type {
|
|
10
|
+
BooleanLiteral,
|
|
11
|
+
Identifier,
|
|
12
|
+
NullLiteral,
|
|
13
|
+
NumericLiteral,
|
|
14
|
+
StringLiteral,
|
|
15
|
+
ThisExpression,
|
|
16
|
+
PropertyName,
|
|
17
|
+
} from "./expressions.js";
|
|
18
|
+
import type { Parameter, TypeParameterDeclaration } from "./declarations.js";
|
|
19
|
+
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Type nodes
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
export interface TypeReference extends Node {
|
|
25
|
+
readonly kind: SyntaxKind.TypeReference;
|
|
26
|
+
readonly typeName: Identifier | QualifiedName;
|
|
27
|
+
readonly typeArguments: TypeNode[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface QualifiedName extends Node {
|
|
31
|
+
readonly kind: SyntaxKind.QualifiedName;
|
|
32
|
+
readonly left: Identifier | QualifiedName;
|
|
33
|
+
readonly right: Identifier;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface TypePredicate extends Node {
|
|
37
|
+
readonly kind: SyntaxKind.TypePredicate;
|
|
38
|
+
readonly parameterName: Identifier | ThisExpression;
|
|
39
|
+
readonly type?: TypeNode;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface KeywordTypeNode extends Node {
|
|
43
|
+
readonly kind:
|
|
44
|
+
| SyntaxKind.AnyKeywordType
|
|
45
|
+
| SyntaxKind.UnknownKeywordType
|
|
46
|
+
| SyntaxKind.NumberKeywordType
|
|
47
|
+
| SyntaxKind.BigIntKeywordType
|
|
48
|
+
| SyntaxKind.StringKeywordType
|
|
49
|
+
| SyntaxKind.BooleanKeywordType
|
|
50
|
+
| SyntaxKind.SymbolKeywordType
|
|
51
|
+
| SyntaxKind.VoidKeywordType
|
|
52
|
+
| SyntaxKind.UndefinedKeywordType
|
|
53
|
+
| SyntaxKind.NullKeywordType
|
|
54
|
+
| SyntaxKind.NeverKeywordType
|
|
55
|
+
| SyntaxKind.ObjectKeywordType
|
|
56
|
+
| SyntaxKind.ThisKeywordType;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface LiteralTypeNode extends Node {
|
|
60
|
+
readonly kind: SyntaxKind.LiteralType;
|
|
61
|
+
readonly literal: StringLiteral | NumericLiteral | BooleanLiteral | NullLiteral;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface ArrayTypeNode extends Node {
|
|
65
|
+
readonly kind: SyntaxKind.ArrayType;
|
|
66
|
+
readonly elementType: TypeNode;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface TupleTypeNode extends Node {
|
|
70
|
+
readonly kind: SyntaxKind.TupleType;
|
|
71
|
+
readonly elements: TypeNode[];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface UnionTypeNode extends Node {
|
|
75
|
+
readonly kind: SyntaxKind.UnionType;
|
|
76
|
+
readonly types: TypeNode[];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface IntersectionTypeNode extends Node {
|
|
80
|
+
readonly kind: SyntaxKind.IntersectionType;
|
|
81
|
+
readonly types: TypeNode[];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface FunctionTypeNode extends Node {
|
|
85
|
+
readonly kind: SyntaxKind.FunctionType;
|
|
86
|
+
readonly typeParameters: TypeParameterDeclaration[];
|
|
87
|
+
readonly parameters: Parameter[];
|
|
88
|
+
readonly returnType: TypeNode;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export type TypeElement = PropertySignature | MethodSignature | IndexSignature;
|
|
92
|
+
|
|
93
|
+
export interface PropertySignature extends Node {
|
|
94
|
+
readonly kind: SyntaxKind.PropertySignature;
|
|
95
|
+
readonly name: PropertyName;
|
|
96
|
+
readonly questionToken: boolean;
|
|
97
|
+
readonly readonlyToken: boolean;
|
|
98
|
+
readonly type?: TypeNode;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface MethodSignature extends Node {
|
|
102
|
+
readonly kind: SyntaxKind.MethodSignature;
|
|
103
|
+
readonly name: PropertyName;
|
|
104
|
+
readonly questionToken: boolean;
|
|
105
|
+
readonly typeParameters: TypeParameterDeclaration[];
|
|
106
|
+
readonly parameters: Parameter[];
|
|
107
|
+
readonly returnType?: TypeNode;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface IndexSignature extends Node {
|
|
111
|
+
readonly kind: SyntaxKind.IndexSignature;
|
|
112
|
+
readonly parameters: Parameter[];
|
|
113
|
+
readonly type?: TypeNode;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export interface TypeLiteralNode extends Node {
|
|
117
|
+
readonly kind: SyntaxKind.TypeLiteral;
|
|
118
|
+
readonly members: TypeElement[];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface ParenthesizedTypeNode extends Node {
|
|
122
|
+
readonly kind: SyntaxKind.ParenthesizedType;
|
|
123
|
+
readonly type: TypeNode;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface TypeQueryNode extends Node {
|
|
127
|
+
readonly kind: SyntaxKind.TypeQuery;
|
|
128
|
+
readonly exprName: Identifier | QualifiedName;
|
|
129
|
+
readonly typeArguments: TypeNode[];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export interface IndexedAccessTypeNode extends Node {
|
|
133
|
+
readonly kind: SyntaxKind.IndexedAccessType;
|
|
134
|
+
readonly objectType: TypeNode;
|
|
135
|
+
readonly indexType: TypeNode;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface TypeOperatorNode extends Node {
|
|
139
|
+
readonly kind: SyntaxKind.TypeOperator;
|
|
140
|
+
readonly operator: TypeOperator;
|
|
141
|
+
readonly type: TypeNode;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface MappedTypeNode extends Node {
|
|
145
|
+
readonly kind: SyntaxKind.MappedType;
|
|
146
|
+
readonly readonlyToken: boolean | "+" | "-";
|
|
147
|
+
readonly typeParameter: TypeParameterDeclaration;
|
|
148
|
+
readonly questionToken: boolean | "+" | "-";
|
|
149
|
+
readonly type?: TypeNode;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export interface ConditionalTypeNode extends Node {
|
|
153
|
+
readonly kind: SyntaxKind.ConditionalType;
|
|
154
|
+
readonly checkType: TypeNode;
|
|
155
|
+
readonly extendsType: TypeNode;
|
|
156
|
+
readonly trueType: TypeNode;
|
|
157
|
+
readonly falseType: TypeNode;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export interface InferTypeNode extends Node {
|
|
161
|
+
readonly kind: SyntaxKind.InferType;
|
|
162
|
+
readonly typeParameter: TypeParameterDeclaration;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export interface OptionalTypeNode extends Node {
|
|
166
|
+
readonly kind: SyntaxKind.OptionalType;
|
|
167
|
+
readonly type: TypeNode;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface RestTypeNode extends Node {
|
|
171
|
+
readonly kind: SyntaxKind.RestType;
|
|
172
|
+
readonly type: TypeNode;
|
|
173
|
+
}
|
package/src/binder/binder.ts
CHANGED
|
@@ -9,14 +9,21 @@
|
|
|
9
9
|
* cached, serialized for the incremental build, and unit tested in isolation.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import { NodeFlags, ModifierKind } from "../ast/kinds.js";
|
|
12
13
|
import {
|
|
13
14
|
SyntaxKind,
|
|
14
15
|
type ArrowFunction,
|
|
15
16
|
type Block,
|
|
17
|
+
type ClassDeclaration,
|
|
18
|
+
type ClassExpression,
|
|
19
|
+
type ConstructorDeclaration,
|
|
16
20
|
type FunctionDeclaration,
|
|
17
21
|
type FunctionExpression,
|
|
18
22
|
type Identifier,
|
|
23
|
+
type MethodDeclaration,
|
|
19
24
|
type Node,
|
|
25
|
+
type PropertyDeclaration,
|
|
26
|
+
type PropertyName,
|
|
20
27
|
type SourceFileNode,
|
|
21
28
|
type Statement,
|
|
22
29
|
type Expression,
|
|
@@ -76,6 +83,40 @@ export interface FunctionInfo {
|
|
|
76
83
|
readonly captureIndex: Map<number, number>;
|
|
77
84
|
readonly isModule: boolean;
|
|
78
85
|
readonly isArrow: boolean;
|
|
86
|
+
/** True when the function was declared `async`. */
|
|
87
|
+
readonly isAsync: boolean;
|
|
88
|
+
/** True when this function's body mentions `this` directly. */
|
|
89
|
+
usesThis: boolean;
|
|
90
|
+
/** True when an arrow function must receive `this` from its enclosing scope. */
|
|
91
|
+
capturesThis: boolean;
|
|
92
|
+
/** Set for class methods/constructors; carries the owning class. */
|
|
93
|
+
classInfo?: ClassInfo;
|
|
94
|
+
/** True for `static` class members. */
|
|
95
|
+
isStatic?: boolean;
|
|
96
|
+
/** True for an explicit `constructor`. */
|
|
97
|
+
isConstructor?: boolean;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface ClassInfo {
|
|
101
|
+
readonly id: number;
|
|
102
|
+
readonly name: string;
|
|
103
|
+
readonly node: Node;
|
|
104
|
+
readonly scope: Scope;
|
|
105
|
+
readonly parent?: ClassInfo;
|
|
106
|
+
readonly parentExpression?: Expression;
|
|
107
|
+
/** `this`-bearing fields declared on the class. */
|
|
108
|
+
readonly fields: ClassFieldInfo[];
|
|
109
|
+
readonly methods: FunctionInfo[];
|
|
110
|
+
readonly statics: FunctionInfo[];
|
|
111
|
+
ctor?: FunctionInfo;
|
|
112
|
+
/** The symbol the class name binds to, when there is one. */
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface ClassFieldInfo {
|
|
116
|
+
readonly name: string;
|
|
117
|
+
readonly initializer: Expression | undefined;
|
|
118
|
+
readonly fn: FunctionInfo;
|
|
119
|
+
readonly isStatic: boolean;
|
|
79
120
|
}
|
|
80
121
|
|
|
81
122
|
export enum ScopeKind {
|
|
@@ -98,6 +139,9 @@ export interface Scope {
|
|
|
98
139
|
export interface BindResult {
|
|
99
140
|
readonly moduleFunction: FunctionInfo;
|
|
100
141
|
readonly functions: FunctionInfo[];
|
|
142
|
+
readonly classes: ClassInfo[];
|
|
143
|
+
/** Maps a class-like AST node to the ClassInfo the binder built. */
|
|
144
|
+
readonly classOfNode: Map<Node, ClassInfo>;
|
|
101
145
|
/** Maps a function-like AST node to the FunctionInfo the binder built for it. */
|
|
102
146
|
readonly functionOfNode: Map<Node, FunctionInfo>;
|
|
103
147
|
readonly symbolOfDeclaration: Map<Node, SymbolInfo>;
|
|
@@ -120,12 +164,15 @@ export function bind(sourceFile: SourceFileNode): BindResult {
|
|
|
120
164
|
|
|
121
165
|
class Binder {
|
|
122
166
|
private readonly functions: FunctionInfo[] = [];
|
|
167
|
+
private readonly classes: ClassInfo[] = [];
|
|
168
|
+
private readonly classOfNode = new Map<Node, ClassInfo>();
|
|
123
169
|
private readonly symbolOfDeclaration = new Map<Node, SymbolInfo>();
|
|
124
170
|
private readonly symbolOfIdentifier = new Map<Identifier, SymbolInfo>();
|
|
125
171
|
private readonly scopes = new Map<Node, Scope>();
|
|
126
172
|
private readonly unresolved: Identifier[] = [];
|
|
127
173
|
private nextSymbolId = 1;
|
|
128
174
|
private nextFunctionId = 1;
|
|
175
|
+
private nextClassId = 1;
|
|
129
176
|
private current!: MutableFunction;
|
|
130
177
|
|
|
131
178
|
constructor(private readonly sourceFile: SourceFileNode) {}
|
|
@@ -140,9 +187,22 @@ class Binder {
|
|
|
140
187
|
this.collectFunctionScoped(this.sourceFile.statements, this.current);
|
|
141
188
|
this.bindStatements(this.sourceFile.statements, scope);
|
|
142
189
|
|
|
190
|
+
// Arrows inherit `this` lexically: propagate the need to capture it up the
|
|
191
|
+
// chain of arrow functions until reaching a regular function.
|
|
192
|
+
for (let index = this.functions.length - 1; index >= 0; index--) {
|
|
193
|
+
const fn = this.functions[index]! as MutableFunction;
|
|
194
|
+
if (fn.usesThis && fn.isArrow) {
|
|
195
|
+
fn.capturesThis = true;
|
|
196
|
+
const parent = fn.parent as MutableFunction | undefined;
|
|
197
|
+
if (parent && parent.isArrow) parent.usesThis = true;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
143
201
|
return {
|
|
144
202
|
moduleFunction: this.current,
|
|
145
203
|
functions: this.functions,
|
|
204
|
+
classes: this.classes,
|
|
205
|
+
classOfNode: this.classOfNode,
|
|
146
206
|
functionOfNode: new Map(this.functions.map((fn) => [fn.node as Node, fn])),
|
|
147
207
|
symbolOfDeclaration: this.symbolOfDeclaration,
|
|
148
208
|
symbolOfIdentifier: this.symbolOfIdentifier,
|
|
@@ -172,6 +232,9 @@ class Binder {
|
|
|
172
232
|
captureIndex: new Map(),
|
|
173
233
|
isModule,
|
|
174
234
|
isArrow,
|
|
235
|
+
isAsync: (((node as { flags?: number }).flags ?? 0) & NodeFlags.Async) !== 0,
|
|
236
|
+
usesThis: false,
|
|
237
|
+
capturesThis: false,
|
|
175
238
|
};
|
|
176
239
|
this.functions.push(fn);
|
|
177
240
|
return fn;
|
|
@@ -369,6 +432,13 @@ class Binder {
|
|
|
369
432
|
case SyntaxKind.Identifier:
|
|
370
433
|
this.reference(node as Identifier, scope);
|
|
371
434
|
return;
|
|
435
|
+
case SyntaxKind.ThisKeyword:
|
|
436
|
+
this.current.usesThis = true;
|
|
437
|
+
return;
|
|
438
|
+
case SyntaxKind.ClassDeclaration:
|
|
439
|
+
case SyntaxKind.ClassExpression:
|
|
440
|
+
this.bindClass(node as ClassDeclaration | ClassExpression, scope);
|
|
441
|
+
return;
|
|
372
442
|
case SyntaxKind.InterfaceDeclaration:
|
|
373
443
|
case SyntaxKind.TypeAliasDeclaration:
|
|
374
444
|
// Type-only: skip the body entirely.
|
|
@@ -490,7 +560,118 @@ class Binder {
|
|
|
490
560
|
this.current = parentFn;
|
|
491
561
|
}
|
|
492
562
|
|
|
563
|
+
private bindClass(node: ClassDeclaration | ClassExpression, scope: Scope): void {
|
|
564
|
+
const parentFn = this.current;
|
|
565
|
+
const name = node.name ? node.name.text : "(anonymous)";
|
|
566
|
+
|
|
567
|
+
let parentExpression: Expression | undefined;
|
|
568
|
+
let parentClass: ClassInfo | undefined;
|
|
569
|
+
const heritage = node.heritage.find((clause) => clause.token === "extends");
|
|
570
|
+
if (heritage && heritage.types.length > 0) {
|
|
571
|
+
parentExpression = heritage.types[0]!.expression;
|
|
572
|
+
this.bindNode(parentExpression, scope);
|
|
573
|
+
if (parentExpression.kind === SyntaxKind.Identifier) {
|
|
574
|
+
const symbol = this.symbolOfIdentifier.get(parentExpression as Identifier);
|
|
575
|
+
const declaration = symbol?.declarations[0];
|
|
576
|
+
if (declaration) parentClass = this.classOfNode.get(declaration);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
const info: ClassInfo = {
|
|
581
|
+
id: this.nextClassId++,
|
|
582
|
+
name,
|
|
583
|
+
node,
|
|
584
|
+
scope,
|
|
585
|
+
parent: parentClass,
|
|
586
|
+
parentExpression,
|
|
587
|
+
fields: [],
|
|
588
|
+
methods: [],
|
|
589
|
+
statics: [],
|
|
590
|
+
};
|
|
591
|
+
this.classes.push(info);
|
|
592
|
+
this.classOfNode.set(node, info);
|
|
593
|
+
|
|
594
|
+
const classScope = this.createScope(ScopeKind.Block, node, scope);
|
|
595
|
+
this.scopes.set(node, classScope);
|
|
596
|
+
|
|
597
|
+
let constructor: FunctionInfo | undefined;
|
|
598
|
+
for (const member of node.members) {
|
|
599
|
+
if (member.kind === SyntaxKind.ConstructorDeclaration) {
|
|
600
|
+
const ctor = member as ConstructorDeclaration;
|
|
601
|
+
constructor = this.createClassFunction(ctor, "constructor", ctor.parameters, ctor.body, classScope, info, false, true);
|
|
602
|
+
} else if (member.kind === SyntaxKind.MethodDeclaration) {
|
|
603
|
+
const method = member as MethodDeclaration;
|
|
604
|
+
const isStatic = method.modifiers.some((modifier) => modifier.modifierKind === ModifierKind.Static);
|
|
605
|
+
const fn = this.createClassFunction(method, classMemberName(method.name), method.parameters, method.body, classScope, info, isStatic, false);
|
|
606
|
+
if (isStatic) (info.statics as FunctionInfo[]).push(fn);
|
|
607
|
+
else (info.methods as FunctionInfo[]).push(fn);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
if (!constructor) {
|
|
611
|
+
constructor = this.createClassFunction(node, "constructor", [], undefined, classScope, info, false, true);
|
|
612
|
+
}
|
|
613
|
+
info.ctor = constructor;
|
|
614
|
+
|
|
615
|
+
// Field initializers run in the constructor's context so they can capture
|
|
616
|
+
// enclosing variables.
|
|
617
|
+
for (const member of node.members) {
|
|
618
|
+
if (member.kind === SyntaxKind.PropertyDeclaration) {
|
|
619
|
+
const property = member as PropertyDeclaration;
|
|
620
|
+
const isStatic = property.modifiers.some((modifier) => modifier.modifierKind === ModifierKind.Static);
|
|
621
|
+
const owner = this.current;
|
|
622
|
+
this.current = constructor as MutableFunction;
|
|
623
|
+
if (property.initializer) this.bindNode(property.initializer, classScope);
|
|
624
|
+
this.current = owner;
|
|
625
|
+
info.fields.push({ name: classMemberName(property.name), initializer: property.initializer, fn: constructor, isStatic });
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
this.current = parentFn;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
private createClassFunction(
|
|
633
|
+
member: Node,
|
|
634
|
+
name: string,
|
|
635
|
+
parameters: readonly import("../ast/declarations.js").Parameter[],
|
|
636
|
+
body: Block | undefined,
|
|
637
|
+
parentScope: Scope,
|
|
638
|
+
info: ClassInfo,
|
|
639
|
+
isStatic: boolean,
|
|
640
|
+
isConstructor: boolean,
|
|
641
|
+
): FunctionInfo {
|
|
642
|
+
const parentFn = this.current;
|
|
643
|
+
const fn = this.createFunction(name, member as unknown as FunctionNode, parentFn, false, false);
|
|
644
|
+
(fn as MutableFunction & { classInfo: ClassInfo }).classInfo = info;
|
|
645
|
+
(fn as MutableFunction & { isStatic: boolean }).isStatic = isStatic;
|
|
646
|
+
(fn as MutableFunction & { isConstructor: boolean }).isConstructor = isConstructor;
|
|
647
|
+
this.current = fn as MutableFunction;
|
|
648
|
+
const scope = this.createScope(ScopeKind.Function, member, parentScope);
|
|
649
|
+
(fn as { scope: Scope }).scope = scope;
|
|
650
|
+
this.scopes.set(member, scope);
|
|
651
|
+
|
|
652
|
+
const params: SymbolInfo[] = [];
|
|
653
|
+
for (const parameter of parameters) {
|
|
654
|
+
const paramSymbol = this.declare(parameter.name.text, SymbolKind.Parameter, parameter, scope, true);
|
|
655
|
+
params.push(paramSymbol);
|
|
656
|
+
if (parameter.initializer) this.bindNode(parameter.initializer, scope);
|
|
657
|
+
}
|
|
658
|
+
(fn as { params: SymbolInfo[] }).params = params;
|
|
659
|
+
|
|
660
|
+
if (body) {
|
|
661
|
+
this.collectFunctionScoped([body], fn as MutableFunction);
|
|
662
|
+
this.predeclareStatements(body.statements, scope);
|
|
663
|
+
this.bindStatements(body.statements, scope);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
this.current = parentFn;
|
|
667
|
+
return fn;
|
|
668
|
+
}
|
|
669
|
+
|
|
493
670
|
private reference(identifier: Identifier, scope: Scope): void {
|
|
671
|
+
if (identifier.text === "super") {
|
|
672
|
+
this.current.usesThis = true;
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
494
675
|
let current: Scope | undefined = scope;
|
|
495
676
|
while (current) {
|
|
496
677
|
const symbol = current.symbols.get(identifier.text);
|
|
@@ -547,3 +728,18 @@ function isCapturable(kind: SymbolKind): boolean {
|
|
|
547
728
|
kind === SymbolKind.Parameter
|
|
548
729
|
);
|
|
549
730
|
}
|
|
731
|
+
|
|
732
|
+
/** Extract the textual name of a class member (`method`, `"key"`, `0`). */
|
|
733
|
+
function classMemberName(name: PropertyName): string {
|
|
734
|
+
switch (name.kind) {
|
|
735
|
+
case SyntaxKind.Identifier:
|
|
736
|
+
case SyntaxKind.PrivateIdentifier:
|
|
737
|
+
return (name as unknown as { text: string }).text;
|
|
738
|
+
case SyntaxKind.StringLiteral:
|
|
739
|
+
return (name as unknown as { value: string }).value;
|
|
740
|
+
case SyntaxKind.NumericLiteral:
|
|
741
|
+
return String((name as unknown as { value: number }).value);
|
|
742
|
+
default:
|
|
743
|
+
return "";
|
|
744
|
+
}
|
|
745
|
+
}
|