@nudojs/core 1.10.2 → 1.11.1

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.
@@ -47,7 +47,7 @@ import {
47
47
  withEvalBudgetOverride,
48
48
  withExecPhi,
49
49
  withFnBudgetOverride
50
- } from "./chunk-VKSROGOF.js";
50
+ } from "./chunk-YRRR6AWI.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,
@@ -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());
@@ -13826,6 +13857,10 @@ function leafGrew(acc, next) {
13826
13857
  if (aR.ok) return true;
13827
13858
  return !leqAbs(next, acc).ok;
13828
13859
  }
13860
+ function joinElems(t) {
13861
+ const parts = t.holes?.length ? [...t.elements, oobUndef()] : t.elements;
13862
+ return parts.length > 0 ? parts.reduce((x, y) => joinAbs(x, y)) : void 0;
13863
+ }
13829
13864
  function diffGrowth(acc, next) {
13830
13865
  const as = acc.shape;
13831
13866
  const ns = next.shape;
@@ -13843,7 +13878,10 @@ function diffGrowth(acc, next) {
13843
13878
  return any2 ? { slots } : null;
13844
13879
  }
13845
13880
  if (as.k === "tuple" && ns.k === "tuple") {
13846
- if (as.elements.length !== ns.elements.length) return true;
13881
+ if (as.elements.length !== ns.elements.length) {
13882
+ const g = diffGrowth(joinElems(as) ?? never, joinElems(ns) ?? never);
13883
+ return { el: g };
13884
+ }
13847
13885
  let any2 = false;
13848
13886
  const els = [];
13849
13887
  for (let i = 0; i < ns.elements.length; i++) {
@@ -13871,6 +13909,51 @@ function primTop(type) {
13871
13909
  return abs({ k: "prim", type }, void 0, void 0, "exact");
13872
13910
  }
13873
13911
  }
13912
+ function sumArrParts(s) {
13913
+ const elems = [];
13914
+ const lengths = /* @__PURE__ */ new Set();
13915
+ let hasArr = false;
13916
+ for (const m of s.members) {
13917
+ const ms = m.shape;
13918
+ if (ms.k === "tuple") {
13919
+ lengths.add(ms.elements.length);
13920
+ const e = joinElems(ms);
13921
+ if (e) elems.push(e);
13922
+ } else if (ms.k === "arr") {
13923
+ hasArr = true;
13924
+ elems.push(ms.element);
13925
+ } else {
13926
+ return { ok: false, collapse: false };
13927
+ }
13928
+ }
13929
+ return {
13930
+ ok: true,
13931
+ collapse: hasArr || lengths.size > 1,
13932
+ element: elems.length > 0 ? elems.reduce((x, y) => joinAbs(x, y)) : void 0
13933
+ };
13934
+ }
13935
+ function arrify(v2) {
13936
+ const s = v2.shape;
13937
+ if (s.k === "tuple") {
13938
+ return abs(
13939
+ { k: "arr", element: joinElems(s) ?? unknown },
13940
+ void 0,
13941
+ void 0,
13942
+ confJoin(v2.conf, "widened")
13943
+ );
13944
+ }
13945
+ if (s.k === "sum") {
13946
+ const p = sumArrParts(s);
13947
+ if (!p.ok) return void 0;
13948
+ return abs(
13949
+ { k: "arr", element: p.element ?? unknown },
13950
+ void 0,
13951
+ void 0,
13952
+ confJoin(v2.conf, "widened")
13953
+ );
13954
+ }
13955
+ return void 0;
13956
+ }
13874
13957
  function domainTop(v2) {
13875
13958
  const s = v2.shape;
13876
13959
  if (s.k === "sum" && s.members.length === 2) {
@@ -13882,6 +13965,17 @@ function domainTop(v2) {
13882
13965
  }
13883
13966
  let top;
13884
13967
  if (s.k === "sum") {
13968
+ const collapsed = arrify(v2);
13969
+ if (collapsed) {
13970
+ return confJoin22(
13971
+ abs(
13972
+ { k: "arr", element: domainTop(collapsed.shape.element) },
13973
+ void 0,
13974
+ void 0,
13975
+ collapsed.conf
13976
+ )
13977
+ );
13978
+ }
13885
13979
  let acc;
13886
13980
  for (const m of s.members) {
13887
13981
  const t = domainTop(m);
@@ -13891,15 +13985,9 @@ function domainTop(v2) {
13891
13985
  } else if (s.k === "prim") {
13892
13986
  top = primTop(s.type);
13893
13987
  } else if (s.k === "tuple") {
13894
- const els = s.elements.map((e) => domainTop(e));
13895
- const known = els.length ? els.reduce((x, y) => joinAbs(x, y)) : unknown;
13896
- top = abs(
13897
- { k: "arr", element: joinAbs(known, abs({ k: "unknown" }, { op: "lit", value: void 0 }, void 0, "partial")) },
13898
- void 0,
13899
- void 0,
13900
- "widened"
13901
- );
13902
- return top;
13988
+ const parts = s.holes?.length ? [...s.elements, oobUndef()] : s.elements;
13989
+ const known = parts.length > 0 ? parts.map((e) => domainTop(e)).reduce((x, y) => joinAbs(x, y)) : unknown;
13990
+ return abs({ k: "arr", element: known }, void 0, void 0, "widened");
13903
13991
  } else if (s.k === "arr") {
13904
13992
  top = abs({ k: "arr", element: domainTop(s.element) }, void 0, void 0, v2.conf);
13905
13993
  } else if (s.k === "obj") {
@@ -13915,6 +14003,23 @@ function confJoin22(top) {
13915
14003
  const c = confJoin(top.conf, "widened");
13916
14004
  return c === top.conf ? top : { ...top, conf: c };
13917
14005
  }
14006
+ function normalizeForWiden(v2, g) {
14007
+ if (g === null) return v2;
14008
+ const s = v2.shape;
14009
+ let target = v2;
14010
+ if (s.k === "sum" && s.members.length > 0 && s.members.every((m) => m.shape.k === "obj")) {
14011
+ target = s.members.reduce((x, y) => joinObjects(x, y));
14012
+ }
14013
+ if (g === true || !("slots" in g)) return target;
14014
+ const ts = target.shape;
14015
+ if (ts.k !== "obj") return target;
14016
+ const slots = {};
14017
+ for (const [k, slot] of Object.entries(ts.slots)) {
14018
+ const gi = g.slots[k];
14019
+ slots[k] = gi === void 0 ? slot : { ...slot, value: normalizeForWiden(slot.value, gi) };
14020
+ }
14021
+ return abs({ ...ts, slots }, void 0, void 0, target.conf);
14022
+ }
13918
14023
  function widenWithPath(v2, g) {
13919
14024
  if (g === null) return v2;
13920
14025
  if (g === true) return domainTop(v2);
@@ -13931,11 +14036,40 @@ function widenWithPath(v2, g) {
13931
14036
  const elements = s.elements.map((e, i) => widenWithPath(e, g.els[i] ?? null));
13932
14037
  return abs({ ...s, elements }, void 0, void 0, v2.conf);
13933
14038
  }
13934
- if ("el" in g && s.k === "arr") {
13935
- return abs({ k: "arr", element: widenWithPath(s.element, g.el) }, void 0, void 0, v2.conf);
14039
+ if ("el" in g) {
14040
+ const a = s.k === "arr" ? v2 : arrify(v2);
14041
+ if (a && a.shape.k === "arr") {
14042
+ return abs(
14043
+ { k: "arr", element: widenWithPath(a.shape.element, g.el) },
14044
+ void 0,
14045
+ void 0,
14046
+ a.conf
14047
+ );
14048
+ }
13936
14049
  }
13937
14050
  return domainTop(v2);
13938
14051
  }
14052
+ function collapseArrSums(v2) {
14053
+ const s = v2.shape;
14054
+ if (s.k === "sum") {
14055
+ const p = sumArrParts(s);
14056
+ if (p.ok && p.collapse && p.element) {
14057
+ return abs({ k: "arr", element: p.element }, void 0, void 0, v2.conf);
14058
+ }
14059
+ return v2;
14060
+ }
14061
+ if (s.k === "obj") {
14062
+ let changed = false;
14063
+ const slots = {};
14064
+ for (const [k, slot] of Object.entries(s.slots)) {
14065
+ const w = collapseArrSums(slot.value);
14066
+ if (w !== slot.value) changed = true;
14067
+ slots[k] = { ...slot, value: w };
14068
+ }
14069
+ return changed ? abs({ ...s, slots }, void 0, void 0, v2.conf) : v2;
14070
+ }
14071
+ return v2;
14072
+ }
13939
14073
  function makeLoopWidener() {
13940
14074
  let acc;
13941
14075
  let growth = null;
@@ -13957,7 +14091,10 @@ function makeLoopWidener() {
13957
14091
  observe(final);
13958
14092
  const base = acc ?? final;
13959
14093
  const g = interrupted ? true : growth;
13960
- return g === null ? base : widenWithPath(base, g === true ? true : g);
14094
+ if (g === null) {
14095
+ return collapseArrSums(base);
14096
+ }
14097
+ return widenWithPath(normalizeForWiden(base, g), g);
13961
14098
  }
13962
14099
  };
13963
14100
  }
@@ -15887,7 +16024,7 @@ function widenLoopJoin(a) {
15887
16024
  const known = els.length ? els.reduce((x, y) => joinAbs(x, y)) : unknown;
15888
16025
  const element = undefArms.length ? undefArms.reduce((x, y) => joinAbs(x, y), known) : known;
15889
16026
  return abs(
15890
- { k: "arr", element: joinAbs(element, oobUndef()) },
16027
+ { k: "arr", element },
15891
16028
  void 0,
15892
16029
  void 0,
15893
16030
  confJoin(v2.conf, "widened")
@@ -16649,6 +16786,15 @@ var intFlaggedBuilders = /* @__PURE__ */ new WeakSet();
16649
16786
  function isIntFlag(c) {
16650
16787
  return c.int === true || intFlaggedBuilders.has(c);
16651
16788
  }
16789
+ function finiteBoundArg(method, n) {
16790
+ if (typeof n !== "number" || !Number.isFinite(n)) {
16791
+ const shown = typeof n === "string" ? JSON.stringify(n) : String(n);
16792
+ throw new Error(
16793
+ `nudo ${method}(): finite numeric bound expected, got ${shown} \u2014 variable references are not supported; express cross-variable lemmas with @nudo:assume (issue #152)`
16794
+ );
16795
+ }
16796
+ return n;
16797
+ }
16652
16798
  function makeBuilder(prim, preds, extra) {
16653
16799
  const fields = extra?.fields;
16654
16800
  const element = extra?.element;
@@ -16673,17 +16819,16 @@ function makeBuilder(prim, preds, extra) {
16673
16819
  /* @__PURE__ */ Object.create(null),
16674
16820
  base,
16675
16821
  {
16676
- gt: (n) => add2(gt(selfTerm(), lit(n))),
16677
- ge: (n) => add2(ge(selfTerm(), lit(n))),
16678
- lt: (n) => add2(lt(selfTerm(), lit(n))),
16679
- le: (n) => add2(le(selfTerm(), lit(n))),
16822
+ gt: (n) => add2(gt(selfTerm(), lit(finiteBoundArg("gt", n)))),
16823
+ ge: (n) => add2(ge(selfTerm(), lit(finiteBoundArg("ge", n)))),
16824
+ lt: (n) => add2(lt(selfTerm(), lit(finiteBoundArg("lt", n)))),
16825
+ le: (n) => add2(le(selfTerm(), lit(finiteBoundArg("le", n)))),
16680
16826
  int: () => makeBuilder(prim ?? "number", preds, { ...extra, int: true }),
16681
- min: (n) => add2(ge(lenTerm(selfTerm()), lit(n))),
16682
- max: (n) => add2(le(lenTerm(selfTerm()), lit(n))),
16827
+ min: (n) => add2(ge(lenTerm(selfTerm()), lit(finiteBoundArg("min", n)))),
16828
+ max: (n) => add2(le(lenTerm(selfTerm()), lit(finiteBoundArg("max", n)))),
16683
16829
  length: (n) => add2(and(ge(lenTerm(selfTerm()), lit(n)), le(lenTerm(selfTerm()), lit(n)))),
16684
16830
  shift: (n) => {
16685
- if (!Number.isFinite(n))
16686
- throw new Error("nudo shift(): offset must be a finite number");
16831
+ finiteBoundArg("shift", n);
16687
16832
  if (fields || element || members || fnSlot || lazySlot)
16688
16833
  throw new Error("nudo shift(): only numeric scalar constraint chains are allowed (shape/array/union/fn are not supported)");
16689
16834
  if (prim !== void 0 && prim !== "number")
@@ -17340,6 +17485,7 @@ function argLacksInformation(a) {
17340
17485
  return false;
17341
17486
  }
17342
17487
  function adoptCallArgsToFaces(args, faces) {
17488
+ if (currentAssumePremises() !== pTrue) return args;
17343
17489
  const n = Math.min(args.length, faces.paramFaces.length);
17344
17490
  let changed = false;
17345
17491
  const out = args.slice();
@@ -25193,7 +25339,50 @@ function mul(a, b, phi2 = pTrue) {
25193
25339
  noteAbstractArithMayThrow(a, b);
25194
25340
  return abs({ k: "unknown" }, void 0, void 0, "partial");
25195
25341
  }
25196
- function div(a, b, phi2 = pTrue) {
25342
+ function assumePremiseList(assume) {
25343
+ if (!assume || assume.op === "true") return [];
25344
+ const out = [];
25345
+ const walk = (p) => {
25346
+ if (p.op === "and") {
25347
+ p.args.forEach(walk);
25348
+ return;
25349
+ }
25350
+ if (p.op !== "true") out.push(p);
25351
+ };
25352
+ walk(assume);
25353
+ return out;
25354
+ }
25355
+ function divAssumeBounds(a, b, resultTerm, phi2, assume) {
25356
+ const premises = assumePremiseList(assume);
25357
+ if (premises.length === 0) return void 0;
25358
+ if (!a.term || !b.term) return void 0;
25359
+ const bb = numericBounds(b, phi2);
25360
+ const posDen = bb?.lo !== void 0 && (bb.lo.value > 0 || bb.lo.value === 0 && bb.lo.strict);
25361
+ const negDen = bb?.hi !== void 0 && (bb.hi.value < 0 || bb.hi.value === 0 && bb.hi.strict);
25362
+ if (!posDen && !negDen) return void 0;
25363
+ let aLeB = false;
25364
+ let bLeA = false;
25365
+ for (const p of premises) {
25366
+ if (p.op !== "le") continue;
25367
+ if (termEquals(p.a, a.term) && termEquals(p.b, b.term)) aLeB = true;
25368
+ else if (termEquals(p.a, b.term) && termEquals(p.b, a.term)) bLeA = true;
25369
+ }
25370
+ if (!aLeB && !bLeA) return void 0;
25371
+ const facts = [];
25372
+ if (aLeB) facts.push(posDen ? le(resultTerm, lit(1)) : ge(resultTerm, lit(1)));
25373
+ if (bLeA) facts.push(posDen ? ge(resultTerm, lit(1)) : le(resultTerm, lit(1)));
25374
+ const ab = numericBounds(a, phi2);
25375
+ if (ab?.lo !== void 0 && (ab.lo.value > 0 || ab.lo.value === 0)) {
25376
+ if (posDen) facts.push(ab.lo.strict ? gt(resultTerm, lit(0)) : ge(resultTerm, lit(0)));
25377
+ else facts.push(ab.lo.strict ? lt(resultTerm, lit(0)) : le(resultTerm, lit(0)));
25378
+ }
25379
+ if (ab?.hi !== void 0 && (ab.hi.value < 0 || ab.hi.value === 0)) {
25380
+ if (posDen) facts.push(ab.hi.strict ? lt(resultTerm, lit(0)) : le(resultTerm, lit(0)));
25381
+ else facts.push(ab.hi.strict ? gt(resultTerm, lit(0)) : ge(resultTerm, lit(0)));
25382
+ }
25383
+ return facts.length ? and(...facts) : void 0;
25384
+ }
25385
+ function div(a, b, phi2 = pTrue, assume) {
25197
25386
  {
25198
25387
  const fa = builtinBrandToPrimitive(a, "number");
25199
25388
  const fb = builtinBrandToPrimitive(b, "number");
@@ -25248,7 +25437,13 @@ function div(a, b, phi2 = pTrue) {
25248
25437
  term.op === "lit" ? "exact" : confJoin(confJoin(a.conf, b.conf), "path")
25249
25438
  );
25250
25439
  }
25251
- return abs(num().shape, term, void 0, confJoin(confJoin(a.conf, b.conf), "path"));
25440
+ const assumePred = divAssumeBounds(a, b, term, phi2, assume);
25441
+ return abs(
25442
+ num().shape,
25443
+ term,
25444
+ assumePred,
25445
+ confJoin(confJoin(a.conf, b.conf), "path")
25446
+ );
25252
25447
  }
25253
25448
  if (isNumericLike(a) && isNumericLike(b)) {
25254
25449
  return abs(num().shape, void 0, void 0, "partial");
@@ -25259,7 +25454,7 @@ function div(a, b, phi2 = pTrue) {
25259
25454
  if (isAnyLike(a) || isAnyLike(b)) {
25260
25455
  return toNumberResult(a, b, "/");
25261
25456
  }
25262
- const distributed = distributeSumBinOp("/", a, b, phi2, div);
25457
+ const distributed = distributeSumBinOp("/", a, b, phi2, (x, y, p) => div(x, y, p, assume));
25263
25458
  if (distributed) return distributed;
25264
25459
  noteAbstractArithMayThrow(a, b);
25265
25460
  return abs({ k: "unknown" }, void 0, void 0, "partial");
@@ -25962,6 +26157,8 @@ export {
25962
26157
  clearStaleTermPred,
25963
26158
  currentExecPhi,
25964
26159
  withExecPhi,
26160
+ currentAssumePremises,
26161
+ withAssumePremises,
25965
26162
  asAbsVal,
25966
26163
  $absVal,
25967
26164
  callAtFunctionBoundary,
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-dg1bW60I.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-dg1bW60I.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-VKSROGOF.js";
205
+ } from "./chunk-YRRR6AWI.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-dg1bW60I.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-dg1bW60I.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-B0c9KEhd.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-B0c9KEhd.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-GHFGZ6PZ.js";
68
+ } from "./chunk-5VGO4YJT.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-VKSROGOF.js";
527
+ } from "./chunk-YRRR6AWI.js";
526
528
 
527
529
  // src/environment.ts
528
530
  function createEnvironment(parent, bindings = /* @__PURE__ */ new Map()) {
@@ -793,7 +795,18 @@ 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");
799
+ }
800
+ function constraintMatchesStructuralArm(arm, c) {
801
+ if (c.element) return arm.shape.k === "arr" || arm.shape.k === "tuple";
802
+ if (c.fields) return arm.shape.k === "obj";
803
+ if (c.members) {
804
+ return c.members.some((m) => constraintMatchesStructuralArm(arm, derefConstraint(m)));
805
+ }
806
+ return false;
807
+ }
808
+ function isWidenedStructuralArm(arm, constraint) {
809
+ return arm.conf === "widened" && constraintMatchesStructuralArm(arm, constraint);
797
810
  }
798
811
  function provesBarePrimDomain(arm, constraint) {
799
812
  if (constraint.members) {
@@ -820,7 +833,7 @@ function assertImplies(ret, constraint, opts) {
820
833
  const phi = opts?.phi ?? pTrue;
821
834
  if (ret.shape.k === "never") return proved();
822
835
  if (isAnyConstraint(constraint)) return proved();
823
- if (isValueSetUnknown(ret)) {
836
+ if (isValueSetUnknown(ret) && ret.conf !== "widened") {
824
837
  return unprovable(
825
838
  ret.shape.k === "any" ? "any does not establish the return contract" : "inference failure (unknown/opaque) \u2014 cannot prove the return contract"
826
839
  );
@@ -853,6 +866,11 @@ function assertSumArms(arms, parent, constraint, opts, phi) {
853
866
  if (isWidenedSumArm(arm, parent) && provesBarePrimDomain(arm, constraint)) {
854
867
  continue;
855
868
  }
869
+ if (isWidenedStructuralArm(arm, constraint)) {
870
+ const r2 = assertImpliesSingle(arm, constraint, opts, phi);
871
+ if (r2.status !== "proved") sawUnprovable = true;
872
+ continue;
873
+ }
856
874
  sawUnprovable = true;
857
875
  continue;
858
876
  }
@@ -875,7 +893,10 @@ function assertImpliesSingle(arm, constraint, opts, phi) {
875
893
  if (isNullishLitAbs(arm)) {
876
894
  return constraintAdmitsNullish(constraint) ? proved() : disproved(`nullish return \u22AD ${formatConstraint(constraint)}`);
877
895
  }
878
- if (isValueSetUnknown(arm)) {
896
+ if (isValueSetUnknown(arm) && !isWidenedStructuralArm(arm, constraint)) {
897
+ if (arm.conf === "widened" && arm.shape.k === "prim" && !arm.term && (!arm.pred || arm.pred.op === "true") && provesBarePrimDomain(arm, constraint)) {
898
+ return proved();
899
+ }
879
900
  return unprovable(
880
901
  arm.shape.k === "any" ? "any does not establish the return contract" : "inference failure (unknown/opaque) \u2014 cannot prove the return contract"
881
902
  );
@@ -1372,6 +1393,7 @@ function numericBound(p, self) {
1372
1393
  if (p.op !== "gt" && p.op !== "ge" && p.op !== "lt" && p.op !== "le") return void 0;
1373
1394
  if (!self) return void 0;
1374
1395
  if (termEquals(p.a, self) && p.b.op === "lit" && typeof p.b.value === "number") {
1396
+ if (!Number.isFinite(p.b.value)) return void 0;
1375
1397
  return { op: p.op, n: p.b.value };
1376
1398
  }
1377
1399
  return void 0;
@@ -2340,6 +2362,49 @@ function sidecarDiagIssues(diags) {
2340
2362
  }
2341
2363
  return out;
2342
2364
  }
2365
+ function assumePremisesPhiOf(name, source, file, issues) {
2366
+ const segs = extractAssumeSegs(source, name);
2367
+ if (segs.length === 0) return void 0;
2368
+ const meta = extractFn(source, name, file);
2369
+ const bindable = /* @__PURE__ */ new Set([
2370
+ ...contractParamNameSet(meta?.formals ?? []),
2371
+ ...meta?.params ?? []
2372
+ ]);
2373
+ const surface = [...bindable].join(", ");
2374
+ const preds = [];
2375
+ const display = [];
2376
+ for (const seg of segs) {
2377
+ if (seg.kind === "bad") {
2378
+ issues.push({
2379
+ severity: "error",
2380
+ code: "nudo:assume-invalid",
2381
+ message: `${name}: malformed @nudo:assume '${seg.raw}' (expected <param> <= <param> or <param> >= <param>; constant bounds belong to sidecar contracts)`,
2382
+ actual: seg.raw,
2383
+ expected: "<param> <= <param>",
2384
+ suggestion: "cross-variable lemmas: @nudo:assume d <= max \u2014 constant bounds: sidecar number().le(10)",
2385
+ fn: name
2386
+ });
2387
+ continue;
2388
+ }
2389
+ const bad = [seg.lhs, seg.rhs].filter((n) => !bindable.has(n));
2390
+ if (bad.length > 0) {
2391
+ issues.push({
2392
+ severity: "error",
2393
+ code: "nudo:assume-invalid",
2394
+ message: `${name}: @nudo:assume parameter name(s) not in the formal parameter list (${bad.join(", ")})`,
2395
+ actual: bad.join(", "),
2396
+ expected: surface || "(no params)",
2397
+ suggestion: `reference one of: ${surface || "(function has no params)"}`,
2398
+ fn: name
2399
+ });
2400
+ continue;
2401
+ }
2402
+ preds.push(le(v(seg.lhs), v(seg.rhs)));
2403
+ display.push(`${seg.lhs} <= ${seg.rhs}`);
2404
+ }
2405
+ if (preds.length === 0) return void 0;
2406
+ return { phi: and(...preds), display };
2407
+ }
2343
2408
  function checkSourceInner(filePath, source, file, phi, opts, issues, signatures, names, truncated, identityOpts = opts, depsFp, sidecarFp) {
2344
2409
  const hasRefineDirective = stripStringsKeepComments(source).includes("@nudo:contract");
2345
2410
  const entryNames = localNamedExports(source);
@@ -2367,6 +2432,8 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
2367
2432
  return eff;
2368
2433
  };
2369
2434
  for (const name of names) {
2435
+ const assumePhi = assumePremisesPhiOf(name, source, file, issues);
2436
+ const runSeeded = (body) => assumePhi === void 0 ? body() : withAssumePremises(assumePhi.phi, body);
2370
2437
  if (opts.skips?.has(name)) {
2371
2438
  const declared = opts.skips.get(name) ?? null;
2372
2439
  const meta = extractFn(source, name, file);
@@ -2411,19 +2478,21 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
2411
2478
  }
2412
2479
  continue;
2413
2480
  }
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
- });
2481
+ const g = runSeeded(
2482
+ () => generalizeFromAst(name, source, {
2483
+ file,
2484
+ refine: {
2485
+ loadModule: refineLoad,
2486
+ fromFile: refineFrom,
2487
+ ...autoBind !== void 0 ? { autoBind } : {},
2488
+ ...projectDir !== void 0 ? { projectDir } : {}
2489
+ },
2490
+ depsFp,
2491
+ sidecarFp,
2492
+ modules: opts.modules,
2493
+ ...opts.inject ? { inject: opts.inject } : {}
2494
+ })
2495
+ );
2427
2496
  if (!g) {
2428
2497
  const isEntryCandidate = entryNames.has(name) || name === "default" || entryNames.has("default") && isDefaultExportName(source, name);
2429
2498
  if (isEntryCandidate && entryThrowsMode !== "off") {
@@ -2483,7 +2552,7 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
2483
2552
  const isEntry = entryNames.has(name) || name === "default" || entryNames.has("default") && isDefaultExportName(source, name) || name.includes(".") && entryNames.has(name);
2484
2553
  let throwsDisplay;
2485
2554
  if (isEntry && entryThrowsMode !== "off") {
2486
- const effects = collectEntryMayThrows(source, name, g, file, phi, opts);
2555
+ const effects = runSeeded(() => collectEntryMayThrows(source, name, g, file, phi, opts));
2487
2556
  throwsDisplay = formatThrowsAbs(mayThrowEffectsToAbs(effects));
2488
2557
  const declared = extractDeclaredThrows(source, name) ?? effectiveInterfaceCached(name)?.throws?.kinds;
2489
2558
  const remaining = filterGateThrows(effects, declared, ignoreThrows);
@@ -2504,7 +2573,7 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
2504
2573
  });
2505
2574
  }
2506
2575
  } else if (isEntry) {
2507
- const effects = collectEntryMayThrows(source, name, g, file, phi, opts);
2576
+ const effects = runSeeded(() => collectEntryMayThrows(source, name, g, file, phi, opts));
2508
2577
  throwsDisplay = formatThrowsAbs(mayThrowEffectsToAbs(effects));
2509
2578
  }
2510
2579
  const fmt = formatSigCached(g.symbolic, name);
@@ -2598,7 +2667,8 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
2598
2667
  name,
2599
2668
  display,
2600
2669
  eff.returns.constraint,
2601
- g.symbolic
2670
+ g.symbolic,
2671
+ assumePhi?.display
2602
2672
  );
2603
2673
  if (retIssues.some((i) => i.severity === "error")) returnViolated.add(name);
2604
2674
  issues.push(...retIssues);
@@ -2794,9 +2864,24 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
2794
2864
  }
2795
2865
  };
2796
2866
  }
2797
- function checkReturnConstraint(fnName, cName, constraint, ret) {
2867
+ function checkReturnConstraint(fnName, cName, constraint, ret, assumeDisplay) {
2798
2868
  const proof = assertImplies(ret, constraint);
2799
- if (proof.status === "proved") return [];
2869
+ if (proof.status === "proved") {
2870
+ if (assumeDisplay && assumeDisplay.length > 0) {
2871
+ return [
2872
+ {
2873
+ severity: "info",
2874
+ code: "nudo:assume-relied",
2875
+ message: `${fnName}: return contract proved via @nudo:assume ${assumeDisplay.join("; ")}`,
2876
+ actual: `proof relies on user lemma${assumeDisplay.length > 1 ? "s" : ""}`,
2877
+ expected: "engine verifies the obligation, not the lemma itself",
2878
+ suggestion: "@nudo:assume is a user-supplied axiom \u2014 falsify it with concrete @nudo:case runs (nudo test)",
2879
+ fn: fnName
2880
+ }
2881
+ ];
2882
+ }
2883
+ return [];
2884
+ }
2800
2885
  const push = (severity, actual, expected, suggestion) => [
2801
2886
  {
2802
2887
  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-B0c9KEhd.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-B0c9KEhd.js';
3
+ import { A as Abs, T as Term, c as AbsModuleExports, d as AstEnv } from './run-dg1bW60I.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-dg1bW60I.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-GHFGZ6PZ.js";
24
+ } from "./chunk-5VGO4YJT.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-VKSROGOF.js";
172
+ } from "./chunk-YRRR6AWI.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-dg1bW60I.js';
3
3
 
4
4
  declare function resetParseSourceCache(): void;
5
5
  declare function getParseSourceCacheSize(): number;
@@ -840,7 +840,9 @@ type TranspiledCallResult = {
840
840
  declare function isAbsVal(v: unknown): v is Abs;
841
841
  /** 调用 runTranspiled 导出(捕获 $throw)。opts.phi:入口 Φ 种子
842
842
  * (instantiate/symbolic 的约束入口——eval 侧路径条件收窄)。
843
- * 嵌套进入(导出桥 apply)继承外层预算;仅最外层宿主入口重置。 */
843
+ * 嵌套进入(导出桥 apply)继承外层预算;仅最外层宿主入口重置。
844
+ * #152 assume 前提不设选项位:播种统一走 withAssumePremises 动态域
845
+ * 包裹(check.ts 的 runSeeded extent),单一机制无第二路径。 */
844
846
  declare function callTranspiledExportFull(exports: Record<string, unknown>, name: string, args: Abs[], opts?: {
845
847
  phi?: Phi;
846
848
  }): TranspiledCallResult;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nudojs/core",
3
- "version": "1.10.2",
3
+ "version": "1.11.1",
4
4
  "engines": {
5
5
  "node": ">=20"
6
6
  },