@nudojs/core 1.10.1 → 1.11.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.
@@ -4391,6 +4391,19 @@ function withExecPhi(p, body) {
4391
4391
  phi = prev;
4392
4392
  }
4393
4393
  }
4394
+ var assumePremises = pTrue;
4395
+ function currentAssumePremises() {
4396
+ return assumePremises;
4397
+ }
4398
+ function withAssumePremises(p, body) {
4399
+ const prev = assumePremises;
4400
+ assumePremises = p;
4401
+ try {
4402
+ return body();
4403
+ } finally {
4404
+ assumePremises = prev;
4405
+ }
4406
+ }
4394
4407
  var noBody2 = { type: "BlockStatement", body: [], directives: [] };
4395
4408
  var hostGlobalFnCall;
4396
4409
  function setHostGlobalFnCall(bridge) {
@@ -4429,6 +4442,12 @@ function $absVal(v2) {
4429
4442
  return asAbsVal(v2);
4430
4443
  }
4431
4444
  function callAtFunctionBoundary(body) {
4445
+ if (assumePremises !== pTrue) {
4446
+ return withAssumePremises(pTrue, () => boundaryBody(body));
4447
+ }
4448
+ return boundaryBody(body);
4449
+ }
4450
+ function boundaryBody(body) {
4432
4451
  let forwarded = [];
4433
4452
  try {
4434
4453
  return runWithLoopExits(() => {
@@ -8679,7 +8698,12 @@ function emitArrMutatorRebinds(expr, opts, pad) {
8679
8698
  if (node.type === "CallExpression" && node.callee?.type === "MemberExpression" && node.callee.computed !== true && node.callee.property?.type === "Identifier" && ARR_MUTATOR_NAMES.has(node.callee.property.name)) {
8680
8699
  const methodName = node.callee.property.name;
8681
8700
  const argSrcs = (node.arguments ?? []).map(
8682
- (a) => a.type === "SpreadElement" ? "$unknown()" : isExpression(a) ? emitTranspileExpression(a, opts) : "$unknown()"
8701
+ (a) => (
8702
+ // spread 实参展开(issue #153):$elems → JS Abs[],数组字面量 JS
8703
+ // spread 平铺(与 expr.ts 普通调用同口径);此前折 $unknown() 单参
8704
+ // 让重绑行以 unknown 实参执行真实变更,污染容器元素域
8705
+ a.type === "SpreadElement" ? `...$elems(${emitTranspileExpression(a.argument, opts)})` : isExpression(a) ? emitTranspileExpression(a, opts) : "$unknown()"
8706
+ )
8683
8707
  ).join(", ");
8684
8708
  const objNode = node.callee.object;
8685
8709
  if (objNode.type === "Identifier") {
@@ -9809,7 +9833,12 @@ ${pad}export default ${name};`;
9809
9833
  const methodName = expr.callee.property.name;
9810
9834
  if (["push", "unshift", "splice", "pop", "shift", "reverse", "sort"].includes(methodName)) {
9811
9835
  const argSrcs = expr.arguments.map(
9812
- (a) => a.type === "SpreadElement" ? "$unknown()" : emitTranspileExpression(a, opts)
9836
+ (a) => (
9837
+ // spread 实参展开(issue #153):$elems → JS Abs[],数组字面量 JS spread
9838
+ // 平铺(与普通调用 $callNamed/$invoke 同口径,DEC-006 K5);
9839
+ // 此前折 $unknown() 单参会污染容器元素域
9840
+ a.type === "SpreadElement" ? `...$elems(${emitTranspileExpression(a.argument, opts)})` : emitTranspileExpression(a, opts)
9841
+ )
9813
9842
  ).join(", ");
9814
9843
  const objNode = expr.callee.object;
9815
9844
  if (objNode.type === "Identifier") {
@@ -12160,6 +12189,7 @@ __export(runtime_exports, {
12160
12189
  callAtFunctionBoundary: () => callAtFunctionBoundary,
12161
12190
  clearStaleTermPred: () => clearStaleTermPred,
12162
12191
  confPartial: () => confPartial,
12192
+ currentAssumePremises: () => currentAssumePremises,
12163
12193
  currentExecPhi: () => currentExecPhi,
12164
12194
  fillTuple: () => fillTuple,
12165
12195
  isArrMutator: () => isArrMutator,
@@ -12177,6 +12207,7 @@ __export(runtime_exports, {
12177
12207
  runWithLoopExits: () => runWithLoopExits,
12178
12208
  takeLoopExits: () => takeLoopExits,
12179
12209
  takeThrowExits: () => takeThrowExits,
12210
+ withAssumePremises: () => withAssumePremises,
12180
12211
  withExecPhi: () => withExecPhi,
12181
12212
  withNewTargetReset: () => withNewTargetReset
12182
12213
  });
@@ -12218,7 +12249,7 @@ function $mul(a, b) {
12218
12249
  return mul(a, b, currentExecPhi());
12219
12250
  }
12220
12251
  function $div(a, b) {
12221
- return div(a, b, currentExecPhi());
12252
+ return div(a, b, currentExecPhi(), currentAssumePremises());
12222
12253
  }
12223
12254
  function $mod(a, b) {
12224
12255
  return mod(a, b, currentExecPhi());
@@ -14772,14 +14803,32 @@ function $concat(a, b) {
14772
14803
  if (isMapAbs(x)) return mapEntriesAbs(x);
14773
14804
  const mi = matchIterElements(x);
14774
14805
  if (mi) return mi;
14806
+ if (x.shape.k === "brand") return expand(x.shape.shape);
14807
+ if (x.shape.k === "tuple") return [...x.shape.elements];
14775
14808
  return null;
14776
14809
  };
14810
+ const sideEl = (x, expanded) => {
14811
+ if (expanded) {
14812
+ return expanded.length ? expanded.reduce((u, y) => joinAbs(u, y)) : abs({ k: "never" }, void 0, void 0, "exact");
14813
+ }
14814
+ if (x?.shape?.k === "any") return anyMemberResult();
14815
+ if (x?.shape?.k === "tuple") {
14816
+ const els = x.shape.elements;
14817
+ return els.length ? els.reduce((u, y) => joinAbs(u, y)) : abs({ k: "never" }, void 0, void 0, "exact");
14818
+ }
14819
+ if (x?.shape?.k === "prim" && x.shape.type === "string") {
14820
+ return abs({ k: "prim", type: "string" }, void 0, void 0, "path");
14821
+ }
14822
+ if (x?.shape?.k === "arr") return x.shape.element;
14823
+ if (x?.shape?.k === "brand") return sideEl(x.shape.shape, null);
14824
+ return unknown;
14825
+ };
14777
14826
  if (as.k === "tuple") {
14778
14827
  const be = expand(b);
14779
14828
  if (be) {
14780
14829
  return tupleOrWiden([...as.elements, ...be], confJoin(a.conf, b.conf));
14781
14830
  }
14782
- const bEl = b?.shape?.k === "any" ? anyMemberResult() : unknown;
14831
+ const bEl = sideEl(b, be);
14783
14832
  return abs(
14784
14833
  { k: "arr", element: [...as.elements, bEl].reduce((x, y) => joinAbs(x, y)) },
14785
14834
  void 0,
@@ -14791,20 +14840,6 @@ function $concat(a, b) {
14791
14840
  if (ae && bs.k === "tuple") {
14792
14841
  return tupleOrWiden([...ae, ...bs.elements], confJoin(a.conf, b.conf));
14793
14842
  }
14794
- const sideEl = (x, expanded) => {
14795
- if (expanded) {
14796
- return expanded.length ? expanded.reduce((u, y) => joinAbs(u, y)) : abs({ k: "never" }, void 0, void 0, "exact");
14797
- }
14798
- if (x?.shape?.k === "any") return anyMemberResult();
14799
- if (x?.shape?.k === "tuple") {
14800
- const els = x.shape.elements;
14801
- return els.length ? els.reduce((u, y) => joinAbs(u, y)) : abs({ k: "never" }, void 0, void 0, "exact");
14802
- }
14803
- if (x?.shape?.k === "prim" && x.shape.type === "string") {
14804
- return abs({ k: "prim", type: "string" }, void 0, void 0, "path");
14805
- }
14806
- return unknown;
14807
- };
14808
14843
  return abs(
14809
14844
  { k: "arr", element: joinAbs(sideEl(a, ae), sideEl(b, expand(b))) },
14810
14845
  void 0,
@@ -14838,6 +14873,9 @@ function iterabilityKind(a) {
14838
14873
  if (s.slots["@@iterator"]) return "total";
14839
14874
  return s.open ? "may" : "definite";
14840
14875
  }
14876
+ if (s.k === "brand") {
14877
+ return iterabilityKind(s.shape) === "total" ? "total" : "may";
14878
+ }
14841
14879
  return "may";
14842
14880
  }
14843
14881
  function asyncIterabilityKind(a) {
@@ -14855,6 +14893,12 @@ function asyncIterabilityKind(a) {
14855
14893
  if (s.k === "obj" && !s.slots["@@iterator"] && s.slots["@@asyncIterator"]) {
14856
14894
  return "total";
14857
14895
  }
14896
+ if (s.k === "brand") {
14897
+ const ish = s.shape.shape;
14898
+ if (ish.k === "obj" && !ish.slots["@@iterator"] && ish.slots["@@asyncIterator"]) {
14899
+ return "total";
14900
+ }
14901
+ }
14858
14902
  return iterabilityKind(a);
14859
14903
  }
14860
14904
  function guardIterable(a, ctx2) {
@@ -14918,6 +14962,7 @@ function elemsOf(a) {
14918
14962
  if (a.shape.k === "prim" && a.shape.type === "string") {
14919
14963
  return [abs({ k: "prim", type: "string" }, void 0, void 0, "path")];
14920
14964
  }
14965
+ if (a.shape.k === "brand") return elemsOf(a.shape.shape);
14921
14966
  return [unknown];
14922
14967
  }
14923
14968
  function $forInKeys(o) {
@@ -16635,6 +16680,15 @@ var intFlaggedBuilders = /* @__PURE__ */ new WeakSet();
16635
16680
  function isIntFlag(c) {
16636
16681
  return c.int === true || intFlaggedBuilders.has(c);
16637
16682
  }
16683
+ function finiteBoundArg(method, n) {
16684
+ if (typeof n !== "number" || !Number.isFinite(n)) {
16685
+ const shown = typeof n === "string" ? JSON.stringify(n) : String(n);
16686
+ throw new Error(
16687
+ `nudo ${method}(): finite numeric bound expected, got ${shown} \u2014 variable references are not supported; express cross-variable lemmas with @nudo:assume (issue #152)`
16688
+ );
16689
+ }
16690
+ return n;
16691
+ }
16638
16692
  function makeBuilder(prim, preds, extra) {
16639
16693
  const fields = extra?.fields;
16640
16694
  const element = extra?.element;
@@ -16659,17 +16713,16 @@ function makeBuilder(prim, preds, extra) {
16659
16713
  /* @__PURE__ */ Object.create(null),
16660
16714
  base,
16661
16715
  {
16662
- gt: (n) => add2(gt(selfTerm(), lit(n))),
16663
- ge: (n) => add2(ge(selfTerm(), lit(n))),
16664
- lt: (n) => add2(lt(selfTerm(), lit(n))),
16665
- le: (n) => add2(le(selfTerm(), lit(n))),
16716
+ gt: (n) => add2(gt(selfTerm(), lit(finiteBoundArg("gt", n)))),
16717
+ ge: (n) => add2(ge(selfTerm(), lit(finiteBoundArg("ge", n)))),
16718
+ lt: (n) => add2(lt(selfTerm(), lit(finiteBoundArg("lt", n)))),
16719
+ le: (n) => add2(le(selfTerm(), lit(finiteBoundArg("le", n)))),
16666
16720
  int: () => makeBuilder(prim ?? "number", preds, { ...extra, int: true }),
16667
- min: (n) => add2(ge(lenTerm(selfTerm()), lit(n))),
16668
- max: (n) => add2(le(lenTerm(selfTerm()), lit(n))),
16721
+ min: (n) => add2(ge(lenTerm(selfTerm()), lit(finiteBoundArg("min", n)))),
16722
+ max: (n) => add2(le(lenTerm(selfTerm()), lit(finiteBoundArg("max", n)))),
16669
16723
  length: (n) => add2(and(ge(lenTerm(selfTerm()), lit(n)), le(lenTerm(selfTerm()), lit(n)))),
16670
16724
  shift: (n) => {
16671
- if (!Number.isFinite(n))
16672
- throw new Error("nudo shift(): offset must be a finite number");
16725
+ finiteBoundArg("shift", n);
16673
16726
  if (fields || element || members || fnSlot || lazySlot)
16674
16727
  throw new Error("nudo shift(): only numeric scalar constraint chains are allowed (shape/array/union/fn are not supported)");
16675
16728
  if (prim !== void 0 && prim !== "number")
@@ -21459,7 +21512,7 @@ ${js}`;
21459
21512
  (k) => !ENV_SHADOW_SKIP.has(k)
21460
21513
  );
21461
21514
  if (envInjectNames.length > 0) {
21462
- const envBinds = envInjectNames.map((k) => `const ${k} = __nudoEnv[${JSON.stringify(k)}];`).join("\n");
21515
+ const envBinds = envInjectNames.map((k) => `let ${k} = __nudoEnv[${JSON.stringify(k)}];`).join("\n");
21463
21516
  js = `${envBinds}
21464
21517
  ${js}`;
21465
21518
  }
@@ -21580,7 +21633,9 @@ function callTranspiledExportFullInner(exports, name, args, opts) {
21580
21633
  return runWithLoopExits(() => {
21581
21634
  try {
21582
21635
  const invoke = () => withNewTargetReset(() => fn2(...callArgs));
21583
- const r = opts?.phi ? withExecPhi(opts.phi, invoke) : invoke();
21636
+ const ap = opts?.assumePremises;
21637
+ const seeded = ap !== void 0 ? () => withAssumePremises(ap, invoke) : invoke;
21638
+ const r = opts?.phi ? withExecPhi(opts.phi, seeded) : seeded();
21584
21639
  drainPromiseMicros();
21585
21640
  if (!isAbsVal(r)) return joinControlExits(asAbsVal(r));
21586
21641
  return joinControlExits(r);
@@ -25179,7 +25234,50 @@ function mul(a, b, phi2 = pTrue) {
25179
25234
  noteAbstractArithMayThrow(a, b);
25180
25235
  return abs({ k: "unknown" }, void 0, void 0, "partial");
25181
25236
  }
25182
- function div(a, b, phi2 = pTrue) {
25237
+ function assumePremiseList(assume) {
25238
+ if (!assume || assume.op === "true") return [];
25239
+ const out = [];
25240
+ const walk = (p) => {
25241
+ if (p.op === "and") {
25242
+ p.args.forEach(walk);
25243
+ return;
25244
+ }
25245
+ if (p.op !== "true") out.push(p);
25246
+ };
25247
+ walk(assume);
25248
+ return out;
25249
+ }
25250
+ function divAssumeBounds(a, b, resultTerm, phi2, assume) {
25251
+ const premises = assumePremiseList(assume);
25252
+ if (premises.length === 0) return void 0;
25253
+ if (!a.term || !b.term) return void 0;
25254
+ const bb = numericBounds(b, phi2);
25255
+ const posDen = bb?.lo !== void 0 && (bb.lo.value > 0 || bb.lo.value === 0 && bb.lo.strict);
25256
+ const negDen = bb?.hi !== void 0 && (bb.hi.value < 0 || bb.hi.value === 0 && bb.hi.strict);
25257
+ if (!posDen && !negDen) return void 0;
25258
+ let aLeB = false;
25259
+ let bLeA = false;
25260
+ for (const p of premises) {
25261
+ if (p.op !== "le") continue;
25262
+ if (termEquals(p.a, a.term) && termEquals(p.b, b.term)) aLeB = true;
25263
+ else if (termEquals(p.a, b.term) && termEquals(p.b, a.term)) bLeA = true;
25264
+ }
25265
+ if (!aLeB && !bLeA) return void 0;
25266
+ const facts = [];
25267
+ if (aLeB) facts.push(posDen ? le(resultTerm, lit(1)) : ge(resultTerm, lit(1)));
25268
+ if (bLeA) facts.push(posDen ? ge(resultTerm, lit(1)) : le(resultTerm, lit(1)));
25269
+ const ab = numericBounds(a, phi2);
25270
+ if (ab?.lo !== void 0 && (ab.lo.value > 0 || ab.lo.value === 0)) {
25271
+ if (posDen) facts.push(ab.lo.strict ? gt(resultTerm, lit(0)) : ge(resultTerm, lit(0)));
25272
+ else facts.push(ab.lo.strict ? lt(resultTerm, lit(0)) : le(resultTerm, lit(0)));
25273
+ }
25274
+ if (ab?.hi !== void 0 && (ab.hi.value < 0 || ab.hi.value === 0)) {
25275
+ if (posDen) facts.push(ab.hi.strict ? lt(resultTerm, lit(0)) : le(resultTerm, lit(0)));
25276
+ else facts.push(ab.hi.strict ? gt(resultTerm, lit(0)) : ge(resultTerm, lit(0)));
25277
+ }
25278
+ return facts.length ? and(...facts) : void 0;
25279
+ }
25280
+ function div(a, b, phi2 = pTrue, assume) {
25183
25281
  {
25184
25282
  const fa = builtinBrandToPrimitive(a, "number");
25185
25283
  const fb = builtinBrandToPrimitive(b, "number");
@@ -25234,7 +25332,13 @@ function div(a, b, phi2 = pTrue) {
25234
25332
  term.op === "lit" ? "exact" : confJoin(confJoin(a.conf, b.conf), "path")
25235
25333
  );
25236
25334
  }
25237
- return abs(num().shape, term, void 0, confJoin(confJoin(a.conf, b.conf), "path"));
25335
+ const assumePred = divAssumeBounds(a, b, term, phi2, assume);
25336
+ return abs(
25337
+ num().shape,
25338
+ term,
25339
+ assumePred,
25340
+ confJoin(confJoin(a.conf, b.conf), "path")
25341
+ );
25238
25342
  }
25239
25343
  if (isNumericLike(a) && isNumericLike(b)) {
25240
25344
  return abs(num().shape, void 0, void 0, "partial");
@@ -25245,7 +25349,7 @@ function div(a, b, phi2 = pTrue) {
25245
25349
  if (isAnyLike(a) || isAnyLike(b)) {
25246
25350
  return toNumberResult(a, b, "/");
25247
25351
  }
25248
- const distributed = distributeSumBinOp("/", a, b, phi2, div);
25352
+ const distributed = distributeSumBinOp("/", a, b, phi2, (x, y, p) => div(x, y, p, assume));
25249
25353
  if (distributed) return distributed;
25250
25354
  noteAbstractArithMayThrow(a, b);
25251
25355
  return abs({ k: "unknown" }, void 0, void 0, "partial");
@@ -25948,6 +26052,8 @@ export {
25948
26052
  clearStaleTermPred,
25949
26053
  currentExecPhi,
25950
26054
  withExecPhi,
26055
+ currentAssumePremises,
26056
+ withAssumePremises,
25951
26057
  asAbsVal,
25952
26058
  $absVal,
25953
26059
  callAtFunctionBoundary,
@@ -47,7 +47,7 @@ import {
47
47
  withEvalBudgetOverride,
48
48
  withExecPhi,
49
49
  withFnBudgetOverride
50
- } from "./chunk-2ZIOQGW3.js";
50
+ } from "./chunk-OYQMVCUV.js";
51
51
 
52
52
  // src/algebra/directive-scan.ts
53
53
  function cleanDirectiveLine(raw, kind) {
@@ -614,6 +614,14 @@ function scanContractSegments(lines) {
614
614
  }
615
615
  return reqs;
616
616
  }
617
+ function scanAssumeSegments(lines) {
618
+ const out = [];
619
+ for (const line of lines) {
620
+ const m = line.match(/^@nudo:assume\s+(.+)$/);
621
+ if (m) out.push(m[1].trim().replace(/\*\/$/, "").trim());
622
+ }
623
+ return out;
624
+ }
617
625
  function scanThrowsDecl(lines) {
618
626
  const kinds = /* @__PURE__ */ new Set();
619
627
  let any = false;
@@ -1490,6 +1498,24 @@ function extractRefineLines(source, fnName) {
1490
1498
  const lines = fnDirectiveCommentLines(source, fnName);
1491
1499
  return scanContractSegments(lines);
1492
1500
  }
1501
+ function extractAssumeSegs(source, fnName) {
1502
+ if (!stripStringsKeepComments(source).includes("@nudo:assume")) return [];
1503
+ const out = [];
1504
+ for (const seg of scanAssumeSegments(fnDirectiveCommentLines(source, fnName))) {
1505
+ const geSeg = seg.match(/^([A-Za-z_$][\w$]*)\s*>=\s*([A-Za-z_$][\w$]*)$/);
1506
+ if (geSeg) {
1507
+ out.push({ kind: "ok", lhs: geSeg[2], rhs: geSeg[1] });
1508
+ continue;
1509
+ }
1510
+ const leSeg = seg.match(/^([A-Za-z_$][\w$]*)\s*<=\s*([A-Za-z_$][\w$]*)$/);
1511
+ if (leSeg) {
1512
+ out.push({ kind: "ok", lhs: leSeg[1], rhs: leSeg[2] });
1513
+ continue;
1514
+ }
1515
+ out.push({ kind: "bad", raw: seg });
1516
+ }
1517
+ return out;
1518
+ }
1493
1519
  function extractRefinesFromSource(source, fnName, opts = {}) {
1494
1520
  if (!stripStringsKeepComments(source).includes("@nudo:contract")) return [];
1495
1521
  const constraints = collectConstraints(source, opts);
@@ -5525,6 +5551,7 @@ export {
5525
5551
  NudoSidecarError,
5526
5552
  execNudoModule,
5527
5553
  resetNudoModuleExecCache,
5554
+ extractAssumeSegs,
5528
5555
  extractRefinesFromSource,
5529
5556
  refineToIndexedFull,
5530
5557
  extractRefineReturnFromSource,
package/dist/exec.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as Abs, M as MayThrowEffect, b as Phi } from './run-Bgj2tCrv.js';
2
- export { W as $assignRecord, X as $call, Y as $callNamed, bI as $nodoPos, Z as $recordBinding, a5 as EvalAbsAssignRecord, a6 as EvalCallRecord, a7 as EvalFallback, g as EvalFallbackStats, a8 as EvalPosRecord, ab as MAX_EVAL_CALL_DEPTH, ac as MAX_EVAL_TOTAL_CALLS, ad as RUNTIME_IMPORT_RE, V as RunTranspiledOptions, af as TranspiledCallResult, at as bindingsOf, aw as callTranspiledExport, ax as callTranspiledExportApply, ay as callTranspiledExportFull, l as clearPureCallMemo, m as clearPureMemo, n as enterEvalCallBudgetSession, aD as evalExprAbs, p as exitEvalCallBudgetSession, v as getEvalCallBudgetState, aG as getEvalCallCollector, w as getEvalFallbackStats, bJ as getPosCollector, aO as isAbsVal, aQ as isCjsMainRun, b5 as noteEvalCallRecord, b6 as noteEvalFallback, bn as resetEvalCallBudget, H as resetEvalFallbackStats, bK as routeApplyThrows, bo as runTranspiled, bp as runTranspiledOptionsMemoKey, bq as setEvalAssignCollector, br as setEvalBindingSink, bs as setEvalCallCollector, bt as setEvalFallbackCollector, bv as setPosCollector, bF as tryRunTranspiled, O as withEvalBudgetOverride } from './run-Bgj2tCrv.js';
1
+ import { A as Abs, M as MayThrowEffect, b as Phi } from './run-CDBM1fJZ.js';
2
+ export { W as $assignRecord, X as $call, Y as $callNamed, bI as $nodoPos, Z as $recordBinding, a5 as EvalAbsAssignRecord, a6 as EvalCallRecord, a7 as EvalFallback, g as EvalFallbackStats, a8 as EvalPosRecord, ab as MAX_EVAL_CALL_DEPTH, ac as MAX_EVAL_TOTAL_CALLS, ad as RUNTIME_IMPORT_RE, V as RunTranspiledOptions, af as TranspiledCallResult, at as bindingsOf, aw as callTranspiledExport, ax as callTranspiledExportApply, ay as callTranspiledExportFull, l as clearPureCallMemo, m as clearPureMemo, n as enterEvalCallBudgetSession, aD as evalExprAbs, p as exitEvalCallBudgetSession, v as getEvalCallBudgetState, aG as getEvalCallCollector, w as getEvalFallbackStats, bJ as getPosCollector, aO as isAbsVal, aQ as isCjsMainRun, b5 as noteEvalCallRecord, b6 as noteEvalFallback, bn as resetEvalCallBudget, H as resetEvalFallbackStats, bK as routeApplyThrows, bo as runTranspiled, bp as runTranspiledOptionsMemoKey, bq as setEvalAssignCollector, br as setEvalBindingSink, bs as setEvalCallCollector, bt as setEvalFallbackCollector, bv as setPosCollector, bF as tryRunTranspiled, O as withEvalBudgetOverride } from './run-CDBM1fJZ.js';
3
3
  import { Node, Expression, File } from '@babel/types';
4
4
 
5
5
  /**
@@ -29,6 +29,8 @@ declare function isNudoThrow(e: unknown): e is NudoThrow;
29
29
  declare function clearStaleTermPred(v: Abs): void;
30
30
  declare function currentExecPhi(): Phi;
31
31
  declare function withExecPhi<T>(p: Phi, body: () => T): T;
32
+ declare function currentAssumePremises(): Phi;
33
+ declare function withAssumePremises<T>(p: Phi, body: () => T): T;
32
34
  /**
33
35
  * transpile 泄漏的 JS 函数值 → 一等 fn Abs。
34
36
  * 求值引擎把函数声明/表达式编译成真实 JS 函数;它们流进对象槽、
@@ -825,4 +827,4 @@ declare class NudoUnsupportedError extends Error {
825
827
  detail?: string);
826
828
  }
827
829
 
828
- export { $absVal, $add, $arguments, $arr, $arrMutContainer, $arrRest, $arrWithHoles, $async, $asyncReturn, $await, $bitand, $bitnot, $bitor, $bitxor, $catchVal, $class, $classExpr, $collectionForEach, $concat, $copy, $del, $delRes, $div, $dynamicImport, $elems, $eq, $eqLoose, $fnVal, $for, $forInKeys, $forIter, $forOf, $fork, $ge, $gen, $get, $getSuper, $getSuperObj, $gt, $idx, $idxSet, $importMeta, $in, $instanceof, $instanceofNonIdent, $invoke, $invokeSuper, $invokeSuperKey, $invokeSuperObj, $isBreakTo, $isForkExit, $iterCheck, $join, $le, $len, $lit, $loopBreak, $loopContinue, $loopReturn, $lt, $mod, $mul, $narrowMemberEq, $narrowTypeOf, $ne, $neLoose, $neg, $new, $newTarget, $not, $nullishTest, $obj, $objAccessor, $objAccessorKey, $objRest, $optionalGet, $optionalInvoke, $orDefault, $pow, $pushLoopExit, $rawThis, $reStateCall, $refineRel, $regex, $removeMemberNullish, $removeNull, $removeNullish, $removeUndefined, $restBind, $rethrowIfNudoReturn, $set, $setKey, $setProto, $shl, $shr, $spread, $staticInit, $staticInvoke, $sub, $super, $switch, $thisGet, $thisSet, $throw, $toNumber, $toNumeric, $tpl, $tryCurrentMark, $tryDetachSoftCatch, $tryDigestSoftCatch, $tryDiscardSoft, $tryMark, $tryOrphanSoft, $tryPopMark, $tryReleaseSoftCatch, $tryReleaseSoftOut, $tryTakeSince, $typeof, $unknown, $updateAdd, $updateSub, $ushr, $while, $whileSeq, $yield, $yieldStar, DEFAULT_MAX_LOOP_ITERS, type EvalClassSpec, NudoLoopSignal, NudoReturn, NudoThrow, NudoUnsupportedError, type TranspileOptions, asAbsVal, callAtFunctionBoundary, clearBClasses, clearStaleTermPred, currentExecPhi, fillTuple, foldRequireSpecArg, foldStaticStringExpr, getEvalClass, isArrMutator, isDefinitelyFalse, isDefinitelyTrue, isNudoBreak, isNudoContinue, isNudoReturn, isNudoThrow, litTruth, lookupObjAccessor, namespaceNameOf, pushLoopExit, pushThrowExit, registerEvalClass, runWithLoopExits, runtimeImportOf, takeLoopExits, takeThrowExits, transpile, transpileBodyNode, transpileExpression, transpileFile, transpileSource, withExecPhi };
830
+ export { $absVal, $add, $arguments, $arr, $arrMutContainer, $arrRest, $arrWithHoles, $async, $asyncReturn, $await, $bitand, $bitnot, $bitor, $bitxor, $catchVal, $class, $classExpr, $collectionForEach, $concat, $copy, $del, $delRes, $div, $dynamicImport, $elems, $eq, $eqLoose, $fnVal, $for, $forInKeys, $forIter, $forOf, $fork, $ge, $gen, $get, $getSuper, $getSuperObj, $gt, $idx, $idxSet, $importMeta, $in, $instanceof, $instanceofNonIdent, $invoke, $invokeSuper, $invokeSuperKey, $invokeSuperObj, $isBreakTo, $isForkExit, $iterCheck, $join, $le, $len, $lit, $loopBreak, $loopContinue, $loopReturn, $lt, $mod, $mul, $narrowMemberEq, $narrowTypeOf, $ne, $neLoose, $neg, $new, $newTarget, $not, $nullishTest, $obj, $objAccessor, $objAccessorKey, $objRest, $optionalGet, $optionalInvoke, $orDefault, $pow, $pushLoopExit, $rawThis, $reStateCall, $refineRel, $regex, $removeMemberNullish, $removeNull, $removeNullish, $removeUndefined, $restBind, $rethrowIfNudoReturn, $set, $setKey, $setProto, $shl, $shr, $spread, $staticInit, $staticInvoke, $sub, $super, $switch, $thisGet, $thisSet, $throw, $toNumber, $toNumeric, $tpl, $tryCurrentMark, $tryDetachSoftCatch, $tryDigestSoftCatch, $tryDiscardSoft, $tryMark, $tryOrphanSoft, $tryPopMark, $tryReleaseSoftCatch, $tryReleaseSoftOut, $tryTakeSince, $typeof, $unknown, $updateAdd, $updateSub, $ushr, $while, $whileSeq, $yield, $yieldStar, DEFAULT_MAX_LOOP_ITERS, type EvalClassSpec, NudoLoopSignal, NudoReturn, NudoThrow, NudoUnsupportedError, type TranspileOptions, asAbsVal, callAtFunctionBoundary, clearBClasses, clearStaleTermPred, currentAssumePremises, currentExecPhi, fillTuple, foldRequireSpecArg, foldStaticStringExpr, getEvalClass, isArrMutator, isDefinitelyFalse, isDefinitelyTrue, isNudoBreak, isNudoContinue, isNudoReturn, isNudoThrow, litTruth, lookupObjAccessor, namespaceNameOf, pushLoopExit, pushThrowExit, registerEvalClass, runWithLoopExits, runtimeImportOf, takeLoopExits, takeThrowExits, transpile, transpileBodyNode, transpileExpression, transpileFile, transpileSource, withAssumePremises, withExecPhi };
package/dist/exec.js CHANGED
@@ -149,6 +149,7 @@ import {
149
149
  clearPureCallMemo,
150
150
  clearPureMemo,
151
151
  clearStaleTermPred,
152
+ currentAssumePremises,
152
153
  currentExecPhi,
153
154
  enterEvalCallBudgetSession,
154
155
  evalExprAbs,
@@ -198,9 +199,10 @@ import {
198
199
  transpileFile,
199
200
  transpileSource,
200
201
  tryRunTranspiled,
202
+ withAssumePremises,
201
203
  withEvalBudgetOverride,
202
204
  withExecPhi
203
- } from "./chunk-2ZIOQGW3.js";
205
+ } from "./chunk-OYQMVCUV.js";
204
206
  export {
205
207
  $absVal,
206
208
  $add,
@@ -351,6 +353,7 @@ export {
351
353
  clearPureCallMemo,
352
354
  clearPureMemo,
353
355
  clearStaleTermPred,
356
+ currentAssumePremises,
354
357
  currentExecPhi,
355
358
  enterEvalCallBudgetSession,
356
359
  evalExprAbs,
@@ -400,6 +403,7 @@ export {
400
403
  transpileFile,
401
404
  transpileSource,
402
405
  tryRunTranspiled,
406
+ withAssumePremises,
403
407
  withEvalBudgetOverride,
404
408
  withExecPhi
405
409
  };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { d as AstEnv, A as Abs, b as Phi, T as Term, Q as HofCollectCtx, C as Confidence, S as Shape, a as Pred, R as RelSource, U as HofSite, c as AbsModuleExports, V as RunTranspiledOptions } from './run-Bgj2tCrv.js';
2
- export { W as $assignRecord, X as $call, Y as $callNamed, Z as $recordBinding, _ as AbsApplyNoThrow, a0 as AbsApplyNoThrowFn, a1 as AbsApplyResult, a2 as AbsApplyReturn, a3 as AbsFnImpl, a4 as AbsSigImpl, a5 as EvalAbsAssignRecord, a6 as EvalCallRecord, a7 as EvalFallback, a8 as EvalPosRecord, a9 as ImplicationOracle, aa as LitValueResult, L as LiteralValue, ab as MAX_EVAL_CALL_DEPTH, ac as MAX_EVAL_TOTAL_CALLS, P as PrimName, ad as RUNTIME_IMPORT_RE, ae as TYPEOF_NAMES, af as TranspiledCallResult, ag as TypeofName, ah as abs, ai as absFunction, aj as absOnly, ak as absToString, al as and, am as anyAbs, an as anyVar, ao as app, ap as assumeFinite, aq as attachFnImpl, ar as bigintLit, as as bindImports, at as bindingsOf, au as bool, av as boolLit, aw as callTranspiledExport, ax as callTranspiledExportApply, ay as callTranspiledExportFull, az as collectAbsExports, aA as confJoin, aB as emptyPhi, aC as eq, aD as evalExprAbs, aE as ge, aF as geNum, aG as getEvalCallCollector, aH as getFnImpl, aI as getImplicationOracle, aJ as gt, aK as gtNum, aL as hostFnCtorFacet, aM as implies, aN as isAbsApplyResult, aO as isAbsVal, aP as isBigPrim, aQ as isCjsMainRun, aR as isExactLit, aS as isNumPrim, aT as isStrPrim, aU as le, aV as leNum, aW as lit, aX as litValue, aY as lt, aZ as ltNum, a_ as makeAbsApplyResult, a$ as markPureFn, b0 as namespaceAbsOf, b1 as ne, b2 as negatePred, b3 as never, b4 as not, b5 as noteEvalCallRecord, b6 as noteEvalFallback, b7 as num, b8 as numLit, b9 as numVar, ba as obj, bb as or, bc as pFalse, bd as pTrue, be as phiAnd, bf as predEquals, bg as predToString, bh as predVars, bi as primToTypeof, bj as ptypeof, bk as pureFnNameOf, bl as relationFingerprint, bm as relationFn, bn as resetEvalCallBudget, bo as runTranspiled, bp as runTranspiledOptionsMemoKey, bq as setEvalAssignCollector, br as setEvalBindingSink, bs as setEvalCallCollector, bt as setEvalFallbackCollector, bu as setImplicationOracle, bv as setPosCollector, bw as shapeOfTerm, bx as shapeOnlyFn, by as shapeToString, bz as simplifyTerm, bA as str, bB as strLit, bC as substPred, bD as termEquals, bE as termToString, bF as tryRunTranspiled, bG as unknown, bH as v } from './run-Bgj2tCrv.js';
1
+ import { d as AstEnv, A as Abs, b as Phi, T as Term, Q as HofCollectCtx, C as Confidence, S as Shape, a as Pred, R as RelSource, U as HofSite, c as AbsModuleExports, V as RunTranspiledOptions } from './run-CDBM1fJZ.js';
2
+ export { W as $assignRecord, X as $call, Y as $callNamed, Z as $recordBinding, _ as AbsApplyNoThrow, a0 as AbsApplyNoThrowFn, a1 as AbsApplyResult, a2 as AbsApplyReturn, a3 as AbsFnImpl, a4 as AbsSigImpl, a5 as EvalAbsAssignRecord, a6 as EvalCallRecord, a7 as EvalFallback, a8 as EvalPosRecord, a9 as ImplicationOracle, aa as LitValueResult, L as LiteralValue, ab as MAX_EVAL_CALL_DEPTH, ac as MAX_EVAL_TOTAL_CALLS, P as PrimName, ad as RUNTIME_IMPORT_RE, ae as TYPEOF_NAMES, af as TranspiledCallResult, ag as TypeofName, ah as abs, ai as absFunction, aj as absOnly, ak as absToString, al as and, am as anyAbs, an as anyVar, ao as app, ap as assumeFinite, aq as attachFnImpl, ar as bigintLit, as as bindImports, at as bindingsOf, au as bool, av as boolLit, aw as callTranspiledExport, ax as callTranspiledExportApply, ay as callTranspiledExportFull, az as collectAbsExports, aA as confJoin, aB as emptyPhi, aC as eq, aD as evalExprAbs, aE as ge, aF as geNum, aG as getEvalCallCollector, aH as getFnImpl, aI as getImplicationOracle, aJ as gt, aK as gtNum, aL as hostFnCtorFacet, aM as implies, aN as isAbsApplyResult, aO as isAbsVal, aP as isBigPrim, aQ as isCjsMainRun, aR as isExactLit, aS as isNumPrim, aT as isStrPrim, aU as le, aV as leNum, aW as lit, aX as litValue, aY as lt, aZ as ltNum, a_ as makeAbsApplyResult, a$ as markPureFn, b0 as namespaceAbsOf, b1 as ne, b2 as negatePred, b3 as never, b4 as not, b5 as noteEvalCallRecord, b6 as noteEvalFallback, b7 as num, b8 as numLit, b9 as numVar, ba as obj, bb as or, bc as pFalse, bd as pTrue, be as phiAnd, bf as predEquals, bg as predToString, bh as predVars, bi as primToTypeof, bj as ptypeof, bk as pureFnNameOf, bl as relationFingerprint, bm as relationFn, bn as resetEvalCallBudget, bo as runTranspiled, bp as runTranspiledOptionsMemoKey, bq as setEvalAssignCollector, br as setEvalBindingSink, bs as setEvalCallCollector, bt as setEvalFallbackCollector, bu as setImplicationOracle, bv as setPosCollector, bw as shapeOfTerm, bx as shapeOnlyFn, by as shapeToString, bz as simplifyTerm, bA as str, bB as strLit, bC as substPred, bD as termEquals, bE as termToString, bF as tryRunTranspiled, bG as unknown, bH as v } from './run-CDBM1fJZ.js';
3
3
  import { Node, File } from '@babel/types';
4
- import { p as parseSource, L as LeakBudget, E as EffectiveInterfaceOpts, b as LoadDepsFingerprint, v as CheckReport, N as NudoConstraint, c as ProjectionBudget } from './projection-budget-Dey0IUJa.js';
5
- export { w as CONSTRAINT_BUILDERS, x as CONSTRAINT_BUILDER_NAMES, y as CONSTRAINT_EXPR_RE, z as CheckAction, C as CheckIssue, A as CheckJson, B as CheckJsonMulti, D as ConstraintBuilder, F as Diagnostic, G as EffectiveInterface, H as GitlabCodeQualityIssue, J as INTERFACE_SOURCE_ABBR, K as InterfaceDiag, I as InterfaceSource, O as InterfaceTierInfo, a as InterfaceTierOpts, Q as NamedImport, R as NudoField, S as NudoFnConstraint, T as NudoSidecarError, U as NudoSig, V as RefineDiag, W as RefineEntry, X as RefineResolveOpts, Y as SELF, Z as actionsForIssue, _ as andC, $ as any, a0 as array, a1 as boolean, a2 as checkArg, a3 as checkCall, a4 as constraintAdmitsNullish, a5 as constraintToEntryAbs, a6 as derefConstraint, a7 as drainPromiseMicros, a8 as effectiveInterface, a9 as enterPromiseExecutorScope, aa as evalPromiseCtor, ab as evalPromiseMethod, ac as evalPromiseStatic, ad as execNudoModule, ae as extractDeclaredThrows, af as extractFnBudget, ag as extractNudoImports, ah as extractRefineReturnFromSource, ai as extractRefinesFromSource, aj as fn, ak as fnConstraintToEntryReqs, al as formatCheckReport, am as formatConstraint, an as formatDiagnostics, ao as formatEffectiveInterfaceDisplay, ap as formatGithubAnnotations, aq as formatGitlabCodeQuality, ar as formatInterfaceTierLine, as as generatedExportNames, at as getParseSourceCacheSize, au as getTerm, av as instantiateConstraint, aw as interfaceDiagCount, ax as interfaceSourceOf, ay as interfaceTierOf, az as isIntFlag, aA as isNodeModulesPath, aB as isNudoConstraint, aC as lazy, aD as leavePromiseExecutorScope, aE as lenTerm, aF as litC, aG as localNamedExports, aH as notePromiseExecutorFork, aI as nullable, aJ as number, aK as omit, aL as partial, aM as pick, aN as queuePromiseMicro, aO as refineDiagCount, aP as refineToIndexedFull, aQ as resetNudoModuleExecCache, aR as resetParseSourceCache, aS as resetSidecarLoadFailureCache, aT as serializeCheckJson, aU as serializeCheckJsonMulti, aV as setInterfaceDiagCollector, aW as setRefineDiagCollector, aX as shape, aY as sidecarClosureFingerprint, aZ as sidecarPathOf, a_ as string, a$ as takeInterfaceDiags, b0 as takeInterfaceDiagsSince, b1 as takeRefineDiags, b2 as takeRefineDiagsSince, b3 as throwConstraintToKinds, b4 as union } from './projection-budget-Dey0IUJa.js';
4
+ import { p as parseSource, L as LeakBudget, E as EffectiveInterfaceOpts, b as LoadDepsFingerprint, v as CheckReport, N as NudoConstraint, c as ProjectionBudget } from './projection-budget-BB2U2rwC.js';
5
+ export { w as CONSTRAINT_BUILDERS, x as CONSTRAINT_BUILDER_NAMES, y as CONSTRAINT_EXPR_RE, z as CheckAction, C as CheckIssue, A as CheckJson, B as CheckJsonMulti, D as ConstraintBuilder, F as Diagnostic, G as EffectiveInterface, H as GitlabCodeQualityIssue, J as INTERFACE_SOURCE_ABBR, K as InterfaceDiag, I as InterfaceSource, O as InterfaceTierInfo, a as InterfaceTierOpts, Q as NamedImport, R as NudoField, S as NudoFnConstraint, T as NudoSidecarError, U as NudoSig, V as RefineDiag, W as RefineEntry, X as RefineResolveOpts, Y as SELF, Z as actionsForIssue, _ as andC, $ as any, a0 as array, a1 as boolean, a2 as checkArg, a3 as checkCall, a4 as constraintAdmitsNullish, a5 as constraintToEntryAbs, a6 as derefConstraint, a7 as drainPromiseMicros, a8 as effectiveInterface, a9 as enterPromiseExecutorScope, aa as evalPromiseCtor, ab as evalPromiseMethod, ac as evalPromiseStatic, ad as execNudoModule, ae as extractDeclaredThrows, af as extractFnBudget, ag as extractNudoImports, ah as extractRefineReturnFromSource, ai as extractRefinesFromSource, aj as fn, ak as fnConstraintToEntryReqs, al as formatCheckReport, am as formatConstraint, an as formatDiagnostics, ao as formatEffectiveInterfaceDisplay, ap as formatGithubAnnotations, aq as formatGitlabCodeQuality, ar as formatInterfaceTierLine, as as generatedExportNames, at as getParseSourceCacheSize, au as getTerm, av as instantiateConstraint, aw as interfaceDiagCount, ax as interfaceSourceOf, ay as interfaceTierOf, az as isIntFlag, aA as isNodeModulesPath, aB as isNudoConstraint, aC as lazy, aD as leavePromiseExecutorScope, aE as lenTerm, aF as litC, aG as localNamedExports, aH as notePromiseExecutorFork, aI as nullable, aJ as number, aK as omit, aL as partial, aM as pick, aN as queuePromiseMicro, aO as refineDiagCount, aP as refineToIndexedFull, aQ as resetNudoModuleExecCache, aR as resetParseSourceCache, aS as resetSidecarLoadFailureCache, aT as serializeCheckJson, aU as serializeCheckJsonMulti, aV as setInterfaceDiagCollector, aW as setRefineDiagCollector, aX as shape, aY as sidecarClosureFingerprint, aZ as sidecarPathOf, a_ as string, a$ as takeInterfaceDiags, b0 as takeInterfaceDiagsSince, b1 as takeRefineDiags, b2 as takeRefineDiagsSince, b3 as throwConstraintToKinds, b4 as union } from './projection-budget-BB2U2rwC.js';
6
6
  export { $add, $arguments, $arr, $arrMutContainer, $arrRest, $arrWithHoles, $async, $asyncReturn, $await, $bitand, $bitnot, $bitor, $bitxor, $catchVal, $class, $classExpr, $collectionForEach, $concat, $copy, $del, $delRes, $div, $dynamicImport, $elems, $eq, $eqLoose, $fnVal, $for, $forInKeys, $forIter, $forOf, $fork, $ge, $gen, $get, $gt, $idx, $idxSet, $importMeta, $in, $instanceof, $instanceofNonIdent, $invoke, $invokeSuper, $isBreakTo, $isForkExit, $join, $le, $len, $lit, $loopBreak, $loopContinue, $loopReturn, $lt, $mod, $mul, $ne, $neLoose, $neg, $new, $not, $nullishTest, $obj, $objAccessor, $objRest, $optionalGet, $optionalInvoke, $orDefault, $pow, $pushLoopExit, $rawThis, $reStateCall, $regex, $rethrowIfNudoReturn, $set, $setKey, $shl, $shr, $spread, $staticInvoke, $sub, $super, $switch, $thisGet, $thisSet, $throw, $toNumber, $toNumeric, $tryCurrentMark, $tryDetachSoftCatch, $tryDigestSoftCatch, $tryDiscardSoft, $tryMark, $tryOrphanSoft, $tryPopMark, $tryReleaseSoftCatch, $tryReleaseSoftOut, $tryTakeSince, $typeof, $unknown, $updateAdd, $updateSub, $ushr, $while, $whileSeq, $yield, DEFAULT_MAX_LOOP_ITERS, EvalClassSpec, NudoLoopSignal, NudoReturn, NudoThrow, NudoUnsupportedError, TranspileOptions, asAbsVal, callAtFunctionBoundary, clearBClasses, clearStaleTermPred, currentExecPhi, fillTuple, foldRequireSpecArg, foldStaticStringExpr, getEvalClass, isArrMutator, isDefinitelyFalse, isDefinitelyTrue, isNudoBreak, isNudoContinue, isNudoReturn, isNudoThrow, litTruth, lookupObjAccessor, namespaceNameOf, pushLoopExit, pushThrowExit, registerEvalClass, runWithLoopExits, runtimeImportOf, takeLoopExits, takeThrowExits, transpile, transpileBodyNode, transpileExpression, transpileFile, transpileSource, withExecPhi } from './exec.js';
7
7
 
8
8
  /**
@@ -262,7 +262,7 @@ declare function mul(a: Abs, b: Abs, phi?: Phi): Abs;
262
262
  * 除法:字面量折叠;除以正/负常数时按单调性推界。
263
263
  * 除以 0:JS 语义为 ±Infinity / NaN,shape 仍 number(不报违例)。
264
264
  */
265
- declare function div(a: Abs, b: Abs, phi?: Phi): Abs;
265
+ declare function div(a: Abs, b: Abs, phi?: Phi, assume?: Phi): Abs;
266
266
  /**
267
267
  * 取模:字面量折叠;`x % k`(k 为有限非零字面量)仅当被除数有限时
268
268
  * 结果界在 (−|k|, |k|)。整数模可收紧到 [0, k),此处先做保守实数界。
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  effectiveInterface,
9
9
  evictGeneralizeMemoForPaths,
10
10
  execNudoModule,
11
+ extractAssumeSegs,
11
12
  extractBalancedParens,
12
13
  extractDeclaredThrows,
13
14
  extractFileEnvNames,
@@ -64,7 +65,7 @@ import {
64
65
  takeInterfaceDiagsSince,
65
66
  takeRefineDiags,
66
67
  takeRefineDiagsSince
67
- } from "./chunk-PKVKQB5S.js";
68
+ } from "./chunk-UTRLGWJL.js";
68
69
  import {
69
70
  $add,
70
71
  $arguments,
@@ -520,9 +521,10 @@ import {
520
521
  unknown,
521
522
  ushrAbs,
522
523
  v,
524
+ withAssumePremises,
523
525
  withExecPhi,
524
526
  withVar
525
- } from "./chunk-2ZIOQGW3.js";
527
+ } from "./chunk-OYQMVCUV.js";
526
528
 
527
529
  // src/environment.ts
528
530
  function createEnvironment(parent, bindings = /* @__PURE__ */ new Map()) {
@@ -793,7 +795,7 @@ function flattenSumArms(ret) {
793
795
  return out;
794
796
  }
795
797
  function isWidenedSumArm(m, parent) {
796
- return parent.conf === "partial" && m.shape.k === "prim" && !m.term && (!m.pred || m.pred.op === "true");
798
+ return (parent.conf === "partial" || m.conf === "widened") && m.shape.k === "prim" && !m.term && (!m.pred || m.pred.op === "true");
797
799
  }
798
800
  function provesBarePrimDomain(arm, constraint) {
799
801
  if (constraint.members) {
@@ -820,7 +822,7 @@ function assertImplies(ret, constraint, opts) {
820
822
  const phi = opts?.phi ?? pTrue;
821
823
  if (ret.shape.k === "never") return proved();
822
824
  if (isAnyConstraint(constraint)) return proved();
823
- if (isValueSetUnknown(ret)) {
825
+ if (isValueSetUnknown(ret) && ret.conf !== "widened") {
824
826
  return unprovable(
825
827
  ret.shape.k === "any" ? "any does not establish the return contract" : "inference failure (unknown/opaque) \u2014 cannot prove the return contract"
826
828
  );
@@ -876,6 +878,9 @@ function assertImpliesSingle(arm, constraint, opts, phi) {
876
878
  return constraintAdmitsNullish(constraint) ? proved() : disproved(`nullish return \u22AD ${formatConstraint(constraint)}`);
877
879
  }
878
880
  if (isValueSetUnknown(arm)) {
881
+ if (arm.conf === "widened" && arm.shape.k === "prim" && !arm.term && (!arm.pred || arm.pred.op === "true") && provesBarePrimDomain(arm, constraint)) {
882
+ return proved();
883
+ }
879
884
  return unprovable(
880
885
  arm.shape.k === "any" ? "any does not establish the return contract" : "inference failure (unknown/opaque) \u2014 cannot prove the return contract"
881
886
  );
@@ -1372,6 +1377,7 @@ function numericBound(p, self) {
1372
1377
  if (p.op !== "gt" && p.op !== "ge" && p.op !== "lt" && p.op !== "le") return void 0;
1373
1378
  if (!self) return void 0;
1374
1379
  if (termEquals(p.a, self) && p.b.op === "lit" && typeof p.b.value === "number") {
1380
+ if (!Number.isFinite(p.b.value)) return void 0;
1375
1381
  return { op: p.op, n: p.b.value };
1376
1382
  }
1377
1383
  return void 0;
@@ -2340,6 +2346,49 @@ function sidecarDiagIssues(diags) {
2340
2346
  }
2341
2347
  return out;
2342
2348
  }
2349
+ function assumePremisesPhiOf(name, source, file, issues) {
2350
+ const segs = extractAssumeSegs(source, name);
2351
+ if (segs.length === 0) return void 0;
2352
+ const meta = extractFn(source, name, file);
2353
+ const bindable = /* @__PURE__ */ new Set([
2354
+ ...contractParamNameSet(meta?.formals ?? []),
2355
+ ...meta?.params ?? []
2356
+ ]);
2357
+ const surface = [...bindable].join(", ");
2358
+ const preds = [];
2359
+ const display = [];
2360
+ for (const seg of segs) {
2361
+ if (seg.kind === "bad") {
2362
+ issues.push({
2363
+ severity: "error",
2364
+ code: "nudo:assume-invalid",
2365
+ message: `${name}: malformed @nudo:assume '${seg.raw}' (expected <param> <= <param> or <param> >= <param>; constant bounds belong to sidecar contracts)`,
2366
+ actual: seg.raw,
2367
+ expected: "<param> <= <param>",
2368
+ suggestion: "cross-variable lemmas: @nudo:assume d <= max \u2014 constant bounds: sidecar number().le(10)",
2369
+ fn: name
2370
+ });
2371
+ continue;
2372
+ }
2373
+ const bad = [seg.lhs, seg.rhs].filter((n) => !bindable.has(n));
2374
+ if (bad.length > 0) {
2375
+ issues.push({
2376
+ severity: "error",
2377
+ code: "nudo:assume-invalid",
2378
+ message: `${name}: @nudo:assume parameter name(s) not in the formal parameter list (${bad.join(", ")})`,
2379
+ actual: bad.join(", "),
2380
+ expected: surface || "(no params)",
2381
+ suggestion: `reference one of: ${surface || "(function has no params)"}`,
2382
+ fn: name
2383
+ });
2384
+ continue;
2385
+ }
2386
+ preds.push(le(v(seg.lhs), v(seg.rhs)));
2387
+ display.push(`${seg.lhs} <= ${seg.rhs}`);
2388
+ }
2389
+ if (preds.length === 0) return void 0;
2390
+ return { phi: and(...preds), display };
2391
+ }
2343
2392
  function checkSourceInner(filePath, source, file, phi, opts, issues, signatures, names, truncated, identityOpts = opts, depsFp, sidecarFp) {
2344
2393
  const hasRefineDirective = stripStringsKeepComments(source).includes("@nudo:contract");
2345
2394
  const entryNames = localNamedExports(source);
@@ -2367,6 +2416,8 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
2367
2416
  return eff;
2368
2417
  };
2369
2418
  for (const name of names) {
2419
+ const assumePhi = assumePremisesPhiOf(name, source, file, issues);
2420
+ const runSeeded = (body) => assumePhi === void 0 ? body() : withAssumePremises(assumePhi.phi, body);
2370
2421
  if (opts.skips?.has(name)) {
2371
2422
  const declared = opts.skips.get(name) ?? null;
2372
2423
  const meta = extractFn(source, name, file);
@@ -2411,19 +2462,21 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
2411
2462
  }
2412
2463
  continue;
2413
2464
  }
2414
- const g = generalizeFromAst(name, source, {
2415
- file,
2416
- refine: {
2417
- loadModule: refineLoad,
2418
- fromFile: refineFrom,
2419
- ...autoBind !== void 0 ? { autoBind } : {},
2420
- ...projectDir !== void 0 ? { projectDir } : {}
2421
- },
2422
- depsFp,
2423
- sidecarFp,
2424
- modules: opts.modules,
2425
- ...opts.inject ? { inject: opts.inject } : {}
2426
- });
2465
+ const g = runSeeded(
2466
+ () => generalizeFromAst(name, source, {
2467
+ file,
2468
+ refine: {
2469
+ loadModule: refineLoad,
2470
+ fromFile: refineFrom,
2471
+ ...autoBind !== void 0 ? { autoBind } : {},
2472
+ ...projectDir !== void 0 ? { projectDir } : {}
2473
+ },
2474
+ depsFp,
2475
+ sidecarFp,
2476
+ modules: opts.modules,
2477
+ ...opts.inject ? { inject: opts.inject } : {}
2478
+ })
2479
+ );
2427
2480
  if (!g) {
2428
2481
  const isEntryCandidate = entryNames.has(name) || name === "default" || entryNames.has("default") && isDefaultExportName(source, name);
2429
2482
  if (isEntryCandidate && entryThrowsMode !== "off") {
@@ -2483,7 +2536,7 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
2483
2536
  const isEntry = entryNames.has(name) || name === "default" || entryNames.has("default") && isDefaultExportName(source, name) || name.includes(".") && entryNames.has(name);
2484
2537
  let throwsDisplay;
2485
2538
  if (isEntry && entryThrowsMode !== "off") {
2486
- const effects = collectEntryMayThrows(source, name, g, file, phi, opts);
2539
+ const effects = runSeeded(() => collectEntryMayThrows(source, name, g, file, phi, opts));
2487
2540
  throwsDisplay = formatThrowsAbs(mayThrowEffectsToAbs(effects));
2488
2541
  const declared = extractDeclaredThrows(source, name) ?? effectiveInterfaceCached(name)?.throws?.kinds;
2489
2542
  const remaining = filterGateThrows(effects, declared, ignoreThrows);
@@ -2504,7 +2557,7 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
2504
2557
  });
2505
2558
  }
2506
2559
  } else if (isEntry) {
2507
- const effects = collectEntryMayThrows(source, name, g, file, phi, opts);
2560
+ const effects = runSeeded(() => collectEntryMayThrows(source, name, g, file, phi, opts));
2508
2561
  throwsDisplay = formatThrowsAbs(mayThrowEffectsToAbs(effects));
2509
2562
  }
2510
2563
  const fmt = formatSigCached(g.symbolic, name);
@@ -2598,7 +2651,8 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
2598
2651
  name,
2599
2652
  display,
2600
2653
  eff.returns.constraint,
2601
- g.symbolic
2654
+ g.symbolic,
2655
+ assumePhi?.display
2602
2656
  );
2603
2657
  if (retIssues.some((i) => i.severity === "error")) returnViolated.add(name);
2604
2658
  issues.push(...retIssues);
@@ -2794,9 +2848,24 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
2794
2848
  }
2795
2849
  };
2796
2850
  }
2797
- function checkReturnConstraint(fnName, cName, constraint, ret) {
2851
+ function checkReturnConstraint(fnName, cName, constraint, ret, assumeDisplay) {
2798
2852
  const proof = assertImplies(ret, constraint);
2799
- if (proof.status === "proved") return [];
2853
+ if (proof.status === "proved") {
2854
+ if (assumeDisplay && assumeDisplay.length > 0) {
2855
+ return [
2856
+ {
2857
+ severity: "info",
2858
+ code: "nudo:assume-relied",
2859
+ message: `${fnName}: return contract proved via @nudo:assume ${assumeDisplay.join("; ")}`,
2860
+ actual: `proof relies on user lemma${assumeDisplay.length > 1 ? "s" : ""}`,
2861
+ expected: "engine verifies the obligation, not the lemma itself",
2862
+ suggestion: "@nudo:assume is a user-supplied axiom \u2014 falsify it with concrete @nudo:case runs (nudo test)",
2863
+ fn: fnName
2864
+ }
2865
+ ];
2866
+ }
2867
+ return [];
2868
+ }
2800
2869
  const push = (severity, actual, expected, suggestion) => [
2801
2870
  {
2802
2871
  severity,
@@ -1,7 +1,7 @@
1
- import { I as InterfaceSource, a as InterfaceTierOpts, p as parseSource, C as CheckIssue } from './projection-budget-Dey0IUJa.js';
2
- export { L as LeakBudget, b as LoadDepsFingerprint, M as MAX_PROMISE_MICROS, P as PROJECTION_MAX_DEPTH, c as ProjectionBudget, d as ProjectionStopReason, e as defaultLeakBudget, f as exceedsBudget, g as exportedNameOfLocal, h as extractAllLoadSpecs, i as getPromiseMicrosLength, l as leakIfNeeded, j as loadModuleDepsFingerprint, m as maybeLeak, n as normPath, r as resetLeakCounter, k as resolveDepPath, s as sidecarSpecsOf, o as stablePathKey, q as stablePathKeyGraph, t as termDepth, u as termNodes } from './projection-budget-Dey0IUJa.js';
3
- import { A as Abs, T as Term, c as AbsModuleExports, d as AstEnv } from './run-Bgj2tCrv.js';
4
- export { $ as $tryDigestSoft, e as $tryMarkSoft, f as $tryReleaseSoft, E as ERROR_FAMILY, g as EvalFallbackStats, M as MayThrowEffect, h as absLit, i as absNumLit, j as absStrLit, k as allAbsStr, l as clearPureCallMemo, m as clearPureMemo, n as enterEvalCallBudgetSession, o as errorTypeAbs, p as exitEvalCallBudgetSession, q as filterDeclaredThrows, r as filterGateThrows, s as filterIgnoredThrows, t as flushMayThrowEffects, u as formatThrowsAbs, v as getEvalCallBudgetState, w as getEvalFallbackStats, x as getMayThrowCollector, y as isThrowsIgnored, z as mayThrowEffectsToAbs, B as orphanMayThrowEffects, D as popMayThrowFrame, F as pushMayThrowFrame, G as recordMayThrow, H as resetEvalFallbackStats, I as runWithMayThrowSession, J as setMayThrowCollector, K as throwAbsToKinds, N as throwsKindCovered, O as withEvalBudgetOverride } from './run-Bgj2tCrv.js';
1
+ import { I as InterfaceSource, a as InterfaceTierOpts, p as parseSource, C as CheckIssue } from './projection-budget-BB2U2rwC.js';
2
+ export { L as LeakBudget, b as LoadDepsFingerprint, M as MAX_PROMISE_MICROS, P as PROJECTION_MAX_DEPTH, c as ProjectionBudget, d as ProjectionStopReason, e as defaultLeakBudget, f as exceedsBudget, g as exportedNameOfLocal, h as extractAllLoadSpecs, i as getPromiseMicrosLength, l as leakIfNeeded, j as loadModuleDepsFingerprint, m as maybeLeak, n as normPath, r as resetLeakCounter, k as resolveDepPath, s as sidecarSpecsOf, o as stablePathKey, q as stablePathKeyGraph, t as termDepth, u as termNodes } from './projection-budget-BB2U2rwC.js';
3
+ import { A as Abs, T as Term, c as AbsModuleExports, d as AstEnv } from './run-CDBM1fJZ.js';
4
+ export { $ as $tryDigestSoft, e as $tryMarkSoft, f as $tryReleaseSoft, E as ERROR_FAMILY, g as EvalFallbackStats, M as MayThrowEffect, h as absLit, i as absNumLit, j as absStrLit, k as allAbsStr, l as clearPureCallMemo, m as clearPureMemo, n as enterEvalCallBudgetSession, o as errorTypeAbs, p as exitEvalCallBudgetSession, q as filterDeclaredThrows, r as filterGateThrows, s as filterIgnoredThrows, t as flushMayThrowEffects, u as formatThrowsAbs, v as getEvalCallBudgetState, w as getEvalFallbackStats, x as getMayThrowCollector, y as isThrowsIgnored, z as mayThrowEffectsToAbs, B as orphanMayThrowEffects, D as popMayThrowFrame, F as pushMayThrowFrame, G as recordMayThrow, H as resetEvalFallbackStats, I as runWithMayThrowSession, J as setMayThrowCollector, K as throwAbsToKinds, N as throwsKindCovered, O as withEvalBudgetOverride } from './run-CDBM1fJZ.js';
5
5
  import { File, Node } from '@babel/types';
6
6
 
7
7
  /**
package/dist/internal.js CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  stableAnalyzeKeySource,
22
22
  stablePathKey,
23
23
  stablePathKeyGraph
24
- } from "./chunk-PKVKQB5S.js";
24
+ } from "./chunk-UTRLGWJL.js";
25
25
  import {
26
26
  $tryDigestSoft,
27
27
  $tryMarkSoft,
@@ -169,7 +169,7 @@ import {
169
169
  withEvalBudgetOverride,
170
170
  withFnBudgetOverride,
171
171
  wrapPromise
172
- } from "./chunk-2ZIOQGW3.js";
172
+ } from "./chunk-OYQMVCUV.js";
173
173
 
174
174
  // src/algebra/inlay.ts
175
175
  function listFunctions(source) {
@@ -1,5 +1,5 @@
1
1
  import { File } from '@babel/types';
2
- import { A as Abs, T as Term, P as PrimName, a as Pred, L as LiteralValue, b as Phi, C as Confidence } from './run-Bgj2tCrv.js';
2
+ import { A as Abs, T as Term, P as PrimName, a as Pred, L as LiteralValue, b as Phi, C as Confidence } from './run-CDBM1fJZ.js';
3
3
 
4
4
  declare function resetParseSourceCache(): void;
5
5
  declare function getParseSourceCacheSize(): number;
@@ -840,9 +840,12 @@ type TranspiledCallResult = {
840
840
  declare function isAbsVal(v: unknown): v is Abs;
841
841
  /** 调用 runTranspiled 导出(捕获 $throw)。opts.phi:入口 Φ 种子
842
842
  * (instantiate/symbolic 的约束入口——eval 侧路径条件收窄)。
843
+ * opts.assumePremises(#152 用户引理):入口前提独立槽种子——与 phi 分槽
844
+ * (不随调用链继承),消费方经 currentAssumePremises() 读。
843
845
  * 嵌套进入(导出桥 apply)继承外层预算;仅最外层宿主入口重置。 */
844
846
  declare function callTranspiledExportFull(exports: Record<string, unknown>, name: string, args: Abs[], opts?: {
845
847
  phi?: Phi;
848
+ assumePremises?: Phi;
846
849
  }): TranspiledCallResult;
847
850
  /** 调用 runTranspiled 导出(仅结果) */
848
851
  declare function callTranspiledExport(exports: Record<string, unknown>, name: string, args: Abs[]): Abs;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nudojs/core",
3
- "version": "1.10.1",
3
+ "version": "1.11.0",
4
4
  "engines": {
5
5
  "node": ">=20"
6
6
  },