xbintsc 0.3.3 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/dist/src/ast/expressions.d.ts +8 -0
  2. package/dist/src/binder/binder.js +1 -0
  3. package/dist/src/binder/binder.js.map +1 -1
  4. package/dist/src/binder/references.d.ts +1 -1
  5. package/dist/src/binder/references.js +34 -5
  6. package/dist/src/binder/references.js.map +1 -1
  7. package/dist/src/binder/types.d.ts +4 -0
  8. package/dist/src/binder/types.js.map +1 -1
  9. package/dist/src/cli/main.js.map +1 -1
  10. package/dist/src/codegen/generator/calls/access.d.ts +9 -1
  11. package/dist/src/codegen/generator/calls/access.js +146 -13
  12. package/dist/src/codegen/generator/calls/access.js.map +1 -1
  13. package/dist/src/codegen/generator/calls/closures.d.ts +1 -0
  14. package/dist/src/codegen/generator/calls/closures.js +25 -0
  15. package/dist/src/codegen/generator/calls/closures.js.map +1 -1
  16. package/dist/src/codegen/generator/calls/invocation.js +12 -1
  17. package/dist/src/codegen/generator/calls/invocation.js.map +1 -1
  18. package/dist/src/codegen/generator/calls/literals.js +12 -4
  19. package/dist/src/codegen/generator/calls/literals.js.map +1 -1
  20. package/dist/src/codegen/generator/calls/super.js +4 -7
  21. package/dist/src/codegen/generator/calls/super.js.map +1 -1
  22. package/dist/src/codegen/generator/context.d.ts +21 -2
  23. package/dist/src/codegen/generator/context.js +42 -5
  24. package/dist/src/codegen/generator/context.js.map +1 -1
  25. package/dist/src/codegen/generator/expressions/assignment.js +1 -3
  26. package/dist/src/codegen/generator/expressions/assignment.js.map +1 -1
  27. package/dist/src/codegen/generator/expressions/primary.d.ts +3 -1
  28. package/dist/src/codegen/generator/expressions/primary.js +99 -1
  29. package/dist/src/codegen/generator/expressions/primary.js.map +1 -1
  30. package/dist/src/codegen/generator/generator.js.map +1 -1
  31. package/dist/src/codegen/generator/module.js +25 -15
  32. package/dist/src/codegen/generator/module.js.map +1 -1
  33. package/dist/src/codegen/generator/state.d.ts +15 -0
  34. package/dist/src/codegen/generator/state.js +28 -1
  35. package/dist/src/codegen/generator/state.js.map +1 -1
  36. package/dist/src/codegen/generator/statements/control-flow.d.ts +3 -1
  37. package/dist/src/codegen/generator/statements/control-flow.js +85 -0
  38. package/dist/src/codegen/generator/statements/control-flow.js.map +1 -1
  39. package/dist/src/codegen/generator/statements/dispatch.js +15 -6
  40. package/dist/src/codegen/generator/statements/dispatch.js.map +1 -1
  41. package/dist/src/codegen/generator/statements/loops.d.ts +3 -0
  42. package/dist/src/codegen/generator/statements/loops.js +25 -11
  43. package/dist/src/codegen/generator/statements/loops.js.map +1 -1
  44. package/dist/src/codegen/generator/tables.d.ts +7 -0
  45. package/dist/src/codegen/generator/tables.js +41 -1
  46. package/dist/src/codegen/generator/tables.js.map +1 -1
  47. package/dist/src/driver/compiler.d.ts +1 -1
  48. package/dist/src/driver/compiler.js +33 -1
  49. package/dist/src/driver/compiler.js.map +1 -1
  50. package/dist/src/driver/modules.d.ts +4 -3
  51. package/dist/src/driver/modules.js +61 -4
  52. package/dist/src/driver/modules.js.map +1 -1
  53. package/dist/src/driver/toolchain.js +1 -1
  54. package/dist/src/driver/toolchain.js.map +1 -1
  55. package/dist/src/lexer/scanner.js.map +1 -1
  56. package/dist/src/parser/declarations/classes.js +4 -0
  57. package/dist/src/parser/declarations/classes.js.map +1 -1
  58. package/dist/src/parser/declarations/type-members.js.map +1 -1
  59. package/dist/src/parser/expressions.d.ts +2 -1
  60. package/dist/src/parser/expressions.js +10 -1
  61. package/dist/src/parser/expressions.js.map +1 -1
  62. package/dist/src/parser/helpers.js +2 -2
  63. package/dist/src/parser/helpers.js.map +1 -1
  64. package/dist/src/parser/literals.js +79 -6
  65. package/dist/src/parser/literals.js.map +1 -1
  66. package/dist/src/parser/modules.js.map +1 -1
  67. package/dist/src/parser/parser.js +0 -1
  68. package/dist/src/parser/parser.js.map +1 -1
  69. package/dist/src/parser/statements.d.ts +1 -0
  70. package/dist/src/parser/statements.js +13 -1
  71. package/dist/src/parser/statements.js.map +1 -1
  72. package/dist/src/parser/types.js +2 -2
  73. package/dist/src/parser/types.js.map +1 -1
  74. package/dist/tests/ast/factory.test.d.ts +1 -0
  75. package/dist/tests/ast/factory.test.js +35 -0
  76. package/dist/tests/ast/factory.test.js.map +1 -0
  77. package/dist/tests/ast/visitor.test.d.ts +1 -0
  78. package/dist/tests/ast/visitor.test.js +53 -0
  79. package/dist/tests/ast/visitor.test.js.map +1 -0
  80. package/dist/tests/cli/main.test.js +109 -9
  81. package/dist/tests/cli/main.test.js.map +1 -1
  82. package/dist/tests/codegen/closures.test.d.ts +1 -0
  83. package/dist/tests/codegen/closures.test.js +32 -0
  84. package/dist/tests/codegen/closures.test.js.map +1 -0
  85. package/dist/tests/codegen/expressions.test.d.ts +1 -0
  86. package/dist/tests/codegen/expressions.test.js +149 -0
  87. package/dist/tests/codegen/expressions.test.js.map +1 -0
  88. package/dist/tests/codegen/llvm.test.js +14 -0
  89. package/dist/tests/codegen/llvm.test.js.map +1 -1
  90. package/dist/tests/codegen/values.test.d.ts +1 -0
  91. package/dist/tests/codegen/values.test.js +48 -0
  92. package/dist/tests/codegen/values.test.js.map +1 -0
  93. package/dist/tests/diagnostics/diagnostic.test.d.ts +1 -0
  94. package/dist/tests/diagnostics/diagnostic.test.js +117 -0
  95. package/dist/tests/diagnostics/diagnostic.test.js.map +1 -0
  96. package/dist/tests/diagnostics/source.test.d.ts +1 -0
  97. package/dist/tests/diagnostics/source.test.js +58 -0
  98. package/dist/tests/diagnostics/source.test.js.map +1 -0
  99. package/dist/tests/driver/modules.test.d.ts +1 -0
  100. package/dist/tests/driver/modules.test.js +140 -0
  101. package/dist/tests/driver/modules.test.js.map +1 -0
  102. package/dist/tests/driver/paths.test.js +17 -1
  103. package/dist/tests/driver/paths.test.js.map +1 -1
  104. package/dist/tests/driver/runtime-lib.test.d.ts +1 -0
  105. package/dist/tests/driver/runtime-lib.test.js +19 -0
  106. package/dist/tests/driver/runtime-lib.test.js.map +1 -0
  107. package/dist/tests/driver/toolchain-provider.test.js +91 -0
  108. package/dist/tests/driver/toolchain-provider.test.js.map +1 -1
  109. package/dist/tests/driver/toolchain.test.js +11 -1
  110. package/dist/tests/driver/toolchain.test.js.map +1 -1
  111. package/dist/tests/e2e/compile-node.test.js +14 -1
  112. package/dist/tests/e2e/compile-node.test.js.map +1 -1
  113. package/dist/tests/e2e/compile.test.js +465 -2
  114. package/dist/tests/e2e/compile.test.js.map +1 -1
  115. package/dist/tests/e2e/differential.test.d.ts +7 -0
  116. package/dist/tests/e2e/differential.test.js +581 -0
  117. package/dist/tests/e2e/differential.test.js.map +1 -0
  118. package/dist/tests/e2e/harness.d.ts +21 -0
  119. package/dist/tests/e2e/harness.js +26 -0
  120. package/dist/tests/e2e/harness.js.map +1 -1
  121. package/dist/tests/extensions/node.test.d.ts +1 -0
  122. package/dist/tests/extensions/node.test.js +32 -0
  123. package/dist/tests/extensions/node.test.js.map +1 -0
  124. package/dist/tests/lexer/identifiers.test.d.ts +1 -0
  125. package/dist/tests/lexer/identifiers.test.js +13 -0
  126. package/dist/tests/lexer/identifiers.test.js.map +1 -0
  127. package/dist/tests/lexer/numbers.test.d.ts +1 -0
  128. package/dist/tests/lexer/numbers.test.js +23 -0
  129. package/dist/tests/lexer/numbers.test.js.map +1 -0
  130. package/dist/tests/lexer/strings.test.d.ts +1 -0
  131. package/dist/tests/lexer/strings.test.js +72 -0
  132. package/dist/tests/lexer/strings.test.js.map +1 -0
  133. package/dist/tests/parser/declarations.test.d.ts +1 -0
  134. package/dist/tests/parser/declarations.test.js +70 -0
  135. package/dist/tests/parser/declarations.test.js.map +1 -0
  136. package/dist/tests/parser/expressions.test.d.ts +1 -0
  137. package/dist/tests/parser/expressions.test.js +47 -0
  138. package/dist/tests/parser/expressions.test.js.map +1 -0
  139. package/dist/tests/parser/helpers.test.d.ts +1 -0
  140. package/dist/tests/parser/helpers.test.js +58 -0
  141. package/dist/tests/parser/helpers.test.js.map +1 -0
  142. package/dist/tests/parser/literals.test.d.ts +1 -0
  143. package/dist/tests/parser/literals.test.js +70 -0
  144. package/dist/tests/parser/literals.test.js.map +1 -0
  145. package/dist/tests/parser/module-syntax.test.d.ts +1 -0
  146. package/dist/tests/parser/module-syntax.test.js +91 -0
  147. package/dist/tests/parser/module-syntax.test.js.map +1 -0
  148. package/dist/tests/parser/statements.test.d.ts +1 -0
  149. package/dist/tests/parser/statements.test.js +85 -0
  150. package/dist/tests/parser/statements.test.js.map +1 -0
  151. package/dist/tests/parser/type-members.test.d.ts +1 -0
  152. package/dist/tests/parser/type-members.test.js +86 -0
  153. package/dist/tests/parser/type-members.test.js.map +1 -0
  154. package/dist/tests/parser/types.test.d.ts +1 -0
  155. package/dist/tests/parser/types.test.js +143 -0
  156. package/dist/tests/parser/types.test.js.map +1 -0
  157. package/package.json +6 -1
  158. package/runtime/ext_node/fs/fs_ops.c +36 -1
  159. package/runtime/rt.h +17 -0
  160. package/runtime/rt_internal.h +88 -2
  161. package/runtime/xt_builtins.c +174 -6
  162. package/runtime/xt_containers.c +234 -42
  163. package/runtime/xt_generator.c +304 -0
  164. package/runtime/xt_io.c +170 -30
  165. package/runtime/xt_promise.c +6 -1
  166. package/runtime/xt_regex.h +105 -35
  167. package/runtime/xt_stdlib/dispatch.inc +255 -4
  168. package/runtime/xt_stdlib/strings.inc +17 -13
  169. package/runtime/xt_stdlib2/arrays.inc +126 -19
  170. package/runtime/xt_stdlib2/date.inc +9 -2
  171. package/runtime/xt_stdlib2/error.inc +162 -12
  172. package/runtime/xt_stdlib2/helpers.inc +4 -0
  173. package/runtime/xt_stdlib2/json.inc +19 -6
  174. package/runtime/xt_stdlib2/number-string-statics.inc +1 -1
  175. package/runtime/xt_stdlib2/numbers.inc +4 -5
  176. package/runtime/xt_stdlib2/objects.inc +29 -0
  177. package/runtime/xt_stdlib2/regexp-match.inc +293 -51
  178. package/runtime/xt_stdlib2/set.inc +58 -2
  179. package/runtime/xt_stdlib2/strings.inc +38 -0
  180. package/runtime/xt_symbol.c +149 -0
  181. package/runtime/xt_values.c +221 -15
  182. package/scripts/build-runtime.ts +1 -1
  183. package/src/ast/expressions.ts +8 -0
  184. package/src/binder/binder.ts +1 -1
  185. package/src/binder/references.ts +47 -4
  186. package/src/binder/types.ts +4 -0
  187. package/src/cli/main.ts +1 -2
  188. package/src/codegen/generator/calls/access.ts +158 -13
  189. package/src/codegen/generator/calls/closures.ts +24 -0
  190. package/src/codegen/generator/calls/invocation.ts +11 -1
  191. package/src/codegen/generator/calls/literals.ts +10 -4
  192. package/src/codegen/generator/calls/super.ts +6 -9
  193. package/src/codegen/generator/context.ts +44 -7
  194. package/src/codegen/generator/expressions/assignment.ts +1 -3
  195. package/src/codegen/generator/expressions/primary.ts +108 -2
  196. package/src/codegen/generator/generator.ts +0 -1
  197. package/src/codegen/generator/module.ts +24 -18
  198. package/src/codegen/generator/state.ts +44 -1
  199. package/src/codegen/generator/statements/control-flow.ts +86 -0
  200. package/src/codegen/generator/statements/dispatch.ts +18 -6
  201. package/src/codegen/generator/statements/loops.ts +29 -11
  202. package/src/codegen/generator/tables.ts +44 -1
  203. package/src/driver/compiler.ts +32 -2
  204. package/src/driver/modules.ts +64 -4
  205. package/src/driver/toolchain.ts +1 -1
  206. package/src/lexer/scanner.ts +0 -1
  207. package/src/parser/declarations/classes.ts +4 -0
  208. package/src/parser/declarations/type-members.ts +0 -2
  209. package/src/parser/expressions.ts +13 -1
  210. package/src/parser/helpers.ts +2 -2
  211. package/src/parser/literals.ts +82 -7
  212. package/src/parser/modules.ts +0 -1
  213. package/src/parser/parser.ts +0 -1
  214. package/src/parser/statements.ts +14 -0
  215. package/src/parser/types.ts +2 -2
@@ -6,9 +6,10 @@
6
6
  * Each module's top-level bindings are renamed to a globally unique name and
7
7
  * imported names are rewritten to the (renamed) exported binding.
8
8
  *
9
- * This is intentionally simple: it supports named imports/exports, `export
10
- * default` for declarations, and `export ... from`. Namespace imports and
11
- * `export *` are approximated, and circular graphs are reported as an error.
9
+ * This is intentionally simple: it supports named imports/exports, namespace
10
+ * imports, `export default` for declarations, `export ... from` and `export *`.
11
+ * Namespace names are live bindings only at the granularity of the module's
12
+ * final names, and circular graphs are reported as an error.
12
13
  */
13
14
 
14
15
  import { existsSync, readFileSync, statSync } from "node:fs";
@@ -21,6 +22,8 @@ import {
21
22
  type Identifier,
22
23
  type ImportDeclaration,
23
24
  type Node,
25
+ type ObjectLiteralExpression,
26
+ type PropertyAssignment,
24
27
  type SourceFileNode,
25
28
  type Statement,
26
29
  type VariableDeclaration,
@@ -284,7 +287,10 @@ export function bundleModules(entryPath: string, diagnostics: DiagnosticBag): Bu
284
287
  }
285
288
  }
286
289
 
287
- // Phase 3: rewrite imported names and record re-exports.
290
+ // Phase 3: rewrite imported names and record re-exports. Namespace imports
291
+ // are lowered to a synthetic object literal holding every export, built
292
+ // from the dependency's (already renamed) final names.
293
+ const namespaceStatements = new Map<Statement, Statement>();
288
294
  for (const record of records) {
289
295
  const scope = moduleScope(record);
290
296
  if (!scope) continue;
@@ -307,6 +313,11 @@ export function bundleModules(entryPath: string, diagnostics: DiagnosticBag): Bu
307
313
  const local = scope.symbols.get(specifier.name.text);
308
314
  if (target && local) renameReferences(local, target);
309
315
  }
316
+ } else if (bindings && bindings.kind === SyntaxKind.NamespaceImport) {
317
+ const local = scope.symbols.get(bindings.name.text);
318
+ const finalName = `${record.prefix}${bindings.name.text}`;
319
+ if (local) renameReferences(local, finalName);
320
+ namespaceStatements.set(statement, namespaceImportToStatement(statement, finalName, dependency));
310
321
  }
311
322
  }
312
323
  }
@@ -320,6 +331,9 @@ export function bundleModules(entryPath: string, diagnostics: DiagnosticBag): Bu
320
331
  // External (extension) imports stay in place for code generation.
321
332
  if (isExternalSpecifier((statement as ImportDeclaration).moduleSpecifier.value)) {
322
333
  merged.push(statement);
334
+ } else {
335
+ const synthetic = namespaceStatements.get(statement);
336
+ if (synthetic) merged.push(synthetic);
323
337
  }
324
338
  continue;
325
339
  }
@@ -383,6 +397,52 @@ function collectBindingIdentifiers(name: import("../ast/declarations.js").Bindin
383
397
  }
384
398
  }
385
399
 
400
+ /** Lower `import * as ns from "./mod"` to `const m0_ns = { ...exports }`. */
401
+ function namespaceImportToStatement(
402
+ statement: Statement,
403
+ finalName: string,
404
+ dependency: ModuleRecord,
405
+ ): Statement {
406
+ const properties: PropertyAssignment[] = [];
407
+ for (const [exportedName, target] of dependency.exports) {
408
+ properties.push({
409
+ kind: SyntaxKind.PropertyAssignment,
410
+ name: { kind: SyntaxKind.Identifier, text: exportedName, start: statement.start, end: statement.start },
411
+ initializer: { kind: SyntaxKind.Identifier, text: target, start: statement.start, end: statement.start },
412
+ start: statement.start,
413
+ end: statement.start,
414
+ });
415
+ }
416
+ const initializer: ObjectLiteralExpression = {
417
+ kind: SyntaxKind.ObjectLiteralExpression,
418
+ properties,
419
+ start: statement.start,
420
+ end: statement.end,
421
+ };
422
+ const declaration: VariableDeclaration = {
423
+ kind: SyntaxKind.VariableDeclaration,
424
+ name: { kind: SyntaxKind.Identifier, text: finalName, start: statement.start, end: statement.start },
425
+ exclamation: false,
426
+ initializer,
427
+ start: statement.start,
428
+ end: statement.end,
429
+ };
430
+ const list: VariableDeclarationList = {
431
+ kind: SyntaxKind.VariableDeclarationList,
432
+ declarationKind: "const" as const,
433
+ declarations: [declaration],
434
+ start: statement.start,
435
+ end: statement.end,
436
+ };
437
+ return {
438
+ kind: SyntaxKind.VariableStatement,
439
+ declarationList: list,
440
+ modifiers: [],
441
+ start: statement.start,
442
+ end: statement.end,
443
+ };
444
+ }
445
+
386
446
  /** Turn `export default expr` into a synthetic `const` declaration. */
387
447
  function exportAssignmentToStatement(record: ModuleRecord, assignment: ExportAssignment): Statement {
388
448
  const name: Identifier = {
@@ -114,7 +114,7 @@ export function compileC(
114
114
  ): void {
115
115
  const result = runner.run(
116
116
  clang,
117
- ["-O2", "-D_CRT_SECURE_NO_WARNINGS", "-c", sourcePath, "-o", objectPath, `-I${includeDir}`],
117
+ ["-O2", "-Wall", "-Wextra", "-D_CRT_SECURE_NO_WARNINGS", "-c", sourcePath, "-o", objectPath, `-I${includeDir}`],
118
118
  { env },
119
119
  );
120
120
  if (result.status !== 0) throw new ToolchainError(`${clang} ${sourcePath}`, result.status, result.stderr);
@@ -168,7 +168,6 @@ export class Scanner {
168
168
  }
169
169
  }
170
170
 
171
- // eslint-disable-next-line @typescript-eslint/no-empty-interface
172
171
  export interface Scanner
173
172
  extends IdentifierMethods,
174
173
  NumberMethods,
@@ -196,6 +196,10 @@ export const declarationClassMethods: DeclarationClassMethods = {
196
196
 
197
197
  parsePropertyName(this: Parser): PropertyName {
198
198
  const token = this.token;
199
+ if (token.kind === TokenKind.PrivateIdentifier) {
200
+ this.nextToken();
201
+ return { kind: SyntaxKind.PrivateIdentifier, text: token.text, start: token.start, end: token.end };
202
+ }
199
203
  if (token.kind === TokenKind.StringLiteral) {
200
204
  this.nextToken();
201
205
  return { kind: SyntaxKind.StringLiteral, text: token.text, raw: token.text, value: String(token.value ?? ""), start: token.start, end: token.end };
@@ -11,13 +11,11 @@ import {
11
11
  type EnumMember,
12
12
  type Expression,
13
13
  type Identifier,
14
- type IndexSignature,
15
14
  type InterfaceDeclaration,
16
15
  type MethodSignature,
17
16
  type Modifier,
18
17
  type ModuleDeclaration,
19
18
  type Parameter,
20
- type PropertyName,
21
19
  type PropertySignature,
22
20
  type StringLiteral,
23
21
  type TypeAliasDeclaration,
@@ -19,6 +19,7 @@ import {
19
19
  type CallExpression,
20
20
  type ConditionalExpression,
21
21
  type Expression,
22
+ type Identifier,
22
23
  type NewExpression,
23
24
  type NumericLiteral,
24
25
  type Parameter,
@@ -54,6 +55,7 @@ export interface ExpressionMethods {
54
55
  parseCallAndMemberTail(this: Parser, base: Expression): Expression;
55
56
  previousEnd(this: Parser, args: readonly Expression[], fallback: number): number;
56
57
  parsePropertyAccess(this: Parser, expression: Expression): Expression;
58
+ parseMemberName(this: Parser): Identifier;
57
59
  parseArguments(this: Parser): Expression[];
58
60
  }
59
61
 
@@ -459,10 +461,20 @@ export const expressionMethods: ExpressionMethods = {
459
461
  const close = this.parseExpected(TokenKind.CloseBracket);
460
462
  return { kind: SyntaxKind.ElementAccessExpression, expression, argumentExpression: argument, optional: true, start: expression.start, end: close.end };
461
463
  }
462
- const name = this.parseIdentifierName();
464
+ const name = this.parseMemberName();
463
465
  return { kind: SyntaxKind.PropertyAccessExpression, expression, name, optional, start: expression.start, end: name.end };
464
466
  },
465
467
 
468
+ /** Member name after `.`: a normal identifier or a `#private` name. */
469
+ parseMemberName(this: Parser): Identifier {
470
+ const token = this.token;
471
+ if (token.kind === TokenKind.PrivateIdentifier) {
472
+ this.nextToken();
473
+ return { kind: SyntaxKind.Identifier, text: token.text, escaped: true, start: token.start, end: token.end };
474
+ }
475
+ return this.parseIdentifierName();
476
+ },
477
+
466
478
  parseArguments(this: Parser): Expression[] {
467
479
  this.parseExpected(TokenKind.OpenParen);
468
480
  const args: Expression[] = [];
@@ -36,12 +36,12 @@ export function propertyNameText(name: PropertyName): string {
36
36
 
37
37
  export function isAssignmentTarget(expr: Expression): boolean {
38
38
  switch (expr.kind) {
39
+ // Array/object literals are valid on the left of `=` as destructuring
40
+ // patterns (`[a, b] = xs`, `({ a } = obj)`).
39
41
  case SyntaxKind.Identifier:
40
42
  case SyntaxKind.PropertyAccessExpression:
41
43
  case SyntaxKind.ElementAccessExpression:
42
44
  case SyntaxKind.ParenthesizedExpression:
43
- // Array/object literals are valid on the left of `=` as destructuring
44
- // patterns (`[a, b] = xs`, `({ a } = obj)`).
45
45
  case SyntaxKind.ArrayLiteralExpression:
46
46
  case SyntaxKind.ObjectLiteralExpression:
47
47
  return true;
@@ -33,6 +33,12 @@ export interface LiteralMethods {
33
33
  parseRegularExpression(this: Parser): RegularExpressionLiteral;
34
34
  }
35
35
 
36
+ /** Strip the delimiters from a scanned template chunk and normalize newlines. */
37
+ function rawTemplateChunk(text: string, leading: number, trailing: number): string {
38
+ const end = Math.max(leading, text.length - trailing);
39
+ return text.slice(leading, end).replace(/\r\n?/g, "\n");
40
+ }
41
+
36
42
  export const literalMethods: LiteralMethods = {
37
43
  parseArrayLiteral(this: Parser): ArrayLiteralExpression {
38
44
  const open = this.parseExpected(TokenKind.OpenBracket);
@@ -66,6 +72,50 @@ export const literalMethods: LiteralMethods = {
66
72
  const start = this.nextToken().start;
67
73
  const expression = this.parseAssignmentExpression();
68
74
  properties.push({ kind: SyntaxKind.SpreadElement, expression, start, end: expression.end });
75
+ } else if (
76
+ (this.at(TokenKind.GetKeyword) || this.at(TokenKind.SetKeyword)) &&
77
+ !this.atAhead(1, TokenKind.OpenParen) &&
78
+ !this.atAhead(1, TokenKind.Colon) &&
79
+ !this.atAhead(1, TokenKind.Comma) &&
80
+ !this.atAhead(1, TokenKind.CloseBrace) &&
81
+ !this.atAhead(1, TokenKind.Equals) &&
82
+ !this.atAhead(1, TokenKind.Question) &&
83
+ !this.atAhead(1, TokenKind.LessThan)
84
+ ) {
85
+ // `{ get x() {} }` / `{ set x(v) {} }` object-literal accessors.
86
+ const start = this.token.start;
87
+ const accessorToken = this.nextToken();
88
+ const name = this.parsePropertyName();
89
+ const parameters = this.parseParameters();
90
+ let returnType: TypeNode | undefined;
91
+ if (this.at(TokenKind.Colon)) {
92
+ this.nextToken();
93
+ returnType = this.parseReturnType();
94
+ }
95
+ const body = this.parseBlock();
96
+ const fn: FunctionExpression = { kind: SyntaxKind.FunctionExpression, typeParameters: [], parameters, returnType, body, flags: NodeFlags.None, start, end: body.end };
97
+ properties.push({
98
+ kind: SyntaxKind.PropertyAssignment,
99
+ name,
100
+ initializer: fn,
101
+ accessor: accessorToken.kind === TokenKind.GetKeyword ? "get" : "set",
102
+ start,
103
+ end: body.end,
104
+ });
105
+ } else if (this.at(TokenKind.Asterisk)) {
106
+ // `{ *gen() {} }` object-literal generator method.
107
+ const start = this.nextToken().start;
108
+ const name = this.parsePropertyName();
109
+ const typeParameters = this.at(TokenKind.LessThan) ? this.parseTypeParameters() : [];
110
+ const parameters = this.parseParameters();
111
+ let returnType: TypeNode | undefined;
112
+ if (this.at(TokenKind.Colon)) {
113
+ this.nextToken();
114
+ returnType = this.parseReturnType();
115
+ }
116
+ const body = this.parseBlock();
117
+ const fn: FunctionExpression = { kind: SyntaxKind.FunctionExpression, typeParameters, parameters, returnType, body, flags: NodeFlags.Generator, start, end: body.end };
118
+ properties.push({ kind: SyntaxKind.PropertyAssignment, name, initializer: fn, start, end: body.end });
69
119
  } else {
70
120
  const start = this.token.start;
71
121
  const name = this.parsePropertyName();
@@ -142,7 +192,14 @@ export const literalMethods: LiteralMethods = {
142
192
  const startToken = this.token;
143
193
  if (startToken.kind === TokenKind.NoSubstitutionTemplateLiteral) {
144
194
  this.nextToken();
145
- return { kind: SyntaxKind.NoSubstitutionTemplateLiteral, text: startToken.text, value: String(startToken.value ?? ""), start: startToken.start, end: startToken.end } as unknown as TemplateLiteral;
195
+ return {
196
+ kind: SyntaxKind.NoSubstitutionTemplateLiteral,
197
+ text: startToken.text,
198
+ value: String(startToken.value ?? ""),
199
+ raw: rawTemplateChunk(startToken.text, 1, 1),
200
+ start: startToken.start,
201
+ end: startToken.end,
202
+ } as unknown as TemplateLiteral;
146
203
  }
147
204
  if (startToken.kind === TokenKind.Backtick) {
148
205
  // Re-scan from the backtick so the scanner produces a TemplateHead.
@@ -150,14 +207,16 @@ export const literalMethods: LiteralMethods = {
150
207
  this.tokens = [this.scanner.nextToken()];
151
208
  this.index = 0;
152
209
  return this.parseTemplateLiteral();
153
- } const head = String(startToken.value ?? "");
210
+ }
211
+ const head = String(startToken.value ?? "");
212
+ const headRaw = rawTemplateChunk(startToken.text, 1, 2);
154
213
  this.nextToken();
155
214
  const spans: TemplateSpan[] = [];
156
215
  for (;;) {
157
216
  const expression = this.parseExpression();
158
217
  if (!this.at(TokenKind.CloseBrace)) {
159
218
  this.error(DiagnosticCode.UnterminatedTemplate, "Expected '}' to close template substitution");
160
- return { kind: SyntaxKind.TemplateLiteral, head, spans, start: startToken.start, end: this.token.end };
219
+ return { kind: SyntaxKind.TemplateLiteral, head, raw: headRaw, spans, start: startToken.start, end: this.token.end };
161
220
  }
162
221
  // The `}` terminates a substitution; re-read it as template text without
163
222
  // first scanning the following (template) characters as normal tokens.
@@ -167,16 +226,32 @@ export const literalMethods: LiteralMethods = {
167
226
  const literalToken = this.token;
168
227
  if (literalToken.kind === TokenKind.NoSubstitutionTemplateLiteral) {
169
228
  this.nextToken();
170
- spans.push({ kind: SyntaxKind.TemplateSpan, expression, literal: String(literalToken.value ?? ""), isTail: true, start: expression.start, end: literalToken.end });
171
- return { kind: SyntaxKind.TemplateLiteral, head, spans, start: startToken.start, end: literalToken.end };
229
+ spans.push({
230
+ kind: SyntaxKind.TemplateSpan,
231
+ expression,
232
+ literal: String(literalToken.value ?? ""),
233
+ raw: rawTemplateChunk(literalToken.text, 0, 1),
234
+ isTail: true,
235
+ start: expression.start,
236
+ end: literalToken.end,
237
+ });
238
+ return { kind: SyntaxKind.TemplateLiteral, head, raw: headRaw, spans, start: startToken.start, end: literalToken.end };
172
239
  }
173
240
  if (literalToken.kind === TokenKind.TemplateHead) {
174
241
  this.nextToken();
175
- spans.push({ kind: SyntaxKind.TemplateSpan, expression, literal: String(literalToken.value ?? ""), isTail: false, start: expression.start, end: literalToken.end });
242
+ spans.push({
243
+ kind: SyntaxKind.TemplateSpan,
244
+ expression,
245
+ literal: String(literalToken.value ?? ""),
246
+ raw: rawTemplateChunk(literalToken.text, 0, 2),
247
+ isTail: false,
248
+ start: expression.start,
249
+ end: literalToken.end,
250
+ });
176
251
  continue;
177
252
  }
178
253
  this.error(DiagnosticCode.UnterminatedTemplate, "Unterminated template literal", literalToken);
179
- return { kind: SyntaxKind.TemplateLiteral, head, spans, start: startToken.start, end: literalToken.end };
254
+ return { kind: SyntaxKind.TemplateLiteral, head, raw: headRaw, spans, start: startToken.start, end: literalToken.end };
180
255
  }
181
256
  },
182
257
 
@@ -13,7 +13,6 @@ import {
13
13
  type ImportClause,
14
14
  type ImportDeclaration,
15
15
  type ImportSpecifier,
16
- type Modifier,
17
16
  type NamedExports,
18
17
  type NamedImports,
19
18
  type NamespaceImport,
@@ -24,7 +24,6 @@ export class Parser extends ParserContext {
24
24
  const statements: Statement[] = [];
25
25
  while (!this.at(TokenKind.EndOfFile)) {
26
26
  const before = this.consumed;
27
- const beforePos = this.scanner.position;
28
27
  const statement = this.parseStatement();
29
28
  if (statement) statements.push(statement);
30
29
  if (this.consumed === before) {
@@ -43,6 +43,7 @@ export interface StatementMethods {
43
43
  parseDoStatement(this: Parser): Statement;
44
44
  parseForStatement(this: Parser): ForStatement | ForOfStatement | ForInStatement;
45
45
  parseReturnStatement(this: Parser): Statement;
46
+ parseLabeledStatement(this: Parser): Statement;
46
47
  parseBreakStatement(this: Parser): Statement;
47
48
  parseContinueStatement(this: Parser): Statement;
48
49
  parseThrowStatement(this: Parser): Statement;
@@ -60,6 +61,8 @@ export const statementMethods: StatementMethods = {
60
61
  const kind = this.token.kind;
61
62
  const nextKind = this.lookAhead(1).kind;
62
63
  const nextStartsName =
64
+ nextKind === TokenKind.Identifier ||
65
+ nextKind === TokenKind.PrivateIdentifier ||
63
66
  isIdentifierNameToken(nextKind) ||
64
67
  isKeywordKind(nextKind) ||
65
68
  nextKind === TokenKind.OpenBracket ||
@@ -126,6 +129,9 @@ export const statementMethods: StatementMethods = {
126
129
 
127
130
  parseStatement(this: Parser): Statement | undefined {
128
131
  const token = this.token;
132
+ if (this.isIdentifierLike(token) && this.atAhead(1, TokenKind.Colon)) {
133
+ return this.parseLabeledStatement();
134
+ }
129
135
  switch (token.kind) {
130
136
  case TokenKind.OpenBrace:
131
137
  return this.parseBlock();
@@ -381,6 +387,14 @@ export const statementMethods: StatementMethods = {
381
387
  return { kind: SyntaxKind.ReturnStatement, expression, start, end: expression?.end ?? start + 6 } as Statement;
382
388
  },
383
389
 
390
+ parseLabeledStatement(this: Parser): Statement {
391
+ const label = this.parseIdentifier();
392
+ this.parseExpected(TokenKind.Colon);
393
+ const statement = this.parseStatement();
394
+ const node = statement ?? ({ kind: SyntaxKind.EmptyStatement, start: label.end, end: label.end } as Statement);
395
+ return { kind: SyntaxKind.LabeledStatement, label, statement: node, start: label.start, end: node.end } as Statement;
396
+ },
397
+
384
398
  parseBreakStatement(this: Parser): Statement {
385
399
  const start = this.parseExpected(TokenKind.BreakKeyword).start;
386
400
  let label: Identifier | undefined;
@@ -330,13 +330,13 @@ export const typeMethods: TypeMethods = {
330
330
  if (this.atAhead(1, TokenKind.OpenBracket)) {
331
331
  cursor = 1;
332
332
  if (this.atAhead(2, TokenKind.Identifier)) {
333
- let i = 3;
333
+ const i = 3;
334
334
  if (this.lookAhead(i).kind === TokenKind.InKeyword) {
335
335
  const open = this.parseExpected(TokenKind.OpenBrace);
336
336
  this.parseExpected(TokenKind.OpenBracket);
337
337
  const name = this.parseIdentifier();
338
338
  this.parseExpected(TokenKind.InKeyword);
339
- let constraint = this.parseType();
339
+ const constraint = this.parseType();
340
340
  this.parseExpected(TokenKind.CloseBracket);
341
341
  let questionToken: boolean | "+" | "-" = false;
342
342
  if (this.at(TokenKind.Question)) {