@nudojs/core 1.0.0 → 1.0.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.
@@ -309,11 +309,18 @@ var phiAnd = and;
309
309
  function implies(phi2, pred) {
310
310
  if (pred.op === "true") return true;
311
311
  if (pred.op === "false") return false;
312
+ if (phi2.op === "false") return true;
313
+ if (predEquals(phi2, pred)) return true;
314
+ if (phi2.op === "and" && phi2.args.some((c) => predEquals(c, pred))) return true;
315
+ if (phi2.op === "or") {
316
+ return phi2.args.every((a) => implies(a, pred));
317
+ }
318
+ if (pred.op === "or") {
319
+ return pred.args.some((b) => implies(phi2, b));
320
+ }
312
321
  if (phi2.op === "true") {
313
322
  return decideLiteralPred(pred) === true;
314
323
  }
315
- if (predEquals(phi2, pred)) return true;
316
- if (phi2.op === "and" && phi2.args.some((c) => predEquals(c, pred))) return true;
317
324
  const bounds = extractBounds(phi2);
318
325
  const implied = impliesViaBounds(pred, bounds);
319
326
  if (implied !== void 0) return implied;
@@ -869,6 +876,141 @@ function coerceToStringParts(a) {
869
876
  return void 0;
870
877
  }
871
878
 
879
+ // src/algebra/derivation.ts
880
+ var collector = null;
881
+ var nextId = 1;
882
+ var byAbs = /* @__PURE__ */ new WeakMap();
883
+ var sessionNodes = null;
884
+ function setDerivationCollector(fn) {
885
+ collector = fn;
886
+ }
887
+ function hasDerivationSession() {
888
+ return sessionNodes !== null;
889
+ }
890
+ function beginDerivationSession() {
891
+ sessionNodes = /* @__PURE__ */ new Map();
892
+ nextId = 1;
893
+ }
894
+ function endDerivationSession() {
895
+ const nodes = sessionNodes ? [...sessionNodes.values()] : [];
896
+ sessionNodes = null;
897
+ collector = null;
898
+ return nodes;
899
+ }
900
+ function abortDerivationSession() {
901
+ sessionNodes = null;
902
+ collector = null;
903
+ }
904
+ function note(node) {
905
+ const full = { ...node, id: nextId++ };
906
+ if (sessionNodes) sessionNodes.set(full.id, full);
907
+ collector?.(full);
908
+ return full;
909
+ }
910
+ function tagDerivationRoot(abs2, meta) {
911
+ const node = note({
912
+ kind: "root",
913
+ expr: meta.expr,
914
+ ...meta.importFrom !== void 0 ? { importFrom: meta.importFrom } : {},
915
+ ...meta.importName !== void 0 ? { importName: meta.importName } : {},
916
+ parents: []
917
+ });
918
+ byAbs.set(abs2, node);
919
+ return node;
920
+ }
921
+ function getDerivation(abs2) {
922
+ return byAbs.get(abs2);
923
+ }
924
+ function setDerivation(abs2, node) {
925
+ byAbs.set(abs2, node);
926
+ }
927
+ function derivationChain(node) {
928
+ const chain = [node];
929
+ const seen = /* @__PURE__ */ new Set([node.id]);
930
+ let cur = node;
931
+ while (cur.kind !== "root" && cur.parents.length > 0) {
932
+ const pid = cur.parents[0];
933
+ if (seen.has(pid) || !sessionNodes) break;
934
+ const parent = sessionNodes.get(pid);
935
+ if (!parent) break;
936
+ seen.add(pid);
937
+ chain.push(parent);
938
+ cur = parent;
939
+ }
940
+ return chain;
941
+ }
942
+ function noteDerivationAdd(a, b, result) {
943
+ if (!sessionNodes) return;
944
+ const vb = litValue(b);
945
+ const va = litValue(a);
946
+ let parent;
947
+ let offset;
948
+ if (typeof vb === "number" && Number.isFinite(vb)) {
949
+ parent = byAbs.get(a);
950
+ offset = vb;
951
+ } else if (typeof va === "number" && Number.isFinite(va)) {
952
+ parent = byAbs.get(b);
953
+ offset = va;
954
+ }
955
+ if (!parent || offset === void 0) return;
956
+ const node = note({
957
+ kind: "shift",
958
+ offset,
959
+ parents: [parent.id]
960
+ });
961
+ byAbs.set(result, node);
962
+ }
963
+ function noteDerivationJoin(inputs, result) {
964
+ if (!sessionNodes) return;
965
+ const parents = [];
966
+ for (const a of inputs) {
967
+ const n = byAbs.get(a);
968
+ if (n && !parents.includes(n.id)) parents.push(n.id);
969
+ }
970
+ if (parents.length === 0) return;
971
+ const node = note({ kind: "join", parents });
972
+ byAbs.set(result, node);
973
+ }
974
+ function projectDerivationDsl(node, localName) {
975
+ const chain = derivationChain(node);
976
+ const root = chain[chain.length - 1];
977
+ if (!root || root.kind !== "root" || root.expr === void 0) return void 0;
978
+ if (chain.some((n) => n.kind === "join" || n.kind === "opaque")) return void 0;
979
+ const shifts = [];
980
+ for (let i = chain.length - 2; i >= 0; i--) {
981
+ const n = chain[i];
982
+ if (n.kind !== "shift" || n.offset === void 0) return void 0;
983
+ shifts.push(n.offset);
984
+ }
985
+ const rootExpr = root.expr;
986
+ const imports = [];
987
+ if (root.importFrom !== void 0) {
988
+ imports.push({
989
+ name: root.importName ?? rootExpr,
990
+ from: root.importFrom
991
+ });
992
+ }
993
+ if (shifts.length === 0) {
994
+ return { prelude: [], expr: rootExpr, imports };
995
+ }
996
+ let current = rootExpr;
997
+ const prelude = [];
998
+ for (let i = 0; i < shifts.length; i++) {
999
+ const step = `${current}.shift(${shifts[i]})`;
1000
+ if (i === shifts.length - 1) {
1001
+ prelude.push(`const ${localName} = ${step};`);
1002
+ return { prelude, expr: localName, imports };
1003
+ }
1004
+ const tmp = `${localName}_${i}`;
1005
+ prelude.push(`const ${tmp} = ${step};`);
1006
+ current = tmp;
1007
+ }
1008
+ return void 0;
1009
+ }
1010
+ function termKey3(t) {
1011
+ return t === void 0 ? "<none>" : termToString(t);
1012
+ }
1013
+
872
1014
  // src/algebra/objects.ts
873
1015
  function objOf(slots, opts) {
874
1016
  const shape = { k: "obj", slots };
@@ -970,29 +1112,59 @@ function flattenSum(xs) {
970
1112
  const seen = /* @__PURE__ */ new Set();
971
1113
  const deduped = [];
972
1114
  for (const x of out) {
973
- const key = shapeKey(x);
1115
+ const key = absShapeKey(x);
974
1116
  if (seen.has(key)) continue;
975
1117
  seen.add(key);
976
1118
  deduped.push(x);
977
1119
  }
978
1120
  return deduped;
979
1121
  }
980
- function shapeKey(a) {
981
- const s = a.shape;
982
- if (s.k === "prim") {
983
- const lv = litValue(a);
984
- if (lv !== void 0) return `prim:${s.type}:${String(lv)}`;
985
- const t = a.term ? termToString(a.term) : "";
986
- const p = a.pred && a.pred.op !== "true" ? predToString(a.pred) : "";
987
- return `prim:${s.type}:${t}:${p}`;
1122
+ function absShapeKey(a, seen = /* @__PURE__ */ new Set()) {
1123
+ if (seen.has(a)) return "cycle";
1124
+ seen.add(a);
1125
+ try {
1126
+ const s = a.shape;
1127
+ if (s.k === "prim") {
1128
+ const lv = litValue(a);
1129
+ if (lv !== void 0) return `prim:${s.type}:${String(lv)}`;
1130
+ const t = a.term ? termToString(a.term) : "";
1131
+ const p = a.pred && a.pred.op !== "true" ? predToString(a.pred) : "";
1132
+ return `prim:${s.type}:${t}:${p}`;
1133
+ }
1134
+ if (s.k === "never") return "never";
1135
+ if (s.k === "any") return "any";
1136
+ if (s.k === "unknown") return "unknown";
1137
+ if (s.k === "arr") return `arr(${absShapeKey(s.element, seen)})`;
1138
+ if (s.k === "tuple") {
1139
+ const els = s.elements.map((e) => absShapeKey(e, seen)).join(",");
1140
+ const rest = s.rest ? `...${absShapeKey(s.rest, seen)}` : "";
1141
+ return `tuple[${els}${rest}]`;
1142
+ }
1143
+ if (s.k === "brand") return `brand:${s.name}(${absShapeKey(s.shape, seen)})`;
1144
+ if (s.k === "eff") return `eff:${s.eff}<${absShapeKey(s.inner, seen)}>`;
1145
+ if (s.k === "obj") {
1146
+ const slots = Object.keys(s.slots).sort().map((k) => {
1147
+ const slot = s.slots[k];
1148
+ const flags = (slot.optional ? "?" : "") + (slot.readonly ? "r" : "");
1149
+ return `${k}${flags}:${absShapeKey(slot.value, seen)}`;
1150
+ }).join(",");
1151
+ const idx = s.index ? `idx(${absShapeKey(s.index.key, seen)}\u2192${absShapeKey(s.index.value, seen)})` : "";
1152
+ const open = s.open ? "open" : "";
1153
+ return `obj{${slots}}${idx}${open}`;
1154
+ }
1155
+ if (s.k === "fn") {
1156
+ const pts = (s.paramTypes ?? []).map((t) => absShapeKey(t, seen)).join(",");
1157
+ const ret = s.returnType ? absShapeKey(s.returnType, seen) : "?";
1158
+ const name = s.name ? `#${s.name}` : "";
1159
+ return `fn${name}(${s.params.join(",")}|${pts})=>${ret}`;
1160
+ }
1161
+ if (s.k === "sum") {
1162
+ return `sum(${s.members.map((m) => absShapeKey(m, seen)).join("|")})`;
1163
+ }
1164
+ return "other";
1165
+ } finally {
1166
+ seen.delete(a);
988
1167
  }
989
- if (s.k === "never") return "never";
990
- if (s.k === "any") return "any";
991
- if (s.k === "unknown") return "unknown";
992
- if (s.k === "obj") return `obj:${Object.keys(s.slots).sort().join(",")}`;
993
- if (s.k === "fn") return `fn:${s.params.length}`;
994
- if (s.k === "sum") return `sum:${s.members.length}`;
995
- return "other";
996
1168
  }
997
1169
  function fnOf(params, name) {
998
1170
  const shape = { k: "fn", params };
@@ -1017,7 +1189,9 @@ function joinAbs(a, b) {
1017
1189
  if (b.shape.k === "never") return a;
1018
1190
  if (isObj(a) && isObj(b)) return joinObjects(a, b);
1019
1191
  if (a.shape.k === "fn" && b.shape.k === "fn") return joinFunctions(a, b);
1020
- return joinValues(a, b);
1192
+ const result = joinValues(a, b);
1193
+ noteDerivationJoin([a, b], result);
1194
+ return result;
1021
1195
  }
1022
1196
 
1023
1197
  // src/algebra/arithmetic.ts
@@ -1042,7 +1216,9 @@ function add(a, b, phi2 = pTrue) {
1042
1216
  const term = simplifyTerm(app("+", [a.term, b.term]));
1043
1217
  const pred = addPred(a, b, term, phi2);
1044
1218
  const conf = term.op === "lit" ? "exact" : confJoin(confJoin(a.conf, b.conf), "path");
1045
- return abs({ k: "prim", type: "number" }, term, pred, conf);
1219
+ const result = abs({ k: "prim", type: "number" }, term, pred, conf);
1220
+ noteDerivationAdd(a, b, result);
1221
+ return result;
1046
1222
  }
1047
1223
  if (isAnyLike(a) || isAnyLike(b)) {
1048
1224
  const term = a.term && b.term ? simplifyTerm(app("+", [a.term, b.term])) : void 0;
@@ -1081,7 +1257,7 @@ function dedupAbsMembers(ms) {
1081
1257
  const seen = /* @__PURE__ */ new Set();
1082
1258
  const out = [];
1083
1259
  for (const m of ms) {
1084
- const key = m.shape.k === "prim" ? `prim:${m.shape.type}` : m.shape.k === "sum" ? `sum:${m.shape.members.length}` : m.shape.k;
1260
+ const key = absShapeKey(m);
1085
1261
  if (seen.has(key)) continue;
1086
1262
  seen.add(key);
1087
1263
  out.push(m);
@@ -1161,7 +1337,7 @@ function collectBoundsFromPred(pred, term, acc) {
1161
1337
  }
1162
1338
  if (p.op === "gt" && match(p.a) && p.b.op === "lit" && typeof p.b.value === "number") {
1163
1339
  const n = p.b.value;
1164
- if (acc.lo === void 0 || n > acc.lo.value || n === acc.lo.value && p.op === "gt") {
1340
+ if (acc.lo === void 0 || n > acc.lo.value || n === acc.lo.value && !acc.lo.strict) {
1165
1341
  acc.lo = { value: n, strict: true };
1166
1342
  }
1167
1343
  return;
@@ -1175,7 +1351,7 @@ function collectBoundsFromPred(pred, term, acc) {
1175
1351
  }
1176
1352
  if (p.op === "lt" && match(p.a) && p.b.op === "lit" && typeof p.b.value === "number") {
1177
1353
  const n = p.b.value;
1178
- if (acc.hi === void 0 || n < acc.hi.value) {
1354
+ if (acc.hi === void 0 || n < acc.hi.value || n === acc.hi.value && !acc.hi.strict) {
1179
1355
  acc.hi = { value: n, strict: true };
1180
1356
  }
1181
1357
  return;
@@ -1194,7 +1370,7 @@ function collectBoundsFromPhi(phi2, id, acc) {
1194
1370
  for (const p of conjs) {
1195
1371
  if (p.op === "gt" && p.a.op === "var" && p.a.id === id && p.b.op === "lit" && typeof p.b.value === "number") {
1196
1372
  const n = p.b.value;
1197
- if (acc.lo === void 0 || n > acc.lo.value) {
1373
+ if (acc.lo === void 0 || n > acc.lo.value || n === acc.lo.value && !acc.lo.strict) {
1198
1374
  acc.lo = { value: n, strict: true };
1199
1375
  }
1200
1376
  }
@@ -1206,7 +1382,7 @@ function collectBoundsFromPhi(phi2, id, acc) {
1206
1382
  }
1207
1383
  if (p.op === "lt" && p.a.op === "var" && p.a.id === id && p.b.op === "lit" && typeof p.b.value === "number") {
1208
1384
  const n = p.b.value;
1209
- if (acc.hi === void 0 || n < acc.hi.value) {
1385
+ if (acc.hi === void 0 || n < acc.hi.value || n === acc.hi.value && !acc.hi.strict) {
1210
1386
  acc.hi = { value: n, strict: true };
1211
1387
  }
1212
1388
  }
@@ -1640,7 +1816,7 @@ function flipBounds(pred, src, dst, out) {
1640
1816
  if (p.op !== "gt" && p.op !== "ge" && p.op !== "lt" && p.op !== "le") {
1641
1817
  return;
1642
1818
  }
1643
- if (termKey3(p.a) !== termKey3(src)) return;
1819
+ if (termKey4(p.a) !== termKey4(src)) return;
1644
1820
  if (p.b.op !== "lit" || typeof p.b.value !== "number") return;
1645
1821
  const n = p.b.value;
1646
1822
  if (p.op === "gt") out.push(lt(dst, lit(-n)));
@@ -1650,7 +1826,7 @@ function flipBounds(pred, src, dst, out) {
1650
1826
  };
1651
1827
  apply(pred);
1652
1828
  }
1653
- function termKey3(t) {
1829
+ function termKey4(t) {
1654
1830
  if (t.op === "lit") return `lit:${JSON.stringify(t.value)}`;
1655
1831
  if (t.op === "var") return `var:${t.id}`;
1656
1832
  return `app:${t.fn}`;
@@ -2138,6 +2314,8 @@ function evalMathMethod(name, args) {
2138
2314
  case "round":
2139
2315
  if (typeof a0 === "number") return numLit(Math.round(a0));
2140
2316
  return numPrim();
2317
+ case "random":
2318
+ return numPrim("path");
2141
2319
  case "sqrt":
2142
2320
  if (typeof a0 === "number") return numLit(Math.sqrt(a0));
2143
2321
  return numPrim();
@@ -2217,6 +2395,12 @@ function evalJsonMethod(name, args) {
2217
2395
  if (name === "parse") return unknown;
2218
2396
  return void 0;
2219
2397
  }
2398
+ function foldParseInt(s, radix) {
2399
+ const str2 = String(s);
2400
+ if (radix === void 0) return numLit(parseInt(str2));
2401
+ if (!Number.isInteger(radix) || radix < 2 || radix > 36) return numLit(NaN);
2402
+ return numLit(parseInt(str2, radix));
2403
+ }
2220
2404
  function evalNumberStatic(name, args) {
2221
2405
  const a0 = args[0] ? litValue(args[0]) : void 0;
2222
2406
  switch (name) {
@@ -2230,12 +2414,16 @@ function evalNumberStatic(name, args) {
2230
2414
  if (typeof a0 === "number") return boolLit(Number.isFinite(a0));
2231
2415
  return boolPrim();
2232
2416
  case "parseInt":
2233
- case "parseFloat":
2234
2417
  if (typeof a0 === "string" || typeof a0 === "number") {
2235
- const n = name === "parseInt" ? parseInt(String(a0), 10) : parseFloat(String(a0));
2236
- return numLit(n);
2418
+ const radix = args[1] ? litValue(args[1]) : void 0;
2419
+ if (radix === void 0) return foldParseInt(a0, void 0);
2420
+ if (typeof radix === "number") return foldParseInt(a0, radix);
2421
+ return numPrim();
2237
2422
  }
2238
2423
  return numPrim();
2424
+ case "parseFloat":
2425
+ if (typeof a0 === "string" || typeof a0 === "number") return numLit(parseFloat(String(a0)));
2426
+ return numPrim();
2239
2427
  case "MAX_SAFE_INTEGER":
2240
2428
  return numLit(Number.MAX_SAFE_INTEGER);
2241
2429
  default:
@@ -2246,7 +2434,12 @@ function evalGlobalFn(name, args) {
2246
2434
  const a0 = args[0] ? litValue(args[0]) : void 0;
2247
2435
  switch (name) {
2248
2436
  case "parseInt":
2249
- if (typeof a0 === "string" || typeof a0 === "number") return numLit(parseInt(String(a0), 10));
2437
+ if (typeof a0 === "string" || typeof a0 === "number") {
2438
+ const radix = args[1] ? litValue(args[1]) : void 0;
2439
+ if (radix === void 0) return foldParseInt(a0, void 0);
2440
+ if (typeof radix === "number") return foldParseInt(a0, radix);
2441
+ return numPrim();
2442
+ }
2250
2443
  return numPrim();
2251
2444
  case "parseFloat":
2252
2445
  if (typeof a0 === "string" || typeof a0 === "number") return numLit(parseFloat(String(a0)));
@@ -2269,13 +2462,20 @@ function evalGlobalFn(name, args) {
2269
2462
  return void 0;
2270
2463
  }
2271
2464
  }
2465
+ function peelBrand(shape) {
2466
+ let s = shape;
2467
+ while (s.k === "brand") s = s.shape.shape;
2468
+ return s;
2469
+ }
2272
2470
  function evalArrayStatic(name, args) {
2273
2471
  const a0 = args[0];
2274
2472
  switch (name) {
2275
2473
  case "isArray": {
2276
2474
  if (!a0) return boolLit(false);
2277
- const k = a0.shape.k;
2278
- return boolLit(k === "arr" || k === "tuple");
2475
+ const s = peelBrand(a0.shape);
2476
+ if (s.k === "arr" || s.k === "tuple") return boolLit(true);
2477
+ if (s.k === "any" || s.k === "unknown" || s.k === "sum") return boolPrim();
2478
+ return boolLit(false);
2279
2479
  }
2280
2480
  case "of":
2281
2481
  return abs({ k: "arr", element: a0 ?? unknown }, void 0, void 0, "path");
@@ -2313,7 +2513,7 @@ function evalDateCtor(args) {
2313
2513
  );
2314
2514
  }
2315
2515
  function evalDateStatic(name, _args) {
2316
- if (name === "now") return numLit(Date.now());
2516
+ if (name === "now") return numPrim("path");
2317
2517
  return void 0;
2318
2518
  }
2319
2519
  function evalDateMethod(name, _recv, _args) {
@@ -3355,7 +3555,7 @@ function callAbsMethod(recv, name, args) {
3355
3555
  const parts = lit3.split(sep).map((s) => strLit(s));
3356
3556
  return abs({ k: "tuple", elements: parts }, void 0, void 0, "exact");
3357
3557
  }
3358
- return abs({ k: "tuple", elements: [strLit(lit3)] }, void 0, void 0, "path");
3558
+ return strArr("path");
3359
3559
  }
3360
3560
  return strArr("path");
3361
3561
  }
@@ -3640,8 +3840,8 @@ function callBudgetKey(kind, id, args) {
3640
3840
  return `${kind}|${id}|${parts.join(",")}`;
3641
3841
  }
3642
3842
  var absTruncCollector = null;
3643
- function setAbsTruncationCollector(collector) {
3644
- absTruncCollector = collector;
3843
+ function setAbsTruncationCollector(collector2) {
3844
+ absTruncCollector = collector2;
3645
3845
  }
3646
3846
  function noteTruncation(label) {
3647
3847
  if (!absTruncCollector) return;
@@ -3665,8 +3865,10 @@ function exitCall() {
3665
3865
  _activeCallKeys.pop();
3666
3866
  }
3667
3867
  var absCallCollector = null;
3668
- function setAbsCallCollector(collector) {
3669
- absCallCollector = collector;
3868
+ function setAbsCallCollector(collector2) {
3869
+ const prev = absCallCollector;
3870
+ absCallCollector = collector2;
3871
+ return prev;
3670
3872
  }
3671
3873
  function recordAbsCall(fnName, args, result, callLoc, threw) {
3672
3874
  if (!absCallCollector) return;
@@ -3676,8 +3878,8 @@ function recordAbsCall(fnName, args, result, callLoc, threw) {
3676
3878
  }
3677
3879
  }
3678
3880
  var absNodeCollector = null;
3679
- function setAbsNodeCollector(collector) {
3680
- absNodeCollector = collector;
3881
+ function setAbsNodeCollector(collector2) {
3882
+ absNodeCollector = collector2;
3681
3883
  }
3682
3884
  function recordAbsNode(node, value) {
3683
3885
  if (!absNodeCollector || !value) return;
@@ -3688,8 +3890,8 @@ function recordAbsNode(node, value) {
3688
3890
  }
3689
3891
  var absAssignCollector = null;
3690
3892
  var assignFlowDepth = 0;
3691
- function setAbsAssignCollector(collector) {
3692
- absAssignCollector = collector;
3893
+ function setAbsAssignCollector(collector2) {
3894
+ absAssignCollector = collector2;
3693
3895
  }
3694
3896
  function evalInConditionalFlow(body) {
3695
3897
  assignFlowDepth++;
@@ -3718,6 +3920,16 @@ function evalSource(source, entry, opts = {}) {
3718
3920
  const file = opts.file ?? parseSource(source);
3719
3921
  const env = emptyEnv();
3720
3922
  let phi2 = opts.phi ?? pTrue;
3923
+ if (opts.seedVars) {
3924
+ for (const [k, v2] of Object.entries(opts.seedVars)) {
3925
+ env.vars.set(k, v2);
3926
+ }
3927
+ }
3928
+ if (opts.seedFns) {
3929
+ for (const [k, fn] of Object.entries(opts.seedFns)) {
3930
+ env.fns.set(k, fn);
3931
+ }
3932
+ }
3721
3933
  if (opts.modules) {
3722
3934
  for (const stmt of file.program.body) {
3723
3935
  if (stmt.type === "ImportDeclaration") {
@@ -3751,8 +3963,13 @@ function evalSource(source, entry, opts = {}) {
3751
3963
  }
3752
3964
  }
3753
3965
  }
3754
- const value = callFunction(env, entry.fn, entry.args, phi2, opts.budget);
3755
- return { value, phi: phi2, env };
3966
+ const full = callFunctionFull(env, entry.fn, entry.args, phi2, opts.budget);
3967
+ return {
3968
+ value: full.result,
3969
+ phi: phi2,
3970
+ env,
3971
+ ...full.throws.shape.k !== "never" ? { threw: true, ...full.throwLoc ? { throwLoc: full.throwLoc } : {} } : {}
3972
+ };
3756
3973
  }
3757
3974
  function registerClassDecl(env, node) {
3758
3975
  const cls = node;
@@ -3808,6 +4025,37 @@ function registerFunction(env, decl) {
3808
4025
  async: decl.async === true
3809
4026
  });
3810
4027
  }
4028
+ function callFunctionFull(env, name, args, phi2 = pTrue, budget = defaultLeakBudget) {
4029
+ const fn = env.fns.get(name);
4030
+ const neverAbs = abs({ k: "never" }, void 0, void 0, "exact");
4031
+ if (!fn) return { result: unknown, throws: neverAbs };
4032
+ const key = callBudgetKey("fn", name, args);
4033
+ if (!enterCall(key, name)) {
4034
+ return { result: truncatedAbs(), throws: neverAbs };
4035
+ }
4036
+ try {
4037
+ let local = { vars: new Map(env.vars), fns: env.fns, hofCollect: env.hofCollect };
4038
+ const cls = env.classes;
4039
+ if (cls) local.classes = cls;
4040
+ fn.params.forEach((p, i) => {
4041
+ local.vars.set(p, args[i] ?? unknown);
4042
+ });
4043
+ const result = evalNode(fn.body, local, phi2, budget);
4044
+ if (result.threw) {
4045
+ return {
4046
+ result: neverAbs,
4047
+ throws: result.value,
4048
+ ...result.throwLoc ? { throwLoc: result.throwLoc } : {}
4049
+ };
4050
+ }
4051
+ if (fn.async) {
4052
+ return { result: coerceAsyncReturn(result.value), throws: neverAbs };
4053
+ }
4054
+ return { result: result.value, throws: neverAbs };
4055
+ } finally {
4056
+ exitCall();
4057
+ }
4058
+ }
3811
4059
  function callFunction(env, name, args, phi2 = pTrue, budget = defaultLeakBudget) {
3812
4060
  const fn = env.fns.get(name);
3813
4061
  if (!fn) return unknown;
@@ -3974,7 +4222,18 @@ function evalNodeInner(node, env, phi2, budget) {
3974
4222
  case "ThrowStatement": {
3975
4223
  const arg = node.argument;
3976
4224
  const v2 = arg ? evalNode(arg, env, phi2, budget).value : unknown;
3977
- return { value: v2, phi: phi2, env, threw: true };
4225
+ const loc = node.loc ? { line: node.loc.start.line, column: node.loc.start.column } : void 0;
4226
+ return { value: v2, phi: phi2, env, threw: true, ...loc ? { throwLoc: loc } : {} };
4227
+ }
4228
+ case "ConditionalExpression": {
4229
+ const cond = node;
4230
+ const t = evalNode(cond.test, env, phi2, budget).value;
4231
+ const tv = litValue(t);
4232
+ if (tv === true) return evalNode(cond.consequent, env, phi2, budget);
4233
+ if (tv === false) return evalNode(cond.alternate, env, phi2, budget);
4234
+ const a = evalNode(cond.consequent, env, phi2, budget);
4235
+ const b = evalNode(cond.alternate, env, phi2, budget);
4236
+ return { value: joinAbs(a.value, b.value), phi: phi2, env };
3978
4237
  }
3979
4238
  case "ForStatement":
3980
4239
  return evalFor(node, env, phi2, budget);
@@ -4425,18 +4684,27 @@ function evalCall(node, env, phi2, budget) {
4425
4684
  }
4426
4685
  if (obj2.shape.k === "tuple") {
4427
4686
  const kept = [];
4428
- for (const el of obj2.shape.elements) {
4429
- const p = applyUnaryCallback(fnNode, el, env, phi2, budget);
4687
+ let anyUncertain = false;
4688
+ for (const el2 of obj2.shape.elements) {
4689
+ const p = applyUnaryCallback(fnNode, el2, env, phi2, budget);
4430
4690
  const lv = litValue(p);
4431
4691
  if (lv === false) continue;
4432
- kept.push(el);
4692
+ if (lv !== true) anyUncertain = true;
4693
+ kept.push(el2);
4433
4694
  }
4434
4695
  if (kept.length === 0) {
4435
4696
  return ok2(abs({ k: "arr", element: unknown }, void 0, void 0, "path"), phi2, env);
4436
4697
  }
4437
- if (kept.length === 1) return ok2(kept[0], phi2, env);
4698
+ if (!anyUncertain) {
4699
+ return ok2(
4700
+ abs({ k: "tuple", elements: kept }, void 0, void 0, confJoin(obj2.conf, "path")),
4701
+ phi2,
4702
+ env
4703
+ );
4704
+ }
4705
+ const el = kept.reduce((a, b) => joinAbs(a, b));
4438
4706
  return ok2(
4439
- abs({ k: "tuple", elements: kept }, void 0, void 0, confJoin(obj2.conf, "path")),
4707
+ abs({ k: "arr", element: el }, void 0, void 0, confJoin(obj2.conf, "path")),
4440
4708
  phi2,
4441
4709
  env
4442
4710
  );
@@ -4647,7 +4915,16 @@ function evalBlock(node, env, phi2, budget) {
4647
4915
  pendingPartial = void 0;
4648
4916
  }
4649
4917
  if (r.returned || r.brk || r.cont || r.threw) {
4650
- return { value: last, phi: curPhi, env: local, returned: r.returned, brk: r.brk, cont: r.cont, threw: r.threw };
4918
+ return {
4919
+ value: last,
4920
+ phi: curPhi,
4921
+ env: local,
4922
+ returned: r.returned,
4923
+ brk: r.brk,
4924
+ cont: r.cont,
4925
+ threw: r.threw,
4926
+ ...r.throwLoc ? { throwLoc: r.throwLoc } : {}
4927
+ };
4651
4928
  }
4652
4929
  }
4653
4930
  if (pendingPartial !== void 0) {
@@ -4838,6 +5115,20 @@ function evalIf(node, env, phi2, budget) {
4838
5115
  function analyzeFn(source, fnName, args, phi2 = pTrue, budget, file, modules) {
4839
5116
  return evalSource(source, { fn: fnName, args }, { phi: phi2, budget, file, modules }).value;
4840
5117
  }
5118
+ function analyzeFnFull(source, fnName, args, opts = {}) {
5119
+ const r = evalSource(source, { fn: fnName, args }, opts);
5120
+ if (r.threw) {
5121
+ return {
5122
+ result: abs({ k: "never" }, void 0, void 0, "exact"),
5123
+ throws: r.value,
5124
+ ...r.throwLoc ? { throwLoc: r.throwLoc } : {}
5125
+ };
5126
+ }
5127
+ return {
5128
+ result: r.value,
5129
+ throws: abs({ k: "never" }, void 0, void 0, "exact")
5130
+ };
5131
+ }
4841
5132
  function evalProgramAbs(source, opts = {}) {
4842
5133
  resetAbsCallBudget();
4843
5134
  const file = opts.file ?? parseSource(source);
@@ -4971,8 +5262,8 @@ var GLOBAL_FNS = /* @__PURE__ */ new Set([
4971
5262
  "String",
4972
5263
  "Boolean"
4973
5264
  ]);
4974
- function setBCallCollector(collector) {
4975
- bCallCollector = collector;
5265
+ function setBCallCollector(collector2) {
5266
+ bCallCollector = collector2;
4976
5267
  }
4977
5268
  function getBCallCollector() {
4978
5269
  return bCallCollector;
@@ -6725,6 +7016,10 @@ function invokeArrMethod(arr, method, args) {
6725
7016
  return acc;
6726
7017
  }
6727
7018
  if (method === "filter" && args[0]) {
7019
+ if (shape.k === "tuple") {
7020
+ const el = shape.elements.length > 0 ? shape.elements.reduce((a, b) => joinAbs(a, b)) : unknown;
7021
+ return abs({ k: "arr", element: el }, void 0, void 0, confJoin(arr.conf, "path"));
7022
+ }
6728
7023
  return arr;
6729
7024
  }
6730
7025
  if (method === "flatMap" && args[0]) {
@@ -7150,22 +7445,6 @@ export {
7150
7445
  isStrPrim,
7151
7446
  isExactLit,
7152
7447
  litValue,
7153
- viewTemplateParts,
7154
- knownPrefixOfViews,
7155
- knownSuffixOfViews,
7156
- allFixedTextOfViews,
7157
- fixedLengthOfViews,
7158
- formatTemplateNameViews,
7159
- mergeAdjacentFixedViews,
7160
- templateMatchesValue,
7161
- decideStartsWith,
7162
- decideEndsWith,
7163
- decideIncludes,
7164
- absTemplateViews,
7165
- templatePartsOf,
7166
- createTemplateAbs,
7167
- isTemplateLike,
7168
- concatString,
7169
7448
  stripTypes,
7170
7449
  resetParseSourceCache,
7171
7450
  getParseSourceCacheSize,
@@ -7176,6 +7455,19 @@ export {
7176
7455
  relationFingerprint,
7177
7456
  relationFn,
7178
7457
  shapeOnlyFn,
7458
+ setDerivationCollector,
7459
+ hasDerivationSession,
7460
+ beginDerivationSession,
7461
+ endDerivationSession,
7462
+ abortDerivationSession,
7463
+ tagDerivationRoot,
7464
+ getDerivation,
7465
+ setDerivation,
7466
+ derivationChain,
7467
+ noteDerivationAdd,
7468
+ noteDerivationJoin,
7469
+ projectDerivationDsl,
7470
+ termKey3 as termKey,
7179
7471
  objOf,
7180
7472
  isObj,
7181
7473
  getSlot,
@@ -7183,6 +7475,7 @@ export {
7183
7475
  joinObjects,
7184
7476
  joinValues,
7185
7477
  makeSum,
7478
+ absShapeKey,
7186
7479
  fnOf,
7187
7480
  joinFunctions,
7188
7481
  joinAbs,
@@ -7205,6 +7498,22 @@ export {
7205
7498
  mapElementFallback,
7206
7499
  projectFlatMapResult,
7207
7500
  asAbs,
7501
+ viewTemplateParts,
7502
+ knownPrefixOfViews,
7503
+ knownSuffixOfViews,
7504
+ allFixedTextOfViews,
7505
+ fixedLengthOfViews,
7506
+ formatTemplateNameViews,
7507
+ mergeAdjacentFixedViews,
7508
+ templateMatchesValue,
7509
+ decideStartsWith,
7510
+ decideEndsWith,
7511
+ decideIncludes,
7512
+ absTemplateViews,
7513
+ templatePartsOf,
7514
+ createTemplateAbs,
7515
+ isTemplateLike,
7516
+ concatString,
7208
7517
  add,
7209
7518
  sub,
7210
7519
  mul,
@@ -7283,11 +7592,13 @@ export {
7283
7592
  setAbsNodeCollector,
7284
7593
  setAbsAssignCollector,
7285
7594
  evalSource,
7595
+ callFunctionFull,
7286
7596
  callFunction,
7287
7597
  evalMethodBody,
7288
7598
  evalNode,
7289
7599
  applyAbsFn,
7290
7600
  analyzeFn,
7601
+ analyzeFnFull,
7291
7602
  evalProgramAbs,
7292
7603
  collectAbsNodeTypes,
7293
7604
  findAbsAtPosition,