@tsonic/frontend 0.0.38 → 0.0.40

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 (67) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/ir/binding/index.d.ts.map +1 -1
  3. package/dist/ir/binding/index.js +78 -9
  4. package/dist/ir/binding/index.js.map +1 -1
  5. package/dist/ir/binding-resolution.test.js +128 -0
  6. package/dist/ir/binding-resolution.test.js.map +1 -1
  7. package/dist/ir/bindings-disambiguation.test.js +9 -0
  8. package/dist/ir/bindings-disambiguation.test.js.map +1 -1
  9. package/dist/ir/converters/expressions/access.d.ts.map +1 -1
  10. package/dist/ir/converters/expressions/access.js +14 -24
  11. package/dist/ir/converters/expressions/access.js.map +1 -1
  12. package/dist/ir/converters/expressions/calls.d.ts +2 -2
  13. package/dist/ir/converters/expressions/calls.d.ts.map +1 -1
  14. package/dist/ir/converters/expressions/calls.js +133 -12
  15. package/dist/ir/converters/expressions/calls.js.map +1 -1
  16. package/dist/ir/converters/expressions/functions.js +1 -1
  17. package/dist/ir/converters/expressions/functions.js.map +1 -1
  18. package/dist/ir/converters/statements/control/exceptions.js +1 -1
  19. package/dist/ir/converters/statements/control/exceptions.js.map +1 -1
  20. package/dist/ir/converters/statements/control/loops.d.ts.map +1 -1
  21. package/dist/ir/converters/statements/control/loops.js +5 -5
  22. package/dist/ir/converters/statements/control/loops.js.map +1 -1
  23. package/dist/ir/converters/statements/declarations/classes/orchestrator.d.ts.map +1 -1
  24. package/dist/ir/converters/statements/declarations/classes/orchestrator.js +25 -3
  25. package/dist/ir/converters/statements/declarations/classes/orchestrator.js.map +1 -1
  26. package/dist/ir/converters/statements/declarations/interfaces.d.ts.map +1 -1
  27. package/dist/ir/converters/statements/declarations/interfaces.js +20 -1
  28. package/dist/ir/converters/statements/declarations/interfaces.js.map +1 -1
  29. package/dist/ir/converters/statements/declarations/variables.js +1 -1
  30. package/dist/ir/converters/statements/declarations/variables.js.map +1 -1
  31. package/dist/ir/converters/statements/helpers.d.ts +7 -0
  32. package/dist/ir/converters/statements/helpers.d.ts.map +1 -1
  33. package/dist/ir/converters/statements/helpers.js +14 -2
  34. package/dist/ir/converters/statements/helpers.js.map +1 -1
  35. package/dist/ir/expression-converter.d.ts.map +1 -1
  36. package/dist/ir/expression-converter.js +4 -3
  37. package/dist/ir/expression-converter.js.map +1 -1
  38. package/dist/ir/type-system/internal/type-converter/orchestrator.d.ts.map +1 -1
  39. package/dist/ir/type-system/internal/type-converter/orchestrator.js +15 -16
  40. package/dist/ir/type-system/internal/type-converter/orchestrator.js.map +1 -1
  41. package/dist/ir/type-system/type-system.d.ts +12 -1
  42. package/dist/ir/type-system/type-system.d.ts.map +1 -1
  43. package/dist/ir/type-system/type-system.js +161 -11
  44. package/dist/ir/type-system/type-system.js.map +1 -1
  45. package/dist/ir/types/expressions.d.ts +19 -1
  46. package/dist/ir/types/expressions.d.ts.map +1 -1
  47. package/dist/ir/types/index.d.ts +1 -1
  48. package/dist/ir/types/index.d.ts.map +1 -1
  49. package/dist/ir/types/index.js.map +1 -1
  50. package/dist/ir/types.d.ts +1 -1
  51. package/dist/ir/types.d.ts.map +1 -1
  52. package/dist/ir/types.js.map +1 -1
  53. package/dist/ir/validation/anonymous-type-lowering-pass.d.ts.map +1 -1
  54. package/dist/ir/validation/anonymous-type-lowering-pass.js +6 -0
  55. package/dist/ir/validation/anonymous-type-lowering-pass.js.map +1 -1
  56. package/dist/ir/validation/numeric-proof-pass.d.ts.map +1 -1
  57. package/dist/ir/validation/numeric-proof-pass.js +3 -1
  58. package/dist/ir/validation/numeric-proof-pass.js.map +1 -1
  59. package/dist/ir/validation/soundness-gate.d.ts.map +1 -1
  60. package/dist/ir/validation/soundness-gate.js +9 -3
  61. package/dist/ir/validation/soundness-gate.js.map +1 -1
  62. package/dist/types/diagnostic.d.ts +1 -1
  63. package/dist/types/diagnostic.d.ts.map +1 -1
  64. package/dist/validation/core-intrinsics.d.ts.map +1 -1
  65. package/dist/validation/core-intrinsics.js +4 -0
  66. package/dist/validation/core-intrinsics.js.map +1 -1
  67. package/package.json +1 -1
@@ -230,11 +230,37 @@ export const createTypeSystem = (config) => {
230
230
  * 1) AliasTable (primitives/globals/System.* canonicalization)
231
231
  * 2) UnifiedTypeCatalog by tsName
232
232
  * 3) UnifiedTypeCatalog by clrName
233
+ *
234
+ * IMPORTANT (airplane-grade):
235
+ * Resolution must be arity-aware when type arguments are present. Facade
236
+ * types often omit the `_N` generic arity suffix (e.g. `IList<T>` is a
237
+ * facade over `IList_1<T>`). When `arity` is provided and the direct
238
+ * resolution doesn't match, we deterministically try `<name>_<arity>`.
233
239
  */
234
- const resolveTypeIdByName = (name) => {
235
- return (aliasTable.get(name) ??
240
+ const resolveTypeIdByName = (name, arity) => {
241
+ const direct = aliasTable.get(name) ??
236
242
  unifiedCatalog.resolveTsName(name) ??
237
- unifiedCatalog.resolveClrName(name));
243
+ unifiedCatalog.resolveClrName(name);
244
+ if (arity === undefined)
245
+ return direct;
246
+ if (direct) {
247
+ const directArity = unifiedCatalog.getTypeParameters(direct).length;
248
+ if (directArity === arity)
249
+ return direct;
250
+ }
251
+ // Facade name without arity suffix → try tsbindgen's structural encoding.
252
+ if (arity > 0) {
253
+ const suffixed = `${name}_${arity}`;
254
+ const candidate = aliasTable.get(suffixed) ??
255
+ unifiedCatalog.resolveTsName(suffixed) ??
256
+ unifiedCatalog.resolveClrName(suffixed);
257
+ if (candidate) {
258
+ const candidateArity = unifiedCatalog.getTypeParameters(candidate).length;
259
+ if (candidateArity === arity)
260
+ return candidate;
261
+ }
262
+ }
263
+ return undefined;
238
264
  };
239
265
  /**
240
266
  * Attach canonical TypeIds to IR types where possible.
@@ -267,7 +293,7 @@ export const createTypeSystem = (config) => {
267
293
  switch (type.kind) {
268
294
  case "referenceType": {
269
295
  const typeId = type.typeId ??
270
- resolveTypeIdByName(type.resolvedClrType ?? type.name);
296
+ resolveTypeIdByName(type.resolvedClrType ?? type.name, type.typeArguments?.length);
271
297
  return {
272
298
  ...type,
273
299
  ...(type.typeArguments
@@ -331,22 +357,24 @@ export const createTypeSystem = (config) => {
331
357
  */
332
358
  const normalizeToNominal = (type) => {
333
359
  if (type.kind === "referenceType") {
360
+ const arity = type.typeArguments?.length;
334
361
  const typeId = type.typeId ??
335
362
  (type.resolvedClrType
336
- ? resolveTypeIdByName(type.resolvedClrType)
337
- : undefined) ?? resolveTypeIdByName(type.name);
363
+ ? resolveTypeIdByName(type.resolvedClrType, arity)
364
+ : undefined) ??
365
+ resolveTypeIdByName(type.name, arity);
338
366
  if (!typeId)
339
367
  return undefined;
340
368
  return { typeId, typeArgs: type.typeArguments ?? [] };
341
369
  }
342
370
  if (type.kind === "primitiveType") {
343
- const typeId = resolveTypeIdByName(type.name);
371
+ const typeId = resolveTypeIdByName(type.name, 0);
344
372
  if (!typeId)
345
373
  return undefined;
346
374
  return { typeId, typeArgs: [] };
347
375
  }
348
376
  if (type.kind === "arrayType") {
349
- const arrayTypeId = resolveTypeIdByName("Array");
377
+ const arrayTypeId = resolveTypeIdByName("Array", 1);
350
378
  if (!arrayTypeId)
351
379
  return undefined;
352
380
  return { typeId: arrayTypeId, typeArgs: [type.elementType] };
@@ -543,12 +571,31 @@ export const createTypeSystem = (config) => {
543
571
  return { kind: "unionType", types: filtered };
544
572
  };
545
573
  const unwrapAwaitedForInference = (type) => {
574
+ if (type.kind === "unionType") {
575
+ return {
576
+ kind: "unionType",
577
+ types: type.types.map((t) => (t ? unwrapAwaitedForInference(t) : t)),
578
+ };
579
+ }
546
580
  if (type.kind === "referenceType" &&
547
581
  (type.name === "Promise" || type.name === "PromiseLike")) {
548
582
  const inner = type.typeArguments?.[0];
549
583
  if (inner)
550
584
  return unwrapAwaitedForInference(inner);
551
585
  }
586
+ if (type.kind === "referenceType") {
587
+ const clrName = type.typeId?.clrName;
588
+ if (clrName === "System.Threading.Tasks.Task" ||
589
+ clrName === "System.Threading.Tasks.ValueTask") {
590
+ return voidType;
591
+ }
592
+ if (clrName?.startsWith("System.Threading.Tasks.Task`") ||
593
+ clrName?.startsWith("System.Threading.Tasks.ValueTask`")) {
594
+ const inner = type.typeArguments?.[0];
595
+ if (inner)
596
+ return unwrapAwaitedForInference(inner);
597
+ }
598
+ }
552
599
  return type;
553
600
  };
554
601
  /**
@@ -636,6 +683,9 @@ export const createTypeSystem = (config) => {
636
683
  if (objectType.kind === "primitiveType" && objectType.name === "string") {
637
684
  return { kind: "primitiveType", name: "string" };
638
685
  }
686
+ if (objectType.kind === "referenceType") {
687
+ return getIndexerInfo(objectType)?.valueType;
688
+ }
639
689
  return undefined;
640
690
  }
641
691
  if (ts.isIdentifier(unwrapped)) {
@@ -1231,6 +1281,86 @@ export const createTypeSystem = (config) => {
1231
1281
  emitDiagnostic("TSN5203", `Member '${memberName}' not found`, site);
1232
1282
  return unknownType;
1233
1283
  };
1284
+ const parseIndexerKeyClrType = (stableId) => {
1285
+ const memberSep = stableId.indexOf("::");
1286
+ if (memberSep < 0)
1287
+ return undefined;
1288
+ const bracketStart = stableId.indexOf("[", memberSep);
1289
+ if (bracketStart < 0)
1290
+ return undefined;
1291
+ let depth = 0;
1292
+ let bracketEnd = -1;
1293
+ for (let i = bracketStart; i < stableId.length; i++) {
1294
+ const ch = stableId[i];
1295
+ if (ch === "[")
1296
+ depth++;
1297
+ if (ch === "]") {
1298
+ depth--;
1299
+ if (depth === 0) {
1300
+ bracketEnd = i;
1301
+ break;
1302
+ }
1303
+ }
1304
+ }
1305
+ if (bracketEnd < 0)
1306
+ return undefined;
1307
+ const rawParams = stableId.slice(bracketStart + 1, bracketEnd);
1308
+ // Split on top-level commas to support nested generic types.
1309
+ const splitTopLevel = (value) => {
1310
+ const parts = [];
1311
+ let start = 0;
1312
+ let bracketDepth = 0;
1313
+ for (let i = 0; i < value.length; i++) {
1314
+ const c = value[i];
1315
+ if (c === "[")
1316
+ bracketDepth++;
1317
+ else if (c === "]" && bracketDepth > 0)
1318
+ bracketDepth--;
1319
+ else if (c === "," && bracketDepth === 0) {
1320
+ parts.push(value.slice(start, i).trim());
1321
+ start = i + 1;
1322
+ }
1323
+ }
1324
+ parts.push(value.slice(start).trim());
1325
+ return parts.filter((p) => p.length > 0);
1326
+ };
1327
+ const params = splitTopLevel(rawParams);
1328
+ if (params.length !== 1)
1329
+ return undefined;
1330
+ const first = params[0];
1331
+ if (!first)
1332
+ return undefined;
1333
+ // Strip assembly qualification (", Assembly, Version=..., ...") if present.
1334
+ const withoutAsm = first.includes(",") ? (first.split(",")[0] ?? first) : first;
1335
+ return withoutAsm.trim();
1336
+ };
1337
+ const getIndexerInfo = (receiver, _site) => {
1338
+ const normalized = normalizeToNominal(receiver);
1339
+ if (!normalized)
1340
+ return undefined;
1341
+ // Walk inheritance chain to find the first indexer property.
1342
+ const chain = nominalEnv.getInheritanceChain(normalized.typeId);
1343
+ for (const typeId of chain) {
1344
+ const members = unifiedCatalog.getMembers(typeId);
1345
+ const indexers = Array.from(members.values()).filter((m) => m.memberKind === "property" && m.isIndexer);
1346
+ if (indexers.length === 0)
1347
+ continue;
1348
+ if (indexers.length > 1)
1349
+ return undefined;
1350
+ const indexer = indexers[0];
1351
+ if (!indexer?.type)
1352
+ return undefined;
1353
+ const keyClrType = parseIndexerKeyClrType(indexer.stableId);
1354
+ if (!keyClrType)
1355
+ return undefined;
1356
+ const inst = nominalEnv.getInstantiation(normalized.typeId, normalized.typeArgs, typeId);
1357
+ const valueType = inst && inst.size > 0
1358
+ ? irSubstitute(indexer.type, inst)
1359
+ : indexer.type;
1360
+ return { keyClrType, valueType };
1361
+ }
1362
+ return undefined;
1363
+ };
1234
1364
  // ─────────────────────────────────────────────────────────────────────────
1235
1365
  // resolveCall — THE HEART OF DETERMINISM
1236
1366
  // Resolve a call site: returns fully instantiated param/return types + modes
@@ -1804,7 +1934,7 @@ export const createTypeSystem = (config) => {
1804
1934
  // - ReturnType/Parameters: F must be function type
1805
1935
  // - NonNullable: Works on any type
1806
1936
  // - Exclude/Extract: Works on any types
1807
- // - Awaited: Recursive on Promise<T>
1937
+ // - Awaited: Recursive on Promise<T>, Task<T>, ValueTask<T>
1808
1938
  // - Record: K must be finite literal union (string/number infinite → dictionary)
1809
1939
  // ─────────────────────────────────────────────────────────────────────────
1810
1940
  const expandUtility = (name, args, site) => {
@@ -2084,9 +2214,12 @@ export const createTypeSystem = (config) => {
2084
2214
  return { kind: "unionType", types: filtered };
2085
2215
  };
2086
2216
  /**
2087
- * Expand Awaited<T>: Unwrap Promise types recursively
2217
+ * Expand Awaited<T>: Unwrap Promise / Task / ValueTask types recursively.
2088
2218
  */
2089
2219
  const expandAwaitedUtility = (type) => {
2220
+ if (type.kind === "unionType") {
2221
+ return { kind: "unionType", types: type.types.map((t) => expandAwaitedUtility(t)) };
2222
+ }
2090
2223
  // Check for Promise<T>
2091
2224
  if (type.kind === "referenceType" &&
2092
2225
  (type.name === "Promise" || type.name === "PromiseLike")) {
@@ -2096,7 +2229,23 @@ export const createTypeSystem = (config) => {
2096
2229
  return expandAwaitedUtility(innerType);
2097
2230
  }
2098
2231
  }
2099
- // Not a Promise - return as-is
2232
+ // CLR awaitables: Task / ValueTask
2233
+ if (type.kind === "referenceType") {
2234
+ const clrName = type.typeId?.clrName;
2235
+ // Non-generic: await Task / await ValueTask => void
2236
+ if (clrName === "System.Threading.Tasks.Task" ||
2237
+ clrName === "System.Threading.Tasks.ValueTask") {
2238
+ return voidType;
2239
+ }
2240
+ // Generic: await Task<T> / await ValueTask<T> => T (recursively)
2241
+ if (clrName?.startsWith("System.Threading.Tasks.Task`") ||
2242
+ clrName?.startsWith("System.Threading.Tasks.ValueTask`")) {
2243
+ const innerType = type.typeArguments?.[0];
2244
+ if (innerType)
2245
+ return expandAwaitedUtility(innerType);
2246
+ }
2247
+ }
2248
+ // Not an awaitable - return as-is
2100
2249
  return type;
2101
2250
  };
2102
2251
  /**
@@ -2559,6 +2708,7 @@ export const createTypeSystem = (config) => {
2559
2708
  typeFromSyntax,
2560
2709
  typeOfDecl,
2561
2710
  typeOfMember,
2711
+ getIndexerInfo,
2562
2712
  typeOfMemberId,
2563
2713
  getFQNameOfDecl,
2564
2714
  isTypeDecl,