@nudojs/core 1.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import {
2
2
  $add,
3
3
  $arr,
4
+ $arrMutContainer,
5
+ $arrRest,
4
6
  $async,
5
7
  $asyncReturn,
6
8
  $await,
@@ -12,6 +14,7 @@ import {
12
14
  $div,
13
15
  $elems,
14
16
  $eq,
17
+ $eqLoose,
15
18
  $fnVal,
16
19
  $for,
17
20
  $forIter,
@@ -25,22 +28,29 @@ import {
25
28
  $idxSet,
26
29
  $invoke,
27
30
  $invokeSuper,
31
+ $isForkExit,
28
32
  $join,
29
33
  $le,
30
34
  $len,
31
35
  $lit,
36
+ $loopReturn,
32
37
  $lt,
33
38
  $mod,
34
39
  $mul,
35
40
  $ne,
41
+ $neLoose,
36
42
  $neg,
37
43
  $new,
38
44
  $not,
45
+ $nullishTest,
39
46
  $obj,
47
+ $objRest,
40
48
  $optionalGet,
41
49
  $optionalInvoke,
42
50
  $orDefault,
51
+ $pushLoopExit,
43
52
  $regex,
53
+ $rethrowIfNudoReturn,
44
54
  $set,
45
55
  $setKey,
46
56
  $spread,
@@ -51,6 +61,10 @@ import {
51
61
  $thisGet,
52
62
  $thisSet,
53
63
  $throw,
64
+ $tryCurrentMark,
65
+ $tryMark,
66
+ $tryPopMark,
67
+ $tryTakeSince,
54
68
  $typeof,
55
69
  $while,
56
70
  $whileSeq,
@@ -58,6 +72,7 @@ import {
58
72
  DEFAULT_MAX_LOOP_ITERS,
59
73
  MAX_CALL_DEPTH,
60
74
  MAX_TOTAL_CALLS,
75
+ NudoReturn,
61
76
  NudoThrow,
62
77
  abortDerivationSession,
63
78
  abs,
@@ -79,22 +94,27 @@ import {
79
94
  asAbsVal,
80
95
  attachFnImpl,
81
96
  awaitAbs,
97
+ beginCollectionFork,
82
98
  beginDerivationSession,
83
99
  betaOf,
84
100
  bindImports,
85
101
  bool,
86
102
  boolLit,
87
103
  callAbsMethod,
104
+ callAtFunctionBoundary,
88
105
  callFunction,
89
106
  callFunctionFull,
90
107
  callTranspiledExport,
91
108
  callTranspiledExportFull,
92
109
  classFromMethods,
93
110
  clearBClasses,
111
+ clearCollectionTables,
94
112
  cmp,
95
113
  coerceAsyncReturn,
96
114
  collectAbsExports,
97
115
  collectAbsNodeTypes,
116
+ collectionElementJoin,
117
+ collectionExactLen,
98
118
  concatString,
99
119
  confJoin,
100
120
  createHofCollectCtx,
@@ -110,8 +130,10 @@ import {
110
130
  div,
111
131
  emptyEnv,
112
132
  emptyPhi,
133
+ endCollectionFork,
113
134
  endDerivationSession,
114
135
  eq,
136
+ errorBrandAbs,
115
137
  evalArrayStatic,
116
138
  evalBuiltinInstanceMethod,
117
139
  evalBuiltinNew,
@@ -157,14 +179,20 @@ import {
157
179
  instanceOf,
158
180
  instantiateClass,
159
181
  instantiateReturn,
182
+ isArrMutator,
160
183
  isDefinitelyFalse,
161
184
  isDefinitelyTrue,
185
+ isErrorCtorName,
186
+ isEvalMissingSlotEnabled,
162
187
  isExactLit,
188
+ isMapAbs,
189
+ isNudoReturn,
163
190
  isNudoThrow,
164
191
  isNullishLitAbs,
165
192
  isNumPrim,
166
193
  isObj,
167
194
  isRelFn,
195
+ isSetAbs,
168
196
  isStrPrim,
169
197
  isTemplateLike,
170
198
  joinAbs,
@@ -183,13 +211,25 @@ import {
183
211
  lookupMethod,
184
212
  lookupMethodWithOwner,
185
213
  lookupSuperMethod,
214
+ looseEqAbs,
186
215
  lt,
187
216
  ltNum,
217
+ makeMapAbs,
218
+ makeSetAbs,
188
219
  makeSum,
220
+ mapClearEntries,
221
+ mapDeleteEntry,
189
222
  mapElementFallback,
223
+ mapEntriesAbs,
224
+ mapGetEntry,
225
+ mapHasEntry,
226
+ mapSetEntry,
227
+ mapSizeAbs,
228
+ mapValuesAbs,
190
229
  matchRelIdentLit,
191
230
  maybeLeak,
192
231
  mergeAdjacentFixedViews,
232
+ mergeCollectionArms,
193
233
  mod,
194
234
  mul,
195
235
  namespaceNameOf,
@@ -198,9 +238,11 @@ import {
198
238
  never,
199
239
  not,
200
240
  notAbs,
241
+ noteCollectionWrite,
201
242
  noteDerivationAdd,
202
243
  noteDerivationJoin,
203
244
  noteMemberDispatchMiss,
245
+ noteObjSlotMissing,
204
246
  notePrimMemberMissing,
205
247
  noteUnknownMemberMissing,
206
248
  num,
@@ -213,6 +255,7 @@ import {
213
255
  pTrue,
214
256
  parseSource,
215
257
  phiAnd,
258
+ popCollectionArm,
216
259
  predEquals,
217
260
  predToString,
218
261
  predVars,
@@ -221,6 +264,9 @@ import {
221
264
  projectFlatMapResult,
222
265
  promoteParamShape,
223
266
  ptypeof,
267
+ pushCollectionArm,
268
+ pushLoopExit,
269
+ pushThrowExit,
224
270
  recordMemberDiag,
225
271
  refineAbsForRelTrue,
226
272
  registerBClass,
@@ -230,15 +276,24 @@ import {
230
276
  resetLeakCounter,
231
277
  resetParseSourceCache,
232
278
  runTranspiled,
279
+ runWithEvalMissingSlot,
280
+ runWithLoopExits,
233
281
  setAbsAssignCollector,
234
282
  setAbsCallCollector,
235
283
  setAbsNodeCollector,
236
284
  setAbsTruncationCollector,
285
+ setAddEntry,
237
286
  setApplyCallbackHost,
238
287
  setBCallCollector,
288
+ setClearEntries,
289
+ setDeleteEntry,
239
290
  setDerivation,
240
291
  setDerivationCollector,
292
+ setElementsAbs,
293
+ setEvalMissingSlotEnabled,
294
+ setHasEntry,
241
295
  setMemberDiagCollector,
296
+ setSizeAbs,
242
297
  shapeOfTerm,
243
298
  shapeOnlyFn,
244
299
  shapeToString,
@@ -256,6 +311,8 @@ import {
256
311
  superNameOf,
257
312
  tagAbsOrigin,
258
313
  tagDerivationRoot,
314
+ takeLoopExits,
315
+ takeThrowExits,
259
316
  templateMatchesValue,
260
317
  templatePartsOf,
261
318
  termDepth,
@@ -280,7 +337,7 @@ import {
280
337
  withExecPhi,
281
338
  withVar,
282
339
  wrapPromise
283
- } from "./chunk-P3G2TODS.js";
340
+ } from "./chunk-VVSVQKWF.js";
284
341
 
285
342
  // src/environment.ts
286
343
  function createEnvironment(parent, bindings = /* @__PURE__ */ new Map()) {
@@ -409,6 +466,9 @@ function formatAbs(a, opts = {}) {
409
466
  parts.push(`where ${predToString(a.pred)}`);
410
467
  }
411
468
  parts.push(`#${a.conf}`);
469
+ if (a.pathNote) {
470
+ parts.push(a.pathNote);
471
+ }
412
472
  return parts.join(" ");
413
473
  }
414
474
  function formatShapeSlot(a) {
@@ -425,8 +485,10 @@ function formatShape(a) {
425
485
  return "never";
426
486
  case "any":
427
487
  return "any";
428
- case "unknown":
488
+ case "unknown": {
489
+ if (a.term?.op === "lit" && a.term.value === void 0) return "undefined";
429
490
  return "unknown";
491
+ }
430
492
  case "prim": {
431
493
  const lv = litValue(a);
432
494
  if (typeof lv === "number" && !Number.isFinite(lv)) return String(lv);
@@ -573,6 +635,9 @@ function string() {
573
635
  function boolean() {
574
636
  return makeBuilder("boolean", []);
575
637
  }
638
+ function any() {
639
+ return makeBuilder(void 0, []);
640
+ }
576
641
  function array(item) {
577
642
  if (!isConstraint(item))
578
643
  throw new Error("nudo: array(item) \u671F\u671B\u7EA6\u675F\u503C\uFF08number()/string()/\u2026\u6216\u5176\u7EC4\u5408\u5B50\uFF09");
@@ -1039,12 +1104,13 @@ function rewriteSidecarSource(src, fromFile) {
1039
1104
  const keepTs = fromFile?.endsWith(".nudo.ts") === true;
1040
1105
  const ast = parseSource(src, keepTs ? { keepTs: true } : void 0);
1041
1106
  const cuts = [];
1042
- const exportNames = [];
1107
+ const exportPairs = [];
1043
1108
  const imports = [];
1109
+ const DEFAULT_LOCAL = "__nudoDefault";
1044
1110
  const badExport = (what) => {
1045
1111
  collectDiag({
1046
1112
  code: "nudo:interface-load",
1047
- message: `sidecar ${what}; only 'export const <name> = \u2026' is a recognized export form`,
1113
+ message: `sidecar ${what}; recognized export forms are 'export const <name> = \u2026' and 'export default <constraint|fn>'`,
1048
1114
  file: fromFile
1049
1115
  });
1050
1116
  };
@@ -1068,7 +1134,7 @@ function rewriteSidecarSource(src, fromFile) {
1068
1134
  if (decl.kind === "const") {
1069
1135
  let simple = true;
1070
1136
  for (const d of decl.declarations) {
1071
- if (d.id.type === "Identifier") exportNames.push(d.id.name);
1137
+ if (d.id.type === "Identifier") exportPairs.push({ key: d.id.name, expr: d.id.name });
1072
1138
  else simple = false;
1073
1139
  }
1074
1140
  if (!simple) badExport("'export const' with destructuring pattern");
@@ -1092,15 +1158,40 @@ function rewriteSidecarSource(src, fromFile) {
1092
1158
  }
1093
1159
  if (stmt.type === "ExportDefaultDeclaration") {
1094
1160
  const decl = stmt.declaration;
1095
- if ((decl?.type === "FunctionDeclaration" || decl?.type === "ClassDeclaration") && stmt.start != null && decl.start != null) {
1096
- const kind = decl.type === "FunctionDeclaration" ? "function" : "class";
1097
- badExport(`'export default ${kind}'`);
1098
- cuts.push({ start: stmt.start, end: decl.start, text: "" });
1099
- } else {
1100
- badExport("'export default'");
1101
- if (stmt.start != null && stmt.end != null) {
1102
- cuts.push({ start: stmt.start, end: stmt.end, text: "" });
1161
+ if (decl && (decl.type === "FunctionDeclaration" || decl.type === "ClassDeclaration") && stmt.start != null && decl.start != null) {
1162
+ if (decl.id?.name) {
1163
+ exportPairs.push({ key: decl.id.name, expr: decl.id.name });
1164
+ exportPairs.push({ key: "default", expr: decl.id.name });
1165
+ } else {
1166
+ exportPairs.push({ key: "default", expr: DEFAULT_LOCAL });
1167
+ if (decl.start != null && decl.end != null) {
1168
+ const kind = decl.type === "FunctionDeclaration" ? "function" : "class";
1169
+ cuts.push({
1170
+ start: stmt.start,
1171
+ end: decl.start,
1172
+ text: `var ${DEFAULT_LOCAL} = `
1173
+ });
1174
+ void kind;
1175
+ }
1176
+ }
1177
+ if (decl.id?.name) {
1178
+ cuts.push({ start: stmt.start, end: decl.start, text: "" });
1103
1179
  }
1180
+ continue;
1181
+ }
1182
+ if (decl && stmt.start != null && decl.start != null && decl.end != null) {
1183
+ exportPairs.push({ key: "default", expr: DEFAULT_LOCAL });
1184
+ cuts.push({
1185
+ start: stmt.start,
1186
+ end: decl.start,
1187
+ text: `var ${DEFAULT_LOCAL} = `
1188
+ });
1189
+ cuts.push({ start: decl.end, end: stmt.end ?? decl.end, text: ";" });
1190
+ continue;
1191
+ }
1192
+ badExport("'export default'");
1193
+ if (stmt.start != null && stmt.end != null) {
1194
+ cuts.push({ start: stmt.start, end: stmt.end, text: "" });
1104
1195
  }
1105
1196
  continue;
1106
1197
  }
@@ -1120,20 +1211,21 @@ function rewriteSidecarSource(src, fromFile) {
1120
1211
  const merged = [];
1121
1212
  for (const c of cuts) {
1122
1213
  const last = merged[merged.length - 1];
1123
- if (last && c.start <= last.end) {
1214
+ if (last && c.start <= last.end && last.text === "" && c.text === "") {
1124
1215
  last.end = Math.max(last.end, c.end);
1125
1216
  } else {
1126
- merged.push({ start: c.start, end: c.end });
1217
+ merged.push({ start: c.start, end: c.end, text: c.text });
1127
1218
  }
1128
1219
  }
1129
1220
  let code = "";
1130
1221
  let pos = 0;
1131
1222
  for (const c of merged) {
1132
- code += src.slice(pos, c.start);
1223
+ if (c.start < pos) continue;
1224
+ code += src.slice(pos, c.start) + c.text;
1133
1225
  pos = c.end;
1134
1226
  }
1135
1227
  code += src.slice(pos);
1136
- return { code, exportNames, imports };
1228
+ return { code, exportPairs, imports };
1137
1229
  }
1138
1230
  var TS_STMT_CUT_TYPES = /* @__PURE__ */ new Set([
1139
1231
  "TSInterfaceDeclaration",
@@ -1207,7 +1299,7 @@ function collectTsSyntaxCuts(node, src, cuts = []) {
1207
1299
  }
1208
1300
  function execSidecar(src, opts, chain, preloaded) {
1209
1301
  const fromFile = opts?.fromFile;
1210
- const { code, exportNames, imports } = rewriteSidecarSource(src, fromFile);
1302
+ const { code, exportPairs, imports } = rewriteSidecarSource(src, fromFile);
1211
1303
  const prologue = [];
1212
1304
  const deps = {};
1213
1305
  for (const imp of imports) {
@@ -1319,9 +1411,12 @@ function execSidecar(src, opts, chain, preloaded) {
1319
1411
  for (const local of Object.keys(deps)) {
1320
1412
  prologue.push(`var ${local} = __nudoDeps[${JSON.stringify(local)}];`);
1321
1413
  }
1414
+ const returnObj = exportPairs.map(
1415
+ (p) => p.key === p.expr ? p.key : `${JSON.stringify(p.key)}: ${p.expr}`
1416
+ ).join(", ");
1322
1417
  const body = `${prologue.length > 0 ? `${prologue.join("\n")}
1323
1418
  ` : ""}${code}
1324
- return { ${exportNames.join(", ")} };`;
1419
+ return { ${returnObj} };`;
1325
1420
  const fn2 = new Function(
1326
1421
  ...Object.keys(sidecarInjects),
1327
1422
  "__nudoInjects",
@@ -1573,28 +1668,134 @@ function localNamedExports(source) {
1573
1668
  }
1574
1669
  }
1575
1670
  }
1671
+ const identName = (n) => {
1672
+ if (!n) return void 0;
1673
+ if (n.type === "Identifier" && typeof n.name === "string") return n.name;
1674
+ if (n.type === "Literal" && typeof n.value === "string") return n.value;
1675
+ return void 0;
1676
+ };
1677
+ const localClasses = /* @__PURE__ */ new Map();
1576
1678
  for (const stmt of ast.program.body) {
1577
- if (stmt.type !== "ExportNamedDeclaration") continue;
1578
- if (stmt.source) continue;
1579
- const d = stmt.declaration;
1580
- if (!d) {
1581
- for (const spec of stmt.specifiers) {
1582
- if (spec.type !== "ExportSpecifier") continue;
1583
- const exported = spec.exported;
1584
- const name = exported.type === "Identifier" ? exported.name : exported.value;
1585
- if (!name || name === "default") continue;
1586
- const local = spec.local;
1587
- const localName = local.type === "Identifier" ? local.name : local.value;
1588
- if (localName && importedLocalNames.has(localName)) continue;
1589
- out.add(name);
1679
+ const s = stmt;
1680
+ if (s.type !== "ClassDeclaration") continue;
1681
+ const idName = identName(s.id);
1682
+ if (idName) localClasses.set(idName, s);
1683
+ }
1684
+ const addClassMethodKeys = (out2, decl) => {
1685
+ if (!decl || decl.type !== "ClassDeclaration") return;
1686
+ const idName = identName(decl.id);
1687
+ if (!idName) return;
1688
+ const body = decl.body?.body ?? [];
1689
+ for (const m of body) {
1690
+ const mem = m;
1691
+ const isMethod = mem.type === "MethodDefinition" || mem.type === "ClassMethod" || mem.type === "TSDeclareMethod";
1692
+ if (!isMethod) continue;
1693
+ if (mem.kind && mem.kind !== "method") continue;
1694
+ if (mem.static) continue;
1695
+ const keyName = identName(mem.key);
1696
+ if (keyName) out2.add(`${idName}.${keyName}`);
1697
+ }
1698
+ };
1699
+ const isExportsTarget = (n) => {
1700
+ if (!n) return false;
1701
+ if (n.type === "Identifier") return n.name === "exports";
1702
+ if (n.type === "MemberExpression") {
1703
+ return identName(n.object) === "module" && n.property !== void 0 ? identName(n.property) === "exports" : false;
1704
+ }
1705
+ return false;
1706
+ };
1707
+ const cjsPropName = (left) => {
1708
+ if (!left || left.type !== "MemberExpression") return void 0;
1709
+ if (left.computed === true) return void 0;
1710
+ const obj2 = left.object;
1711
+ if (!isExportsTarget(obj2)) return void 0;
1712
+ return identName(left.property);
1713
+ };
1714
+ for (const stmt of ast.program.body) {
1715
+ const s = stmt;
1716
+ if (s.type === "ExportNamedDeclaration") {
1717
+ if (s.source) continue;
1718
+ const d = s.declaration;
1719
+ if (!d) {
1720
+ const specs = s.specifiers ?? [];
1721
+ for (const spec of specs) {
1722
+ if (spec.type !== "ExportSpecifier") continue;
1723
+ const name = identName(spec.exported);
1724
+ if (!name) continue;
1725
+ const localName = identName(spec.local);
1726
+ if (name === "default") {
1727
+ out.add("default");
1728
+ if (localName && !importedLocalNames.has(localName)) out.add(localName);
1729
+ if (localName && !importedLocalNames.has(localName)) {
1730
+ addClassMethodKeys(out, localClasses.get(localName));
1731
+ }
1732
+ continue;
1733
+ }
1734
+ if (localName && importedLocalNames.has(localName)) continue;
1735
+ out.add(name);
1736
+ if (localName) addClassMethodKeys(out, localClasses.get(localName));
1737
+ }
1738
+ continue;
1739
+ }
1740
+ if (d.type === "FunctionDeclaration" || d.type === "ClassDeclaration") {
1741
+ const idName = identName(d.id);
1742
+ if (idName) out.add(idName);
1743
+ if (d.type === "ClassDeclaration" && idName) {
1744
+ addClassMethodKeys(out, d);
1745
+ }
1746
+ } else if (d.type === "VariableDeclaration") {
1747
+ const decls = d.declarations ?? [];
1748
+ for (const decl of decls) {
1749
+ const idName = identName(decl.id);
1750
+ if (idName) out.add(idName);
1751
+ }
1590
1752
  }
1591
1753
  continue;
1592
1754
  }
1593
- if (d.type === "FunctionDeclaration" || d.type === "ClassDeclaration") {
1594
- if (d.id) out.add(d.id.name);
1595
- } else if (d.type === "VariableDeclaration") {
1596
- for (const decl of d.declarations) {
1597
- if (decl.id.type === "Identifier") out.add(decl.id.name);
1755
+ if (s.type === "ExportDefaultDeclaration") {
1756
+ out.add("default");
1757
+ const d = s.declaration;
1758
+ if (d) {
1759
+ if ((d.type === "FunctionDeclaration" || d.type === "ClassDeclaration") && d.id) {
1760
+ const idName = identName(d.id);
1761
+ if (idName) out.add(idName);
1762
+ if (d.type === "ClassDeclaration" && idName) {
1763
+ addClassMethodKeys(out, d);
1764
+ }
1765
+ } else if (d.type === "Identifier") {
1766
+ const n = identName(d);
1767
+ if (n && !importedLocalNames.has(n)) {
1768
+ out.add(n);
1769
+ addClassMethodKeys(out, localClasses.get(n));
1770
+ }
1771
+ }
1772
+ }
1773
+ continue;
1774
+ }
1775
+ if (s.type === "ExpressionStatement") {
1776
+ const expr = s.expression;
1777
+ if (!expr || expr.type !== "AssignmentExpression" || expr.operator !== "=") continue;
1778
+ const left = expr.left;
1779
+ const right = expr.right;
1780
+ if (!left || !right) continue;
1781
+ const prop = cjsPropName(left);
1782
+ if (prop && prop !== "default") out.add(prop);
1783
+ if (isExportsTarget(left)) {
1784
+ if (right.type === "ObjectExpression") {
1785
+ const props = right.properties ?? [];
1786
+ for (const p of props) {
1787
+ if (p.type !== "ObjectProperty" && p.type !== "Property") continue;
1788
+ const keyName = identName(p.key);
1789
+ if (keyName && keyName !== "default") out.add(keyName);
1790
+ else {
1791
+ const valName = identName(p.value);
1792
+ if (valName) out.add(valName);
1793
+ }
1794
+ }
1795
+ } else if (right.type === "Identifier") {
1796
+ const n = identName(right);
1797
+ if (n && !importedLocalNames.has(n)) out.add(n);
1798
+ }
1598
1799
  }
1599
1800
  }
1600
1801
  }
@@ -1651,6 +1852,18 @@ function sidecarAutoBindAllowed(sidecarPath, autoBind) {
1651
1852
  if (typeof autoBind === "function") return autoBind(sidecarPath) === true;
1652
1853
  return false;
1653
1854
  }
1855
+ function isDefaultExportLocal(source, localName) {
1856
+ const reList = new RegExp(
1857
+ `export\\s*\\{[^}]*\\b${localName}\\s+as\\s+default\\b[^}]*\\}`,
1858
+ "m"
1859
+ );
1860
+ const reDefaultFn = new RegExp(
1861
+ `export\\s+default\\s+(?:async\\s+)?function\\s+${localName}\\b`,
1862
+ "m"
1863
+ );
1864
+ const reDefaultId = new RegExp(`export\\s+default\\s+${localName}\\b`, "m");
1865
+ return reList.test(source) || reDefaultFn.test(source) || reDefaultId.test(source);
1866
+ }
1654
1867
  function loadSidecarBinding(source, fnName, opts) {
1655
1868
  const { loadModule, fromFile, autoBind } = opts;
1656
1869
  if (!loadModule || !fromFile) return { ok: false };
@@ -1660,6 +1873,7 @@ function loadSidecarBinding(source, fnName, opts) {
1660
1873
  const spec = `./${sidecarPath.slice(sidecarPath.lastIndexOf("/") + 1)}`;
1661
1874
  const sidecarSrc = loadModule(spec, fromFile);
1662
1875
  if (sidecarSrc === void 0) return { ok: false };
1876
+ if (sidecarSrc === source) return { ok: false };
1663
1877
  let exports;
1664
1878
  try {
1665
1879
  exports = execNudoModule(sidecarSrc, { loadModule, fromFile: sidecarPath });
@@ -1671,7 +1885,20 @@ function loadSidecarBinding(source, fnName, opts) {
1671
1885
  });
1672
1886
  return { ok: false };
1673
1887
  }
1674
- const binding = exports[fnName];
1888
+ let binding = exports[fnName];
1889
+ if (binding === void 0 && exports.default !== void 0 && isDefaultExportLocal(source, fnName)) {
1890
+ binding = exports.default;
1891
+ }
1892
+ if (binding === void 0 && fnName.includes(".")) {
1893
+ const [cls, method] = fnName.split(".", 2);
1894
+ binding = exports[`${cls}_${method}`];
1895
+ if (binding === void 0) {
1896
+ const bag = exports[cls];
1897
+ if (bag && typeof bag === "object" && !isNudoConstraint(bag)) {
1898
+ binding = bag[method];
1899
+ }
1900
+ }
1901
+ }
1675
1902
  if (binding === void 0) return { ok: false };
1676
1903
  if (!isNudoConstraint(binding)) {
1677
1904
  collectDiag2({
@@ -1689,11 +1916,16 @@ function loadSidecarBinding(source, fnName, opts) {
1689
1916
  });
1690
1917
  return { ok: false };
1691
1918
  }
1919
+ const generatedNames = generatedExportNames(sidecarSrc);
1920
+ const isGenerated = generatedNames.has(fnName) || (fnName.includes(".") ? (() => {
1921
+ const [cls, method] = fnName.split(".", 2);
1922
+ return generatedNames.has(`${cls}_${method}`) || generatedNames.has(cls);
1923
+ })() : false);
1692
1924
  return {
1693
1925
  ok: true,
1694
1926
  sidecarPath,
1695
1927
  constraint: binding,
1696
- generated: generatedExportNames(sidecarSrc).has(fnName)
1928
+ generated: isGenerated
1697
1929
  };
1698
1930
  }
1699
1931
  function boundsOf(c) {
@@ -1990,6 +2222,27 @@ function fmtConstraint(c) {
1990
2222
  function formatConstraint(c) {
1991
2223
  return fmtConstraint(c);
1992
2224
  }
2225
+ function formatEffectiveInterfaceDisplay(eff) {
2226
+ const params = eff.params.map((p) => `${p.param}: ${formatConstraint(p.constraint)}`).join(", ");
2227
+ let s = `(${params})`;
2228
+ if (eff.returns) s += ` \u2192 ${formatConstraint(eff.returns.constraint)}`;
2229
+ return s;
2230
+ }
2231
+ function formatInterfaceTierLine(source) {
2232
+ return `\u25CF interface / ${source}`;
2233
+ }
2234
+ function interfaceTierOf(source, fnName, fromFile, opts = {}) {
2235
+ if (!localNamedExports(source).has(fnName)) return void 0;
2236
+ const eff = effectiveInterface(source, fnName, { fromFile, ...opts });
2237
+ const src = eff?.source ?? "implicit";
2238
+ if (eff && src !== "implicit") {
2239
+ return { source: src, display: formatEffectiveInterfaceDisplay(eff) };
2240
+ }
2241
+ return { source: src };
2242
+ }
2243
+ function interfaceSourceOf(source, fnName, fromFile, opts = {}) {
2244
+ return interfaceTierOf(source, fnName, fromFile, opts)?.source;
2245
+ }
1993
2246
 
1994
2247
  // src/algebra/fn-fp.ts
1995
2248
  var fnFpCache = /* @__PURE__ */ new Map();
@@ -2176,11 +2429,167 @@ function canSkipLiteralCallScan(source, file) {
2176
2429
  return true;
2177
2430
  }
2178
2431
 
2432
+ // src/algebra/param-surface.ts
2433
+ function collectPatternNames(p, top, nested, depth, propKey) {
2434
+ if (!p) return;
2435
+ if (p.type === "Identifier" && p.name) {
2436
+ if (depth === 0) top.push(p.name);
2437
+ else nested.push(p.name);
2438
+ return;
2439
+ }
2440
+ if (p.type === "AssignmentPattern") {
2441
+ collectPatternNames(p.left, top, nested, depth, propKey);
2442
+ return;
2443
+ }
2444
+ if (p.type === "RestElement") {
2445
+ collectPatternNames(p.argument, top, nested, depth, propKey);
2446
+ return;
2447
+ }
2448
+ if (p.type === "ObjectPattern") {
2449
+ for (const prop of p.properties ?? []) {
2450
+ if (prop.type === "RestElement" || prop.argument) {
2451
+ collectPatternNames(prop.argument, top, nested, depth, propKey);
2452
+ continue;
2453
+ }
2454
+ const keyName = prop.key?.type === "Identifier" && prop.key.name ? prop.key.name : prop.key && "value" in prop.key ? String(prop.key.value ?? "") : void 0;
2455
+ const v2 = prop.value ?? prop.key;
2456
+ if (!v2) continue;
2457
+ if (keyName && v2.type === "Identifier" && v2.name && keyName !== v2.name) {
2458
+ if (depth === 0) top.push(keyName);
2459
+ else nested.push(keyName);
2460
+ if (propKey && depth === 0) propKey[keyName] = keyName;
2461
+ }
2462
+ if (v2.type === "Identifier" && v2.name) {
2463
+ if (depth === 0) {
2464
+ top.push(v2.name);
2465
+ if (propKey && keyName) propKey[v2.name] = keyName;
2466
+ } else nested.push(v2.name);
2467
+ } else {
2468
+ collectPatternNames(v2, top, nested, depth + 1, propKey);
2469
+ }
2470
+ }
2471
+ return;
2472
+ }
2473
+ if (p.type === "ArrayPattern") {
2474
+ for (const el of p.elements ?? []) {
2475
+ if (!el) continue;
2476
+ if (el.type === "Identifier" && el.name) {
2477
+ if (depth === 0) top.push(el.name);
2478
+ else nested.push(el.name);
2479
+ } else {
2480
+ collectPatternNames(el, top, nested, depth + 1, propKey);
2481
+ }
2482
+ }
2483
+ }
2484
+ }
2485
+ function formalParamsFromNodes(params) {
2486
+ const list = params ?? [];
2487
+ return list.map((p, index) => {
2488
+ if (p?.type === "Identifier" && p.name) {
2489
+ return { kind: "id", name: p.name, index };
2490
+ }
2491
+ if (p?.type === "AssignmentPattern") {
2492
+ const left = p.left;
2493
+ if (left?.type === "Identifier" && left.name) {
2494
+ return { kind: "default", name: left.name, index };
2495
+ }
2496
+ const top2 = [];
2497
+ const nested2 = [];
2498
+ const propKey2 = {};
2499
+ if (left) collectPatternNames(left, top2, nested2, 0, propKey2);
2500
+ return {
2501
+ kind: "pattern",
2502
+ placeholder: `_p${index}`,
2503
+ bound: top2,
2504
+ propKey: propKey2,
2505
+ nested: nested2,
2506
+ index
2507
+ };
2508
+ }
2509
+ if (p?.type === "RestElement") {
2510
+ const arg = p.argument;
2511
+ const name = arg?.type === "Identifier" && arg.name ? arg.name : `arg${index}`;
2512
+ return { kind: "rest", name, display: `...${name}`, index };
2513
+ }
2514
+ const top = [];
2515
+ const nested = [];
2516
+ const propKey = {};
2517
+ if (p) collectPatternNames(p, top, nested, 0, propKey);
2518
+ return {
2519
+ kind: "pattern",
2520
+ placeholder: `_p${index}`,
2521
+ bound: top,
2522
+ propKey,
2523
+ nested,
2524
+ index
2525
+ };
2526
+ });
2527
+ }
2528
+ function formalParamDisplayNames(formals) {
2529
+ return formals.map((f) => {
2530
+ switch (f.kind) {
2531
+ case "id":
2532
+ case "default":
2533
+ return f.name;
2534
+ case "rest":
2535
+ return f.display;
2536
+ case "pattern":
2537
+ return f.placeholder;
2538
+ }
2539
+ });
2540
+ }
2541
+ function contractParamNameSet(formals) {
2542
+ const out = /* @__PURE__ */ new Set();
2543
+ for (const f of formals) {
2544
+ if (f.kind === "id" || f.kind === "default") out.add(f.name);
2545
+ else if (f.kind === "rest") {
2546
+ out.add(f.name);
2547
+ out.add(f.display);
2548
+ } else if (f.kind === "pattern") {
2549
+ out.add(f.placeholder);
2550
+ out.add("_");
2551
+ for (const b of f.bound) out.add(b);
2552
+ }
2553
+ }
2554
+ return out;
2555
+ }
2556
+ function locateContractParam(formals, contractName) {
2557
+ for (const f of formals) {
2558
+ if (f.kind === "id" || f.kind === "default") {
2559
+ if (f.name === contractName) return { index: f.index };
2560
+ } else if (f.kind === "rest") {
2561
+ if (f.name === contractName || f.display === contractName) {
2562
+ return { index: f.index, rest: true };
2563
+ }
2564
+ } else if (f.kind === "pattern") {
2565
+ if (f.placeholder === contractName || contractName === "_") {
2566
+ return { index: f.index };
2567
+ }
2568
+ if (f.bound.includes(contractName)) {
2569
+ return { index: f.index, field: f.propKey?.[contractName] ?? contractName };
2570
+ }
2571
+ }
2572
+ }
2573
+ return void 0;
2574
+ }
2575
+
2179
2576
  // src/algebra/load-deps-fp.ts
2180
2577
  var MAX_LOAD_DEP_NODES = 64;
2181
2578
  function extractAllLoadSpecs(source) {
2182
2579
  const specs = /* @__PURE__ */ new Set();
2183
2580
  for (const imp of extractNudoImports(source)) specs.add(imp.spec);
2581
+ const isPathLikeSpec = (spec) => spec.startsWith("./") || spec.startsWith("../") || spec.startsWith("/") || /\.(ts|js|mjs|cjs|tsx|jsx)$/.test(spec);
2582
+ const envRe = /@nudo:env\s+([^\n*]+)/g;
2583
+ let envM;
2584
+ while (envM = envRe.exec(source)) {
2585
+ for (const part of envM[1].split(",")) {
2586
+ const spec = part.trim().replace(/^['"]|['"]$/g, "");
2587
+ if (spec && isPathLikeSpec(spec)) specs.add(spec);
2588
+ }
2589
+ }
2590
+ const mockFromRe = /@nudo:mock-module\s+"[^"]+"\s+(?:\{[^}]*\}\s+)?from\s+["']([^"']+)["']/g;
2591
+ let mockM;
2592
+ while (mockM = mockFromRe.exec(source)) specs.add(mockM[1]);
2184
2593
  const patterns = [
2185
2594
  /\bfrom\s*['"]([^'"]+)['"]/g,
2186
2595
  /\brequire\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
@@ -2200,6 +2609,7 @@ function sidecarSpecsOf(source) {
2200
2609
  function loadModuleDepsFingerprint(source, loadModule, fromFile) {
2201
2610
  const parts = [];
2202
2611
  const paths = [];
2612
+ const contents = [];
2203
2613
  const seen = /* @__PURE__ */ new Set();
2204
2614
  const queue = extractAllLoadSpecs(source).map(
2205
2615
  (spec) => ({ spec, from: fromFile })
@@ -2208,7 +2618,7 @@ function loadModuleDepsFingerprint(source, loadModule, fromFile) {
2208
2618
  let truncated = false;
2209
2619
  const finish = () => {
2210
2620
  parts.sort();
2211
- return truncated ? { fp: `trunc:${parts.join(",")}`, paths, truncated: true } : { fp: parts.join(","), paths, truncated: false };
2621
+ return truncated ? { fp: `trunc:${parts.join(",")}`, paths, contents, truncated: true } : { fp: parts.join(","), paths, contents, truncated: false };
2212
2622
  };
2213
2623
  const absorbSidecarClosure = (entryFile) => {
2214
2624
  const sidecarPath = sidecarPathOf(entryFile);
@@ -2224,6 +2634,7 @@ function loadModuleDepsFingerprint(source, loadModule, fromFile) {
2224
2634
  n++;
2225
2635
  parts.push(`sidecar:${sidecarPath}=${hashSource(sidecarSrc)}`);
2226
2636
  paths.push(sidecarPath);
2637
+ contents.push({ path: sidecarPath, content: sidecarSrc });
2227
2638
  const sidecarQueue = sidecarSpecsOf(
2228
2639
  sidecarSrc
2229
2640
  ).map((spec) => ({ spec, from: sidecarPath }));
@@ -2240,6 +2651,7 @@ function loadModuleDepsFingerprint(source, loadModule, fromFile) {
2240
2651
  const src = loadModule(cur.spec, cur.from);
2241
2652
  parts.push(`sidecar:${path}=${src === void 0 ? "miss" : hashSource(src)}`);
2242
2653
  paths.push(path);
2654
+ contents.push({ path, content: src ?? null });
2243
2655
  if (src === void 0) continue;
2244
2656
  for (const next of sidecarSpecsOf(src)) {
2245
2657
  const nextPath = resolveDepPath(path, next);
@@ -2260,6 +2672,7 @@ function loadModuleDepsFingerprint(source, loadModule, fromFile) {
2260
2672
  const src = loadModule(cur.spec, cur.from);
2261
2673
  parts.push(`${path}=${src === void 0 ? "miss" : hashSource(src)}`);
2262
2674
  paths.push(path);
2675
+ contents.push({ path, content: src ?? null });
2263
2676
  if (src === void 0) continue;
2264
2677
  for (const next of extractAllLoadSpecs(src)) {
2265
2678
  const nextPath = resolveDepPath(path, next);
@@ -2324,14 +2737,14 @@ function loadModuleId(fn2) {
2324
2737
  }
2325
2738
  function refineDepsFingerprint(source, refine) {
2326
2739
  if (!refine?.loadModule || !refine.fromFile) {
2327
- return { fp: "-", paths: [], truncated: false };
2740
+ return { fp: "-", paths: [], contents: [], truncated: false };
2328
2741
  }
2329
2742
  return loadModuleDepsFingerprint(source, refine.loadModule, refine.fromFile);
2330
2743
  }
2331
2744
  function generalizeMemoKey(fnName, source, opts) {
2332
2745
  const r = opts.refine;
2333
2746
  const budget = opts.budget ?? defaultLeakBudget;
2334
- const deps = opts.depsFp ?? (r ? refineDepsFingerprint(source, r) : { fp: "-", paths: [], truncated: false });
2747
+ const deps = opts.depsFp ?? (r ? refineDepsFingerprint(source, r) : { fp: "-", paths: [], contents: [], truncated: false });
2335
2748
  const sc = opts.sidecarFp ?? (r?.loadModule && r.fromFile ? sidecarClosureFingerprint(r.fromFile, r) : void 0);
2336
2749
  const scPath = sc !== void 0 && !sc.startsWith("trunc:") && r?.fromFile ? normPath(sidecarPathOf(r.fromFile)) : void 0;
2337
2750
  const srcPart = generalizeSourceKeyPart(source, fnName, opts.file);
@@ -2529,6 +2942,11 @@ function collectAbsVars(a, acc, seen) {
2529
2942
  return;
2530
2943
  }
2531
2944
  }
2945
+ function collectAbsFreeVars(a) {
2946
+ const acc = /* @__PURE__ */ new Set();
2947
+ collectAbsVars(a, acc, /* @__PURE__ */ new Set());
2948
+ return acc;
2949
+ }
2532
2950
  function renameTerm(t, map) {
2533
2951
  if (t.op === "var") {
2534
2952
  const to = map.get(t.id);
@@ -2645,6 +3063,7 @@ function alphaRenameResult(result, fromOrder, toOrder) {
2645
3063
  function extractFn(source, fnName, fileAst) {
2646
3064
  const file = fileAst ?? parseSource(source);
2647
3065
  const env = emptyEnv();
3066
+ const formalsByName = /* @__PURE__ */ new Map();
2648
3067
  for (const stmt of file.program.body) {
2649
3068
  let decl = stmt;
2650
3069
  if (stmt.type === "ExportNamedDeclaration" && stmt.declaration) {
@@ -2654,30 +3073,53 @@ function extractFn(source, fnName, fileAst) {
2654
3073
  decl = stmt.declaration;
2655
3074
  }
2656
3075
  if (decl.type === "FunctionDeclaration" && decl.id) {
3076
+ const formals = formalParamsFromNodes(decl.params);
2657
3077
  env.fns.set(decl.id.name, {
2658
- params: decl.params.map((p) => p.type === "Identifier" ? p.name : "_"),
3078
+ params: formalParamDisplayNames(formals),
2659
3079
  body: decl.body,
2660
3080
  async: decl.async === true
2661
3081
  });
3082
+ formalsByName.set(decl.id.name, formals);
3083
+ }
3084
+ if (decl.type === "ClassDeclaration" && decl.id?.name) {
3085
+ const cname = decl.id.name;
3086
+ const body = decl.body?.body ?? [];
3087
+ for (const m of body) {
3088
+ const mem = m;
3089
+ const isMethod = mem.type === "MethodDefinition" || mem.type === "ClassMethod" || mem.type === "TSDeclareMethod";
3090
+ if (!isMethod || !mem.body) continue;
3091
+ if (mem.kind && mem.kind !== "method") continue;
3092
+ if (mem.static) continue;
3093
+ const keyName = mem.key?.type === "Identifier" ? mem.key.name : void 0;
3094
+ if (!keyName) continue;
3095
+ const fullName = `${cname}.${keyName}`;
3096
+ const formals = formalParamsFromNodes(mem.params ?? []);
3097
+ env.fns.set(fullName, {
3098
+ params: formalParamDisplayNames(formals),
3099
+ body: mem.body,
3100
+ async: mem.async === true
3101
+ });
3102
+ formalsByName.set(fullName, formals);
3103
+ }
2662
3104
  }
2663
3105
  if (decl.type === "VariableDeclaration") {
2664
3106
  for (const d of decl.declarations) {
2665
3107
  if (d.id.type === "Identifier" && d.init && (d.init.type === "ArrowFunctionExpression" || d.init.type === "FunctionExpression")) {
2666
3108
  const init = d.init;
3109
+ const formals = formalParamsFromNodes(init.params);
2667
3110
  env.fns.set(d.id.name, {
2668
- params: init.params.map(
2669
- (p) => p.type === "Identifier" ? p.name ?? "_" : "_"
2670
- ),
3111
+ params: formalParamDisplayNames(formals),
2671
3112
  body: init.body,
2672
3113
  async: init.async === true
2673
3114
  });
3115
+ formalsByName.set(d.id.name, formals);
2674
3116
  }
2675
3117
  }
2676
3118
  }
2677
3119
  }
2678
3120
  const fn2 = env.fns.get(fnName);
2679
3121
  if (!fn2) return void 0;
2680
- return { params: fn2.params, body: fn2.body, env };
3122
+ return { params: fn2.params, body: fn2.body, env, formals: formalsByName.get(fnName) ?? [] };
2681
3123
  }
2682
3124
  function generalizeFromAst(fnName, source, opts = {}) {
2683
3125
  const { key, depPaths, truncated } = generalizeMemoKey(fnName, source, opts);
@@ -2696,7 +3138,7 @@ function generalizeFromAst(fnName, source, opts = {}) {
2696
3138
  function generalizeFromAstUncached(fnName, source, opts = {}) {
2697
3139
  const extracted = extractFn(source, fnName, opts.file);
2698
3140
  if (!extracted) return void 0;
2699
- const { params, body, env } = extracted;
3141
+ const { params, body, env, formals } = extracted;
2700
3142
  const budget = opts.budget ?? defaultLeakBudget;
2701
3143
  const label = opts.label ?? "A";
2702
3144
  const typeParams = params.map((p, i) => ({
@@ -2812,6 +3254,7 @@ function generalizeFromAstUncached(fnName, source, opts = {}) {
2812
3254
  entryShapes,
2813
3255
  fnRels
2814
3256
  ),
3257
+ ...formals.length > 0 ? { formals } : {},
2815
3258
  ...entryReqs ? { entryReqs } : {},
2816
3259
  ...fnRels ? { fnRels } : {},
2817
3260
  ...entryShapes ? { entryShapes } : {},
@@ -3506,6 +3949,26 @@ function hofFnArgOk(src, tgt) {
3506
3949
  function listTopFunctions(source, file) {
3507
3950
  const f = file ?? parseSource(source);
3508
3951
  const names = [];
3952
+ const localClasses = /* @__PURE__ */ new Map();
3953
+ for (const stmt of f.program.body) {
3954
+ if (stmt.type === "ClassDeclaration") {
3955
+ const cname = stmt.id?.name;
3956
+ if (cname) localClasses.set(cname, stmt);
3957
+ }
3958
+ }
3959
+ const exportedClassNames = /* @__PURE__ */ new Set();
3960
+ const collectClassMethods = (cname, decl) => {
3961
+ const body = decl.body?.body ?? [];
3962
+ for (const m of body) {
3963
+ const mem = m;
3964
+ const isMethod = mem.type === "MethodDefinition" || mem.type === "ClassMethod" || mem.type === "TSDeclareMethod";
3965
+ if (!isMethod) continue;
3966
+ if (mem.kind && mem.kind !== "method") continue;
3967
+ if (mem.static) continue;
3968
+ const keyName = mem.key?.type === "Identifier" ? mem.key.name : void 0;
3969
+ if (keyName) names.push(`${cname}.${keyName}`);
3970
+ }
3971
+ };
3509
3972
  for (const stmt of f.program.body) {
3510
3973
  let decl = stmt;
3511
3974
  if (stmt.type === "ExportNamedDeclaration" && stmt.declaration) {
@@ -3522,121 +3985,48 @@ function listTopFunctions(source, file) {
3522
3985
  }
3523
3986
  }
3524
3987
  }
3525
- }
3526
- return names;
3527
- }
3528
- function absUnknown() {
3529
- return { shape: { k: "unknown" }, conf: "partial" };
3530
- }
3531
- function collectParamStructReqs(source, fnName, fileAst) {
3532
- const reqs = /* @__PURE__ */ new Map();
3533
- const extracted = extractFn(source, fnName, fileAst);
3534
- if (!extracted) return reqs;
3535
- const params = new Set(extracted.params);
3536
- const body = extracted.body;
3537
- const BUILTIN_METHODS = /* @__PURE__ */ new Set([
3538
- "map",
3539
- "filter",
3540
- "reduce",
3541
- "flatMap",
3542
- "forEach",
3543
- "some",
3544
- "every",
3545
- "find",
3546
- "findIndex",
3547
- "includes",
3548
- "indexOf",
3549
- "lastIndexOf",
3550
- "join",
3551
- "slice",
3552
- "splice",
3553
- "push",
3554
- "pop",
3555
- "shift",
3556
- "unshift",
3557
- "sort",
3558
- "reverse",
3559
- "concat",
3560
- "at",
3561
- "replace",
3562
- "replaceAll",
3563
- "split",
3564
- "trim",
3565
- "toLowerCase",
3566
- "toUpperCase",
3567
- "startsWith",
3568
- "endsWith",
3569
- "charAt",
3570
- "charCodeAt",
3571
- "padStart",
3572
- "padEnd",
3573
- "repeat",
3574
- "toString",
3575
- "valueOf",
3576
- "substring",
3577
- "match",
3578
- "search",
3579
- "hasOwnProperty",
3580
- "keys",
3581
- "values",
3582
- "entries",
3583
- "then",
3584
- "catch",
3585
- "finally"
3586
- ]);
3587
- const visit = (n, isMethodCallee = false, guarded = false) => {
3588
- if (!n || typeof n !== "object") return;
3589
- const obj2 = n;
3590
- if (obj2.type === "LogicalExpression") {
3591
- visit(obj2.left, false, guarded);
3592
- visit(obj2.right, false, true);
3593
- return;
3594
- }
3595
- if (obj2.type === "ConditionalExpression") {
3596
- visit(obj2.test, false, guarded);
3597
- visit(obj2.consequent, false, true);
3598
- visit(obj2.alternate, false, true);
3599
- return;
3988
+ if (decl.type === "ClassDeclaration" && decl.id?.name && (stmt.type === "ExportNamedDeclaration" || stmt.type === "ExportDefaultDeclaration")) {
3989
+ const cname = decl.id.name;
3990
+ exportedClassNames.add(cname);
3991
+ collectClassMethods(cname, decl);
3600
3992
  }
3601
- if (obj2.type === "IfStatement") {
3602
- visit(obj2.test, false, guarded);
3603
- visit(obj2.consequent, false, true);
3604
- visit(obj2.alternate, false, true);
3605
- return;
3606
- }
3607
- if (obj2.type === "MemberExpression" && !obj2.computed && !isMethodCallee) {
3608
- const o = obj2.object;
3609
- const p = obj2.property;
3610
- if (o?.type === "Identifier" && o.name && params.has(o.name) && p?.type === "Identifier" && p.name) {
3611
- if (BUILTIN_METHODS.has(p.name)) return;
3612
- if (guarded) return;
3613
- let set = reqs.get(o.name);
3614
- if (!set) {
3615
- set = /* @__PURE__ */ new Set();
3616
- reqs.set(o.name, set);
3993
+ }
3994
+ for (const stmt of f.program.body) {
3995
+ if (stmt.type === "ExportNamedDeclaration" && !stmt.declaration) {
3996
+ const specs = stmt.specifiers ?? [];
3997
+ for (const spec of specs) {
3998
+ const s = spec;
3999
+ if (s.type !== "ExportSpecifier") continue;
4000
+ const localName = s.local?.name;
4001
+ if (!localName || exportedClassNames.has(localName)) continue;
4002
+ const exportedName = s.exported?.name ?? s.exported?.value;
4003
+ const isDefault = exportedName === "default";
4004
+ if (!isDefault && exportedName !== localName) {
3617
4005
  }
3618
- set.add(p.name);
4006
+ const decl = localClasses.get(localName);
4007
+ if (!decl) continue;
4008
+ exportedClassNames.add(localName);
4009
+ collectClassMethods(localName, decl);
3619
4010
  }
3620
4011
  }
3621
- if (obj2.type === "CallExpression") {
3622
- visit(obj2.callee, true, guarded);
3623
- for (const key of Object.keys(obj2)) {
3624
- if (key === "loc" || key === "start" || key === "end" || key === "callee") continue;
3625
- const val = obj2[key];
3626
- if (Array.isArray(val)) val.forEach((v2) => visit(v2, false, guarded));
3627
- else if (val && typeof val === "object") visit(val, false, guarded);
4012
+ if (stmt.type === "ExportDefaultDeclaration" && stmt.declaration) {
4013
+ const d = stmt.declaration;
4014
+ if (d.type === "Identifier") {
4015
+ const localName = d.name;
4016
+ if (!exportedClassNames.has(localName)) {
4017
+ const decl = localClasses.get(localName);
4018
+ if (decl) {
4019
+ exportedClassNames.add(localName);
4020
+ collectClassMethods(localName, decl);
4021
+ }
4022
+ }
3628
4023
  }
3629
- return;
3630
4024
  }
3631
- for (const key of Object.keys(obj2)) {
3632
- if (key === "loc" || key === "start" || key === "end") continue;
3633
- const val = obj2[key];
3634
- if (Array.isArray(val)) val.forEach((v2) => visit(v2, isMethodCallee, guarded));
3635
- else if (val && typeof val === "object") visit(val, isMethodCallee, guarded);
3636
- }
3637
- };
3638
- visit(body);
3639
- return reqs;
4025
+ }
4026
+ return names;
4027
+ }
4028
+ function absUnknown() {
4029
+ return { shape: { k: "unknown" }, conf: "partial" };
3640
4030
  }
3641
4031
  function evalArgAbs(node, lookupVar) {
3642
4032
  if (node.type === "Identifier" && typeof node.name === "string" && lookupVar) {
@@ -4009,14 +4399,37 @@ function scanLiteralCalls(source, knownFns, phi, opts) {
4009
4399
  eiCache.set(key, r);
4010
4400
  return r;
4011
4401
  };
4012
- const interfaceToIndexed = (ei, paramNames) => {
4402
+ const projectArgField = (arg, field) => {
4403
+ if (!arg) return void 0;
4404
+ if (arg.shape.k === "brand") {
4405
+ return projectArgField(arg.shape.shape, field);
4406
+ }
4407
+ if (arg.shape.k !== "obj") return void 0;
4408
+ return getSlot(arg.shape.slots, field)?.value;
4409
+ };
4410
+ const interfaceToIndexed = (ei, paramNames, formals) => {
4013
4411
  const conflict = new Set(ei.conflict?.params ?? []);
4014
4412
  const entries = [];
4015
4413
  for (const { param, constraint } of ei.params) {
4016
- if (conflict.has(param)) continue;
4414
+ if (!param || conflict.has(param)) continue;
4017
4415
  const idx = paramNames.indexOf(param);
4018
4416
  if (idx >= 0) {
4019
- entries.push([idx, { param, pred: instantiateConstraint(constraint, param), constraint }]);
4417
+ entries.push([
4418
+ idx,
4419
+ { param, pred: instantiateConstraint(constraint, param), constraint },
4420
+ void 0
4421
+ ]);
4422
+ continue;
4423
+ }
4424
+ if (formals && formals.length > 0) {
4425
+ const hit = locateContractParam(formals, param);
4426
+ if (hit) {
4427
+ entries.push([
4428
+ hit.index,
4429
+ { param, pred: instantiateConstraint(constraint, param), constraint },
4430
+ hit.field
4431
+ ]);
4432
+ }
4020
4433
  }
4021
4434
  }
4022
4435
  return entries;
@@ -4050,15 +4463,36 @@ function scanLiteralCalls(source, knownFns, phi, opts) {
4050
4463
  return lv <= n;
4051
4464
  };
4052
4465
  const checkReqs = (displayName, reqs, paramNames, absArgs, argIndexOf, loc) => {
4053
- for (const [idx, pred] of reqs) {
4466
+ for (const [idx, pred, field, contractParam] of reqs) {
4054
4467
  const argIdx = argIndexOf(idx);
4055
4468
  if (argIdx === void 0) continue;
4056
- const arg = absArgs[argIdx];
4469
+ let arg = absArgs[argIdx];
4057
4470
  if (!arg) continue;
4471
+ const paramName = contractParam || paramNames[idx] || `arg${idx}`;
4472
+ if (field) {
4473
+ const projected = projectArgField(arg, field);
4474
+ if (!projected) {
4475
+ const k = arg.shape.k;
4476
+ if (k !== "unknown" && k !== "any") {
4477
+ out.push({
4478
+ severity: "error",
4479
+ code: "nudo:constraint-violated",
4480
+ message: `${displayName}[${paramName}]: \u5B9E\u53C2 \u22AD \u524D\u7F6E`,
4481
+ actual: formatAbs(arg),
4482
+ expected: `missing field ${field}`,
4483
+ suggestion: `\u8865\u5168\u5B57\u6BB5 ${field}`,
4484
+ fn: displayName,
4485
+ line: loc?.start.line,
4486
+ column: loc?.start.column
4487
+ });
4488
+ }
4489
+ continue;
4490
+ }
4491
+ arg = projected;
4492
+ }
4058
4493
  const lv = litValue(arg);
4059
4494
  const isStr = arg.shape.k === "prim" && arg.shape.type === "string";
4060
4495
  const strLen = typeof lv === "string" ? lv.length : void 0;
4061
- const paramName = paramNames[idx] ?? `arg${idx}`;
4062
4496
  for (const p of flattenPred(pred)) {
4063
4497
  if (p.op === "typeof") {
4064
4498
  if (p.t.op !== "var") continue;
@@ -4135,14 +4569,13 @@ function scanLiteralCalls(source, knownFns, phi, opts) {
4135
4569
  if (p.op === "lt") ok2 = strLen < n;
4136
4570
  if (p.op === "le") ok2 = strLen <= n;
4137
4571
  if (!ok2) {
4138
- const paramName2 = paramNames[idx] ?? `arg${idx}`;
4139
4572
  out.push({
4140
4573
  severity: "error",
4141
4574
  code: "nudo:constraint-violated",
4142
- message: `${displayName}[${paramName2}]: \u5B9E\u53C2 \u22AD \u524D\u7F6E`,
4575
+ message: `${displayName}[${paramName}]: \u5B9E\u53C2 \u22AD \u524D\u7F6E`,
4143
4576
  actual: formatAbs(arg),
4144
- expected: `length(${paramName2}) ${opSym} ${n}`,
4145
- suggestion: `\u6539\u7528\u6EE1\u8DB3\u957F\u5EA6 ${opSym} ${n} \u7684\u503C\uFF0C\u6216\u653E\u5BBD ${paramName2} \u7684\u524D\u7F6E`,
4577
+ expected: `length(${paramName}) ${opSym} ${n}`,
4578
+ suggestion: `\u6539\u7528\u6EE1\u8DB3\u957F\u5EA6 ${opSym} ${n} \u7684\u503C\uFF0C\u6216\u653E\u5BBD ${paramName} \u7684\u524D\u7F6E`,
4146
4579
  fn: displayName,
4147
4580
  line: loc?.start.line,
4148
4581
  column: loc?.start.column
@@ -4157,14 +4590,13 @@ function scanLiteralCalls(source, knownFns, phi, opts) {
4157
4590
  if (p.op === "lt") ok = lv < n;
4158
4591
  if (p.op === "le") ok = lv <= n;
4159
4592
  if (!ok) {
4160
- const paramName2 = paramNames[idx] ?? `arg${idx}`;
4161
4593
  out.push({
4162
4594
  severity: "error",
4163
4595
  code: "nudo:constraint-violated",
4164
- message: `${displayName}[${paramName2}]: \u5B9E\u53C2 \u22AD \u524D\u7F6E`,
4596
+ message: `${displayName}[${paramName}]: \u5B9E\u53C2 \u22AD \u524D\u7F6E`,
4165
4597
  actual: formatAbs(arg),
4166
4598
  expected: predToString(p),
4167
- suggestion: `\u6539\u7528\u6EE1\u8DB3 ${predToString(p)} \u7684\u503C\uFF0C\u6216\u653E\u5BBD ${paramName2} \u7684\u524D\u7F6E`,
4599
+ suggestion: `\u6539\u7528\u6EE1\u8DB3 ${predToString(p)} \u7684\u503C\uFF0C\u6216\u653E\u5BBD ${paramName} \u7684\u524D\u7F6E`,
4168
4600
  fn: displayName,
4169
4601
  line: loc?.start.line,
4170
4602
  column: loc?.start.column
@@ -4346,14 +4778,35 @@ function scanLiteralCalls(source, knownFns, phi, opts) {
4346
4778
  }
4347
4779
  };
4348
4780
  const checkShapeReqs = (displayName, reqs, paramNames, absArgs, argIndexOf, loc) => {
4349
- for (const [idx, entry] of reqs) {
4781
+ for (const [idx, entry, field] of reqs) {
4350
4782
  const c = entry.constraint;
4351
4783
  if (!c.fields && !c.element && !isIntFlag(c) && !c.prim) continue;
4352
4784
  const argIdx = argIndexOf(idx);
4353
4785
  if (argIdx === void 0) continue;
4354
- const arg = absArgs[argIdx];
4786
+ let arg = absArgs[argIdx];
4355
4787
  if (!arg) continue;
4356
4788
  const paramName = entry.param || paramNames[idx] || `arg${idx}`;
4789
+ if (field) {
4790
+ const projected = projectArgField(arg, field);
4791
+ if (!projected) {
4792
+ const k = arg.shape.k;
4793
+ if (k !== "unknown" && k !== "any") {
4794
+ out.push({
4795
+ severity: "error",
4796
+ code: "nudo:constraint-violated",
4797
+ message: `${displayName}[${paramName}]: \u5B9E\u53C2 \u22AD \u524D\u7F6E`,
4798
+ actual: formatAbs(arg),
4799
+ expected: `missing field ${field}`,
4800
+ suggestion: `\u8865\u5168\u5B57\u6BB5 ${field}`,
4801
+ fn: displayName,
4802
+ line: loc?.start.line,
4803
+ column: loc?.start.column
4804
+ });
4805
+ }
4806
+ continue;
4807
+ }
4808
+ arg = projected;
4809
+ }
4357
4810
  if (c.fields) {
4358
4811
  checkShapeAgainstAbs(displayName, paramName, c, arg, paramName, loc);
4359
4812
  }
@@ -4468,11 +4921,11 @@ function scanLiteralCalls(source, knownFns, phi, opts) {
4468
4921
  };
4469
4922
  const ownEi = effectiveInterfaceOf(fnName, source, optsR);
4470
4923
  if (ownEi?.source === "handwritten") {
4471
- const ownFull = interfaceToIndexed(ownEi, paramNames);
4924
+ const ownFull = interfaceToIndexed(ownEi, paramNames, g?.formals);
4472
4925
  checkShapeReqs(fnName, ownFull, paramNames, absArgs, (i) => i, loc);
4473
4926
  checkReqs(
4474
4927
  fnName,
4475
- ownFull.map(([i, e]) => [i, e.pred]),
4928
+ ownFull.map(([i, e, f]) => [i, e.pred, f, e.param]),
4476
4929
  paramNames,
4477
4930
  absArgs,
4478
4931
  (i) => i,
@@ -4484,7 +4937,7 @@ function scanLiteralCalls(source, knownFns, phi, opts) {
4484
4937
  const tg = generalizeFromAst(fwd.target, source, file ? { file } : {});
4485
4938
  const tParams = tg?.params ?? [];
4486
4939
  const tEi = effectiveInterfaceOf(fwd.target, source, optsR);
4487
- const tFull = tEi?.source === "handwritten" ? interfaceToIndexed(tEi, tParams) : [];
4940
+ const tFull = tEi?.source === "handwritten" ? interfaceToIndexed(tEi, tParams, tg?.formals) : [];
4488
4941
  if (tFull.length > 0) {
4489
4942
  const wrapperArgOfTarget = /* @__PURE__ */ new Map();
4490
4943
  fwd.map.forEach((wrapperIdx, targetIdx) => {
@@ -4494,7 +4947,7 @@ function scanLiteralCalls(source, knownFns, phi, opts) {
4494
4947
  checkShapeReqs(`${fnName}\u2192${fwd.target}`, tFull, tParams, absArgs, mapArg, loc);
4495
4948
  checkReqs(
4496
4949
  `${fnName}\u2192${fwd.target}`,
4497
- tFull.map(([i, e]) => [i, e.pred]),
4950
+ tFull.map(([i, e, f]) => [i, e.pred, f, e.param]),
4498
4951
  tParams,
4499
4952
  absArgs,
4500
4953
  mapArg,
@@ -4520,7 +4973,7 @@ function scanLiteralCalls(source, knownFns, phi, opts) {
4520
4973
  };
4521
4974
  const ei = effectiveInterfaceOf(ext.fnName, ext.source, eiOpts);
4522
4975
  if (ei?.source === "handwritten") {
4523
- full = interfaceToIndexed(ei, paramNames);
4976
+ full = interfaceToIndexed(ei, paramNames, g?.formals);
4524
4977
  }
4525
4978
  } catch {
4526
4979
  out.push({
@@ -4536,7 +4989,7 @@ function scanLiteralCalls(source, knownFns, phi, opts) {
4536
4989
  checkShapeReqs(displayName, full, paramNames, absArgs, (i) => i, loc);
4537
4990
  checkReqs(
4538
4991
  displayName,
4539
- full.map(([i, e]) => [i, e.pred]),
4992
+ full.map(([i, e, f]) => [i, e.pred, f, e.param]),
4540
4993
  paramNames,
4541
4994
  absArgs,
4542
4995
  (i) => i,
@@ -4580,19 +5033,15 @@ function scanLiteralCalls(source, knownFns, phi, opts) {
4580
5033
  }
4581
5034
  }
4582
5035
  };
4583
- const checkArgStructures = (fnName, fnSource, args, loc, displayName, interfaceFromFile) => {
4584
- let structReqs;
4585
- let paramNames;
5036
+ const checkArgStructures = (fnName, fnSource, args, loc, displayName, _interfaceFromFile) => {
4586
5037
  let gFn;
4587
5038
  try {
4588
5039
  const sameFile = fnSource === source;
4589
- structReqs = collectParamStructReqs(fnSource, fnName, sameFile ? file : void 0);
4590
5040
  gFn = generalizeFromAst(
4591
5041
  fnName,
4592
5042
  fnSource,
4593
5043
  sameFile && file ? { file } : {}
4594
5044
  );
4595
- paramNames = gFn?.params ?? [];
4596
5045
  } catch (e) {
4597
5046
  out.push({
4598
5047
  severity: "warning",
@@ -4613,65 +5062,6 @@ function scanLiteralCalls(source, knownFns, phi, opts) {
4613
5062
  (n) => evalArgAbs(n, (x) => varAbs.get(x))
4614
5063
  );
4615
5064
  }
4616
- if (structReqs.size === 0) return;
4617
- let refinedParams;
4618
- try {
4619
- const sameFile = fnSource === source;
4620
- const eiOpts = sameFile ? {
4621
- loadModule: opts?.loadModule,
4622
- fromFile: opts?.fromFile ?? "",
4623
- ...opts?.autoBind !== void 0 ? { autoBind: opts.autoBind } : {}
4624
- } : {
4625
- loadModule: opts?.loadModule,
4626
- fromFile: interfaceFromFile ?? opts?.fromFile ?? "",
4627
- ...interfaceFromFile ? opts?.autoBind !== void 0 ? { autoBind: opts.autoBind } : {} : { autoBind: false }
4628
- };
4629
- const ei = effectiveInterfaceOf(fnName, fnSource, eiOpts);
4630
- if (ei?.source === "handwritten" && ei.params.length > 0) {
4631
- refinedParams = new Set(ei.params.map((p) => p.param));
4632
- }
4633
- } catch {
4634
- out.push({
4635
- severity: "warning",
4636
- code: "nudo:no-signature",
4637
- message: `${displayName ?? fnName}: handwritten interface load failed; falling back to body structure inference`,
4638
- fn: displayName ?? fnName,
4639
- line: loc?.start.line,
4640
- column: loc?.start.column
4641
- });
4642
- }
4643
- for (let i = 0; i < args.length; i++) {
4644
- const pname = paramNames[i];
4645
- if (!pname) continue;
4646
- if (refinedParams?.has(pname)) continue;
4647
- const keys = structReqs.get(pname);
4648
- if (!keys || keys.size === 0) continue;
4649
- const argNode = args[i];
4650
- if (!argNode) continue;
4651
- const absArg = evalArgAbs(argNode, (n) => varAbs.get(n));
4652
- if (!absArg || absArg.shape.k === "unknown") continue;
4653
- const isLeny = absArg.shape.k === "arr" || absArg.shape.k === "tuple" || absArg.shape.k === "prim" && absArg.shape.type === "string";
4654
- const needKeys = isLeny ? [...keys].filter((k) => k !== "length") : [...keys];
4655
- if (needKeys.length === 0) continue;
4656
- const slots = {};
4657
- for (const k of needKeys) slots[k] = { value: absUnknown() };
4658
- const target = abs({ k: "obj", slots }, void 0, void 0, "exact");
4659
- const leq = leqAbs(absArg, target);
4660
- if (!leq.ok) {
4661
- const name = displayName ?? fnName;
4662
- out.push({
4663
- severity: "error",
4664
- code: "nudo:arg-structure",
4665
- message: `${name}[${pname}]: \u5B9E\u53C2\u7ED3\u6784 \u22AD \u5F62\u53C2`,
4666
- actual: formatAbs(absArg),
4667
- expected: formatAbs(target),
4668
- suggestion: leq.reason ?? `\u8865\u5168 ${pname} \u4E0A\u88AB\u8BBF\u95EE\u7684\u5B57\u6BB5`,
4669
- fn: name,
4670
- line: loc?.start.line,
4671
- column: loc?.start.column
4672
- });
4673
- }
4674
- }
4675
5065
  };
4676
5066
  const visit = (n) => {
4677
5067
  if (!n || typeof n !== "object") return;
@@ -4768,6 +5158,14 @@ function extractLiteralEvidence(rec, idx) {
4768
5158
  }
4769
5159
 
4770
5160
  // src/algebra/check.ts
5161
+ function projectCaseArgField(arg, field) {
5162
+ if (!arg) return void 0;
5163
+ if (arg.shape.k === "brand") {
5164
+ return projectCaseArgField(arg.shape.shape, field);
5165
+ }
5166
+ if (arg.shape.k !== "obj") return void 0;
5167
+ return getSlot(arg.shape.slots, field)?.value;
5168
+ }
4771
5169
  var checkReportMemo = /* @__PURE__ */ new Map();
4772
5170
  var checkKeyDeps = /* @__PURE__ */ new Map();
4773
5171
  var checkDepIndex = /* @__PURE__ */ new Map();
@@ -4791,7 +5189,7 @@ function loadModuleId2(fn2) {
4791
5189
  }
4792
5190
  function checkDepsFingerprint(source, opts) {
4793
5191
  if (!opts.loadModule || !opts.fromFile) {
4794
- return { fp: "-", paths: [], truncated: false };
5192
+ return { fp: "-", paths: [], contents: [], truncated: false };
4795
5193
  }
4796
5194
  return loadModuleDepsFingerprint(source, opts.loadModule, opts.fromFile);
4797
5195
  }
@@ -4838,7 +5236,8 @@ function checkMemoKey(filePath, source, identityOpts, deps, sidecarFp) {
4838
5236
  filePath,
4839
5237
  `${loadModuleId2(identityOpts.loadModule)}:${identityOpts.fromFile ?? ""}`,
4840
5238
  deps.fp,
4841
- sidecarFp ?? "-"
5239
+ sidecarFp ?? "-",
5240
+ identityOpts.autoBind === false ? "ab0" : "ab1"
4842
5241
  ].join("|");
4843
5242
  }
4844
5243
  function checkMemoGet(key) {
@@ -5011,6 +5410,26 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
5011
5410
  });
5012
5411
  if (hasRefineDirective || (exportedNames?.has(name) ?? false)) {
5013
5412
  const eff = effectiveInterfaceCached(name);
5413
+ if (eff?.source === "handwritten") {
5414
+ const contractNames = contractParamNameSet(g.formals ?? []);
5415
+ const formalDisplay = new Set(g.params);
5416
+ const conflictNames = new Set(eff.conflict?.params ?? []);
5417
+ const unknownParams = eff.params.map((p) => p.param).filter(
5418
+ (p) => p && !formalDisplay.has(p) && !contractNames.has(p) && !conflictNames.has(p)
5419
+ );
5420
+ if (unknownParams.length > 0) {
5421
+ const surface = [...contractNames].filter((n) => !n.startsWith("_p") && n !== "_").join(", ");
5422
+ issues.push({
5423
+ severity: "error",
5424
+ code: "nudo:interface-param-mismatch",
5425
+ message: `${name}: \u5951\u7EA6\u53C2\u6570\u540D\u4E0D\u5728\u5F62\u53C2\u8868\uFF08${unknownParams.join(", ")}\uFF09`,
5426
+ actual: unknownParams.join(", "),
5427
+ expected: surface || g.params.join(", ") || "(\u65E0\u53C2)",
5428
+ suggestion: `\u628A @nudo:refine / \u4FA7\u8F66\u7ED1\u5B9A\u53C2\u6570\u540D\u6539\u6210\u5F62\u53C2\u4E4B\u4E00\uFF1A${surface || g.params.join(", ") || "\uFF08\u51FD\u6570\u65E0\u53C2\uFF09"}`,
5429
+ fn: name
5430
+ });
5431
+ }
5432
+ }
5014
5433
  if (eff?.conflict) {
5015
5434
  if (eff.conflict.params.length > 0) {
5016
5435
  issues.push({
@@ -5340,10 +5759,19 @@ function scanCaseInconsistency(source, knownFns, opts) {
5340
5759
  });
5341
5760
  if (!eff || eff.source !== "handwritten") return;
5342
5761
  const conflictParams = new Set(eff.conflict?.params ?? []);
5762
+ const formals = g.formals ?? [];
5343
5763
  const reqs = [];
5344
5764
  for (const p of eff.params) {
5345
5765
  if (conflictParams.has(p.param)) continue;
5346
- const idx = paramNames.indexOf(p.param);
5766
+ let idx = paramNames.indexOf(p.param);
5767
+ let field;
5768
+ if (idx < 0 && formals.length > 0) {
5769
+ const hit = locateContractParam(formals, p.param);
5770
+ if (hit) {
5771
+ idx = hit.index;
5772
+ field = hit.field;
5773
+ }
5774
+ }
5347
5775
  if (idx < 0) continue;
5348
5776
  reqs.push([
5349
5777
  idx,
@@ -5351,15 +5779,40 @@ function scanCaseInconsistency(source, knownFns, opts) {
5351
5779
  param: p.param,
5352
5780
  pred: instantiateConstraint(p.constraint, p.param),
5353
5781
  constraint: p.constraint
5354
- }
5782
+ },
5783
+ field
5355
5784
  ]);
5356
5785
  }
5357
5786
  if (reqs.length === 0) return;
5358
5787
  const absArgs = args.map((a) => parseLitArg(a) ?? absUnknown());
5359
- for (const [idx, entry] of reqs) {
5788
+ for (const req of reqs) {
5789
+ const idx = req[0];
5790
+ const entry = req[1];
5791
+ const field = req[2];
5360
5792
  if (entry.constraint.fields) continue;
5361
- const arg = absArgs[idx];
5793
+ let arg = absArgs[idx];
5362
5794
  if (!arg) continue;
5795
+ if (field) {
5796
+ const projected = projectCaseArgField(arg, field);
5797
+ if (!projected) {
5798
+ const k = arg.shape.k;
5799
+ if (k !== "unknown" && k !== "any") {
5800
+ const paramName = entry.param || paramNames[idx] || `arg${idx}`;
5801
+ out.push({
5802
+ severity: "error",
5803
+ code: "nudo:case-inconsistency",
5804
+ message: `${fnName} case "${caseName}": \u89C1\u8BC1 \u22AD \u5951\u7EA6`,
5805
+ actual: formatAbs(arg),
5806
+ expected: `missing field ${field}`,
5807
+ suggestion: `case \u5B9E\u53C2\u8865\u5168\u5B57\u6BB5 ${field}\uFF08\u5951\u7EA6\u4F4D ${paramName}\uFF09`,
5808
+ fn: fnName,
5809
+ line
5810
+ });
5811
+ }
5812
+ continue;
5813
+ }
5814
+ arg = projected;
5815
+ }
5363
5816
  const lv = litValue(arg);
5364
5817
  if (lv === void 0 || typeof lv !== "number" && typeof lv !== "string" && typeof lv !== "boolean") {
5365
5818
  continue;
@@ -5658,8 +6111,12 @@ function formatReturnDisplay(g) {
5658
6111
  }
5659
6112
  return memberPath(abs2).text;
5660
6113
  }
5661
- function collectAbsInlays(source, refineOpts) {
6114
+ function collectAbsInlays(source, opts) {
5662
6115
  const inlays = [];
6116
+ const refineOpts = opts?.loadModule || opts?.fromFile ? {
6117
+ ...opts.loadModule ? { loadModule: opts.loadModule } : {},
6118
+ ...opts.fromFile ? { fromFile: opts.fromFile } : {}
6119
+ } : void 0;
5663
6120
  for (const { name, node } of listFunctions(source)) {
5664
6121
  let g;
5665
6122
  try {
@@ -5668,6 +6125,12 @@ function collectAbsInlays(source, refineOpts) {
5668
6125
  continue;
5669
6126
  }
5670
6127
  if (!g) continue;
6128
+ const tier = opts?.fromFile !== void 0 ? interfaceTierOf(source, name, opts.fromFile, {
6129
+ ...opts.loadModule ? { loadModule: opts.loadModule } : {},
6130
+ ...opts.autoBind !== void 0 ? { autoBind: opts.autoBind } : {}
6131
+ }) : void 0;
6132
+ const tierSrc = tier?.source;
6133
+ const isImplicitExport = tierSrc === "implicit";
5671
6134
  const params = g.params;
5672
6135
  const predsByName = /* @__PURE__ */ new Map();
5673
6136
  if (g.entryReqs) {
@@ -5688,7 +6151,8 @@ function collectAbsInlays(source, refineOpts) {
5688
6151
  line: p.loc.end.line,
5689
6152
  character: p.loc.end.column,
5690
6153
  label: ` where ${text}`,
5691
- kind: "parameter"
6154
+ kind: "parameter",
6155
+ ...tierSrc ? { interfaceSource: tierSrc } : {}
5692
6156
  });
5693
6157
  }
5694
6158
  }
@@ -5700,11 +6164,14 @@ function collectAbsInlays(source, refineOpts) {
5700
6164
  } catch {
5701
6165
  label = `: ${formatShape(g.symbolic)}`;
5702
6166
  }
6167
+ if (isImplicitExport) label += " \xB7 derived";
5703
6168
  inlays.push({
5704
6169
  line: bodyLoc.start.line,
5705
6170
  character: Math.max(0, bodyLoc.start.column),
5706
6171
  label: `${label} `,
5707
- kind: "type"
6172
+ kind: "type",
6173
+ ...tierSrc ? { interfaceSource: tierSrc } : {},
6174
+ ...isImplicitExport ? { derived: true } : {}
5708
6175
  });
5709
6176
  }
5710
6177
  }
@@ -5882,6 +6349,8 @@ function termIsValue(t, a) {
5882
6349
  export {
5883
6350
  $add,
5884
6351
  $arr,
6352
+ $arrMutContainer,
6353
+ $arrRest,
5885
6354
  $async,
5886
6355
  $asyncReturn,
5887
6356
  $await,
@@ -5893,6 +6362,7 @@ export {
5893
6362
  $div,
5894
6363
  $elems,
5895
6364
  $eq,
6365
+ $eqLoose,
5896
6366
  $fnVal,
5897
6367
  $for,
5898
6368
  $forIter,
@@ -5906,22 +6376,29 @@ export {
5906
6376
  $idxSet,
5907
6377
  $invoke,
5908
6378
  $invokeSuper,
6379
+ $isForkExit,
5909
6380
  $join,
5910
6381
  $le,
5911
6382
  $len,
5912
6383
  $lit,
6384
+ $loopReturn,
5913
6385
  $lt,
5914
6386
  $mod,
5915
6387
  $mul,
5916
6388
  $ne,
6389
+ $neLoose,
5917
6390
  $neg,
5918
6391
  $new,
5919
6392
  $not,
6393
+ $nullishTest,
5920
6394
  $obj,
6395
+ $objRest,
5921
6396
  $optionalGet,
5922
6397
  $optionalInvoke,
5923
6398
  $orDefault,
6399
+ $pushLoopExit,
5924
6400
  $regex,
6401
+ $rethrowIfNudoReturn,
5925
6402
  $set,
5926
6403
  $setKey,
5927
6404
  $spread,
@@ -5932,6 +6409,10 @@ export {
5932
6409
  $thisGet,
5933
6410
  $thisSet,
5934
6411
  $throw,
6412
+ $tryCurrentMark,
6413
+ $tryMark,
6414
+ $tryPopMark,
6415
+ $tryTakeSince,
5935
6416
  $typeof,
5936
6417
  $while,
5937
6418
  $whileSeq,
@@ -5939,6 +6420,7 @@ export {
5939
6420
  DEFAULT_MAX_LOOP_ITERS,
5940
6421
  MAX_CALL_DEPTH,
5941
6422
  MAX_TOTAL_CALLS,
6423
+ NudoReturn,
5942
6424
  NudoSidecarError,
5943
6425
  NudoThrow,
5944
6426
  SELF,
@@ -5955,6 +6437,7 @@ export {
5955
6437
  analyzeFn,
5956
6438
  analyzeFnFull,
5957
6439
  and,
6440
+ any,
5958
6441
  anyVar,
5959
6442
  app,
5960
6443
  applyAbsFn,
@@ -5964,6 +6447,7 @@ export {
5964
6447
  asAbsVal,
5965
6448
  attachFnImpl,
5966
6449
  awaitAbs,
6450
+ beginCollectionFork,
5967
6451
  beginDerivationSession,
5968
6452
  betaOf,
5969
6453
  bindImports,
@@ -5972,6 +6456,7 @@ export {
5972
6456
  boolean,
5973
6457
  buildArgsFromAssume,
5974
6458
  callAbsMethod,
6459
+ callAtFunctionBoundary,
5975
6460
  callFunction,
5976
6461
  callFunctionFull,
5977
6462
  callTranspiledExport,
@@ -5983,14 +6468,19 @@ export {
5983
6468
  checkSource,
5984
6469
  classFromMethods,
5985
6470
  clearBClasses,
6471
+ clearCollectionTables,
5986
6472
  cmp,
5987
6473
  coerceAsyncReturn,
5988
6474
  collectAbsExports,
6475
+ collectAbsFreeVars,
5989
6476
  collectAbsInlays,
5990
6477
  collectAbsNodeTypes,
6478
+ collectionElementJoin,
6479
+ collectionExactLen,
5991
6480
  concatString,
5992
6481
  confJoin,
5993
6482
  constraintToEntryAbs,
6483
+ contractParamNameSet,
5994
6484
  createEnvironment,
5995
6485
  createHofCollectCtx,
5996
6486
  createTemplateAbs,
@@ -6009,8 +6499,10 @@ export {
6009
6499
  effectiveInterface,
6010
6500
  emptyEnv,
6011
6501
  emptyPhi,
6502
+ endCollectionFork,
6012
6503
  endDerivationSession,
6013
6504
  eq,
6505
+ errorBrandAbs,
6014
6506
  evalArrayStatic,
6015
6507
  evalBuiltinInstanceMethod,
6016
6508
  evalBuiltinNew,
@@ -6047,11 +6539,15 @@ export {
6047
6539
  fnConstraintToEntryReqs,
6048
6540
  fnFingerprints,
6049
6541
  fnOf,
6542
+ formalParamDisplayNames,
6543
+ formalParamsFromNodes,
6050
6544
  formatAbs,
6051
6545
  formatAbsMultiline,
6052
6546
  formatCheckReport,
6053
6547
  formatConstraint,
6054
6548
  formatDiagnostics,
6549
+ formatEffectiveInterfaceDisplay,
6550
+ formatInterfaceTierLine,
6055
6551
  formatShape,
6056
6552
  formatShapeSlot,
6057
6553
  formatTemplateNameViews,
@@ -6084,17 +6580,25 @@ export {
6084
6580
  instantiateConstraint,
6085
6581
  instantiateReturn,
6086
6582
  interfaceDiagCount,
6583
+ interfaceSourceOf,
6584
+ interfaceTierOf,
6585
+ isArrMutator,
6087
6586
  isDefinitelyFalse,
6088
6587
  isDefinitelyTrue,
6588
+ isErrorCtorName,
6589
+ isEvalMissingSlotEnabled,
6089
6590
  isExactLit,
6090
6591
  isIntFlag,
6592
+ isMapAbs,
6091
6593
  isNodeModulesPath,
6092
6594
  isNudoConstraint,
6595
+ isNudoReturn,
6093
6596
  isNudoThrow,
6094
6597
  isNullishLitAbs,
6095
6598
  isNumPrim,
6096
6599
  isObj,
6097
6600
  isRelFn,
6601
+ isSetAbs,
6098
6602
  isStrPrim,
6099
6603
  isTemplateLike,
6100
6604
  joinAbs,
@@ -6116,16 +6620,29 @@ export {
6116
6620
  literalMeetsConstraint,
6117
6621
  loadModuleDepsFingerprint,
6118
6622
  localNamedExports,
6623
+ locateContractParam,
6119
6624
  lookupMethod,
6120
6625
  lookupMethodWithOwner,
6121
6626
  lookupSuperMethod,
6627
+ looseEqAbs,
6122
6628
  lt,
6123
6629
  ltNum,
6630
+ makeMapAbs,
6631
+ makeSetAbs,
6124
6632
  makeSum,
6633
+ mapClearEntries,
6634
+ mapDeleteEntry,
6125
6635
  mapElementFallback,
6636
+ mapEntriesAbs,
6637
+ mapGetEntry,
6638
+ mapHasEntry,
6639
+ mapSetEntry,
6640
+ mapSizeAbs,
6641
+ mapValuesAbs,
6126
6642
  matchRelIdentLit,
6127
6643
  maybeLeak,
6128
6644
  mergeAdjacentFixedViews,
6645
+ mergeCollectionArms,
6129
6646
  mock,
6130
6647
  mod,
6131
6648
  mul,
@@ -6136,9 +6653,11 @@ export {
6136
6653
  normPath,
6137
6654
  not,
6138
6655
  notAbs,
6656
+ noteCollectionWrite,
6139
6657
  noteDerivationAdd,
6140
6658
  noteDerivationJoin,
6141
6659
  noteMemberDispatchMiss,
6660
+ noteObjSlotMissing,
6142
6661
  notePrimMemberMissing,
6143
6662
  noteUnknownMemberMissing,
6144
6663
  num,
@@ -6155,6 +6674,7 @@ export {
6155
6674
  partial,
6156
6675
  phiAnd,
6157
6676
  pick,
6677
+ popCollectionArm,
6158
6678
  popPhi,
6159
6679
  predEquals,
6160
6680
  predToString,
@@ -6164,7 +6684,10 @@ export {
6164
6684
  projectFlatMapResult,
6165
6685
  promoteParamShape,
6166
6686
  ptypeof,
6687
+ pushCollectionArm,
6688
+ pushLoopExit,
6167
6689
  pushPhi,
6690
+ pushThrowExit,
6168
6691
  recordMemberDiag,
6169
6692
  refineAbsForRelTrue,
6170
6693
  refineDiagCount,
@@ -6183,18 +6706,27 @@ export {
6183
6706
  resetPhi,
6184
6707
  resolveDepPath,
6185
6708
  runTranspiled,
6709
+ runWithEvalMissingSlot,
6710
+ runWithLoopExits,
6186
6711
  serializeCheckJson,
6187
6712
  setAbsAssignCollector,
6188
6713
  setAbsCallCollector,
6189
6714
  setAbsNodeCollector,
6190
6715
  setAbsTruncationCollector,
6716
+ setAddEntry,
6191
6717
  setApplyCallbackHost,
6192
6718
  setBCallCollector,
6719
+ setClearEntries,
6720
+ setDeleteEntry,
6193
6721
  setDerivation,
6194
6722
  setDerivationCollector,
6723
+ setElementsAbs,
6724
+ setEvalMissingSlotEnabled,
6725
+ setHasEntry,
6195
6726
  setInterfaceDiagCollector,
6196
6727
  setMemberDiagCollector,
6197
6728
  setRefineDiagCollector,
6729
+ setSizeAbs,
6198
6730
  shape,
6199
6731
  shapeOfTerm,
6200
6732
  shapeOnlyFn,
@@ -6222,8 +6754,10 @@ export {
6222
6754
  tagDerivationRoot,
6223
6755
  takeInterfaceDiags,
6224
6756
  takeInterfaceDiagsSince,
6757
+ takeLoopExits,
6225
6758
  takeRefineDiags,
6226
6759
  takeRefineDiagsSince,
6760
+ takeThrowExits,
6227
6761
  templateMatchesValue,
6228
6762
  templatePartsOf,
6229
6763
  termDepth,