@tsonic/frontend 0.0.31 → 0.0.33

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 (83) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/dotnet-metadata.d.ts +47 -5
  3. package/dist/dotnet-metadata.d.ts.map +1 -1
  4. package/dist/dotnet-metadata.js +131 -31
  5. package/dist/dotnet-metadata.js.map +1 -1
  6. package/dist/dotnet-metadata.test.d.ts +2 -0
  7. package/dist/dotnet-metadata.test.d.ts.map +1 -0
  8. package/dist/dotnet-metadata.test.js +121 -0
  9. package/dist/dotnet-metadata.test.js.map +1 -0
  10. package/dist/ir/converters/expressions/calls.d.ts.map +1 -1
  11. package/dist/ir/converters/expressions/calls.js +33 -0
  12. package/dist/ir/converters/expressions/calls.js.map +1 -1
  13. package/dist/ir/converters/expressions/operators.js +2 -2
  14. package/dist/ir/converters/expressions/operators.js.map +1 -1
  15. package/dist/ir/converters/flow-narrowing.d.ts +4 -3
  16. package/dist/ir/converters/flow-narrowing.d.ts.map +1 -1
  17. package/dist/ir/converters/flow-narrowing.js +28 -5
  18. package/dist/ir/converters/flow-narrowing.js.map +1 -1
  19. package/dist/ir/converters/statements/control/conditionals.js +3 -3
  20. package/dist/ir/converters/statements/control/conditionals.js.map +1 -1
  21. package/dist/ir/converters/statements/declarations/classes/methods.d.ts +8 -1
  22. package/dist/ir/converters/statements/declarations/classes/methods.d.ts.map +1 -1
  23. package/dist/ir/converters/statements/declarations/classes/methods.js +730 -57
  24. package/dist/ir/converters/statements/declarations/classes/methods.js.map +1 -1
  25. package/dist/ir/converters/statements/declarations/classes/orchestrator.d.ts.map +1 -1
  26. package/dist/ir/converters/statements/declarations/classes/orchestrator.js +38 -9
  27. package/dist/ir/converters/statements/declarations/classes/orchestrator.js.map +1 -1
  28. package/dist/ir/converters/statements/declarations/classes/override-detection.d.ts +8 -1
  29. package/dist/ir/converters/statements/declarations/classes/override-detection.d.ts.map +1 -1
  30. package/dist/ir/converters/statements/declarations/classes/override-detection.js +101 -13
  31. package/dist/ir/converters/statements/declarations/classes/override-detection.js.map +1 -1
  32. package/dist/ir/converters/statements/declarations/classes/properties.d.ts.map +1 -1
  33. package/dist/ir/converters/statements/declarations/classes/properties.js +17 -2
  34. package/dist/ir/converters/statements/declarations/classes/properties.js.map +1 -1
  35. package/dist/ir/types/helpers.d.ts +1 -1
  36. package/dist/ir/types/helpers.d.ts.map +1 -1
  37. package/dist/ir/types/index.d.ts +1 -1
  38. package/dist/ir/types/index.d.ts.map +1 -1
  39. package/dist/ir/types/index.js.map +1 -1
  40. package/dist/ir/types/ir-types.d.ts +5 -1
  41. package/dist/ir/types/ir-types.d.ts.map +1 -1
  42. package/dist/ir/types/statements.d.ts +5 -4
  43. package/dist/ir/types/statements.d.ts.map +1 -1
  44. package/dist/ir/types.d.ts +1 -1
  45. package/dist/ir/types.d.ts.map +1 -1
  46. package/dist/ir/types.js.map +1 -1
  47. package/dist/ir/validation/anonymous-type-lowering-pass.d.ts.map +1 -1
  48. package/dist/ir/validation/anonymous-type-lowering-pass.js +22 -3
  49. package/dist/ir/validation/anonymous-type-lowering-pass.js.map +1 -1
  50. package/dist/ir/validation/attribute-collection-pass.d.ts.map +1 -1
  51. package/dist/ir/validation/attribute-collection-pass.js +28 -2
  52. package/dist/ir/validation/attribute-collection-pass.js.map +1 -1
  53. package/dist/ir/validation/numeric-coercion-pass.d.ts.map +1 -1
  54. package/dist/ir/validation/numeric-coercion-pass.js +13 -3
  55. package/dist/ir/validation/numeric-coercion-pass.js.map +1 -1
  56. package/dist/ir/validation/numeric-coercion-pass.test.d.ts +2 -0
  57. package/dist/ir/validation/numeric-coercion-pass.test.d.ts.map +1 -0
  58. package/dist/ir/validation/numeric-coercion-pass.test.js +53 -0
  59. package/dist/ir/validation/numeric-coercion-pass.test.js.map +1 -0
  60. package/dist/ir/validation/rest-type-synthesis-pass.d.ts.map +1 -1
  61. package/dist/ir/validation/rest-type-synthesis-pass.js +70 -22
  62. package/dist/ir/validation/rest-type-synthesis-pass.js.map +1 -1
  63. package/dist/ir/validation/soundness-gate.d.ts.map +1 -1
  64. package/dist/ir/validation/soundness-gate.js +5 -0
  65. package/dist/ir/validation/soundness-gate.js.map +1 -1
  66. package/dist/ir/validation/virtual-marking-pass.d.ts +2 -2
  67. package/dist/ir/validation/virtual-marking-pass.d.ts.map +1 -1
  68. package/dist/ir/validation/virtual-marking-pass.js +26 -6
  69. package/dist/ir/validation/virtual-marking-pass.js.map +1 -1
  70. package/dist/program/bindings.d.ts +8 -0
  71. package/dist/program/bindings.d.ts.map +1 -1
  72. package/dist/program/bindings.js +37 -3
  73. package/dist/program/bindings.js.map +1 -1
  74. package/dist/program/dependency-graph.d.ts.map +1 -1
  75. package/dist/program/dependency-graph.js +9 -1
  76. package/dist/program/dependency-graph.js.map +1 -1
  77. package/dist/types/diagnostic.d.ts +1 -1
  78. package/dist/types/diagnostic.d.ts.map +1 -1
  79. package/dist/types/diagnostic.js.map +1 -1
  80. package/dist/validation/core-intrinsics.d.ts.map +1 -1
  81. package/dist/validation/core-intrinsics.js +2 -0
  82. package/dist/validation/core-intrinsics.js.map +1 -1
  83. package/package.json +1 -1
@@ -5,66 +5,23 @@ import * as ts from "typescript";
5
5
  import { convertBlockStatement } from "../../control.js";
6
6
  import { hasStaticModifier, getAccessibility, convertTypeParameters, convertParameters, } from "../../helpers.js";
7
7
  import { detectOverride } from "./override-detection.js";
8
- /**
9
- * DETERMINISTIC: Convert a TypeNode to a string for signature matching.
10
- * Uses only AST structure, not TypeScript's type inference.
11
- */
12
- const typeNodeToSignatureString = (typeNode) => {
13
- // Handle type references: Foo, List<T>, etc.
14
- if (ts.isTypeReferenceNode(typeNode)) {
15
- // EntityName is Identifier | QualifiedName - handle both
16
- const name = ts.isIdentifier(typeNode.typeName)
17
- ? typeNode.typeName.text
18
- : typeNode.typeName.right.text; // QualifiedName: get rightmost identifier
19
- return name;
20
- }
21
- // Handle keyword types
22
- switch (typeNode.kind) {
23
- case ts.SyntaxKind.NumberKeyword:
24
- return "number";
25
- case ts.SyntaxKind.StringKeyword:
26
- return "string";
27
- case ts.SyntaxKind.BooleanKeyword:
28
- return "boolean";
29
- case ts.SyntaxKind.VoidKeyword:
30
- return "void";
31
- case ts.SyntaxKind.AnyKeyword:
32
- return "any";
33
- case ts.SyntaxKind.UnknownKeyword:
34
- return "unknown";
35
- case ts.SyntaxKind.NeverKeyword:
36
- return "never";
37
- case ts.SyntaxKind.ObjectKeyword:
38
- return "object";
39
- case ts.SyntaxKind.SymbolKeyword:
40
- return "symbol";
41
- case ts.SyntaxKind.BigIntKeyword:
42
- return "bigint";
43
- case ts.SyntaxKind.UndefinedKeyword:
44
- return "undefined";
45
- case ts.SyntaxKind.NullKeyword:
46
- return "null";
47
- }
48
- // Handle array types: T[]
49
- if (ts.isArrayTypeNode(typeNode)) {
50
- return `${typeNodeToSignatureString(typeNode.elementType)}[]`;
51
- }
52
- // For other complex types, fall back to any
53
- return "any";
54
- };
55
8
  /**
56
9
  * Convert method declaration to IR
57
10
  */
58
11
  export const convertMethod = (node, ctx, superClass) => {
59
12
  const memberName = ts.isIdentifier(node.name) ? node.name.text : "[computed]";
60
- // DETERMINISTIC: Extract parameter types directly from TypeNodes
61
- const parameterTypes = node.parameters.map((param) => {
62
- if (param.type) {
63
- return typeNodeToSignatureString(param.type);
64
- }
65
- return "any";
66
- });
67
- const overrideInfo = detectOverride(memberName, "method", superClass, ctx, parameterTypes);
13
+ const parameters = convertParameters(node.parameters, ctx);
14
+ const overrideInfo = detectOverride(memberName, "method", superClass, ctx, parameters);
15
+ const declaredAccessibility = getAccessibility(node);
16
+ const accessibility = (() => {
17
+ if (!overrideInfo.isOverride || !overrideInfo.requiredAccessibility) {
18
+ return declaredAccessibility;
19
+ }
20
+ // Airplane-grade: always emit CLR-required accessibility for overrides.
21
+ // The TS surface may lose access modifiers (e.g., protected members exposed as callable
22
+ // overloads to avoid unstable renames like Dispose2), but C# compilation enforces the truth.
23
+ return overrideInfo.requiredAccessibility;
24
+ })();
68
25
  // Get return type from declared annotation for contextual typing
69
26
  // PHASE 4 (Alice's spec): Use captureTypeSyntax + typeFromSyntax
70
27
  const returnType = node.type
@@ -74,7 +31,7 @@ export const convertMethod = (node, ctx, superClass) => {
74
31
  kind: "methodDeclaration",
75
32
  name: memberName,
76
33
  typeParameters: convertTypeParameters(node.typeParameters, ctx),
77
- parameters: convertParameters(node.parameters, ctx),
34
+ parameters,
78
35
  returnType,
79
36
  // Pass return type to body for contextual typing of return statements
80
37
  body: node.body
@@ -83,9 +40,725 @@ export const convertMethod = (node, ctx, superClass) => {
83
40
  isStatic: hasStaticModifier(node),
84
41
  isAsync: !!node.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword),
85
42
  isGenerator: !!node.asteriskToken,
86
- accessibility: getAccessibility(node),
43
+ accessibility,
87
44
  isOverride: overrideInfo.isOverride ? true : undefined,
88
45
  isShadow: overrideInfo.isShadow ? true : undefined,
89
46
  };
90
47
  };
48
+ const primitiveTypeToClrName = (name) => {
49
+ switch (name) {
50
+ case "string":
51
+ return "System.String";
52
+ case "number":
53
+ return "System.Double";
54
+ case "boolean":
55
+ return "System.Boolean";
56
+ case "int":
57
+ return "System.Int32";
58
+ case "char":
59
+ return "System.Char";
60
+ default:
61
+ return undefined;
62
+ }
63
+ };
64
+ const getClrName = (type) => {
65
+ if (type.kind !== "referenceType")
66
+ return undefined;
67
+ return type.resolvedClrType ?? type.typeId?.clrName;
68
+ };
69
+ const typesEqualForIsType = (a, b) => {
70
+ if (!a || !b)
71
+ return false;
72
+ // Bridge primitive types to their canonical CLR types (System.String etc).
73
+ if (a.kind === "primitiveType" && b.kind === "referenceType") {
74
+ const clr = getClrName(b);
75
+ const expected = primitiveTypeToClrName(a.name);
76
+ return !!expected && clr === expected;
77
+ }
78
+ if (a.kind === "referenceType" && b.kind === "primitiveType") {
79
+ const clr = getClrName(a);
80
+ const expected = primitiveTypeToClrName(b.name);
81
+ return !!expected && clr === expected;
82
+ }
83
+ if (a.kind !== b.kind)
84
+ return false;
85
+ switch (a.kind) {
86
+ case "primitiveType":
87
+ return b.kind === "primitiveType" && a.name === b.name;
88
+ case "typeParameterType":
89
+ return b.kind === "typeParameterType" && a.name === b.name;
90
+ case "arrayType":
91
+ return b.kind === "arrayType" && typesEqualForIsType(a.elementType, b.elementType);
92
+ case "referenceType": {
93
+ if (b.kind !== "referenceType")
94
+ return false;
95
+ const aStable = a.typeId?.stableId ?? a.resolvedClrType;
96
+ const bStable = b.typeId?.stableId ?? b.resolvedClrType;
97
+ if (aStable && bStable)
98
+ return aStable === bStable;
99
+ if (a.name !== b.name)
100
+ return false;
101
+ const aArgs = a.typeArguments ?? [];
102
+ const bArgs = b.typeArguments ?? [];
103
+ if (aArgs.length !== bArgs.length)
104
+ return false;
105
+ for (let i = 0; i < aArgs.length; i++) {
106
+ if (!typesEqualForIsType(aArgs[i], bArgs[i]))
107
+ return false;
108
+ }
109
+ return true;
110
+ }
111
+ default:
112
+ // isType is only supported for primitive/array/nominal/type-param equality during overload specialization.
113
+ return false;
114
+ }
115
+ };
116
+ const specializeExpression = (expr, paramTypesByDeclId) => {
117
+ switch (expr.kind) {
118
+ case "literal":
119
+ case "identifier":
120
+ case "this":
121
+ return expr;
122
+ case "call": {
123
+ const callee = specializeExpression(expr.callee, paramTypesByDeclId);
124
+ const args = expr.arguments.map((a) => a.kind === "spread"
125
+ ? { ...a, expression: specializeExpression(a.expression, paramTypesByDeclId) }
126
+ : specializeExpression(a, paramTypesByDeclId));
127
+ // Compile-time-only isType<T>(param)
128
+ if (callee.kind === "identifier" &&
129
+ callee.name === "isType" &&
130
+ expr.typeArguments &&
131
+ expr.typeArguments.length === 1 &&
132
+ args.length === 1 &&
133
+ args[0]?.kind === "identifier" &&
134
+ args[0].declId) {
135
+ const target = expr.typeArguments[0];
136
+ const actual = paramTypesByDeclId.get(args[0].declId.id);
137
+ const value = typesEqualForIsType(actual, target);
138
+ return { kind: "literal", value, inferredType: { kind: "primitiveType", name: "boolean" }, sourceSpan: expr.sourceSpan };
139
+ }
140
+ return { ...expr, callee, arguments: args };
141
+ }
142
+ case "new":
143
+ return {
144
+ ...expr,
145
+ callee: specializeExpression(expr.callee, paramTypesByDeclId),
146
+ arguments: expr.arguments.map((a) => a.kind === "spread"
147
+ ? { ...a, expression: specializeExpression(a.expression, paramTypesByDeclId) }
148
+ : specializeExpression(a, paramTypesByDeclId)),
149
+ };
150
+ case "functionExpression":
151
+ return {
152
+ ...expr,
153
+ body: specializeStatement(expr.body, paramTypesByDeclId),
154
+ };
155
+ case "arrowFunction":
156
+ return {
157
+ ...expr,
158
+ body: expr.body.kind === "blockStatement"
159
+ ? specializeStatement(expr.body, paramTypesByDeclId)
160
+ : specializeExpression(expr.body, paramTypesByDeclId),
161
+ };
162
+ case "unary": {
163
+ const inner = specializeExpression(expr.expression, paramTypesByDeclId);
164
+ if (expr.operator === "!" && inner.kind === "literal" && typeof inner.value === "boolean") {
165
+ return { kind: "literal", value: !inner.value, inferredType: { kind: "primitiveType", name: "boolean" }, sourceSpan: expr.sourceSpan };
166
+ }
167
+ return { ...expr, expression: inner };
168
+ }
169
+ case "logical": {
170
+ const left = specializeExpression(expr.left, paramTypesByDeclId);
171
+ if (left.kind === "literal" && typeof left.value === "boolean") {
172
+ if (expr.operator === "&&") {
173
+ if (left.value === false) {
174
+ return { kind: "literal", value: false, inferredType: { kind: "primitiveType", name: "boolean" }, sourceSpan: expr.sourceSpan };
175
+ }
176
+ return specializeExpression(expr.right, paramTypesByDeclId);
177
+ }
178
+ if (expr.operator === "||") {
179
+ if (left.value === true) {
180
+ return { kind: "literal", value: true, inferredType: { kind: "primitiveType", name: "boolean" }, sourceSpan: expr.sourceSpan };
181
+ }
182
+ return specializeExpression(expr.right, paramTypesByDeclId);
183
+ }
184
+ }
185
+ const right = specializeExpression(expr.right, paramTypesByDeclId);
186
+ return { ...expr, left, right };
187
+ }
188
+ case "binary":
189
+ return {
190
+ ...expr,
191
+ left: specializeExpression(expr.left, paramTypesByDeclId),
192
+ right: specializeExpression(expr.right, paramTypesByDeclId),
193
+ };
194
+ case "conditional":
195
+ return {
196
+ ...expr,
197
+ condition: specializeExpression(expr.condition, paramTypesByDeclId),
198
+ whenTrue: specializeExpression(expr.whenTrue, paramTypesByDeclId),
199
+ whenFalse: specializeExpression(expr.whenFalse, paramTypesByDeclId),
200
+ };
201
+ case "assignment":
202
+ return {
203
+ ...expr,
204
+ right: specializeExpression(expr.right, paramTypesByDeclId),
205
+ };
206
+ case "templateLiteral":
207
+ return {
208
+ ...expr,
209
+ expressions: expr.expressions.map((e) => specializeExpression(e, paramTypesByDeclId)),
210
+ };
211
+ case "spread":
212
+ return {
213
+ ...expr,
214
+ expression: specializeExpression(expr.expression, paramTypesByDeclId),
215
+ };
216
+ case "await":
217
+ return {
218
+ ...expr,
219
+ expression: specializeExpression(expr.expression, paramTypesByDeclId),
220
+ };
221
+ case "yield":
222
+ return {
223
+ ...expr,
224
+ expression: expr.expression
225
+ ? specializeExpression(expr.expression, paramTypesByDeclId)
226
+ : undefined,
227
+ };
228
+ case "numericNarrowing":
229
+ return {
230
+ ...expr,
231
+ expression: specializeExpression(expr.expression, paramTypesByDeclId),
232
+ };
233
+ case "typeAssertion":
234
+ return {
235
+ ...expr,
236
+ expression: specializeExpression(expr.expression, paramTypesByDeclId),
237
+ };
238
+ case "trycast":
239
+ return {
240
+ ...expr,
241
+ expression: specializeExpression(expr.expression, paramTypesByDeclId),
242
+ };
243
+ case "stackalloc":
244
+ return {
245
+ ...expr,
246
+ size: specializeExpression(expr.size, paramTypesByDeclId),
247
+ };
248
+ case "memberAccess":
249
+ return {
250
+ ...expr,
251
+ object: specializeExpression(expr.object, paramTypesByDeclId),
252
+ property: typeof expr.property === "string"
253
+ ? expr.property
254
+ : specializeExpression(expr.property, paramTypesByDeclId),
255
+ };
256
+ case "array":
257
+ return {
258
+ ...expr,
259
+ elements: expr.elements.map((e) => e
260
+ ? e.kind === "spread"
261
+ ? { ...e, expression: specializeExpression(e.expression, paramTypesByDeclId) }
262
+ : specializeExpression(e, paramTypesByDeclId)
263
+ : undefined),
264
+ };
265
+ case "object":
266
+ return {
267
+ ...expr,
268
+ properties: expr.properties.map((p) => p.kind === "spread"
269
+ ? { ...p, expression: specializeExpression(p.expression, paramTypesByDeclId) }
270
+ : {
271
+ ...p,
272
+ key: typeof p.key === "string" ? p.key : specializeExpression(p.key, paramTypesByDeclId),
273
+ value: specializeExpression(p.value, paramTypesByDeclId),
274
+ }),
275
+ };
276
+ case "update":
277
+ return {
278
+ ...expr,
279
+ expression: specializeExpression(expr.expression, paramTypesByDeclId),
280
+ };
281
+ default:
282
+ return expr;
283
+ }
284
+ };
285
+ const specializeStatement = (stmt, paramTypesByDeclId) => {
286
+ const statementAlwaysTerminates = (s) => {
287
+ switch (s.kind) {
288
+ case "returnStatement":
289
+ case "throwStatement":
290
+ case "generatorReturnStatement":
291
+ return true;
292
+ case "blockStatement": {
293
+ for (const inner of s.statements) {
294
+ if (statementAlwaysTerminates(inner))
295
+ return true;
296
+ }
297
+ return false;
298
+ }
299
+ case "ifStatement":
300
+ return s.elseStatement
301
+ ? statementAlwaysTerminates(s.thenStatement) &&
302
+ statementAlwaysTerminates(s.elseStatement)
303
+ : false;
304
+ case "tryStatement": {
305
+ const tryOk = statementAlwaysTerminates(s.tryBlock);
306
+ const catchOk = s.catchClause
307
+ ? statementAlwaysTerminates(s.catchClause.body)
308
+ : true;
309
+ const finallyOk = s.finallyBlock ? statementAlwaysTerminates(s.finallyBlock) : true;
310
+ return tryOk && catchOk && finallyOk;
311
+ }
312
+ default:
313
+ return false;
314
+ }
315
+ };
316
+ switch (stmt.kind) {
317
+ case "blockStatement": {
318
+ const statements = [];
319
+ for (const s of stmt.statements) {
320
+ const specialized = specializeStatement(s, paramTypesByDeclId);
321
+ statements.push(specialized);
322
+ if (statementAlwaysTerminates(specialized)) {
323
+ break;
324
+ }
325
+ }
326
+ return {
327
+ ...stmt,
328
+ statements,
329
+ };
330
+ }
331
+ case "ifStatement": {
332
+ const condition = specializeExpression(stmt.condition, paramTypesByDeclId);
333
+ const thenStatement = specializeStatement(stmt.thenStatement, paramTypesByDeclId);
334
+ const elseStatement = stmt.elseStatement
335
+ ? specializeStatement(stmt.elseStatement, paramTypesByDeclId)
336
+ : undefined;
337
+ if (condition.kind === "literal" && typeof condition.value === "boolean") {
338
+ return condition.value ? thenStatement : elseStatement ?? { kind: "emptyStatement" };
339
+ }
340
+ return { ...stmt, condition, thenStatement, elseStatement };
341
+ }
342
+ case "expressionStatement":
343
+ return { ...stmt, expression: specializeExpression(stmt.expression, paramTypesByDeclId) };
344
+ case "returnStatement":
345
+ return {
346
+ ...stmt,
347
+ expression: stmt.expression
348
+ ? specializeExpression(stmt.expression, paramTypesByDeclId)
349
+ : undefined,
350
+ };
351
+ case "variableDeclaration":
352
+ return {
353
+ ...stmt,
354
+ declarations: stmt.declarations.map((d) => ({
355
+ ...d,
356
+ initializer: d.initializer
357
+ ? specializeExpression(d.initializer, paramTypesByDeclId)
358
+ : undefined,
359
+ })),
360
+ };
361
+ case "whileStatement":
362
+ return {
363
+ ...stmt,
364
+ condition: specializeExpression(stmt.condition, paramTypesByDeclId),
365
+ body: specializeStatement(stmt.body, paramTypesByDeclId),
366
+ };
367
+ case "forStatement": {
368
+ const initializer = (() => {
369
+ if (!stmt.initializer)
370
+ return undefined;
371
+ if (stmt.initializer.kind === "variableDeclaration") {
372
+ const specialized = specializeStatement(stmt.initializer, paramTypesByDeclId);
373
+ if (specialized.kind !== "variableDeclaration") {
374
+ throw new Error("ICE: forStatement initializer specialization changed kind");
375
+ }
376
+ return specialized;
377
+ }
378
+ return specializeExpression(stmt.initializer, paramTypesByDeclId);
379
+ })();
380
+ return {
381
+ ...stmt,
382
+ initializer,
383
+ condition: stmt.condition
384
+ ? specializeExpression(stmt.condition, paramTypesByDeclId)
385
+ : undefined,
386
+ update: stmt.update
387
+ ? specializeExpression(stmt.update, paramTypesByDeclId)
388
+ : undefined,
389
+ body: specializeStatement(stmt.body, paramTypesByDeclId),
390
+ };
391
+ }
392
+ case "forOfStatement":
393
+ case "forInStatement":
394
+ return {
395
+ ...stmt,
396
+ expression: specializeExpression(stmt.expression, paramTypesByDeclId),
397
+ body: specializeStatement(stmt.body, paramTypesByDeclId),
398
+ };
399
+ case "switchStatement":
400
+ return {
401
+ ...stmt,
402
+ expression: specializeExpression(stmt.expression, paramTypesByDeclId),
403
+ cases: stmt.cases.map((c) => ({
404
+ ...c,
405
+ test: c.test ? specializeExpression(c.test, paramTypesByDeclId) : undefined,
406
+ statements: c.statements.map((s) => specializeStatement(s, paramTypesByDeclId)),
407
+ })),
408
+ };
409
+ case "tryStatement":
410
+ return {
411
+ ...stmt,
412
+ tryBlock: specializeStatement(stmt.tryBlock, paramTypesByDeclId),
413
+ catchClause: stmt.catchClause
414
+ ? {
415
+ ...stmt.catchClause,
416
+ body: specializeStatement(stmt.catchClause.body, paramTypesByDeclId),
417
+ }
418
+ : undefined,
419
+ finallyBlock: stmt.finallyBlock
420
+ ? specializeStatement(stmt.finallyBlock, paramTypesByDeclId)
421
+ : undefined,
422
+ };
423
+ case "throwStatement":
424
+ return {
425
+ ...stmt,
426
+ expression: specializeExpression(stmt.expression, paramTypesByDeclId),
427
+ };
428
+ default:
429
+ return stmt;
430
+ }
431
+ };
432
+ const assertNoIsTypeCalls = (stmt) => {
433
+ const visitExpr = (expr) => {
434
+ switch (expr.kind) {
435
+ case "literal":
436
+ case "identifier":
437
+ case "this":
438
+ return true;
439
+ case "spread":
440
+ return visitExpr(expr.expression);
441
+ case "memberAccess":
442
+ return (visitExpr(expr.object) &&
443
+ (typeof expr.property === "string" ? true : visitExpr(expr.property)));
444
+ case "call":
445
+ return (!(expr.callee.kind === "identifier" && expr.callee.name === "isType") &&
446
+ visitExpr(expr.callee) &&
447
+ expr.arguments.every((a) => a.kind === "spread" ? visitExpr(a.expression) : visitExpr(a)));
448
+ case "new":
449
+ return (visitExpr(expr.callee) &&
450
+ expr.arguments.every((a) => a.kind === "spread" ? visitExpr(a.expression) : visitExpr(a)));
451
+ case "functionExpression":
452
+ return expr.body.statements.every(visitStmt);
453
+ case "arrowFunction":
454
+ return expr.body.kind === "blockStatement"
455
+ ? expr.body.statements.every(visitStmt)
456
+ : visitExpr(expr.body);
457
+ case "update":
458
+ case "unary":
459
+ return visitExpr(expr.expression);
460
+ case "binary":
461
+ case "logical":
462
+ return visitExpr(expr.left) && visitExpr(expr.right);
463
+ case "conditional":
464
+ return (visitExpr(expr.condition) &&
465
+ visitExpr(expr.whenTrue) &&
466
+ visitExpr(expr.whenFalse));
467
+ case "assignment":
468
+ return visitExpr(expr.right);
469
+ case "templateLiteral":
470
+ return expr.expressions.every(visitExpr);
471
+ case "array":
472
+ return expr.elements.every((e) => {
473
+ if (!e)
474
+ return true;
475
+ return e.kind === "spread" ? visitExpr(e.expression) : visitExpr(e);
476
+ });
477
+ case "object":
478
+ return expr.properties.every((p) => {
479
+ if (p.kind === "spread")
480
+ return visitExpr(p.expression);
481
+ const keyOk = typeof p.key === "string" ? true : visitExpr(p.key);
482
+ return keyOk && visitExpr(p.value);
483
+ });
484
+ case "await":
485
+ return visitExpr(expr.expression);
486
+ case "yield":
487
+ return expr.expression ? visitExpr(expr.expression) : true;
488
+ case "numericNarrowing":
489
+ return visitExpr(expr.expression);
490
+ case "typeAssertion":
491
+ return visitExpr(expr.expression);
492
+ case "trycast":
493
+ return visitExpr(expr.expression);
494
+ case "stackalloc":
495
+ return visitExpr(expr.size);
496
+ default:
497
+ return true;
498
+ }
499
+ };
500
+ const visitStmt = (s) => {
501
+ switch (s.kind) {
502
+ case "blockStatement":
503
+ return s.statements.every(visitStmt);
504
+ case "ifStatement":
505
+ return (visitExpr(s.condition) &&
506
+ visitStmt(s.thenStatement) &&
507
+ (s.elseStatement ? visitStmt(s.elseStatement) : true));
508
+ case "expressionStatement":
509
+ return visitExpr(s.expression);
510
+ case "returnStatement":
511
+ return s.expression ? visitExpr(s.expression) : true;
512
+ case "variableDeclaration":
513
+ return s.declarations.every((d) => (d.initializer ? visitExpr(d.initializer) : true));
514
+ case "whileStatement":
515
+ return visitExpr(s.condition) && visitStmt(s.body);
516
+ case "forStatement":
517
+ return ((s.initializer
518
+ ? s.initializer.kind === "variableDeclaration"
519
+ ? visitStmt(s.initializer)
520
+ : visitExpr(s.initializer)
521
+ : true) &&
522
+ (s.condition ? visitExpr(s.condition) : true) &&
523
+ (s.update ? visitExpr(s.update) : true) &&
524
+ visitStmt(s.body));
525
+ case "forOfStatement":
526
+ case "forInStatement":
527
+ return visitExpr(s.expression) && visitStmt(s.body);
528
+ case "switchStatement":
529
+ return (visitExpr(s.expression) &&
530
+ s.cases.every((c) => (c.test ? visitExpr(c.test) : true) && c.statements.every(visitStmt)));
531
+ case "tryStatement":
532
+ return (visitStmt(s.tryBlock) &&
533
+ (s.catchClause ? visitStmt(s.catchClause.body) : true) &&
534
+ (s.finallyBlock ? visitStmt(s.finallyBlock) : true));
535
+ case "throwStatement":
536
+ return visitExpr(s.expression);
537
+ case "yieldStatement":
538
+ return s.output ? visitExpr(s.output) : true;
539
+ case "generatorReturnStatement":
540
+ return s.expression ? visitExpr(s.expression) : true;
541
+ default:
542
+ return true;
543
+ }
544
+ };
545
+ return visitStmt(stmt);
546
+ };
547
+ const assertNoMissingParamRefs = (stmt, missingDeclIds) => {
548
+ const visitExpr = (expr) => {
549
+ switch (expr.kind) {
550
+ case "literal":
551
+ case "this":
552
+ return true;
553
+ case "identifier":
554
+ return expr.declId ? !missingDeclIds.has(expr.declId.id) : true;
555
+ case "spread":
556
+ return visitExpr(expr.expression);
557
+ case "memberAccess":
558
+ return (visitExpr(expr.object) &&
559
+ (typeof expr.property === "string" ? true : visitExpr(expr.property)));
560
+ case "call":
561
+ return (visitExpr(expr.callee) &&
562
+ expr.arguments.every((a) => a.kind === "spread" ? visitExpr(a.expression) : visitExpr(a)));
563
+ case "new":
564
+ return (visitExpr(expr.callee) &&
565
+ expr.arguments.every((a) => a.kind === "spread" ? visitExpr(a.expression) : visitExpr(a)));
566
+ case "functionExpression":
567
+ return expr.body.statements.every(visitStmt);
568
+ case "arrowFunction":
569
+ return expr.body.kind === "blockStatement"
570
+ ? expr.body.statements.every(visitStmt)
571
+ : visitExpr(expr.body);
572
+ case "update":
573
+ case "unary":
574
+ return visitExpr(expr.expression);
575
+ case "binary":
576
+ case "logical":
577
+ return visitExpr(expr.left) && visitExpr(expr.right);
578
+ case "conditional":
579
+ return (visitExpr(expr.condition) &&
580
+ visitExpr(expr.whenTrue) &&
581
+ visitExpr(expr.whenFalse));
582
+ case "assignment":
583
+ return visitExpr(expr.right);
584
+ case "templateLiteral":
585
+ return expr.expressions.every(visitExpr);
586
+ case "array":
587
+ return expr.elements.every((e) => {
588
+ if (!e)
589
+ return true;
590
+ return e.kind === "spread" ? visitExpr(e.expression) : visitExpr(e);
591
+ });
592
+ case "object":
593
+ return expr.properties.every((p) => {
594
+ if (p.kind === "spread")
595
+ return visitExpr(p.expression);
596
+ const keyOk = typeof p.key === "string" ? true : visitExpr(p.key);
597
+ return keyOk && visitExpr(p.value);
598
+ });
599
+ case "await":
600
+ return visitExpr(expr.expression);
601
+ case "yield":
602
+ return expr.expression ? visitExpr(expr.expression) : true;
603
+ case "numericNarrowing":
604
+ return visitExpr(expr.expression);
605
+ case "typeAssertion":
606
+ return visitExpr(expr.expression);
607
+ case "trycast":
608
+ return visitExpr(expr.expression);
609
+ case "stackalloc":
610
+ return visitExpr(expr.size);
611
+ default:
612
+ return true;
613
+ }
614
+ };
615
+ const visitStmt = (s) => {
616
+ switch (s.kind) {
617
+ case "blockStatement":
618
+ return s.statements.every(visitStmt);
619
+ case "ifStatement":
620
+ return (visitExpr(s.condition) &&
621
+ visitStmt(s.thenStatement) &&
622
+ (s.elseStatement ? visitStmt(s.elseStatement) : true));
623
+ case "expressionStatement":
624
+ return visitExpr(s.expression);
625
+ case "returnStatement":
626
+ return s.expression ? visitExpr(s.expression) : true;
627
+ case "variableDeclaration":
628
+ return s.declarations.every((d) => (d.initializer ? visitExpr(d.initializer) : true));
629
+ case "whileStatement":
630
+ return visitExpr(s.condition) && visitStmt(s.body);
631
+ case "forStatement":
632
+ return ((s.initializer
633
+ ? s.initializer.kind === "variableDeclaration"
634
+ ? visitStmt(s.initializer)
635
+ : visitExpr(s.initializer)
636
+ : true) &&
637
+ (s.condition ? visitExpr(s.condition) : true) &&
638
+ (s.update ? visitExpr(s.update) : true) &&
639
+ visitStmt(s.body));
640
+ case "forOfStatement":
641
+ case "forInStatement":
642
+ return visitExpr(s.expression) && visitStmt(s.body);
643
+ case "switchStatement":
644
+ return (visitExpr(s.expression) &&
645
+ s.cases.every((c) => (c.test ? visitExpr(c.test) : true) && c.statements.every(visitStmt)));
646
+ case "tryStatement":
647
+ return (visitStmt(s.tryBlock) &&
648
+ (s.catchClause ? visitStmt(s.catchClause.body) : true) &&
649
+ (s.finallyBlock ? visitStmt(s.finallyBlock) : true));
650
+ case "throwStatement":
651
+ return visitExpr(s.expression);
652
+ case "yieldStatement":
653
+ return s.output ? visitExpr(s.output) : true;
654
+ case "generatorReturnStatement":
655
+ return s.expression ? visitExpr(s.expression) : true;
656
+ default:
657
+ return true;
658
+ }
659
+ };
660
+ return visitStmt(stmt);
661
+ };
662
+ /**
663
+ * Convert a TypeScript overload group (`sig; sig; impl {}`) into one C# method per signature.
664
+ *
665
+ * The implementation body is written once and specialized per overload by erasing
666
+ * `isType<T>(pN)` branches that don't match the current overload signature.
667
+ */
668
+ export const convertMethodOverloadGroup = (nodes, ctx, superClass) => {
669
+ const impls = nodes.filter((n) => !!n.body);
670
+ if (impls.length !== 1) {
671
+ throw new Error(`ICE: method overload group must contain exactly one implementation body (found ${impls.length})`);
672
+ }
673
+ const impl = impls[0];
674
+ const memberName = ts.isIdentifier(impl.name) ? impl.name.text : "[computed]";
675
+ const sigs = nodes.filter((n) => !n.body);
676
+ if (sigs.length === 0) {
677
+ return [convertMethod(impl, ctx, superClass)];
678
+ }
679
+ const implBody = impl.body
680
+ ? convertBlockStatement(impl.body, ctx, undefined)
681
+ : undefined;
682
+ if (!implBody) {
683
+ throw new Error("ICE: overload implementation must have a body");
684
+ }
685
+ const implParams = convertParameters(impl.parameters, ctx);
686
+ // Map implementation param DeclId.id -> index.
687
+ const implParamDeclIds = [];
688
+ for (const p of impl.parameters) {
689
+ if (!ts.isIdentifier(p.name)) {
690
+ throw new Error(`ICE: overload implementations currently require identifier parameters (got non-identifier in '${memberName}')`);
691
+ }
692
+ const id = ctx.binding.resolveIdentifier(p.name);
693
+ if (!id) {
694
+ throw new Error(`ICE: could not resolve parameter '${p.name.text}'`);
695
+ }
696
+ implParamDeclIds.push(id.id);
697
+ }
698
+ const declaredAccessibility = getAccessibility(impl);
699
+ const isStatic = hasStaticModifier(impl);
700
+ const isAsync = !!impl.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword);
701
+ const isGenerator = !!impl.asteriskToken;
702
+ // Convert each signature into a concrete method emission.
703
+ const out = [];
704
+ for (const sig of sigs) {
705
+ const sigParams = convertParameters(sig.parameters, ctx);
706
+ const returnType = sig.type
707
+ ? ctx.typeSystem.typeFromSyntax(ctx.binding.captureTypeSyntax(sig.type))
708
+ : undefined;
709
+ if (sigParams.length > implParams.length) {
710
+ throw new Error(`ICE: overload signature parameter count exceeds implementation for '${memberName}' (sig=${sigParams.length}, impl=${implParams.length})`);
711
+ }
712
+ const parameters = sigParams.map((p, i) => ({
713
+ ...p,
714
+ pattern: implParams[i].pattern,
715
+ }));
716
+ const overrideInfo = detectOverride(memberName, "method", superClass, ctx, parameters);
717
+ // If this signature matches a non-virtual CLR base method, do not emit a new method
718
+ // (avoid accidental `new` shadowing). Users still inherit the base implementation.
719
+ if (overrideInfo.isShadow) {
720
+ continue;
721
+ }
722
+ const accessibility = overrideInfo.isOverride && overrideInfo.requiredAccessibility
723
+ ? overrideInfo.requiredAccessibility
724
+ : declaredAccessibility;
725
+ const paramTypesByDeclId = new Map();
726
+ for (let i = 0; i < implParamDeclIds.length; i++) {
727
+ const declId = implParamDeclIds[i];
728
+ const t = i < parameters.length
729
+ ? parameters[i]?.type
730
+ : { kind: "primitiveType", name: "undefined" };
731
+ if (t)
732
+ paramTypesByDeclId.set(declId, t);
733
+ }
734
+ const specialized = specializeStatement(implBody, paramTypesByDeclId);
735
+ if (!assertNoIsTypeCalls(specialized)) {
736
+ throw new Error(`ICE: isType<T>(...) must be erased during overload specialization for '${memberName}'.`);
737
+ }
738
+ if (sigParams.length < implParams.length) {
739
+ const missing = new Set();
740
+ for (let i = sigParams.length; i < implParamDeclIds.length; i++) {
741
+ missing.add(implParamDeclIds[i]);
742
+ }
743
+ if (missing.size > 0 && !assertNoMissingParamRefs(specialized, missing)) {
744
+ throw new Error(`ICE: overload '${memberName}' implementation references parameters not present in the current signature (sigParams=${sigParams.length}, implParams=${implParams.length}).`);
745
+ }
746
+ }
747
+ out.push({
748
+ kind: "methodDeclaration",
749
+ name: memberName,
750
+ typeParameters: convertTypeParameters(sig.typeParameters, ctx),
751
+ parameters,
752
+ returnType,
753
+ body: specialized,
754
+ isStatic,
755
+ isAsync,
756
+ isGenerator,
757
+ accessibility,
758
+ isOverride: overrideInfo.isOverride ? true : undefined,
759
+ isShadow: overrideInfo.isShadow ? true : undefined,
760
+ });
761
+ }
762
+ return out;
763
+ };
91
764
  //# sourceMappingURL=methods.js.map