@tsonic/frontend 0.0.15 → 0.0.16

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 (184) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/graph/extraction/orchestrator.d.ts.map +1 -1
  3. package/dist/graph/extraction/orchestrator.js +3 -2
  4. package/dist/graph/extraction/orchestrator.js.map +1 -1
  5. package/dist/ir/binding/index.d.ts +21 -0
  6. package/dist/ir/binding/index.d.ts.map +1 -1
  7. package/dist/ir/binding/index.js +316 -6
  8. package/dist/ir/binding/index.js.map +1 -1
  9. package/dist/ir/bindings-disambiguation.test.d.ts +11 -0
  10. package/dist/ir/bindings-disambiguation.test.d.ts.map +1 -0
  11. package/dist/ir/bindings-disambiguation.test.js +416 -0
  12. package/dist/ir/bindings-disambiguation.test.js.map +1 -0
  13. package/dist/ir/builder/orchestrator.d.ts.map +1 -1
  14. package/dist/ir/builder/orchestrator.js +8 -2
  15. package/dist/ir/builder/orchestrator.js.map +1 -1
  16. package/dist/ir/builder/types.d.ts +2 -3
  17. package/dist/ir/builder/types.d.ts.map +1 -1
  18. package/dist/ir/builder.test.js +1 -1
  19. package/dist/ir/converters/context.d.ts.map +1 -1
  20. package/dist/ir/converters/context.js +1 -0
  21. package/dist/ir/converters/context.js.map +1 -1
  22. package/dist/ir/converters/expressions/access.d.ts.map +1 -1
  23. package/dist/ir/converters/expressions/access.js +161 -39
  24. package/dist/ir/converters/expressions/access.js.map +1 -1
  25. package/dist/ir/converters/expressions/calls.d.ts.map +1 -1
  26. package/dist/ir/converters/expressions/calls.js +256 -19
  27. package/dist/ir/converters/expressions/calls.js.map +1 -1
  28. package/dist/ir/converters/expressions/functions.d.ts.map +1 -1
  29. package/dist/ir/converters/expressions/functions.js +30 -12
  30. package/dist/ir/converters/expressions/functions.js.map +1 -1
  31. package/dist/ir/converters/expressions/operators.d.ts.map +1 -1
  32. package/dist/ir/converters/expressions/operators.js +5 -1
  33. package/dist/ir/converters/expressions/operators.js.map +1 -1
  34. package/dist/ir/converters/flow-narrowing.d.ts +27 -0
  35. package/dist/ir/converters/flow-narrowing.d.ts.map +1 -0
  36. package/dist/ir/converters/flow-narrowing.js +73 -0
  37. package/dist/ir/converters/flow-narrowing.js.map +1 -0
  38. package/dist/ir/converters/statements/control/conditionals.d.ts.map +1 -1
  39. package/dist/ir/converters/statements/control/conditionals.js +19 -2
  40. package/dist/ir/converters/statements/control/conditionals.js.map +1 -1
  41. package/dist/ir/expression-converter.d.ts.map +1 -1
  42. package/dist/ir/expression-converter.js +11 -4
  43. package/dist/ir/expression-converter.js.map +1 -1
  44. package/dist/ir/program-context.d.ts +17 -4
  45. package/dist/ir/program-context.d.ts.map +1 -1
  46. package/dist/ir/program-context.js +3 -0
  47. package/dist/ir/program-context.js.map +1 -1
  48. package/dist/ir/thisarg-inference.test.js +18 -18
  49. package/dist/ir/thisarg-inference.test.js.map +1 -1
  50. package/dist/ir/type-system/internal/handle-types.d.ts +7 -0
  51. package/dist/ir/type-system/internal/handle-types.d.ts.map +1 -1
  52. package/dist/ir/type-system/internal/type-converter/primitives.d.ts +3 -3
  53. package/dist/ir/type-system/internal/type-converter/primitives.d.ts.map +1 -1
  54. package/dist/ir/type-system/internal/type-converter/primitives.js +2 -2
  55. package/dist/ir/type-system/internal/type-converter/primitives.js.map +1 -1
  56. package/dist/ir/type-system/internal/type-converter/references.d.ts.map +1 -1
  57. package/dist/ir/type-system/internal/type-converter/references.js +5 -11
  58. package/dist/ir/type-system/internal/type-converter/references.js.map +1 -1
  59. package/dist/ir/type-system/internal/type-registry.d.ts +6 -1
  60. package/dist/ir/type-system/internal/type-registry.d.ts.map +1 -1
  61. package/dist/ir/type-system/internal/type-registry.js +11 -10
  62. package/dist/ir/type-system/internal/type-registry.js.map +1 -1
  63. package/dist/ir/type-system/internal/universe/clr-catalog.d.ts.map +1 -1
  64. package/dist/ir/type-system/internal/universe/clr-catalog.js +20 -4
  65. package/dist/ir/type-system/internal/universe/clr-catalog.js.map +1 -1
  66. package/dist/ir/type-system/internal/universe/source-catalog.d.ts +2 -0
  67. package/dist/ir/type-system/internal/universe/source-catalog.d.ts.map +1 -1
  68. package/dist/ir/type-system/internal/universe/source-catalog.js +8 -3
  69. package/dist/ir/type-system/internal/universe/source-catalog.js.map +1 -1
  70. package/dist/ir/type-system/internal/universe/types.d.ts +1 -1
  71. package/dist/ir/type-system/type-system.d.ts.map +1 -1
  72. package/dist/ir/type-system/type-system.js +192 -33
  73. package/dist/ir/type-system/type-system.js.map +1 -1
  74. package/dist/ir/types/expressions.d.ts +2 -0
  75. package/dist/ir/types/expressions.d.ts.map +1 -1
  76. package/dist/ir/types/ir-types.d.ts +1 -1
  77. package/dist/ir/types/statements.d.ts +9 -0
  78. package/dist/ir/types/statements.d.ts.map +1 -1
  79. package/dist/ir/validation/anonymous-type-lowering-pass.d.ts.map +1 -1
  80. package/dist/ir/validation/anonymous-type-lowering-pass.js +1 -0
  81. package/dist/ir/validation/anonymous-type-lowering-pass.js.map +1 -1
  82. package/dist/ir/validation/char-validation-pass.d.ts +26 -0
  83. package/dist/ir/validation/char-validation-pass.d.ts.map +1 -0
  84. package/dist/ir/validation/char-validation-pass.js +495 -0
  85. package/dist/ir/validation/char-validation-pass.js.map +1 -0
  86. package/dist/program/bindings.d.ts +16 -0
  87. package/dist/program/bindings.d.ts.map +1 -1
  88. package/dist/program/bindings.js +44 -0
  89. package/dist/program/bindings.js.map +1 -1
  90. package/dist/program/creation.d.ts.map +1 -1
  91. package/dist/program/creation.js +11 -104
  92. package/dist/program/creation.js.map +1 -1
  93. package/dist/program/dependency-graph.d.ts.map +1 -1
  94. package/dist/program/dependency-graph.js +8 -1
  95. package/dist/program/dependency-graph.js.map +1 -1
  96. package/dist/program/diagnostics.d.ts.map +1 -1
  97. package/dist/program/diagnostics.js +0 -6
  98. package/dist/program/diagnostics.js.map +1 -1
  99. package/dist/program/types.d.ts +2 -3
  100. package/dist/program/types.d.ts.map +1 -1
  101. package/dist/resolver/clr-bindings-resolver.d.ts +5 -0
  102. package/dist/resolver/clr-bindings-resolver.d.ts.map +1 -1
  103. package/dist/resolver/clr-bindings-resolver.js +121 -31
  104. package/dist/resolver/clr-bindings-resolver.js.map +1 -1
  105. package/dist/resolver/clr-bindings-resolver.test.d.ts +2 -0
  106. package/dist/resolver/clr-bindings-resolver.test.d.ts.map +1 -0
  107. package/dist/resolver/clr-bindings-resolver.test.js +161 -0
  108. package/dist/resolver/clr-bindings-resolver.test.js.map +1 -0
  109. package/dist/resolver/namespace.d.ts +2 -1
  110. package/dist/resolver/namespace.d.ts.map +1 -1
  111. package/dist/resolver/namespace.js +5 -2
  112. package/dist/resolver/namespace.js.map +1 -1
  113. package/dist/resolver/namespace.test.js +6 -6
  114. package/dist/resolver/naming-policy.d.ts +20 -0
  115. package/dist/resolver/naming-policy.d.ts.map +1 -0
  116. package/dist/resolver/naming-policy.js +40 -0
  117. package/dist/resolver/naming-policy.js.map +1 -0
  118. package/dist/resolver/naming.d.ts +2 -5
  119. package/dist/resolver/naming.d.ts.map +1 -1
  120. package/dist/resolver/naming.js +2 -30
  121. package/dist/resolver/naming.js.map +1 -1
  122. package/dist/resolver.d.ts +2 -0
  123. package/dist/resolver.d.ts.map +1 -1
  124. package/dist/resolver.js +1 -0
  125. package/dist/resolver.js.map +1 -1
  126. package/dist/resolver.test.js +7 -6
  127. package/dist/resolver.test.js.map +1 -1
  128. package/dist/types/diagnostic.d.ts +1 -1
  129. package/dist/types/diagnostic.d.ts.map +1 -1
  130. package/dist/types/diagnostic.js.map +1 -1
  131. package/dist/validation/core-intrinsics.d.ts +18 -0
  132. package/dist/validation/core-intrinsics.d.ts.map +1 -0
  133. package/dist/validation/core-intrinsics.js +186 -0
  134. package/dist/validation/core-intrinsics.js.map +1 -0
  135. package/dist/validation/index.d.ts +1 -0
  136. package/dist/validation/index.d.ts.map +1 -1
  137. package/dist/validation/index.js +1 -0
  138. package/dist/validation/index.js.map +1 -1
  139. package/dist/validation/orchestrator.d.ts.map +1 -1
  140. package/dist/validation/orchestrator.js +2 -0
  141. package/dist/validation/orchestrator.js.map +1 -1
  142. package/dist/validator.test.js +52 -6
  143. package/dist/validator.test.js.map +1 -1
  144. package/package.json +1 -1
  145. package/dist/ir/clr-type-mappings.d.ts +0 -42
  146. package/dist/ir/clr-type-mappings.d.ts.map +0 -1
  147. package/dist/ir/clr-type-mappings.js +0 -139
  148. package/dist/ir/clr-type-mappings.js.map +0 -1
  149. package/dist/ir/type-converter.d.ts +0 -9
  150. package/dist/ir/type-converter.d.ts.map +0 -1
  151. package/dist/ir/type-converter.js +0 -9
  152. package/dist/ir/type-converter.js.map +0 -1
  153. package/dist/ir/type-system/core.d.ts +0 -29
  154. package/dist/ir/type-system/core.d.ts.map +0 -1
  155. package/dist/ir/type-system/core.js +0 -456
  156. package/dist/ir/type-system/core.js.map +0 -1
  157. package/dist/ir/type-system/internal/type-converter/patterns.d.ts +0 -12
  158. package/dist/ir/type-system/internal/type-converter/patterns.d.ts.map +0 -1
  159. package/dist/ir/type-system/internal/type-converter/patterns.js +0 -82
  160. package/dist/ir/type-system/internal/type-converter/patterns.js.map +0 -1
  161. package/dist/ir/type-universe/assembly-catalog.d.ts +0 -44
  162. package/dist/ir/type-universe/assembly-catalog.d.ts.map +0 -1
  163. package/dist/ir/type-universe/assembly-catalog.js +0 -532
  164. package/dist/ir/type-universe/assembly-catalog.js.map +0 -1
  165. package/dist/ir/type-universe/assembly-catalog.test.d.ts +0 -7
  166. package/dist/ir/type-universe/assembly-catalog.test.d.ts.map +0 -1
  167. package/dist/ir/type-universe/assembly-catalog.test.js +0 -105
  168. package/dist/ir/type-universe/assembly-catalog.test.js.map +0 -1
  169. package/dist/ir/type-universe/index.d.ts +0 -19
  170. package/dist/ir/type-universe/index.d.ts.map +0 -1
  171. package/dist/ir/type-universe/index.js +0 -21
  172. package/dist/ir/type-universe/index.js.map +0 -1
  173. package/dist/ir/type-universe/types.d.ts +0 -436
  174. package/dist/ir/type-universe/types.d.ts.map +0 -1
  175. package/dist/ir/type-universe/types.js +0 -69
  176. package/dist/ir/type-universe/types.js.map +0 -1
  177. package/dist/ir/type-universe/unified-catalog.d.ts +0 -70
  178. package/dist/ir/type-universe/unified-catalog.d.ts.map +0 -1
  179. package/dist/ir/type-universe/unified-catalog.js +0 -319
  180. package/dist/ir/type-universe/unified-catalog.js.map +0 -1
  181. package/dist/ir/type-universe/unified-catalog.test.d.ts +0 -7
  182. package/dist/ir/type-universe/unified-catalog.test.d.ts.map +0 -1
  183. package/dist/ir/type-universe/unified-catalog.test.js +0 -135
  184. package/dist/ir/type-universe/unified-catalog.test.js.map +0 -1
@@ -63,7 +63,7 @@ export const poisonedCall = (arity, diagnostics) => ({
63
63
  * the returned TypeSystem instance.
64
64
  */
65
65
  export const createTypeSystem = (config) => {
66
- const { handleRegistry, typeRegistry, nominalEnv, convertTypeNode, unifiedCatalog, aliasTable, resolveIdentifier, resolveCallSignature, resolveConstructorSignature, } = config;
66
+ const { handleRegistry, typeRegistry, nominalEnv, convertTypeNode: convertTypeNodeRaw, unifiedCatalog, aliasTable, resolveIdentifier, resolveCallSignature, resolveConstructorSignature, } = config;
67
67
  // ─────────────────────────────────────────────────────────────────────────
68
68
  // INTERNAL CACHES — Step 4 Implementation
69
69
  // ─────────────────────────────────────────────────────────────────────────
@@ -236,6 +236,92 @@ export const createTypeSystem = (config) => {
236
236
  unifiedCatalog.resolveTsName(name) ??
237
237
  unifiedCatalog.resolveClrName(name));
238
238
  };
239
+ /**
240
+ * Attach canonical TypeIds to IR types where possible.
241
+ *
242
+ * This keeps nominal identity stable throughout the pipeline and enables
243
+ * emit-time resolution without relying on string name matching.
244
+ */
245
+ const attachParameterTypeIds = (p) => ({
246
+ ...p,
247
+ type: p.type ? attachTypeIds(p.type) : undefined,
248
+ });
249
+ const attachTypeParameterTypeIds = (tp) => ({
250
+ ...tp,
251
+ constraint: tp.constraint ? attachTypeIds(tp.constraint) : undefined,
252
+ default: tp.default ? attachTypeIds(tp.default) : undefined,
253
+ structuralMembers: tp.structuralMembers?.map(attachInterfaceMemberTypeIds),
254
+ });
255
+ const attachInterfaceMemberTypeIds = (m) => {
256
+ if (m.kind === "propertySignature") {
257
+ return { ...m, type: attachTypeIds(m.type) };
258
+ }
259
+ return {
260
+ ...m,
261
+ typeParameters: m.typeParameters?.map(attachTypeParameterTypeIds),
262
+ parameters: m.parameters.map(attachParameterTypeIds),
263
+ returnType: m.returnType ? attachTypeIds(m.returnType) : undefined,
264
+ };
265
+ };
266
+ const attachTypeIds = (type) => {
267
+ switch (type.kind) {
268
+ case "referenceType": {
269
+ const typeId = type.typeId ??
270
+ resolveTypeIdByName(type.resolvedClrType ?? type.name);
271
+ return {
272
+ ...type,
273
+ ...(type.typeArguments
274
+ ? { typeArguments: type.typeArguments.map(attachTypeIds) }
275
+ : {}),
276
+ ...(type.structuralMembers
277
+ ? {
278
+ structuralMembers: type.structuralMembers.map(attachInterfaceMemberTypeIds),
279
+ }
280
+ : {}),
281
+ ...(typeId ? { typeId } : {}),
282
+ };
283
+ }
284
+ case "arrayType":
285
+ return { ...type, elementType: attachTypeIds(type.elementType) };
286
+ case "tupleType":
287
+ return {
288
+ ...type,
289
+ elementTypes: type.elementTypes.map(attachTypeIds),
290
+ };
291
+ case "functionType":
292
+ return {
293
+ ...type,
294
+ parameters: type.parameters.map(attachParameterTypeIds),
295
+ returnType: attachTypeIds(type.returnType),
296
+ };
297
+ case "objectType":
298
+ return {
299
+ ...type,
300
+ members: type.members.map(attachInterfaceMemberTypeIds),
301
+ };
302
+ case "dictionaryType":
303
+ return {
304
+ ...type,
305
+ keyType: attachTypeIds(type.keyType),
306
+ valueType: attachTypeIds(type.valueType),
307
+ };
308
+ case "unionType":
309
+ case "intersectionType":
310
+ return { ...type, types: type.types.map(attachTypeIds) };
311
+ default:
312
+ return type;
313
+ }
314
+ };
315
+ /**
316
+ * Deterministic type syntax conversion with canonical TypeId attachment.
317
+ *
318
+ * The underlying converter is syntax-only; this wrapper re-attaches the
319
+ * nominal identity from the UnifiedUniverse so downstream passes (including
320
+ * the emitter) can resolve CLR types without re-driving a parallel lookup.
321
+ */
322
+ const convertTypeNode = (node) => {
323
+ return attachTypeIds(convertTypeNodeRaw(node));
324
+ };
239
325
  /**
240
326
  * Normalize a receiver type to nominal form for member lookup.
241
327
  *
@@ -245,9 +331,10 @@ export const createTypeSystem = (config) => {
245
331
  */
246
332
  const normalizeToNominal = (type) => {
247
333
  if (type.kind === "referenceType") {
248
- const typeId = (type.resolvedClrType
249
- ? resolveTypeIdByName(type.resolvedClrType)
250
- : undefined) ?? resolveTypeIdByName(type.name);
334
+ const typeId = type.typeId ??
335
+ (type.resolvedClrType
336
+ ? resolveTypeIdByName(type.resolvedClrType)
337
+ : undefined) ?? resolveTypeIdByName(type.name);
251
338
  if (!typeId)
252
339
  return undefined;
253
340
  return { typeId, typeArgs: type.typeArguments ?? [] };
@@ -443,17 +530,53 @@ export const createTypeSystem = (config) => {
443
530
  }
444
531
  return undefined;
445
532
  };
533
+ const stripNullishForInference = (type) => {
534
+ if (isNullishPrimitive(type))
535
+ return undefined;
536
+ if (type.kind !== "unionType")
537
+ return type;
538
+ const filtered = type.types.filter((t) => !isNullishPrimitive(t));
539
+ if (filtered.length === 0)
540
+ return undefined;
541
+ if (filtered.length === 1 && filtered[0])
542
+ return filtered[0];
543
+ return { kind: "unionType", types: filtered };
544
+ };
545
+ const unwrapAwaitedForInference = (type) => {
546
+ if (type.kind === "referenceType" &&
547
+ (type.name === "Promise" || type.name === "PromiseLike")) {
548
+ const inner = type.typeArguments?.[0];
549
+ if (inner)
550
+ return unwrapAwaitedForInference(inner);
551
+ }
552
+ return type;
553
+ };
446
554
  /**
447
555
  * Deterministically infer an expression's type using only:
448
556
  * - local lambda parameter environment
449
557
  * - declaration types (typeOfDecl)
450
- * - numeric literal lexeme rules
451
- *
452
- * This is intentionally small: it's used only to type lambda bodies for
453
- * initializer-driven generic inference (e.g., `Enumerable.select(..., x => x * 2)`).
454
- */
558
+ * - numeric literal lexeme rules
559
+ *
560
+ * This is intentionally small: it's used only to type lambda bodies for
561
+ * initializer-driven generic inference (e.g., `Enumerable.select(..., x => x * 2)`).
562
+ */
455
563
  const inferExpressionType = (expr, env) => {
456
564
  const unwrapped = unwrapParens(expr);
565
+ if (ts.isAsExpression(unwrapped) || ts.isTypeAssertionExpression(unwrapped)) {
566
+ return convertTypeNode(unwrapped.type);
567
+ }
568
+ if (ts.isNonNullExpression(unwrapped)) {
569
+ const inner = inferExpressionType(unwrapped.expression, env);
570
+ if (!inner || inner.kind === "unknownType")
571
+ return undefined;
572
+ return stripNullishForInference(inner);
573
+ }
574
+ if (ts.isAwaitExpression(unwrapped)) {
575
+ const inner = inferExpressionType(unwrapped.expression, env);
576
+ if (!inner || inner.kind === "unknownType")
577
+ return undefined;
578
+ return unwrapAwaitedForInference(inner);
579
+ }
457
580
  if (ts.isCallExpression(unwrapped)) {
458
581
  return tryInferReturnTypeFromCallExpression(unwrapped, env);
459
582
  }
@@ -532,6 +655,10 @@ export const createTypeSystem = (config) => {
532
655
  if (ts.isStringLiteral(unwrapped)) {
533
656
  return { kind: "primitiveType", name: "string" };
534
657
  }
658
+ if (ts.isNoSubstitutionTemplateLiteral(unwrapped) ||
659
+ ts.isTemplateExpression(unwrapped)) {
660
+ return { kind: "primitiveType", name: "string" };
661
+ }
535
662
  if (unwrapped.kind === ts.SyntaxKind.TrueKeyword ||
536
663
  unwrapped.kind === ts.SyntaxKind.FalseKeyword) {
537
664
  return { kind: "primitiveType", name: "boolean" };
@@ -717,13 +844,8 @@ export const createTypeSystem = (config) => {
717
844
  if (!ts.isPropertyAccessExpression(call.expression))
718
845
  return undefined;
719
846
  const receiverExpr = call.expression.expression;
720
- if (!ts.isIdentifier(receiverExpr))
721
- return undefined;
722
- const receiverDeclId = resolveIdentifier(receiverExpr);
723
- if (!receiverDeclId)
724
- return undefined;
725
- const receiver = typeOfDecl(receiverDeclId);
726
- return receiver.kind === "unknownType" ? undefined : receiver;
847
+ const receiver = inferExpressionType(receiverExpr, env);
848
+ return receiver && receiver.kind !== "unknownType" ? receiver : undefined;
727
849
  })();
728
850
  const argumentCount = call.arguments.length;
729
851
  // Two-pass: resolve once to get expected parameter types, then infer non-lambda args,
@@ -845,9 +967,12 @@ export const createTypeSystem = (config) => {
845
967
  const node = declNode;
846
968
  if (!ts.isVariableDeclaration(node))
847
969
  return undefined;
848
- const init = node.initializer;
970
+ let init = node.initializer;
849
971
  if (!init)
850
972
  return undefined;
973
+ while (ts.isParenthesizedExpression(init)) {
974
+ init = init.expression;
975
+ }
851
976
  // Explicit type assertions are deterministic sources for variable typing.
852
977
  // This supports patterns like:
853
978
  // const xs = numbers as unknown as LinqSeq<int>;
@@ -855,6 +980,18 @@ export const createTypeSystem = (config) => {
855
980
  if (ts.isAsExpression(init) || ts.isTypeAssertionExpression(init)) {
856
981
  return convertTypeNode(init.type);
857
982
  }
983
+ if (ts.isNonNullExpression(init)) {
984
+ const inner = inferExpressionType(init.expression, new Map());
985
+ if (!inner || inner.kind === "unknownType")
986
+ return undefined;
987
+ return stripNullishForInference(inner);
988
+ }
989
+ if (ts.isAwaitExpression(init)) {
990
+ const inner = inferExpressionType(init.expression, new Map());
991
+ if (!inner || inner.kind === "unknownType")
992
+ return undefined;
993
+ return unwrapAwaitedForInference(inner);
994
+ }
858
995
  if (ts.isCallExpression(init)) {
859
996
  return tryInferReturnTypeFromCallExpression(init, new Map());
860
997
  }
@@ -953,22 +1090,16 @@ export const createTypeSystem = (config) => {
953
1090
  return sourceType.kind === "unknownType" ? undefined : sourceType;
954
1091
  }
955
1092
  // Property access: const output = response.outputStream
956
- // DETERMINISTIC: Infer via TypeSystem member lookup on a typed receiver identifier.
1093
+ // DETERMINISTIC: Infer via TypeSystem member lookup on a deterministically typed receiver.
957
1094
  if (ts.isPropertyAccessExpression(init)) {
958
- const receiver = init.expression;
959
- if (ts.isIdentifier(receiver)) {
960
- const receiverDeclId = resolveIdentifier(receiver);
961
- if (!receiverDeclId)
962
- return undefined;
963
- const receiverType = typeOfDecl(receiverDeclId);
964
- if (receiverType.kind === "unknownType")
965
- return undefined;
966
- const memberType = typeOfMember(receiverType, {
967
- kind: "byName",
968
- name: init.name.text,
969
- });
970
- return memberType.kind === "unknownType" ? undefined : memberType;
971
- }
1095
+ const receiverType = inferExpressionType(init.expression, new Map());
1096
+ if (!receiverType || receiverType.kind === "unknownType")
1097
+ return undefined;
1098
+ const memberType = typeOfMember(receiverType, {
1099
+ kind: "byName",
1100
+ name: init.name.text,
1101
+ });
1102
+ return memberType.kind === "unknownType" ? undefined : memberType;
972
1103
  }
973
1104
  return undefined;
974
1105
  };
@@ -1623,13 +1754,41 @@ export const createTypeSystem = (config) => {
1623
1754
  workingReturn = unknownType;
1624
1755
  }
1625
1756
  }
1626
- return {
1757
+ const resolved = {
1627
1758
  parameterTypes: workingParams,
1628
1759
  parameterModes: rawSig.parameterModes,
1629
1760
  returnType: workingReturn,
1630
1761
  typePredicate: workingPredicate,
1631
1762
  diagnostics: [],
1632
1763
  };
1764
+ // CLR overload correction (airplane-grade determinism):
1765
+ //
1766
+ // TypeScript cannot always select the correct overload for CLR APIs because some
1767
+ // Tsonic surface types intentionally erase to TS primitives (e.g., `char` is `string`
1768
+ // in @tsonic/core for TSC compatibility). This can cause TS to resolve calls like
1769
+ // Console.writeLine("Hello") to a `char` overload, which is semantically invalid.
1770
+ //
1771
+ // When we have full argument types, and the call targets an assembly-origin type,
1772
+ // prefer the best matching overload from the UnifiedTypeCatalog if it scores higher
1773
+ // than the TS-selected signature.
1774
+ if (!resolved.typePredicate &&
1775
+ argTypes &&
1776
+ rawSig.declaringTypeTsName &&
1777
+ rawSig.declaringMemberName) {
1778
+ const hasAllArgTypes = argTypes.length >= argumentCount &&
1779
+ Array.from({ length: argumentCount }, (_, i) => argTypes[i]).every((t) => t !== undefined);
1780
+ if (hasAllArgTypes) {
1781
+ const catalogResolved = tryResolveCallFromUnifiedCatalog(rawSig.declaringTypeTsName, rawSig.declaringMemberName, query);
1782
+ if (catalogResolved) {
1783
+ const currentScore = scoreSignatureMatch(resolved.parameterTypes, argTypes, argumentCount);
1784
+ const catalogScore = scoreSignatureMatch(catalogResolved.parameterTypes, argTypes, argumentCount);
1785
+ if (catalogScore > currentScore) {
1786
+ return catalogResolved;
1787
+ }
1788
+ }
1789
+ }
1790
+ }
1791
+ return resolved;
1633
1792
  };
1634
1793
  // ─────────────────────────────────────────────────────────────────────────
1635
1794
  // expandUtility — Utility type expansion (Step 8)