@nudojs/core 1.0.1 → 2.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.
@@ -9,6 +9,8 @@ var runtime_exports = {};
9
9
  __export(runtime_exports, {
10
10
  $add: () => $add,
11
11
  $arr: () => $arr,
12
+ $arrMutContainer: () => $arrMutContainer,
13
+ $arrRest: () => $arrRest,
12
14
  $async: () => $async,
13
15
  $asyncReturn: () => $asyncReturn,
14
16
  $await: () => $await,
@@ -17,6 +19,7 @@ __export(runtime_exports, {
17
19
  $div: () => $div,
18
20
  $elems: () => $elems,
19
21
  $eq: () => $eq,
22
+ $eqLoose: () => $eqLoose,
20
23
  $fnVal: () => $fnVal,
21
24
  $for: () => $for,
22
25
  $forIter: () => $forIter,
@@ -28,38 +31,59 @@ __export(runtime_exports, {
28
31
  $gt: () => $gt,
29
32
  $idx: () => $idx,
30
33
  $idxSet: () => $idxSet,
34
+ $isForkExit: () => $isForkExit,
31
35
  $join: () => $join,
32
36
  $le: () => $le,
33
37
  $len: () => $len,
34
38
  $lit: () => $lit,
39
+ $loopReturn: () => $loopReturn,
35
40
  $lt: () => $lt,
36
41
  $mod: () => $mod,
37
42
  $mul: () => $mul,
38
43
  $ne: () => $ne,
44
+ $neLoose: () => $neLoose,
39
45
  $neg: () => $neg,
40
46
  $not: () => $not,
47
+ $nullishTest: () => $nullishTest,
41
48
  $obj: () => $obj,
49
+ $objRest: () => $objRest,
50
+ $pushLoopExit: () => $pushLoopExit,
42
51
  $regex: () => $regex,
52
+ $rethrowIfNudoReturn: () => $rethrowIfNudoReturn,
43
53
  $set: () => $set,
44
54
  $spread: () => $spread,
45
55
  $sub: () => $sub,
46
56
  $switch: () => $switch,
47
57
  $throw: () => $throw,
58
+ $tryCurrentMark: () => $tryCurrentMark,
59
+ $tryMark: () => $tryMark,
60
+ $tryPopMark: () => $tryPopMark,
61
+ $tryTakeSince: () => $tryTakeSince,
48
62
  $typeof: () => $typeof,
49
63
  $while: () => $while,
50
64
  $whileSeq: () => $whileSeq,
51
65
  $yield: () => $yield,
52
66
  DEFAULT_MAX_LOOP_ITERS: () => DEFAULT_MAX_LOOP_ITERS,
67
+ NudoReturn: () => NudoReturn,
53
68
  NudoThrow: () => NudoThrow,
54
69
  asAbsVal: () => asAbsVal,
70
+ callAtFunctionBoundary: () => callAtFunctionBoundary,
55
71
  currentExecPhi: () => currentExecPhi,
72
+ isArrMutator: () => isArrMutator,
56
73
  isDefinitelyFalse: () => isDefinitelyFalse,
57
74
  isDefinitelyTrue: () => isDefinitelyTrue,
75
+ isNudoReturn: () => isNudoReturn,
58
76
  isNudoThrow: () => isNudoThrow,
59
77
  litTruth: () => litTruth,
60
78
  namespaceNameOf: () => namespaceNameOf,
79
+ pushLoopExit: () => pushLoopExit,
80
+ pushThrowExit: () => pushThrowExit,
81
+ runWithLoopExits: () => runWithLoopExits,
82
+ takeLoopExits: () => takeLoopExits,
83
+ takeThrowExits: () => takeThrowExits,
61
84
  withExecPhi: () => withExecPhi
62
85
  });
86
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
63
87
 
64
88
  // src/algebra/term.ts
65
89
  var lit = (value) => ({
@@ -170,11 +194,16 @@ var ptypeof = (t, type) => ({
170
194
  });
171
195
  function and(...preds) {
172
196
  const flat = [];
197
+ const pushUnique = (p) => {
198
+ if (flat.some((q) => predEquals(q, p))) return;
199
+ flat.push(p);
200
+ };
173
201
  for (const p of preds) {
174
202
  if (p.op === "true") continue;
175
203
  if (p.op === "false") return pFalse;
176
- if (p.op === "and") flat.push(...p.args);
177
- else flat.push(p);
204
+ if (p.op === "and") {
205
+ for (const q of p.args) pushUnique(q);
206
+ } else pushUnique(p);
178
207
  }
179
208
  if (flat.length === 0) return pTrue;
180
209
  if (flat.length === 1) return flat[0];
@@ -182,11 +211,16 @@ function and(...preds) {
182
211
  }
183
212
  function or(...preds) {
184
213
  const flat = [];
214
+ const pushUnique = (p) => {
215
+ if (flat.some((q) => predEquals(q, p))) return;
216
+ flat.push(p);
217
+ };
185
218
  for (const p of preds) {
186
219
  if (p.op === "false") continue;
187
220
  if (p.op === "true") return pTrue;
188
- if (p.op === "or") flat.push(...p.args);
189
- else flat.push(p);
221
+ if (p.op === "or") {
222
+ for (const q of p.args) pushUnique(q);
223
+ } else pushUnique(p);
190
224
  }
191
225
  if (flat.length === 0) return pFalse;
192
226
  if (flat.length === 1) return flat[0];
@@ -380,6 +414,25 @@ function extractBounds(phi2) {
380
414
  return { lo, hi };
381
415
  }
382
416
  function impliesViaBounds(pred, bounds) {
417
+ if (pred.op === "eq") {
418
+ const left2 = pred.a;
419
+ const right2 = pred.b;
420
+ if (right2.op !== "lit" || typeof right2.value !== "number") return void 0;
421
+ const n2 = right2.value;
422
+ if (left2.op === "var") {
423
+ return eqFromBounds(left2.id, n2, bounds);
424
+ }
425
+ if (left2.op === "app" && left2.fn === "+" && left2.args.length === 2) {
426
+ const [a, b] = left2.args;
427
+ if (a.op === "var" && b.op === "lit" && typeof b.value === "number") {
428
+ return eqFromBounds(a.id, n2 - b.value, bounds);
429
+ }
430
+ if (b.op === "var" && a.op === "lit" && typeof a.value === "number") {
431
+ return eqFromBounds(b.id, n2 - a.value, bounds);
432
+ }
433
+ }
434
+ return void 0;
435
+ }
383
436
  if (pred.op !== "gt" && pred.op !== "ge" && pred.op !== "lt" && pred.op !== "le") {
384
437
  return void 0;
385
438
  }
@@ -401,6 +454,20 @@ function impliesViaBounds(pred, bounds) {
401
454
  }
402
455
  return void 0;
403
456
  }
457
+ function eqFromBounds(id, n, bounds) {
458
+ const lo = bounds.lo.get(id);
459
+ const hi = bounds.hi.get(id);
460
+ if (!lo || !hi) return void 0;
461
+ const loCovers = lo.strict ? lo.bound <= n : lo.bound <= n;
462
+ const hiCovers = hi.strict ? hi.bound >= n : hi.bound >= n;
463
+ if (lo.strict && lo.bound >= n) return false;
464
+ if (hi.strict && hi.bound <= n) return false;
465
+ if (!lo.strict && lo.bound > n) return false;
466
+ if (!hi.strict && hi.bound < n) return false;
467
+ if (!loCovers || !hiCovers) return void 0;
468
+ if (!lo.strict && !hi.strict && lo.bound === n && hi.bound === n) return true;
469
+ return void 0;
470
+ }
404
471
  function cmpVar(id, op, n, bounds) {
405
472
  const lo = bounds.lo.get(id);
406
473
  const hi = bounds.hi.get(id);
@@ -709,173 +776,6 @@ function shapeOnlyFn(paramTypes, returnType, opts) {
709
776
  );
710
777
  }
711
778
 
712
- // src/algebra/template.ts
713
- function viewTemplateParts(parts, describe) {
714
- return parts.map((p) => {
715
- const d = describe(p);
716
- return "fixed" in d ? { fixed: d.fixed, render: d.fixed, part: p } : { fixed: void 0, render: d.render, part: p };
717
- });
718
- }
719
- function knownPrefixOfViews(views) {
720
- let s = "";
721
- for (const v2 of views) {
722
- if (v2.fixed !== void 0) s += v2.fixed;
723
- else break;
724
- }
725
- return s;
726
- }
727
- function knownSuffixOfViews(views) {
728
- let s = "";
729
- for (let i = views.length - 1; i >= 0; i--) {
730
- const v2 = views[i];
731
- if (v2.fixed !== void 0) s = v2.fixed + s;
732
- else break;
733
- }
734
- return s;
735
- }
736
- function allFixedTextOfViews(views) {
737
- return views.filter((v2) => v2.fixed !== void 0).map((v2) => v2.fixed).join("");
738
- }
739
- function fixedLengthOfViews(views) {
740
- if (views.some((v2) => v2.fixed === void 0)) return void 0;
741
- return allFixedTextOfViews(views).length;
742
- }
743
- function formatTemplateNameViews(views) {
744
- const inner = views.map((v2) => v2.fixed !== void 0 ? v2.fixed : `\${${v2.render}}`).join("");
745
- return `\`${inner}\``;
746
- }
747
- function mergeAdjacentFixedViews(views, rebuildFixed) {
748
- const out = [];
749
- for (const v2 of views) {
750
- const last = out[out.length - 1];
751
- if (last && last.fixed !== void 0 && v2.fixed !== void 0) {
752
- out[out.length - 1] = rebuildFixed(last.fixed + v2.fixed);
753
- } else {
754
- out.push(v2);
755
- }
756
- }
757
- return out;
758
- }
759
- function templateMatchesValue(value, views) {
760
- let pos = 0;
761
- for (let i = 0; i < views.length; i++) {
762
- const v2 = views[i];
763
- if (v2.fixed !== void 0) {
764
- if (!value.startsWith(v2.fixed, pos)) return false;
765
- pos += v2.fixed.length;
766
- } else {
767
- if (i === views.length - 1) return true;
768
- const next = views[i + 1];
769
- if (next?.fixed !== void 0) {
770
- const idx = value.indexOf(next.fixed, pos);
771
- if (idx === -1) return false;
772
- pos = idx;
773
- } else {
774
- return true;
775
- }
776
- }
777
- }
778
- return pos === value.length;
779
- }
780
- function decideStartsWith(prefix, search) {
781
- if (prefix.length >= search.length) return prefix.startsWith(search);
782
- if (search.startsWith(prefix)) return "unknown";
783
- return false;
784
- }
785
- function decideEndsWith(suffix, search) {
786
- if (suffix.length >= search.length) return suffix.endsWith(search);
787
- if (search.endsWith(suffix)) return "unknown";
788
- return false;
789
- }
790
- function decideIncludes(fixedText, search) {
791
- return fixedText.includes(search) ? true : "unknown";
792
- }
793
- function isStrLit(a) {
794
- return a.shape.k === "prim" && a.shape.type === "string" && a.term?.op === "lit" && typeof a.term.value === "string";
795
- }
796
- function isStrPrim2(a) {
797
- return a.shape.k === "prim" && a.shape.type === "string";
798
- }
799
- function isTemplateAbs(a) {
800
- return a.shape.k === "prim" && a.shape.type === "string" && !!a.pred && a.pred.name?.startsWith("`") === true && Array.isArray(a.pred.meta?.templateParts);
801
- }
802
- function describeAbsPart(p) {
803
- if (isStrLit(p)) return { fixed: String(litValue(p)) };
804
- return { render: p.term ? termToString(p.term) : "string" };
805
- }
806
- function absTemplateViews(parts) {
807
- return viewTemplateParts(parts, describeAbsPart);
808
- }
809
- function templatePartsOf(a) {
810
- if (isTemplateAbs(a)) {
811
- const meta = a.pred.meta;
812
- return meta.templateParts;
813
- }
814
- return [a];
815
- }
816
- function rebuildAbsFixedView(text) {
817
- return {
818
- fixed: text,
819
- render: text,
820
- part: abs({ k: "prim", type: "string" }, lit(text), void 0, "exact")
821
- };
822
- }
823
- function normalizeParts(parts) {
824
- return mergeAdjacentFixedViews(absTemplateViews(parts), rebuildAbsFixedView).map((v2) => v2.part);
825
- }
826
- function formatTemplateName(parts) {
827
- return formatTemplateNameViews(absTemplateViews(parts));
828
- }
829
- function createTemplateAbs(parts) {
830
- const normalized = normalizeParts(parts);
831
- if (normalized.length === 1) {
832
- const only = normalized[0];
833
- if (isStrLit(only)) return only;
834
- if (isStrPrim2(only) && !isTemplateAbs(only)) return only;
835
- }
836
- const name = formatTemplateName(normalized);
837
- const predObj = {
838
- op: "true",
839
- name,
840
- meta: { templateParts: normalized }
841
- };
842
- return {
843
- shape: { k: "prim", type: "string" },
844
- term: void 0,
845
- pred: predObj,
846
- conf: "path"
847
- };
848
- }
849
- function isTemplateLike(a) {
850
- return isTemplateAbs(a);
851
- }
852
- function concatString(a, b) {
853
- if (isStrLit(a) && isStrLit(b)) {
854
- return abs(
855
- { k: "prim", type: "string" },
856
- lit(String(litValue(a)) + String(litValue(b))),
857
- void 0,
858
- "exact"
859
- );
860
- }
861
- const aParts = coerceToStringParts(a);
862
- const bParts = coerceToStringParts(b);
863
- if (!aParts || !bParts) return abs({ k: "unknown" }, void 0, void 0, "partial");
864
- return createTemplateAbs([...aParts, ...bParts]);
865
- }
866
- function coerceToStringParts(a) {
867
- if (isTemplateAbs(a) || isStrPrim2(a)) return templatePartsOf(a);
868
- if (isStrLit(a)) return [a];
869
- const lv = litValue(a);
870
- if (typeof lv === "number" || typeof lv === "boolean") {
871
- return [abs({ k: "prim", type: "string" }, lit(String(lv)), void 0, "exact")];
872
- }
873
- if (a.shape.k === "prim" && a.shape.type === "number") {
874
- return [a];
875
- }
876
- return void 0;
877
- }
878
-
879
779
  // src/algebra/derivation.ts
880
780
  var collector = null;
881
781
  var nextId = 1;
@@ -1084,114 +984,903 @@ function joinValues(a, b) {
1084
984
  if (va !== void 0 && Object.is(va, vb)) return a;
1085
985
  if (a.shape.k === "prim" && b.shape.k === "prim" && a.shape.type === b.shape.type) {
1086
986
  if (va !== void 0 && vb !== void 0) {
1087
- return abs(
1088
- a.shape,
1089
- void 0,
1090
- void 0,
1091
- confJoin(a.conf, "path")
1092
- );
987
+ const nanA = typeof va === "number" && Number.isNaN(va);
988
+ const nanB = typeof vb === "number" && Number.isNaN(vb);
989
+ if (nanA || nanB) {
990
+ return abs(a.shape, void 0, void 0, confJoin(confJoin(a.conf, b.conf), "path"));
991
+ }
992
+ return makeSum(a, b);
1093
993
  }
1094
994
  return abs(a.shape, void 0, void 0, confJoin(confJoin(a.conf, b.conf), "path"));
1095
995
  }
1096
- return makeSum(a, b);
996
+ return makeSum(a, b);
997
+ }
998
+ function makeSum(a, b) {
999
+ const members = flattenSum([a, b]);
1000
+ if (members.length === 1) return members[0];
1001
+ if (members.length > 16) {
1002
+ const first = members[0];
1003
+ const samePrimLit = first.shape.k === "prim" && members.every(
1004
+ (m) => m.shape.k === "prim" && m.shape.type === first.shape.type && litValue(m) !== void 0
1005
+ );
1006
+ if (samePrimLit) {
1007
+ return abs(first.shape, void 0, void 0, "path");
1008
+ }
1009
+ }
1010
+ return {
1011
+ shape: { k: "sum", members },
1012
+ conf: confJoin(a.conf, b.conf)
1013
+ };
1014
+ }
1015
+ function flattenSum(xs) {
1016
+ const out = [];
1017
+ for (const x of xs) {
1018
+ if (x.shape.k === "sum") out.push(...x.shape.members);
1019
+ else out.push(x);
1020
+ }
1021
+ const seen = /* @__PURE__ */ new Set();
1022
+ const deduped = [];
1023
+ for (const x of out) {
1024
+ const key = absShapeKey(x);
1025
+ if (seen.has(key)) continue;
1026
+ seen.add(key);
1027
+ deduped.push(x);
1028
+ }
1029
+ return deduped;
1030
+ }
1031
+ function absShapeKey(a, seen = /* @__PURE__ */ new Set()) {
1032
+ if (seen.has(a)) return "cycle";
1033
+ seen.add(a);
1034
+ try {
1035
+ const s = a.shape;
1036
+ if (s.k === "prim") {
1037
+ const lv = litValue(a);
1038
+ if (lv !== void 0) return `prim:${s.type}:${String(lv)}`;
1039
+ const t = a.term ? termToString(a.term) : "";
1040
+ const p = a.pred && a.pred.op !== "true" ? predToString(a.pred) : "";
1041
+ return `prim:${s.type}:${t}:${p}`;
1042
+ }
1043
+ if (s.k === "never") return "never";
1044
+ if (s.k === "any") return "any";
1045
+ if (s.k === "unknown") {
1046
+ if (a.term?.op === "lit" && a.term.value === void 0) return "unknown:undefined";
1047
+ return "unknown";
1048
+ }
1049
+ if (s.k === "arr") return `arr(${absShapeKey(s.element, seen)})`;
1050
+ if (s.k === "tuple") {
1051
+ const els = s.elements.map((e) => absShapeKey(e, seen)).join(",");
1052
+ const rest = s.rest ? `...${absShapeKey(s.rest, seen)}` : "";
1053
+ return `tuple[${els}${rest}]`;
1054
+ }
1055
+ if (s.k === "brand") return `brand:${s.name}(${absShapeKey(s.shape, seen)})`;
1056
+ if (s.k === "eff") return `eff:${s.eff}<${absShapeKey(s.inner, seen)}>`;
1057
+ if (s.k === "obj") {
1058
+ const slots = Object.keys(s.slots).sort().map((k) => {
1059
+ const slot = s.slots[k];
1060
+ const flags = (slot.optional ? "?" : "") + (slot.readonly ? "r" : "");
1061
+ return `${k}${flags}:${absShapeKey(slot.value, seen)}`;
1062
+ }).join(",");
1063
+ const idx = s.index ? `idx(${absShapeKey(s.index.key, seen)}\u2192${absShapeKey(s.index.value, seen)})` : "";
1064
+ const open = s.open ? "open" : "";
1065
+ return `obj{${slots}}${idx}${open}`;
1066
+ }
1067
+ if (s.k === "fn") {
1068
+ const pts = (s.paramTypes ?? []).map((t) => absShapeKey(t, seen)).join(",");
1069
+ const ret = s.returnType ? absShapeKey(s.returnType, seen) : "?";
1070
+ const name = s.name ? `#${s.name}` : "";
1071
+ return `fn${name}(${s.params.join(",")}|${pts})=>${ret}`;
1072
+ }
1073
+ if (s.k === "sum") {
1074
+ return `sum(${s.members.map((m) => absShapeKey(m, seen)).join("|")})`;
1075
+ }
1076
+ return "other";
1077
+ } finally {
1078
+ seen.delete(a);
1079
+ }
1080
+ }
1081
+ function fnOf(params, name) {
1082
+ const shape = { k: "fn", params };
1083
+ if (name) shape.name = name;
1084
+ return { shape, conf: "exact" };
1085
+ }
1086
+ function joinFunctions(a, b) {
1087
+ const sa = a.shape;
1088
+ const sb = b.shape;
1089
+ if (sa.k !== "fn" || sb.k !== "fn") return makeSum(a, b);
1090
+ const an = sa.name;
1091
+ const bn = sb.name;
1092
+ if (an && an === bn) {
1093
+ if (sa.params.length === sb.params.length && sa.params.every((p, i) => p === sb.params[i])) {
1094
+ return a;
1095
+ }
1096
+ }
1097
+ return makeSum(a, b);
1098
+ }
1099
+ function shapeBrief(a) {
1100
+ const s = a.shape;
1101
+ switch (s.k) {
1102
+ case "never":
1103
+ return "never";
1104
+ case "unknown":
1105
+ case "any":
1106
+ return s.k;
1107
+ case "prim":
1108
+ return s.type;
1109
+ case "arr":
1110
+ return `${shapeBrief(s.element)}[]`;
1111
+ case "obj":
1112
+ return "{\u2026}";
1113
+ case "tuple":
1114
+ return `[${s.elements.length}]`;
1115
+ case "fn":
1116
+ return "fn";
1117
+ case "brand":
1118
+ return s.name;
1119
+ case "eff":
1120
+ return s.eff;
1121
+ case "sum":
1122
+ return s.members.map(shapeBrief).join("|");
1123
+ default:
1124
+ return "\xB7";
1125
+ }
1126
+ }
1127
+ function annotateJoinPath(a, b, result) {
1128
+ if (result === a || result === b) return result;
1129
+ const sa = shapeBrief(a);
1130
+ const sb = shapeBrief(b);
1131
+ if (sa === sb) {
1132
+ const extra = sameShapeJoinNote(a, b);
1133
+ if (!extra) return result;
1134
+ const note3 = `join(${sa}: ${extra})`;
1135
+ if (result.pathNote === note3) return result;
1136
+ return { ...result, pathNote: note3 };
1137
+ }
1138
+ const note2 = `join(${sa} | ${sb})`;
1139
+ if (result.pathNote === note2) return result;
1140
+ return { ...result, pathNote: note2 };
1141
+ }
1142
+ function sameShapeJoinNote(a, b) {
1143
+ if (a.shape.k === "obj" && b.shape.k === "obj") {
1144
+ const ak = Object.keys(a.shape.slots ?? {});
1145
+ const bk = Object.keys(b.shape.slots ?? {});
1146
+ const onlyA = ak.filter((k) => !bk.includes(k));
1147
+ const onlyB = bk.filter((k) => !ak.includes(k));
1148
+ if (onlyA.length === 0 && onlyB.length === 0) return void 0;
1149
+ const parts = [];
1150
+ if (onlyA.length > 0) parts.push(`+${onlyA.join(",")}`);
1151
+ if (onlyB.length > 0) parts.push(`+${onlyB.join(",")}`);
1152
+ return parts.join(" ");
1153
+ }
1154
+ if (a.shape.k === "tuple" && b.shape.k === "tuple") {
1155
+ const la = a.shape.elements.length;
1156
+ const lb = b.shape.elements.length;
1157
+ if (la === lb) return void 0;
1158
+ return `len ${la}|${lb}`;
1159
+ }
1160
+ if (a.shape.k === "brand" && b.shape.k === "brand") {
1161
+ const an = a.shape.name;
1162
+ const bn = b.shape.name;
1163
+ if (an !== bn) return `brand ${an}|${bn}`;
1164
+ const ai = a.shape.shape;
1165
+ const bi = b.shape.shape;
1166
+ return sameShapeJoinNote(ai, bi);
1167
+ }
1168
+ if (a.shape.k === "sum" && b.shape.k === "sum") {
1169
+ const am = a.shape.members.map((m) => shapeBrief(m)).sort().join(",");
1170
+ const bm = b.shape.members.map((m) => shapeBrief(m)).sort().join(",");
1171
+ if (am === bm) return void 0;
1172
+ return `sum ${am}|${bm}`;
1173
+ }
1174
+ return void 0;
1175
+ }
1176
+ function joinAbs(a, b) {
1177
+ if (a.shape.k === "never") return b;
1178
+ if (b.shape.k === "never") return a;
1179
+ if (isObj(a) && isObj(b)) {
1180
+ return annotateJoinPath(a, b, joinObjects(a, b));
1181
+ }
1182
+ if (a.shape.k === "fn" && b.shape.k === "fn") {
1183
+ return annotateJoinPath(a, b, joinFunctions(a, b));
1184
+ }
1185
+ const result = joinValues(a, b);
1186
+ noteDerivationJoin([a, b], result);
1187
+ return annotateJoinPath(a, b, result);
1188
+ }
1189
+
1190
+ // src/algebra/collections.ts
1191
+ var mapTables = /* @__PURE__ */ new WeakMap();
1192
+ var setTables = /* @__PURE__ */ new WeakMap();
1193
+ var armOverlays = [];
1194
+ function pushCollectionArm() {
1195
+ armOverlays.push(/* @__PURE__ */ new WeakMap());
1196
+ }
1197
+ function popCollectionArm() {
1198
+ return armOverlays.pop();
1199
+ }
1200
+ function cloneMapTable(t) {
1201
+ return {
1202
+ byLit: new Map(t.byLit),
1203
+ shadowValues: [...t.shadowValues],
1204
+ maybeAbsent: t.maybeAbsent ? new Set(t.maybeAbsent) : void 0
1205
+ };
1206
+ }
1207
+ function cloneSetTable(t) {
1208
+ return {
1209
+ elements: [...t.elements],
1210
+ maybeAbsent: t.maybeAbsent instanceof Set ? new Set(t.maybeAbsent) : t.maybeAbsent
1211
+ };
1212
+ }
1213
+ function setAbsentKey(t, k) {
1214
+ if (!t) return false;
1215
+ if (t.maybeAbsent === true) return true;
1216
+ return t.maybeAbsent instanceof Set && t.maybeAbsent.has(k);
1217
+ }
1218
+ function setAnyAbsent(t) {
1219
+ if (!t) return false;
1220
+ return t.maybeAbsent === true || t.maybeAbsent instanceof Set && t.maybeAbsent.size > 0;
1221
+ }
1222
+ function mergeCollectionArms(arms) {
1223
+ endCollectionFork(arms);
1224
+ }
1225
+ var forkTouchedStack = [];
1226
+ function beginCollectionFork() {
1227
+ forkTouchedStack.push(/* @__PURE__ */ new Set());
1228
+ }
1229
+ function noteCollectionWrite(id) {
1230
+ const top = forkTouchedStack[forkTouchedStack.length - 1];
1231
+ if (top) top.add(id);
1232
+ }
1233
+ function endCollectionFork(arms) {
1234
+ const touched = forkTouchedStack.pop() ?? /* @__PURE__ */ new Set();
1235
+ const live = arms.filter(Boolean);
1236
+ if (live.length === 0) return;
1237
+ const nested = armOverlays.length > 0;
1238
+ const outerArm = nested ? armOverlays[armOverlays.length - 1] : void 0;
1239
+ const commitMap = (id, merged) => {
1240
+ if (outerArm) {
1241
+ const e = outerArm.get(id) ?? {};
1242
+ outerArm.set(id, { ...e, map: merged });
1243
+ } else {
1244
+ mapTables.set(id, merged);
1245
+ }
1246
+ };
1247
+ const commitSet = (id, merged) => {
1248
+ if (outerArm) {
1249
+ const e = outerArm.get(id) ?? {};
1250
+ outerArm.set(id, { ...e, set: merged });
1251
+ } else {
1252
+ setTables.set(id, merged);
1253
+ }
1254
+ };
1255
+ for (const id of touched) {
1256
+ const armTables = [];
1257
+ const armSetTables = [];
1258
+ let anyMap = false;
1259
+ let anySet = false;
1260
+ for (const arm of live) {
1261
+ const e = arm.get(id);
1262
+ if (e?.map) {
1263
+ anyMap = true;
1264
+ armTables.push(e.map);
1265
+ } else if (anyMap || armTables.length > 0) {
1266
+ armTables.push(void 0);
1267
+ }
1268
+ if (e?.set) {
1269
+ anySet = true;
1270
+ armSetTables.push(e.set);
1271
+ } else if (anySet || armSetTables.length > 0) {
1272
+ armSetTables.push(void 0);
1273
+ }
1274
+ }
1275
+ if (anyMap || armTables.some(Boolean)) {
1276
+ const base = (nested ? mapTableForReadBase(outerArm, id) : mapTables.get(id)) ?? emptyMapTable();
1277
+ const perArm = live.map((arm) => {
1278
+ const e = arm.get(id);
1279
+ return e?.map ?? cloneMapTable(base);
1280
+ });
1281
+ const merged = { byLit: /* @__PURE__ */ new Map(), shadowValues: [], maybeAbsent: /* @__PURE__ */ new Set() };
1282
+ const keyArms = /* @__PURE__ */ new Map();
1283
+ const forcedAbsent = /* @__PURE__ */ new Set();
1284
+ for (const t of perArm) {
1285
+ for (const [k, v2] of t.byLit) {
1286
+ const prev = merged.byLit.get(k);
1287
+ merged.byLit.set(k, prev ? joinAbs(prev, v2) : v2);
1288
+ keyArms.set(k, (keyArms.get(k) ?? 0) + 1);
1289
+ }
1290
+ for (const sv of t.shadowValues) merged.shadowValues.push(sv);
1291
+ if (t.maybeAbsent) {
1292
+ for (const k of t.maybeAbsent) forcedAbsent.add(k);
1293
+ }
1294
+ }
1295
+ for (const [k, count] of keyArms) {
1296
+ if (count < perArm.length) merged.maybeAbsent.add(k);
1297
+ }
1298
+ for (const k of forcedAbsent) merged.maybeAbsent.add(k);
1299
+ if (merged.maybeAbsent.size === 0) delete merged.maybeAbsent;
1300
+ commitMap(id, merged);
1301
+ }
1302
+ if (anySet || armSetTables.some(Boolean)) {
1303
+ const base = (nested ? setTableForReadBase(outerArm, id) : setTables.get(id)) ?? emptySetTable();
1304
+ const perArm = live.map((arm) => {
1305
+ const e = arm.get(id);
1306
+ return e?.set ?? cloneSetTable(base);
1307
+ });
1308
+ const seen = /* @__PURE__ */ new Set();
1309
+ const mergedEls = [];
1310
+ const litArmCount = /* @__PURE__ */ new Map();
1311
+ const forcedAbsent = /* @__PURE__ */ new Set();
1312
+ let wholeUncertain = false;
1313
+ let hasNonLit = false;
1314
+ for (const t of perArm) {
1315
+ if (t.maybeAbsent === true) wholeUncertain = true;
1316
+ if (t.maybeAbsent instanceof Set) {
1317
+ for (const k of t.maybeAbsent) forcedAbsent.add(k);
1318
+ }
1319
+ const armLits = /* @__PURE__ */ new Set();
1320
+ for (const el of t.elements) {
1321
+ const lk = litKeyOf(el);
1322
+ if (lk !== void 0) {
1323
+ if (!seen.has(lk)) {
1324
+ seen.add(lk);
1325
+ mergedEls.push(el);
1326
+ }
1327
+ armLits.add(lk);
1328
+ } else {
1329
+ hasNonLit = true;
1330
+ mergedEls.push(el);
1331
+ }
1332
+ }
1333
+ for (const k of armLits) {
1334
+ litArmCount.set(k, (litArmCount.get(k) ?? 0) + 1);
1335
+ }
1336
+ }
1337
+ const maybeKeys = /* @__PURE__ */ new Set();
1338
+ if (wholeUncertain || hasNonLit) {
1339
+ wholeUncertain = true;
1340
+ } else {
1341
+ for (const [k, count] of litArmCount) {
1342
+ if (count < perArm.length) maybeKeys.add(k);
1343
+ }
1344
+ for (const k of forcedAbsent) maybeKeys.add(k);
1345
+ }
1346
+ commitSet(id, {
1347
+ elements: mergedEls,
1348
+ maybeAbsent: wholeUncertain ? true : maybeKeys.size > 0 ? maybeKeys : void 0
1349
+ });
1350
+ }
1351
+ }
1352
+ }
1353
+ function mapTableForReadBase(arm, id) {
1354
+ return arm.get(id)?.map ?? mapTables.get(id);
1355
+ }
1356
+ function setTableForReadBase(arm, id) {
1357
+ return arm.get(id)?.set ?? setTables.get(id);
1358
+ }
1359
+ function emptyMapTable() {
1360
+ return { byLit: /* @__PURE__ */ new Map(), shadowValues: [] };
1361
+ }
1362
+ function emptySetTable() {
1363
+ return { elements: [] };
1364
+ }
1365
+ function brandOf(name) {
1366
+ return abs(
1367
+ { k: "brand", name, shape: objOf({}) },
1368
+ void 0,
1369
+ void 0,
1370
+ "path"
1371
+ );
1372
+ }
1373
+ function litKeyOf(a) {
1374
+ if (!a) return void 0;
1375
+ if (a.term?.op === "lit") return a.term.value;
1376
+ const v2 = litValue(a);
1377
+ if (v2 === void 0 && a.term === void 0) return void 0;
1378
+ return v2;
1379
+ }
1380
+ function isMapAbs(a) {
1381
+ return !!a && a.shape.k === "brand" && a.shape.name === "Map";
1382
+ }
1383
+ function isSetAbs(a) {
1384
+ return !!a && a.shape.k === "brand" && a.shape.name === "Set";
1385
+ }
1386
+ function elementsFrom(iterable) {
1387
+ if (!iterable) return [];
1388
+ if (iterable.shape.k === "tuple") return [...iterable.shape.elements];
1389
+ if (iterable.shape.k === "arr") {
1390
+ return [iterable.shape.element];
1391
+ }
1392
+ if (iterable.shape.k === "sum") {
1393
+ return iterable.shape.members.flatMap(elementsFrom);
1394
+ }
1395
+ return [];
1396
+ }
1397
+ function makeMapAbs(iterable) {
1398
+ const m = brandOf("Map");
1399
+ const table = emptyMapTable();
1400
+ for (const el of elementsFrom(iterable)) {
1401
+ if (el.shape.k === "tuple" && el.shape.elements.length >= 2) {
1402
+ const k = litKeyOf(el.shape.elements[0]);
1403
+ const v2 = el.shape.elements[1];
1404
+ if (k !== void 0) table.byLit.set(k, v2);
1405
+ else table.shadowValues.push(v2);
1406
+ }
1407
+ }
1408
+ mapTables.set(m, table);
1409
+ return m;
1410
+ }
1411
+ function makeSetAbs(iterable) {
1412
+ const s = brandOf("Set");
1413
+ const table = emptySetTable();
1414
+ const seen = /* @__PURE__ */ new Set();
1415
+ for (const el of elementsFrom(iterable)) {
1416
+ const lk = litKeyOf(el);
1417
+ if (lk !== void 0) {
1418
+ if (seen.has(lk)) continue;
1419
+ seen.add(lk);
1420
+ }
1421
+ table.elements.push(el);
1422
+ }
1423
+ setTables.set(s, table);
1424
+ return s;
1425
+ }
1426
+ function mapTableOf(a) {
1427
+ const existing = mapTables.get(a);
1428
+ if (existing) return existing;
1429
+ const t = emptyMapTable();
1430
+ mapTables.set(a, t);
1431
+ return t;
1432
+ }
1433
+ function setTableOf(a) {
1434
+ const existing = setTables.get(a);
1435
+ if (existing) return existing;
1436
+ const t = emptySetTable();
1437
+ setTables.set(a, t);
1438
+ return t;
1439
+ }
1440
+ function mapTableForWrite(a) {
1441
+ noteCollectionWrite(a);
1442
+ if (armOverlays.length > 0) {
1443
+ let base;
1444
+ for (let i = 0; i < armOverlays.length; i++) {
1445
+ const e = armOverlays[i].get(a);
1446
+ if (e?.map) base = e.map;
1447
+ }
1448
+ if (!base) base = mapTables.get(a);
1449
+ const top = armOverlays[armOverlays.length - 1];
1450
+ let entry = top.get(a);
1451
+ if (!entry?.map) {
1452
+ const cloned = cloneMapTable(base ?? emptyMapTable());
1453
+ entry = { ...entry ?? {}, map: cloned };
1454
+ top.set(a, entry);
1455
+ return cloned;
1456
+ }
1457
+ return entry.map;
1458
+ }
1459
+ return mapTableOf(a);
1460
+ }
1461
+ function mapTableForRead(a) {
1462
+ for (let i = armOverlays.length - 1; i >= 0; i--) {
1463
+ const entry = armOverlays[i].get(a);
1464
+ if (entry?.map) return entry.map;
1465
+ }
1466
+ return mapTables.get(a);
1467
+ }
1468
+ function setTableForWrite(a) {
1469
+ noteCollectionWrite(a);
1470
+ if (armOverlays.length > 0) {
1471
+ let base;
1472
+ for (let i = 0; i < armOverlays.length; i++) {
1473
+ const e = armOverlays[i].get(a);
1474
+ if (e?.set) base = e.set;
1475
+ }
1476
+ if (!base) base = setTables.get(a);
1477
+ const top = armOverlays[armOverlays.length - 1];
1478
+ let entry = top.get(a);
1479
+ if (!entry?.set) {
1480
+ const cloned = cloneSetTable(base ?? emptySetTable());
1481
+ entry = { ...entry ?? {}, set: cloned };
1482
+ top.set(a, entry);
1483
+ return cloned;
1484
+ }
1485
+ return entry.set;
1486
+ }
1487
+ return setTableOf(a);
1488
+ }
1489
+ function setTableForRead(a) {
1490
+ for (let i = armOverlays.length - 1; i >= 0; i--) {
1491
+ const entry = armOverlays[i].get(a);
1492
+ if (entry?.set) return entry.set;
1493
+ }
1494
+ return setTables.get(a);
1495
+ }
1496
+ function mapSetEntry(mapAbs, key, value) {
1497
+ const t = mapTableForWrite(mapAbs);
1498
+ const k = litKeyOf(key);
1499
+ if (k !== void 0) t.byLit.set(k, value);
1500
+ else if (value) t.shadowValues.push(value);
1501
+ return mapAbs;
1502
+ }
1503
+ function mapDeleteEntry(mapAbs, key) {
1504
+ const t = mapTableForWrite(mapAbs);
1505
+ const k = litKeyOf(key);
1506
+ if (k !== void 0) {
1507
+ t.byLit.delete(k);
1508
+ t.maybeAbsent?.delete(k);
1509
+ } else if (t.shadowValues.length === 0 && t.byLit.size > 0) {
1510
+ t.maybeAbsent = new Set(t.byLit.keys());
1511
+ }
1512
+ return abs(
1513
+ { k: "prim", type: "boolean" },
1514
+ void 0,
1515
+ void 0,
1516
+ "path"
1517
+ );
1518
+ }
1519
+ function mapClearEntries(mapAbs) {
1520
+ const t = mapTableForWrite(mapAbs);
1521
+ t.byLit.clear();
1522
+ t.shadowValues.length = 0;
1523
+ delete t.maybeAbsent;
1524
+ return undefAbs();
1525
+ }
1526
+ function undefAbs() {
1527
+ return abs({ k: "unknown" }, { op: "lit", value: void 0 }, void 0, "exact");
1528
+ }
1529
+ function joinAll(els) {
1530
+ if (els.length === 0) return void 0;
1531
+ return els.reduce((a, b) => joinAbs(a, b));
1532
+ }
1533
+ function mapGetEntry(mapAbs, key) {
1534
+ const t = mapTableForRead(mapAbs);
1535
+ if (!t) return unknown;
1536
+ const k = litKeyOf(key);
1537
+ if (k !== void 0) {
1538
+ const v2 = t.byLit.get(k);
1539
+ const absent = t.maybeAbsent?.has(k) === true;
1540
+ if (v2 !== void 0 && !absent && t.shadowValues.length === 0) return v2;
1541
+ if (v2 !== void 0) {
1542
+ return joinAll([v2, ...t.shadowValues, undefAbs()]) ?? undefAbs();
1543
+ }
1544
+ if (t.shadowValues.length === 0) return undefAbs();
1545
+ }
1546
+ const known = [...t.byLit.values(), ...t.shadowValues];
1547
+ const joined = joinAll(known);
1548
+ if (k !== void 0 && t.shadowValues.length === 0) {
1549
+ return undefAbs();
1550
+ }
1551
+ if (joined === void 0) {
1552
+ return k !== void 0 ? undefAbs() : unknown;
1553
+ }
1554
+ return joinAbs(joined, undefAbs());
1555
+ }
1556
+ function mapHasEntry(mapAbs, key) {
1557
+ const t = mapTableForRead(mapAbs);
1558
+ if (!t) return unknown;
1559
+ const k = litKeyOf(key);
1560
+ if (k === void 0) {
1561
+ return t.byLit.size > 0 || t.shadowValues.length > 0 ? abs({ k: "prim", type: "boolean" }, void 0, void 0, "partial") : unknown;
1562
+ }
1563
+ const hit = t.byLit.has(k);
1564
+ const maybeAbsent = t.maybeAbsent?.has(k) === true;
1565
+ if (t.shadowValues.length > 0 || maybeAbsent) {
1566
+ return abs({ k: "prim", type: "boolean" }, void 0, void 0, "partial");
1567
+ }
1568
+ return abs(
1569
+ { k: "prim", type: "boolean" },
1570
+ { op: "lit", value: hit },
1571
+ void 0,
1572
+ "exact"
1573
+ );
1574
+ }
1575
+ function mapSizeAbs(mapAbs) {
1576
+ const t = mapTableForRead(mapAbs);
1577
+ if (!t || t.shadowValues.length > 0 || t.maybeAbsent && t.maybeAbsent.size > 0) {
1578
+ return abs({ k: "prim", type: "number" }, void 0, void 0, "path");
1579
+ }
1580
+ return abs(
1581
+ { k: "prim", type: "number" },
1582
+ { op: "lit", value: t.byLit.size },
1583
+ void 0,
1584
+ "exact"
1585
+ );
1586
+ }
1587
+ function mapValuesAbs(mapAbs) {
1588
+ const t = mapTableForRead(mapAbs);
1589
+ if (!t) return [];
1590
+ return [...t.byLit.values(), ...t.shadowValues];
1591
+ }
1592
+ function keyAbsFromLitKey(k) {
1593
+ if (k === null) {
1594
+ return abs({ k: "unknown" }, { op: "lit", value: null }, void 0, "exact");
1595
+ }
1596
+ if (k === void 0) {
1597
+ return abs({ k: "unknown" }, { op: "lit", value: void 0 }, void 0, "exact");
1598
+ }
1599
+ if (typeof k === "string") return abs({ k: "prim", type: "string" }, { op: "lit", value: k }, void 0, "exact");
1600
+ if (typeof k === "number") return abs({ k: "prim", type: "number" }, { op: "lit", value: k }, void 0, "exact");
1601
+ return abs({ k: "prim", type: "boolean" }, { op: "lit", value: k }, void 0, "exact");
1602
+ }
1603
+ function mapEntriesAbs(mapAbs) {
1604
+ const t = mapTableForRead(mapAbs);
1605
+ if (!t) return [];
1606
+ const entries = [];
1607
+ for (const [k, v2] of t.byLit) {
1608
+ entries.push(
1609
+ abs(
1610
+ { k: "tuple", elements: [keyAbsFromLitKey(k), v2] },
1611
+ void 0,
1612
+ void 0,
1613
+ confJoin(v2.conf, "exact")
1614
+ )
1615
+ );
1616
+ }
1617
+ const unkKey = abs({ k: "unknown" }, void 0, void 0, "partial");
1618
+ for (const v2 of t.shadowValues) {
1619
+ entries.push(
1620
+ abs(
1621
+ { k: "tuple", elements: [unkKey, v2] },
1622
+ void 0,
1623
+ void 0,
1624
+ "partial"
1625
+ )
1626
+ );
1627
+ }
1628
+ return entries;
1629
+ }
1630
+ function setAddEntry(setAbs, value) {
1631
+ const t = setTableForWrite(setAbs);
1632
+ const lk = litKeyOf(value);
1633
+ if (lk !== void 0 && t.elements.some((el) => litKeyOf(el) === lk)) {
1634
+ return setAbs;
1635
+ }
1636
+ t.elements.push(value);
1637
+ return setAbs;
1638
+ }
1639
+ function setDeleteEntry(setAbs, value) {
1640
+ const t = setTableForWrite(setAbs);
1641
+ const lk = litKeyOf(value);
1642
+ if (lk !== void 0) {
1643
+ t.elements = t.elements.filter((el) => litKeyOf(el) !== lk);
1644
+ const hasUnknown = t.elements.some((el) => litKeyOf(el) === void 0);
1645
+ if (hasUnknown) t.maybeAbsent = true;
1646
+ else delete t.maybeAbsent;
1647
+ } else {
1648
+ t.maybeAbsent = true;
1649
+ }
1650
+ return abs({ k: "prim", type: "boolean" }, void 0, void 0, "path");
1651
+ }
1652
+ function setClearEntries(setAbs) {
1653
+ const t = setTableForWrite(setAbs);
1654
+ t.elements = [];
1655
+ delete t.maybeAbsent;
1656
+ return undefAbs();
1657
+ }
1658
+ function setHasEntry(setAbs, value) {
1659
+ const t = setTableForRead(setAbs);
1660
+ if (!t) return unknown;
1661
+ const k = litKeyOf(value);
1662
+ if (k !== void 0) {
1663
+ const hit = t.elements.some((el) => litKeyOf(el) === k);
1664
+ if (setAbsentKey(t, k)) {
1665
+ return abs({ k: "prim", type: "boolean" }, void 0, void 0, "partial");
1666
+ }
1667
+ return abs(
1668
+ { k: "prim", type: "boolean" },
1669
+ { op: "lit", value: hit },
1670
+ void 0,
1671
+ "exact"
1672
+ );
1673
+ }
1674
+ return abs({ k: "prim", type: "boolean" }, void 0, void 0, "partial");
1675
+ }
1676
+ function setSizeAbs(setAbs) {
1677
+ const t = setTableForRead(setAbs);
1678
+ if (!t || setAnyAbsent(t)) {
1679
+ return abs({ k: "prim", type: "number" }, void 0, void 0, "path");
1680
+ }
1681
+ return abs(
1682
+ { k: "prim", type: "number" },
1683
+ { op: "lit", value: t.elements.length },
1684
+ void 0,
1685
+ "exact"
1686
+ );
1687
+ }
1688
+ function setElementsAbs(setAbs) {
1689
+ const t = setTableForRead(setAbs);
1690
+ return t ? [...t.elements] : [];
1691
+ }
1692
+ function collectionExactLen(c) {
1693
+ if (isSetAbs(c)) {
1694
+ const t = setTableForRead(c);
1695
+ if (!t) return void 0;
1696
+ if (t.maybeAbsent === true || t.maybeAbsent instanceof Set && t.maybeAbsent.size > 0) {
1697
+ return void 0;
1698
+ }
1699
+ return t.elements.length;
1700
+ }
1701
+ if (isMapAbs(c)) {
1702
+ const t = mapTableForRead(c);
1703
+ if (!t) return void 0;
1704
+ if (t.shadowValues.length > 0 || t.maybeAbsent && t.maybeAbsent.size > 0) {
1705
+ return void 0;
1706
+ }
1707
+ return t.byLit.size;
1708
+ }
1709
+ return void 0;
1710
+ }
1711
+ function collectionElementJoin(c) {
1712
+ const els = isSetAbs(c) ? setElementsAbs(c) : isMapAbs(c) ? mapEntriesAbs(c) : [];
1713
+ if (els.length === 0) return unknown;
1714
+ return els.reduce((a, b) => joinAbs(a, b));
1715
+ }
1716
+ function clearCollectionTables() {
1717
+ }
1718
+
1719
+ // src/algebra/template.ts
1720
+ function viewTemplateParts(parts, describe) {
1721
+ return parts.map((p) => {
1722
+ const d = describe(p);
1723
+ return "fixed" in d ? { fixed: d.fixed, render: d.fixed, part: p } : { fixed: void 0, render: d.render, part: p };
1724
+ });
1725
+ }
1726
+ function knownPrefixOfViews(views) {
1727
+ let s = "";
1728
+ for (const v2 of views) {
1729
+ if (v2.fixed !== void 0) s += v2.fixed;
1730
+ else break;
1731
+ }
1732
+ return s;
1733
+ }
1734
+ function knownSuffixOfViews(views) {
1735
+ let s = "";
1736
+ for (let i = views.length - 1; i >= 0; i--) {
1737
+ const v2 = views[i];
1738
+ if (v2.fixed !== void 0) s = v2.fixed + s;
1739
+ else break;
1740
+ }
1741
+ return s;
1742
+ }
1743
+ function allFixedTextOfViews(views) {
1744
+ return views.filter((v2) => v2.fixed !== void 0).map((v2) => v2.fixed).join("");
1745
+ }
1746
+ function fixedLengthOfViews(views) {
1747
+ if (views.some((v2) => v2.fixed === void 0)) return void 0;
1748
+ return allFixedTextOfViews(views).length;
1749
+ }
1750
+ function formatTemplateNameViews(views) {
1751
+ const inner = views.map((v2) => v2.fixed !== void 0 ? v2.fixed : `\${${v2.render}}`).join("");
1752
+ return `\`${inner}\``;
1753
+ }
1754
+ function mergeAdjacentFixedViews(views, rebuildFixed) {
1755
+ const out = [];
1756
+ for (const v2 of views) {
1757
+ const last = out[out.length - 1];
1758
+ if (last && last.fixed !== void 0 && v2.fixed !== void 0) {
1759
+ out[out.length - 1] = rebuildFixed(last.fixed + v2.fixed);
1760
+ } else {
1761
+ out.push(v2);
1762
+ }
1763
+ }
1764
+ return out;
1765
+ }
1766
+ function templateMatchesValue(value, views) {
1767
+ let pos = 0;
1768
+ for (let i = 0; i < views.length; i++) {
1769
+ const v2 = views[i];
1770
+ if (v2.fixed !== void 0) {
1771
+ if (!value.startsWith(v2.fixed, pos)) return false;
1772
+ pos += v2.fixed.length;
1773
+ } else {
1774
+ if (i === views.length - 1) return true;
1775
+ const next = views[i + 1];
1776
+ if (next?.fixed !== void 0) {
1777
+ const idx = value.indexOf(next.fixed, pos);
1778
+ if (idx === -1) return false;
1779
+ pos = idx;
1780
+ } else {
1781
+ return true;
1782
+ }
1783
+ }
1784
+ }
1785
+ return pos === value.length;
1786
+ }
1787
+ function decideStartsWith(prefix, search) {
1788
+ if (prefix.length >= search.length) return prefix.startsWith(search);
1789
+ if (search.startsWith(prefix)) return "unknown";
1790
+ return false;
1791
+ }
1792
+ function decideEndsWith(suffix, search) {
1793
+ if (suffix.length >= search.length) return suffix.endsWith(search);
1794
+ if (search.endsWith(suffix)) return "unknown";
1795
+ return false;
1796
+ }
1797
+ function decideIncludes(fixedText, search) {
1798
+ return fixedText.includes(search) ? true : "unknown";
1799
+ }
1800
+ function isStrLit(a) {
1801
+ return a.shape.k === "prim" && a.shape.type === "string" && a.term?.op === "lit" && typeof a.term.value === "string";
1802
+ }
1803
+ function isStrPrim2(a) {
1804
+ return a.shape.k === "prim" && a.shape.type === "string";
1805
+ }
1806
+ function isTemplateAbs(a) {
1807
+ return a.shape.k === "prim" && a.shape.type === "string" && !!a.pred && a.pred.name?.startsWith("`") === true && Array.isArray(a.pred.meta?.templateParts);
1808
+ }
1809
+ function describeAbsPart(p) {
1810
+ if (isStrLit(p)) return { fixed: String(litValue(p)) };
1811
+ return { render: p.term ? termToString(p.term) : "string" };
1812
+ }
1813
+ function absTemplateViews(parts) {
1814
+ return viewTemplateParts(parts, describeAbsPart);
1815
+ }
1816
+ function templatePartsOf(a) {
1817
+ if (isTemplateAbs(a)) {
1818
+ const meta = a.pred.meta;
1819
+ return meta.templateParts;
1820
+ }
1821
+ return [a];
1097
1822
  }
1098
- function makeSum(a, b) {
1099
- const members = flattenSum([a, b]);
1100
- if (members.length === 1) return members[0];
1823
+ function rebuildAbsFixedView(text) {
1101
1824
  return {
1102
- shape: { k: "sum", members },
1103
- conf: confJoin(a.conf, b.conf)
1825
+ fixed: text,
1826
+ render: text,
1827
+ part: abs({ k: "prim", type: "string" }, lit(text), void 0, "exact")
1104
1828
  };
1105
1829
  }
1106
- function flattenSum(xs) {
1107
- const out = [];
1108
- for (const x of xs) {
1109
- if (x.shape.k === "sum") out.push(...x.shape.members);
1110
- else out.push(x);
1111
- }
1112
- const seen = /* @__PURE__ */ new Set();
1113
- const deduped = [];
1114
- for (const x of out) {
1115
- const key = absShapeKey(x);
1116
- if (seen.has(key)) continue;
1117
- seen.add(key);
1118
- deduped.push(x);
1119
- }
1120
- return deduped;
1830
+ function normalizeParts(parts) {
1831
+ return mergeAdjacentFixedViews(absTemplateViews(parts), rebuildAbsFixedView).map((v2) => v2.part);
1121
1832
  }
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);
1833
+ function formatTemplateName(parts) {
1834
+ return formatTemplateNameViews(absTemplateViews(parts));
1835
+ }
1836
+ function createTemplateAbs(parts) {
1837
+ const normalized = normalizeParts(parts);
1838
+ if (normalized.length === 1) {
1839
+ const only = normalized[0];
1840
+ if (isStrLit(only)) return only;
1841
+ if (isStrPrim2(only) && !isTemplateAbs(only)) return only;
1167
1842
  }
1843
+ const name = formatTemplateName(normalized);
1844
+ const predObj = {
1845
+ op: "true",
1846
+ name,
1847
+ meta: { templateParts: normalized }
1848
+ };
1849
+ return {
1850
+ shape: { k: "prim", type: "string" },
1851
+ term: void 0,
1852
+ pred: predObj,
1853
+ conf: "path"
1854
+ };
1168
1855
  }
1169
- function fnOf(params, name) {
1170
- const shape = { k: "fn", params };
1171
- if (name) shape.name = name;
1172
- return { shape, conf: "exact" };
1856
+ function isTemplateLike(a) {
1857
+ return isTemplateAbs(a);
1173
1858
  }
1174
- function joinFunctions(a, b) {
1175
- const sa = a.shape;
1176
- const sb = b.shape;
1177
- if (sa.k !== "fn" || sb.k !== "fn") return makeSum(a, b);
1178
- const an = sa.name;
1179
- const bn = sb.name;
1180
- if (an && an === bn) {
1181
- if (sa.params.length === sb.params.length && sa.params.every((p, i) => p === sb.params[i])) {
1182
- return a;
1183
- }
1859
+ function concatString(a, b) {
1860
+ if (isStrLit(a) && isStrLit(b)) {
1861
+ return abs(
1862
+ { k: "prim", type: "string" },
1863
+ lit(String(litValue(a)) + String(litValue(b))),
1864
+ void 0,
1865
+ "exact"
1866
+ );
1184
1867
  }
1185
- return makeSum(a, b);
1868
+ const aParts = coerceToStringParts(a);
1869
+ const bParts = coerceToStringParts(b);
1870
+ if (!aParts || !bParts) return abs({ k: "unknown" }, void 0, void 0, "partial");
1871
+ return createTemplateAbs([...aParts, ...bParts]);
1186
1872
  }
1187
- function joinAbs(a, b) {
1188
- if (a.shape.k === "never") return b;
1189
- if (b.shape.k === "never") return a;
1190
- if (isObj(a) && isObj(b)) return joinObjects(a, b);
1191
- if (a.shape.k === "fn" && b.shape.k === "fn") return joinFunctions(a, b);
1192
- const result = joinValues(a, b);
1193
- noteDerivationJoin([a, b], result);
1194
- return result;
1873
+ function coerceToStringParts(a) {
1874
+ if (isTemplateAbs(a) || isStrPrim2(a)) return templatePartsOf(a);
1875
+ if (isStrLit(a)) return [a];
1876
+ const lv = litValue(a);
1877
+ if (typeof lv === "number" || typeof lv === "boolean") {
1878
+ return [abs({ k: "prim", type: "string" }, lit(String(lv)), void 0, "exact")];
1879
+ }
1880
+ if (a.shape.k === "prim" && a.shape.type === "number") {
1881
+ return [a];
1882
+ }
1883
+ return void 0;
1195
1884
  }
1196
1885
 
1197
1886
  // src/algebra/arithmetic.ts
@@ -1877,9 +2566,9 @@ function definitelyNotNullishShape(s) {
1877
2566
  }
1878
2567
  }
1879
2568
  function isNullishLitAbs(a) {
1880
- const v2 = litValue(a);
1881
- if (v2 === null || v2 === void 0) return true;
1882
- return false;
2569
+ const t = a.term;
2570
+ if (!t || t.op !== "lit") return false;
2571
+ return t.value === null || t.value === void 0;
1883
2572
  }
1884
2573
  function strictEqAbs(a, b) {
1885
2574
  const va = litValue(a);
@@ -1894,6 +2583,26 @@ function strictEqAbs(a, b) {
1894
2583
  }
1895
2584
  return void 0;
1896
2585
  }
2586
+ function abstractEq(x, y) {
2587
+ if (x === y) return true;
2588
+ if (x === null && y === void 0) return true;
2589
+ if (x === void 0 && y === null) return true;
2590
+ if (typeof x === "number" && Number.isNaN(x)) return false;
2591
+ if (typeof y === "number" && Number.isNaN(y)) return false;
2592
+ if (typeof x === "boolean") return abstractEq(x ? 1 : 0, y);
2593
+ if (typeof y === "boolean") return abstractEq(x, y ? 1 : 0);
2594
+ if (typeof x === "number" && typeof y === "string") return x === Number(y);
2595
+ if (typeof x === "string" && typeof y === "number") return Number(x) === y;
2596
+ return false;
2597
+ }
2598
+ function looseEqAbs(a, b) {
2599
+ const ta = a.term;
2600
+ const tb = b.term;
2601
+ if (ta?.op === "lit" && tb?.op === "lit") {
2602
+ return abstractEq(ta.value, tb.value);
2603
+ }
2604
+ return strictEqAbs(a, b);
2605
+ }
1897
2606
 
1898
2607
  // src/algebra/containers.ts
1899
2608
  var TUPLE_LITERAL_CAP = 8;
@@ -2102,6 +2811,15 @@ function ok() {
2102
2811
  function fail(reason) {
2103
2812
  return { ok: false, reason };
2104
2813
  }
2814
+ function requiredFnArity(params) {
2815
+ if (!params) return 0;
2816
+ let n = 0;
2817
+ for (const p of params) {
2818
+ if (!p || p.startsWith("...") || p.endsWith("?")) continue;
2819
+ n++;
2820
+ }
2821
+ return n;
2822
+ }
2105
2823
  function leqAbs(src, tgt, opts = {}) {
2106
2824
  const phi2 = opts.phi ?? pTrue;
2107
2825
  return leqWithPred(src, tgt, phi2, opts.env ?? null, 0);
@@ -2115,6 +2833,13 @@ function leqWithPred(src, tgt, phi2, env, depth) {
2115
2833
  const tv = litValue(tgt);
2116
2834
  if (sv !== void 0 && tv !== void 0) {
2117
2835
  if (sv === tv) return ok();
2836
+ if (tgt.shape.k === "prim") {
2837
+ return fail(`lit ${String(sv)} \u22AD lit ${String(tv)}`);
2838
+ }
2839
+ } else if (tv !== void 0 && sv === void 0) {
2840
+ if (tgt.shape.k === "prim") {
2841
+ return fail(`non-lit prim \u22AD lit ${String(tv)}`);
2842
+ }
2118
2843
  }
2119
2844
  const shapeR = leqShape(src, tgt, phi2, env, depth);
2120
2845
  if (!shapeR.ok) return shapeR;
@@ -2215,6 +2940,11 @@ function leqShape(src, tgt, phi2, env, depth) {
2215
2940
  if (srcSlot.optional && !slot.optional) {
2216
2941
  return fail(`slot ${key}: optional \u22AD required`);
2217
2942
  }
2943
+ const ssv = litValue(srcSlot.value);
2944
+ const stv = litValue(slot.value);
2945
+ if (ssv !== void 0 && stv !== void 0 && primOf(srcSlot.value) !== void 0 && primOf(srcSlot.value) === primOf(slot.value)) {
2946
+ continue;
2947
+ }
2218
2948
  const r = leqWithPred(srcSlot.value, slot.value, phi2, env, depth + 1);
2219
2949
  if (!r.ok) return fail(`slot ${key}: ${r.reason}`);
2220
2950
  }
@@ -2242,8 +2972,12 @@ function leqShape(src, tgt, phi2, env, depth) {
2242
2972
  }
2243
2973
  if (t.k === "fn") {
2244
2974
  if (s.k !== "fn") return fail(`shape ${s.k} \u22AD fn`);
2245
- if (s.params.length !== t.params.length) {
2246
- return fail(`fn arity ${s.params.length} \u22AD ${t.params.length}`);
2975
+ const sReq = requiredFnArity(s.params);
2976
+ const tReq = requiredFnArity(t.params);
2977
+ if (sReq > tReq) {
2978
+ return fail(
2979
+ `fn arity required ${sReq} \u22AD target required ${tReq} (params ${s.params.length} / ${t.params.length})`
2980
+ );
2247
2981
  }
2248
2982
  if (t.returnType !== void 0) {
2249
2983
  const sr = s.returnType;
@@ -2481,6 +3215,10 @@ function evalArrayStatic(name, args) {
2481
3215
  return abs({ k: "arr", element: a0 ?? unknown }, void 0, void 0, "path");
2482
3216
  case "from": {
2483
3217
  if (!a0) return unknown;
3218
+ if (isSetAbs(a0) || isMapAbs(a0)) {
3219
+ const el = collectionElementJoin(a0);
3220
+ return abs({ k: "arr", element: el }, void 0, void 0, "path");
3221
+ }
2484
3222
  const k = a0.shape.k;
2485
3223
  if (k === "arr") return a0;
2486
3224
  if (k === "tuple") {
@@ -2599,6 +3337,35 @@ function evalNamespaceCall(ns, method, args) {
2599
3337
  return void 0;
2600
3338
  }
2601
3339
  }
3340
+ var ERROR_CTOR_NAMES = /* @__PURE__ */ new Set([
3341
+ "Error",
3342
+ "TypeError",
3343
+ "RangeError",
3344
+ "SyntaxError",
3345
+ "ReferenceError",
3346
+ "URIError",
3347
+ "EvalError",
3348
+ "AggregateError"
3349
+ ]);
3350
+ function isErrorCtorName(name) {
3351
+ return !!name && ERROR_CTOR_NAMES.has(name);
3352
+ }
3353
+ function errorBrandAbs(name, messageArg) {
3354
+ const message = messageArg ?? strPrim();
3355
+ return abs(
3356
+ {
3357
+ k: "brand",
3358
+ name,
3359
+ shape: objOf({
3360
+ name: { value: strLit(name) },
3361
+ message: { value: message }
3362
+ })
3363
+ },
3364
+ void 0,
3365
+ void 0,
3366
+ "path"
3367
+ );
3368
+ }
2602
3369
  function evalBuiltinNew(className, args) {
2603
3370
  switch (className) {
2604
3371
  case "Date":
@@ -2608,20 +3375,13 @@ function evalBuiltinNew(className, args) {
2608
3375
  case "Promise":
2609
3376
  return evalPromiseCtor(args);
2610
3377
  case "Map":
2611
- return abs(
2612
- { k: "brand", name: "Map", shape: abs({ k: "obj", slots: {} }, void 0, void 0, "exact") },
2613
- void 0,
2614
- void 0,
2615
- "path"
2616
- );
3378
+ return makeMapAbs(args[0]);
2617
3379
  case "Set":
2618
- return abs(
2619
- { k: "brand", name: "Set", shape: abs({ k: "obj", slots: {} }, void 0, void 0, "exact") },
2620
- void 0,
2621
- void 0,
2622
- "path"
2623
- );
3380
+ return makeSetAbs(args[0]);
2624
3381
  default:
3382
+ if (isErrorCtorName(className)) {
3383
+ return errorBrandAbs(className, args[0]);
3384
+ }
2625
3385
  return void 0;
2626
3386
  }
2627
3387
  }
@@ -2631,13 +3391,17 @@ function evalBuiltinInstanceMethod(brandName, method, recv, args) {
2631
3391
  if (brandName === "Map") {
2632
3392
  switch (method) {
2633
3393
  case "get":
2634
- return unknown;
3394
+ return mapGetEntry(recv, args[0]);
2635
3395
  case "has":
2636
- return boolPrim();
3396
+ return mapHasEntry(recv, args[0]);
2637
3397
  case "set":
2638
- return recv;
3398
+ return mapSetEntry(recv, args[0], args[1] ?? unknown);
3399
+ case "delete":
3400
+ return mapDeleteEntry(recv, args[0]);
3401
+ case "clear":
3402
+ return mapClearEntries(recv);
2639
3403
  case "size":
2640
- return numPrim("path");
3404
+ return mapSizeAbs(recv);
2641
3405
  default:
2642
3406
  return void 0;
2643
3407
  }
@@ -2645,11 +3409,15 @@ function evalBuiltinInstanceMethod(brandName, method, recv, args) {
2645
3409
  if (brandName === "Set") {
2646
3410
  switch (method) {
2647
3411
  case "has":
2648
- return boolPrim();
3412
+ return setHasEntry(recv, args[0]);
2649
3413
  case "add":
2650
- return recv;
3414
+ return setAddEntry(recv, args[0] ?? unknown);
3415
+ case "delete":
3416
+ return setDeleteEntry(recv, args[0]);
3417
+ case "clear":
3418
+ return setClearEntries(recv);
2651
3419
  case "size":
2652
- return numPrim("path");
3420
+ return setSizeAbs(recv);
2653
3421
  default:
2654
3422
  return void 0;
2655
3423
  }
@@ -2663,11 +3431,15 @@ __export(calls_exports, {
2663
3431
  $callNamed: () => $callNamed,
2664
3432
  getAbsOrigin: () => getAbsOrigin,
2665
3433
  getBCallCollector: () => getBCallCollector,
3434
+ isEvalMissingSlotEnabled: () => isEvalMissingSlotEnabled,
2666
3435
  noteMemberDispatchMiss: () => noteMemberDispatchMiss,
3436
+ noteObjSlotMissing: () => noteObjSlotMissing,
2667
3437
  notePrimMemberMissing: () => notePrimMemberMissing,
2668
3438
  noteUnknownMemberMissing: () => noteUnknownMemberMissing,
2669
3439
  recordMemberDiag: () => recordMemberDiag,
3440
+ runWithEvalMissingSlot: () => runWithEvalMissingSlot,
2670
3441
  setBCallCollector: () => setBCallCollector,
3442
+ setEvalMissingSlotEnabled: () => setEvalMissingSlotEnabled,
2671
3443
  setMemberDiagCollector: () => setMemberDiagCollector,
2672
3444
  tagAbsOrigin: () => tagAbsOrigin
2673
3445
  });
@@ -3120,7 +3892,12 @@ function isRelFn(a) {
3120
3892
  if (!s || s.k !== "fn") return false;
3121
3893
  if (s.returnType === void 0) return false;
3122
3894
  if (s.paramTypes === void 0) return s.params.length === 0;
3123
- return s.paramTypes.length === s.params.length;
3895
+ if (s.paramTypes.length === s.params.length) return true;
3896
+ let required = 0;
3897
+ for (const p of s.params) {
3898
+ if (p && !p.startsWith("...") && !p.endsWith("?")) required++;
3899
+ }
3900
+ return s.paramTypes.length === required;
3124
3901
  }
3125
3902
  function litOfTerm(t) {
3126
3903
  return t.op === "lit" ? t.value : void 0;
@@ -3394,6 +4171,19 @@ function setApplyCallbackHost(fn) {
3394
4171
  applyCallbackHost = fn;
3395
4172
  }
3396
4173
  function applyCallbackAbs(cb, args, env, phi2, budget) {
4174
+ const sumIdx = args.findIndex(
4175
+ (a) => a && typeof a === "object" && "shape" in a && a.shape.k === "sum"
4176
+ );
4177
+ if (sumIdx >= 0) {
4178
+ const members = args[sumIdx].shape.members;
4179
+ let acc;
4180
+ for (const m of members) {
4181
+ const nextArgs = args.map((a, i) => i === sumIdx ? m : a);
4182
+ const r = applyCallbackAbs(cb, nextArgs, env, phi2, budget);
4183
+ acc = acc === void 0 ? r : joinAbs(acc, r);
4184
+ }
4185
+ return acc ?? unknown;
4186
+ }
3397
4187
  if (!applyCallbackHost) {
3398
4188
  if (cb && typeof cb === "object" && "shape" in cb) {
3399
4189
  const a = cb;
@@ -3405,7 +4195,7 @@ function applyCallbackAbs(cb, args, env, phi2, budget) {
3405
4195
  }
3406
4196
  return applyCallbackHost(cb, args, env, phi2, budget);
3407
4197
  }
3408
- function undefAbs() {
4198
+ function undefAbs2() {
3409
4199
  return abs(
3410
4200
  { k: "unknown" },
3411
4201
  { op: "lit", value: void 0 },
@@ -3585,6 +4375,7 @@ function getAbsProperty(recv, name) {
3585
4375
  }
3586
4376
 
3587
4377
  // src/algebra/exec/member-diag.ts
4378
+ import { AsyncLocalStorage } from "async_hooks";
3588
4379
  var memberDiagCollector = null;
3589
4380
  var callLocStack = [];
3590
4381
  var absOrigins = /* @__PURE__ */ new WeakMap();
@@ -3684,7 +4475,41 @@ function noteUnknownMemberMissing(recv, name, kind, loc) {
3684
4475
  }
3685
4476
  function noteMemberDispatchMiss(recv, name, kind, loc) {
3686
4477
  if (notePrimMemberMissing(recv, name, kind, loc)) return;
3687
- noteUnknownMemberMissing(recv, name, kind, loc);
4478
+ if (noteUnknownMemberMissing(recv, name, kind, loc)) return;
4479
+ noteObjSlotMissing(recv, name, loc);
4480
+ }
4481
+ var evalMissingSlotAls = new AsyncLocalStorage();
4482
+ var evalMissingSlotFallback = false;
4483
+ function setEvalMissingSlotEnabled(enabled) {
4484
+ evalMissingSlotFallback = enabled;
4485
+ evalMissingSlotAls.enterWith(enabled);
4486
+ }
4487
+ function isEvalMissingSlotEnabled() {
4488
+ return evalMissingSlotAls.getStore() ?? evalMissingSlotFallback;
4489
+ }
4490
+ function runWithEvalMissingSlot(enabled, body) {
4491
+ return evalMissingSlotAls.run(enabled, body);
4492
+ }
4493
+ function noteObjSlotMissing(recv, name, loc) {
4494
+ if (!isEvalMissingSlotEnabled()) return false;
4495
+ const shape = recv?.shape;
4496
+ if (!shape || shape.k !== "obj") return false;
4497
+ const obj2 = shape;
4498
+ if (obj2.open) return false;
4499
+ if (obj2.slots && name in obj2.slots) return false;
4500
+ const conf = recv?.conf;
4501
+ if (conf === "opaque" || conf === "widened") return false;
4502
+ const origin = getAbsOrigin(recv);
4503
+ recordMemberDiag({
4504
+ kind: "property",
4505
+ name,
4506
+ receiver: "object",
4507
+ code: "nudo:missing-slot",
4508
+ line: loc?.[0],
4509
+ column: loc?.[1],
4510
+ ...origin ? { origin } : {}
4511
+ });
4512
+ return true;
3688
4513
  }
3689
4514
 
3690
4515
  // src/algebra/exec/class-registry.ts
@@ -3809,6 +4634,28 @@ function withVar(env, name, value) {
3809
4634
  vars.set(name, value);
3810
4635
  return { vars, fns: env.fns, classes: env.classes, hofCollect: env.hofCollect };
3811
4636
  }
4637
+ function joinEnvs(a, b, base) {
4638
+ const vars = new Map(base.vars);
4639
+ const keys = /* @__PURE__ */ new Set([...a.vars.keys(), ...b.vars.keys()]);
4640
+ for (const k of keys) {
4641
+ const va = a.vars.get(k);
4642
+ const vb = b.vars.get(k);
4643
+ const baseV = base.vars.get(k);
4644
+ if (va !== void 0 && vb !== void 0) {
4645
+ vars.set(k, va === vb ? va : joinAbs(va, vb));
4646
+ } else if (va !== void 0) {
4647
+ vars.set(k, baseV !== void 0 ? joinAbs(baseV, va) : va);
4648
+ } else if (vb !== void 0) {
4649
+ vars.set(k, baseV !== void 0 ? joinAbs(baseV, vb) : vb);
4650
+ }
4651
+ }
4652
+ return {
4653
+ vars,
4654
+ fns: a.fns ?? b.fns,
4655
+ classes: a.classes ?? b.classes,
4656
+ hofCollect: a.hofCollect ?? b.hofCollect
4657
+ };
4658
+ }
3812
4659
  var MAX_CALL_DEPTH = 64;
3813
4660
  var MAX_TOTAL_CALLS = 2e5;
3814
4661
  var _absCallDepth = 0;
@@ -4169,8 +5016,66 @@ function evalNodeInner(node, env, phi2, budget) {
4169
5016
  }
4170
5017
  case "AssignmentExpression": {
4171
5018
  const ae = node;
4172
- if (ae.operator !== "=") return ok2(unknown, phi2, env);
4173
- const rhs = evalNode(ae.right, env, phi2, budget).value;
5019
+ const op = ae.operator;
5020
+ const applyBin = (binOp, lhs, rhsAbs) => {
5021
+ switch (binOp) {
5022
+ case "+":
5023
+ return leakIfNeeded(add(lhs, rhsAbs, phi2), budget, "add");
5024
+ case "-":
5025
+ return leakIfNeeded(sub(lhs, rhsAbs, phi2), budget, "sub");
5026
+ case "*":
5027
+ return leakIfNeeded(mul(lhs, rhsAbs, phi2), budget, "mul");
5028
+ case "/":
5029
+ return leakIfNeeded(div(lhs, rhsAbs, phi2), budget, "div");
5030
+ case "%":
5031
+ return leakIfNeeded(mod(lhs, rhsAbs, phi2), budget, "mod");
5032
+ default:
5033
+ return unknown;
5034
+ }
5035
+ };
5036
+ let rhs;
5037
+ if (op === "=") {
5038
+ rhs = evalNode(ae.right, env, phi2, budget).value;
5039
+ } else if (op === "||=" || op === "&&=" || op === "??=") {
5040
+ const lhs = evalNode(ae.left, env, phi2, budget).value;
5041
+ const lv = litValue(lhs);
5042
+ const nullishLit = isNullishLitAbs(lhs);
5043
+ const definitelyNotNullish = definitelyNotNullishShape(lhs.shape) && !nullishLit;
5044
+ const falsy = lv === false || nullishLit || lv === null || lv === void 0 && lhs.term?.op === "lit" && lhs.term.value === void 0;
5045
+ const truthy = lv !== void 0 && !falsy && !nullishLit;
5046
+ let assignRhs = null;
5047
+ if (op === "||=") {
5048
+ if (truthy) return ok2(lhs, phi2, env);
5049
+ if (falsy || nullishLit) {
5050
+ assignRhs = evalNode(ae.right, env, phi2, budget).value;
5051
+ }
5052
+ } else if (op === "&&=") {
5053
+ if (falsy) return ok2(lhs, phi2, env);
5054
+ if (truthy) {
5055
+ assignRhs = evalNode(ae.right, env, phi2, budget).value;
5056
+ }
5057
+ } else {
5058
+ if (definitelyNotNullish || lv !== void 0 && lv !== null && !nullishLit) {
5059
+ return ok2(lhs, phi2, env);
5060
+ }
5061
+ if (nullishLit || lv === null || lv === void 0 && lhs.term?.op === "lit") {
5062
+ assignRhs = evalNode(ae.right, env, phi2, budget).value;
5063
+ }
5064
+ }
5065
+ if (assignRhs === null) {
5066
+ const r = evalNode(ae.right, env, phi2, budget).value;
5067
+ rhs = joinAbs(lhs, r);
5068
+ } else {
5069
+ rhs = assignRhs;
5070
+ }
5071
+ } else if (op.endsWith("=")) {
5072
+ const binOp = op.slice(0, -1);
5073
+ const lhs = evalNode(ae.left, env, phi2, budget).value;
5074
+ const rhsVal = evalNode(ae.right, env, phi2, budget).value;
5075
+ rhs = applyBin(binOp, lhs, rhsVal);
5076
+ } else {
5077
+ return ok2(unknown, phi2, env);
5078
+ }
4174
5079
  if (ae.left.type === "MemberExpression" && ae.left.object.type === "ThisExpression") {
4175
5080
  const prop = ae.left.property;
4176
5081
  const key = !ae.left.computed && prop.type === "Identifier" ? prop.name : prop.type === "StringLiteral" ? prop.value : void 0;
@@ -4204,6 +5109,25 @@ function evalNodeInner(node, env, phi2, budget) {
4204
5109
  recordAbsAssign(name, prev, rhs, loc);
4205
5110
  return { value: rhs, phi: phi2, env: withVar(env, name, rhs) };
4206
5111
  }
5112
+ if (ae.left.type === "MemberExpression") {
5113
+ const m = ae.left;
5114
+ if (m.object.type === "Identifier") {
5115
+ const root = m.object.name;
5116
+ const prev = env.vars.get(root);
5117
+ const key = !m.computed ? m.property.type === "Identifier" ? m.property.name : m.property.type === "StringLiteral" ? m.property.value : void 0 : void 0;
5118
+ if (prev && key && prev.shape.k === "obj") {
5119
+ const slots = { ...prev.shape.slots };
5120
+ slots[key] = { value: rhs };
5121
+ const updated = abs(
5122
+ { k: "obj", slots },
5123
+ void 0,
5124
+ void 0,
5125
+ prev.conf === "exact" ? "path" : prev.conf
5126
+ );
5127
+ return { value: rhs, phi: phi2, env: withVar(env, root, updated) };
5128
+ }
5129
+ }
5130
+ }
4207
5131
  return ok2(rhs, phi2, env);
4208
5132
  }
4209
5133
  case "AwaitExpression": {
@@ -4233,7 +5157,7 @@ function evalNodeInner(node, env, phi2, budget) {
4233
5157
  if (tv === false) return evalNode(cond.alternate, env, phi2, budget);
4234
5158
  const a = evalNode(cond.consequent, env, phi2, budget);
4235
5159
  const b = evalNode(cond.alternate, env, phi2, budget);
4236
- return { value: joinAbs(a.value, b.value), phi: phi2, env };
5160
+ return { value: joinAbs(a.value, b.value), phi: phi2, env: joinEnvs(a.env, b.env, env) };
4237
5161
  }
4238
5162
  case "ForStatement":
4239
5163
  return evalFor(node, env, phi2, budget);
@@ -4264,6 +5188,8 @@ function evalNodeInner(node, env, phi2, budget) {
4264
5188
  }
4265
5189
  case "IfStatement":
4266
5190
  return evalIf(node, env, phi2, budget);
5191
+ case "SwitchStatement":
5192
+ return evalSwitch(node, env, phi2, budget);
4267
5193
  case "ExpressionStatement":
4268
5194
  return evalNode(node.expression, env, phi2, budget);
4269
5195
  case "VariableDeclaration":
@@ -4285,8 +5211,10 @@ function evalNodeInner(node, env, phi2, budget) {
4285
5211
  const le3 = node;
4286
5212
  const l = evalNode(le3.left, env, phi2, budget);
4287
5213
  const lv = litValue(l.value);
4288
- const falsy = lv === false || lv === null || lv === void 0;
4289
- const truthy = lv !== void 0 && !falsy;
5214
+ const nullishLit = isNullishLitAbs(l.value);
5215
+ const definitelyNotNullish = definitelyNotNullishShape(l.value.shape) && !nullishLit;
5216
+ const falsy = lv === false || nullishLit || lv === void 0 && l.value.term?.op === "lit" && l.value.term.value === void 0 || lv === null;
5217
+ const truthy = lv !== void 0 && !falsy && !nullishLit;
4290
5218
  if (le3.operator === "&&") {
4291
5219
  if (falsy) return ok2(l.value, phi2, env);
4292
5220
  if (truthy) return evalNode(le3.right, env, phi2, budget);
@@ -4299,6 +5227,14 @@ function evalNodeInner(node, env, phi2, budget) {
4299
5227
  const r = evalNode(le3.right, env, phi2, budget);
4300
5228
  return ok2(joinAbs(l.value, r.value), phi2, env);
4301
5229
  }
5230
+ if (le3.operator === "??") {
5231
+ if (nullishLit || lv === null) return evalNode(le3.right, env, phi2, budget);
5232
+ if (definitelyNotNullish || lv !== void 0 && lv !== null) {
5233
+ return ok2(l.value, phi2, env);
5234
+ }
5235
+ const r = evalNode(le3.right, env, phi2, budget);
5236
+ return ok2(joinAbs(l.value, r.value), phi2, env);
5237
+ }
4302
5238
  return ok2(unknown, phi2, env);
4303
5239
  }
4304
5240
  case "TemplateLiteral": {
@@ -4388,12 +5324,39 @@ function evalNodeInner(node, env, phi2, budget) {
4388
5324
  acc = spread(acc, sp);
4389
5325
  continue;
4390
5326
  }
4391
- const keyNode = p.key;
5327
+ if (p.type === "ObjectMethod") {
5328
+ const om = p;
5329
+ const keyNode2 = om.key;
5330
+ let key2;
5331
+ if (keyNode2 && keyNode2.type === "Identifier") key2 = keyNode2.name;
5332
+ if (keyNode2 && keyNode2.type === "StringLiteral") key2 = keyNode2.value;
5333
+ if (!key2 || !om.body) continue;
5334
+ const paramNames = (om.params ?? []).map(
5335
+ (pp, i) => pp.type === "Identifier" ? pp.name : `_a${i}`
5336
+ );
5337
+ const methodBody = om.body;
5338
+ const fnAbs = absFunction(paramNames, {
5339
+ body: methodBody,
5340
+ apply: (args) => {
5341
+ let e2 = env;
5342
+ for (let i = 0; i < paramNames.length; i++) {
5343
+ e2 = withVar(e2, paramNames[i], args[i] ?? unknown);
5344
+ }
5345
+ const r = evalNode(methodBody, e2, phi2, budget);
5346
+ return r.value;
5347
+ }
5348
+ });
5349
+ pending[key2] = { value: fnAbs };
5350
+ continue;
5351
+ }
5352
+ if (p.type !== "ObjectProperty") continue;
5353
+ const op = p;
5354
+ const keyNode = op.key;
4392
5355
  let key;
4393
5356
  if (keyNode && keyNode.type === "Identifier") key = keyNode.name;
4394
5357
  if (keyNode && keyNode.type === "StringLiteral") key = keyNode.value;
4395
- if (!key || !p.value) continue;
4396
- pending[key] = { value: evalNode(p.value, env, phi2, budget).value };
5358
+ if (!key || !op.value) continue;
5359
+ pending[key] = { value: evalNode(op.value, env, phi2, budget).value };
4397
5360
  }
4398
5361
  acc = flushPending(acc);
4399
5362
  return ok2(acc, phi2, env);
@@ -4446,6 +5409,16 @@ function evalBinary(node, env, phi2, budget) {
4446
5409
  if (eq2 !== void 0) return ok2(boolLit(!eq2), phi2, env);
4447
5410
  return ok2(cmp("ne", l, r, phi2), phi2, env);
4448
5411
  }
5412
+ case "==": {
5413
+ const eq2 = looseEqAbs(l, r);
5414
+ if (eq2 !== void 0) return ok2(boolLit(eq2), phi2, env);
5415
+ return ok2(unknown, phi2, env);
5416
+ }
5417
+ case "!=": {
5418
+ const eq2 = looseEqAbs(l, r);
5419
+ if (eq2 !== void 0) return ok2(boolLit(!eq2), phi2, env);
5420
+ return ok2(unknown, phi2, env);
5421
+ }
4449
5422
  case "/":
4450
5423
  return ok2(leakIfNeeded(div(l, r, phi2), budget, "div"), phi2, env);
4451
5424
  case "%":
@@ -4737,7 +5710,7 @@ function evalCall(node, env, phi2, budget) {
4737
5710
  } else if (obj2.shape.k === "arr") {
4738
5711
  applyUnaryCallback(fnNode, obj2.shape.element, env, phi2, budget);
4739
5712
  }
4740
- return ok2(undefAbs(), phi2, env);
5713
+ return ok2(undefAbs2(), phi2, env);
4741
5714
  }
4742
5715
  if ((method === "some" || method === "every") && rawArgs.length >= 1) {
4743
5716
  const fnNode = rawArgs[0];
@@ -4754,7 +5727,7 @@ function evalCall(node, env, phi2, budget) {
4754
5727
  const fnNode = rawArgs[0];
4755
5728
  const elem = obj2.shape.k === "arr" ? obj2.shape.element : obj2.shape.k === "tuple" ? obj2.shape.elements[0] ?? unknown : unknown;
4756
5729
  applyUnaryCallback(fnNode, elem, env, phi2, budget);
4757
- return ok2(joinAbs(elem, undefAbs()), phi2, env);
5730
+ return ok2(joinAbs(elem, undefAbs2()), phi2, env);
4758
5731
  }
4759
5732
  {
4760
5733
  const loc = node.loc ? [node.loc.start.line, node.loc.start.column] : void 0;
@@ -4819,7 +5792,16 @@ function applyAbsFn(fnVal, args, env, phi2, budget) {
4819
5792
  const label = fnVal.shape.name ?? "anonymous";
4820
5793
  if (!enterCall(key, label)) return truncatedAbs();
4821
5794
  try {
4822
- if (impl.apply) return impl.apply(args);
5795
+ if (impl.apply) {
5796
+ try {
5797
+ return impl.apply(args);
5798
+ } catch (e) {
5799
+ if (e && typeof e === "object" && e.name === "NudoReturn") {
5800
+ return e.absValue;
5801
+ }
5802
+ throw e;
5803
+ }
5804
+ }
4823
5805
  const base = impl.env ?? env;
4824
5806
  let local = { vars: new Map(base.vars), fns: base.fns, hofCollect: env.hofCollect };
4825
5807
  if (base.classes) {
@@ -4939,18 +5921,29 @@ function evalFor(node, env, phi2, budget) {
4939
5921
  const r = evalNode(node.init, local, phi2, budget);
4940
5922
  local = r.env;
4941
5923
  }
5924
+ const entry = local;
4942
5925
  let acc = unknown;
5926
+ let exitEnv;
5927
+ let sawAbstractTest = false;
4943
5928
  for (let i = 0; i < MAX_LOOP_ITERS; i++) {
4944
5929
  if (node.test) {
4945
5930
  const t = evalNode(node.test, local, phi2, budget);
4946
5931
  const lv = litValue(t.value);
4947
- if (lv === false || lv === null || lv === void 0) break;
5932
+ if (lv === false || lv === null || lv === void 0) {
5933
+ exitEnv = exitEnv ? joinEnvs(exitEnv, local, entry) : local;
5934
+ break;
5935
+ }
5936
+ if (lv !== true) {
5937
+ sawAbstractTest = true;
5938
+ exitEnv = exitEnv ? joinEnvs(exitEnv, local, entry) : local;
5939
+ }
4948
5940
  }
4949
5941
  const bodyR = evalInConditionalFlow(() => evalNode(node.body, local, phi2, budget));
4950
5942
  if (bodyR.returned) return bodyR;
4951
5943
  if (bodyR.threw) return bodyR;
4952
5944
  if (bodyR.brk) {
4953
5945
  local = bodyR.env;
5946
+ exitEnv = exitEnv ? joinEnvs(exitEnv, local, entry) : local;
4954
5947
  break;
4955
5948
  }
4956
5949
  local = bodyR.env;
@@ -4960,25 +5953,42 @@ function evalFor(node, env, phi2, budget) {
4960
5953
  local = u.env;
4961
5954
  }
4962
5955
  }
4963
- return ok2(acc, phi2, local);
5956
+ if (sawAbstractTest) {
5957
+ exitEnv = exitEnv ? joinEnvs(exitEnv, local, entry) : local;
5958
+ }
5959
+ return ok2(acc, phi2, exitEnv ?? local);
4964
5960
  }
4965
5961
  function evalWhile(node, env, phi2, budget) {
4966
5962
  let local = env;
5963
+ const entry = local;
4967
5964
  let acc = unknown;
5965
+ let exitEnv;
5966
+ let sawAbstractTest = false;
4968
5967
  for (let i = 0; i < MAX_LOOP_ITERS; i++) {
4969
5968
  const t = evalNode(node.test, local, phi2, budget);
4970
5969
  const lv = litValue(t.value);
4971
- if (lv === false || lv === null || lv === void 0) break;
5970
+ if (lv === false || lv === null || lv === void 0) {
5971
+ exitEnv = exitEnv ? joinEnvs(exitEnv, local, entry) : local;
5972
+ break;
5973
+ }
5974
+ if (lv !== true) {
5975
+ sawAbstractTest = true;
5976
+ exitEnv = exitEnv ? joinEnvs(exitEnv, local, entry) : local;
5977
+ }
4972
5978
  const bodyR = evalInConditionalFlow(() => evalNode(node.body, local, phi2, budget));
4973
5979
  if (bodyR.returned || bodyR.threw) return bodyR;
4974
5980
  if (bodyR.brk) {
4975
5981
  local = bodyR.env;
5982
+ exitEnv = exitEnv ? joinEnvs(exitEnv, local, entry) : local;
4976
5983
  break;
4977
5984
  }
4978
5985
  local = bodyR.env;
4979
5986
  acc = joinAbs(acc, bodyR.value);
4980
5987
  }
4981
- return ok2(acc, phi2, local);
5988
+ if (sawAbstractTest) {
5989
+ exitEnv = exitEnv ? joinEnvs(exitEnv, local, entry) : local;
5990
+ }
5991
+ return ok2(acc, phi2, exitEnv ?? local);
4982
5992
  }
4983
5993
  function evalDoWhile(node, env, phi2, budget) {
4984
5994
  let local = env;
@@ -5009,13 +6019,50 @@ function evalForOf(node, env, phi2, budget) {
5009
6019
  );
5010
6020
  if (promoted) iterVal = promoted;
5011
6021
  }
5012
- const elements = iterVal.shape.k === "arr" ? [iterVal.shape.element] : iterVal.shape.k === "tuple" ? iterVal.shape.elements : iterVal.shape.k === "sum" ? iterVal.shape.members.flatMap(
5013
- (m) => m.shape.k === "arr" ? [m.shape.element] : m.shape.k === "tuple" ? m.shape.elements : []
5014
- ) : [unknown];
5015
- if (elements.length === 0) elements.push(unknown);
6022
+ const shape = iterVal.shape;
6023
+ const isTuple = shape.k === "tuple";
6024
+ const isArr = shape.k === "arr";
6025
+ let elements = [];
6026
+ if (isArr) {
6027
+ elements = [shape.element];
6028
+ } else if (isTuple) {
6029
+ elements = [...shape.elements];
6030
+ } else if (shape.k === "sum") {
6031
+ elements = shape.members.flatMap(
6032
+ (m) => m.shape.k === "arr" ? [m.shape.element] : m.shape.k === "tuple" ? [...m.shape.elements] : []
6033
+ );
6034
+ } else {
6035
+ elements = [unknown];
6036
+ }
5016
6037
  const left = node.left;
5017
6038
  const bindName = left.type === "Identifier" ? left.name : left.type === "VariableDeclaration" ? left.declarations[0]?.id?.name : void 0;
5018
6039
  if (!bindName) return ok2(unknown, phi2, env);
6040
+ if (isTuple && elements.length === 0) {
6041
+ return ok2(unknown, phi2, env);
6042
+ }
6043
+ const unbounded = !isTuple;
6044
+ if (unbounded) {
6045
+ let cur = env;
6046
+ let joinedEnv = env;
6047
+ let joinedVal = unknown;
6048
+ const el = elements.length > 0 ? elements[0] : unknown;
6049
+ const n2 = elements.length > 0 || isArr || shape.k === "sum" ? MAX_LOOP_ITERS : 0;
6050
+ for (let i = 0; i < n2; i++) {
6051
+ cur = withVar(cur, bindName, el);
6052
+ const bodyR = evalInConditionalFlow(() => evalNode(node.body, cur, phi2, budget));
6053
+ if (bodyR.returned || bodyR.threw) return bodyR;
6054
+ if (bodyR.brk) {
6055
+ cur = bodyR.env;
6056
+ joinedEnv = joinEnvs(joinedEnv, cur, env);
6057
+ break;
6058
+ }
6059
+ cur = bodyR.env;
6060
+ joinedEnv = joinEnvs(joinedEnv, cur, env);
6061
+ joinedVal = joinAbs(joinedVal, bodyR.value);
6062
+ }
6063
+ joinedEnv = joinEnvs(joinedEnv, cur, env);
6064
+ return ok2(joinedVal, phi2, joinedEnv);
6065
+ }
5019
6066
  let local = env;
5020
6067
  let acc = unknown;
5021
6068
  const n = Math.min(elements.length, MAX_LOOP_ITERS);
@@ -5053,6 +6100,20 @@ function evalTry(node, env, phi2, budget) {
5053
6100
  if (node.finalizer) evalNode(node.finalizer, local, curPhi, budget);
5054
6101
  return { value: catchR.value, phi: curPhi, env: local, threw: true };
5055
6102
  }
6103
+ } else if (tryR.partialThrow && node.handler) {
6104
+ const param = node.handler.param && node.handler.param.type === "Identifier" ? node.handler.param.name : void 0;
6105
+ let catchEnv = env;
6106
+ if (param) catchEnv = withVar(env, param, tryR.throwValue ?? tryR.value);
6107
+ const catchR = evalNode(node.handler.body, catchEnv, phi2, budget);
6108
+ value = joinAbs(tryR.value, catchR.value);
6109
+ local = joinEnvs(tryR.env, catchR.env, env);
6110
+ curPhi = catchR.phi;
6111
+ if (catchR.returned && tryR.returned) {
6112
+ return { value, phi: curPhi, env: local, returned: true };
6113
+ }
6114
+ if (catchR.threw && tryR.threw) {
6115
+ return { value, phi: curPhi, env: local, threw: true };
6116
+ }
5056
6117
  } else if (tryR.returned) {
5057
6118
  if (node.finalizer) evalNode(node.finalizer, local, curPhi, budget);
5058
6119
  return tryR;
@@ -5065,7 +6126,13 @@ function evalTry(node, env, phi2, budget) {
5065
6126
  if (fR.returned || fR.threw) return fR;
5066
6127
  local = fR.env;
5067
6128
  }
5068
- return { value, phi: curPhi, env: local, returned: tryR.returned };
6129
+ return {
6130
+ value,
6131
+ phi: curPhi,
6132
+ env: local,
6133
+ returned: tryR.returned,
6134
+ ...tryR.partialReturn || tryR.partialThrow ? { partialReturn: tryR.partialReturn } : {}
6135
+ };
5069
6136
  }
5070
6137
  function evalVarDecl(node, env, phi2, budget) {
5071
6138
  let local = env;
@@ -5105,12 +6172,157 @@ function evalIf(node, env, phi2, budget) {
5105
6172
  const b = evalInConditionalFlow(
5106
6173
  () => evalNode(alt, env, fCons ? and(phi2, fCons) : phi2, budget)
5107
6174
  );
5108
- return { value: joinAbs(a.value, b.value), phi: phi2, env, returned: a.returned || b.returned };
6175
+ const bothRet = !!a.returned && !!b.returned;
6176
+ const eitherRet = !!a.returned || !!b.returned;
6177
+ const contEnv = a.returned && !b.returned ? b.env : b.returned && !a.returned ? a.env : a.threw && !b.threw ? b.env : b.threw && !a.threw ? a.env : joinEnvs(a.env, b.env, env);
6178
+ return {
6179
+ value: joinAbs(a.value, b.value),
6180
+ phi: phi2,
6181
+ env: contEnv,
6182
+ ...bothRet ? { returned: true } : eitherRet ? { partialReturn: true } : {},
6183
+ ...a.threw && b.threw ? { threw: true, throwValue: joinAbs(a.value, b.value) } : {},
6184
+ ...(a.threw || b.threw) && !(a.threw && b.threw) ? { partialThrow: true, throwValue: a.threw ? a.value : b.value } : {}
6185
+ };
5109
6186
  }
5110
- if (a.returned || a.threw) {
6187
+ if (a.returned && a.threw) {
5111
6188
  return { value: a.value, phi: phi2, env, partialReturn: true };
5112
6189
  }
5113
- return { value: unknown, phi: phi2, env };
6190
+ if (a.returned || a.threw) {
6191
+ return {
6192
+ value: a.value,
6193
+ phi: phi2,
6194
+ env,
6195
+ ...a.returned ? { partialReturn: true } : {},
6196
+ ...a.threw ? { partialThrow: true, throwValue: a.value } : {}
6197
+ };
6198
+ }
6199
+ return { value: unknown, phi: phi2, env: joinEnvs(a.env, env, env) };
6200
+ }
6201
+ function evalSwitch(node, env, phi2, budget) {
6202
+ const stmtCompletes = (s) => {
6203
+ if (!s) return false;
6204
+ switch (s.type) {
6205
+ case "BreakStatement":
6206
+ case "ReturnStatement":
6207
+ case "ThrowStatement":
6208
+ case "ContinueStatement":
6209
+ return true;
6210
+ case "BlockStatement":
6211
+ return stmtCompletes(s.body[s.body.length - 1]);
6212
+ case "IfStatement": {
6213
+ const ifs = s;
6214
+ return ifs.alternate != null && stmtCompletes(ifs.consequent) && stmtCompletes(ifs.alternate);
6215
+ }
6216
+ default:
6217
+ return false;
6218
+ }
6219
+ };
6220
+ const pre = [];
6221
+ let pending = [];
6222
+ for (const c of node.cases) {
6223
+ if (c.test == null) {
6224
+ if (pending.length > 0 && c.consequent.length > 0) {
6225
+ pre.push({ tests: pending, body: [...c.consequent], isDefault: false });
6226
+ pending = [];
6227
+ }
6228
+ pre.push({ tests: [], body: [...c.consequent], isDefault: true });
6229
+ continue;
6230
+ }
6231
+ if (c.consequent.length === 0) {
6232
+ pending.push(c.test);
6233
+ continue;
6234
+ }
6235
+ pre.push({ tests: [...pending, c.test], body: [...c.consequent], isDefault: false });
6236
+ pending = [];
6237
+ }
6238
+ if (pending.length > 0) pre.push({ tests: pending, body: [], isDefault: false });
6239
+ const arms = pre.map((a) => ({ ...a, tests: [...a.tests], body: [...a.body] }));
6240
+ for (let i = 0; i < arms.length; i++) {
6241
+ const arm = arms[i];
6242
+ const body = [...arm.body];
6243
+ let j = i + 1;
6244
+ while (j < arms.length && !stmtCompletes(body[body.length - 1])) {
6245
+ body.push(...arms[j].body);
6246
+ if (stmtCompletes(body[body.length - 1])) break;
6247
+ j++;
6248
+ }
6249
+ arm.body = body;
6250
+ }
6251
+ const runBody = (body, e) => {
6252
+ let local = e;
6253
+ let value2 = unknown;
6254
+ for (const s of body) {
6255
+ const r = evalInConditionalFlow(() => evalNode(s, local, phi2, budget));
6256
+ local = r.env;
6257
+ value2 = r.value;
6258
+ if (r.returned || r.threw || r.brk) return { ...r, env: local, value: value2 };
6259
+ }
6260
+ return { value: value2, phi: phi2, env: local };
6261
+ };
6262
+ const disc = evalNode(node.discriminant, env, phi2, budget).value;
6263
+ const dlv = litValue(disc);
6264
+ const hasDefault = arms.some((a) => a.isDefault);
6265
+ const testLit = (t) => {
6266
+ if (t == null) return null;
6267
+ return litValue(evalNode(t, env, phi2, budget).value);
6268
+ };
6269
+ if (dlv !== void 0) {
6270
+ let matched = null;
6271
+ let sawAbstractTest = false;
6272
+ for (const arm of arms) {
6273
+ if (arm.isDefault) continue;
6274
+ let hit = false;
6275
+ for (const t of arm.tests) {
6276
+ const tv = testLit(t);
6277
+ if (tv === null) continue;
6278
+ if (tv === void 0) {
6279
+ sawAbstractTest = true;
6280
+ continue;
6281
+ }
6282
+ if (tv === dlv) {
6283
+ hit = true;
6284
+ break;
6285
+ }
6286
+ }
6287
+ if (hit) {
6288
+ matched = arm;
6289
+ break;
6290
+ }
6291
+ }
6292
+ if (!sawAbstractTest) {
6293
+ if (matched) return runBody(matched.body, env);
6294
+ const dflt = arms.find((a) => a.isDefault);
6295
+ if (dflt) return runBody(dflt.body, env);
6296
+ return ok2(unknown, phi2, env);
6297
+ }
6298
+ }
6299
+ const results = [];
6300
+ if (!hasDefault) results.push(ok2(unknown, phi2, env));
6301
+ for (const arm of arms) {
6302
+ if (arm.body.length === 0 && !arm.isDefault) continue;
6303
+ results.push(runBody(arm.body, env));
6304
+ }
6305
+ if (results.length === 0) return ok2(unknown, phi2, env);
6306
+ let value = results[0].value;
6307
+ let envOut = results[0].env;
6308
+ let allRet = !!results[0].returned;
6309
+ let anyRet = !!results[0].returned;
6310
+ let anyThrew = !!results[0].threw;
6311
+ for (let i = 1; i < results.length; i++) {
6312
+ const r = results[i];
6313
+ value = joinAbs(value, r.value);
6314
+ envOut = joinEnvs(envOut, r.env, env);
6315
+ allRet = allRet && !!r.returned;
6316
+ anyRet = anyRet || !!r.returned;
6317
+ anyThrew = anyThrew || !!r.threw;
6318
+ }
6319
+ return {
6320
+ value,
6321
+ phi: phi2,
6322
+ env: envOut,
6323
+ ...allRet ? { returned: true } : anyRet ? { partialReturn: true } : {},
6324
+ ...anyThrew ? { partialThrow: true } : {}
6325
+ };
5114
6326
  }
5115
6327
  function analyzeFn(source, fnName, args, phi2 = pTrue, budget, file, modules) {
5116
6328
  return evalSource(source, { fn: fnName, args }, { phi: phi2, budget, file, modules }).value;
@@ -5281,7 +6493,7 @@ function $callNamed(name, fn, args, loc, argLocs) {
5281
6493
  try {
5282
6494
  if (typeof fn === "function") {
5283
6495
  const g = GLOBAL_FNS.has(name) && fn === globalThis[name] ? evalGlobalFn(name, args) : void 0;
5284
- result = g ?? fn(...args);
6496
+ result = g ?? callAtFunctionBoundary(() => fn(...args));
5285
6497
  } else if (fn && typeof fn === "object" && "shape" in fn) {
5286
6498
  result = $call(fn, args);
5287
6499
  }
@@ -5352,6 +6564,14 @@ function $ne(a, b) {
5352
6564
  const r = strictEqAbs(a, b);
5353
6565
  return r === void 0 ? bool() : boolLit(!r);
5354
6566
  }
6567
+ function $eqLoose(a, b) {
6568
+ const r = looseEqAbs(a, b);
6569
+ return r === void 0 ? bool() : boolLit(r);
6570
+ }
6571
+ function $neLoose(a, b) {
6572
+ const r = looseEqAbs(a, b);
6573
+ return r === void 0 ? bool() : boolLit(!r);
6574
+ }
5355
6575
  function $lt(a, b) {
5356
6576
  return cmp("lt", a, b, phi);
5357
6577
  }
@@ -5375,13 +6595,28 @@ function asAbsVal(v2) {
5375
6595
  const params = Array.from({ length: n }, (_, i) => `arg${i}`);
5376
6596
  return absFunction(params, {
5377
6597
  body: noBody,
5378
- apply: (args) => v2(...args)
6598
+ // 与 $fnVal / $callNamed 同边界:callee 的 NudoReturn 不得冒泡成 caller
6599
+ apply: (args) => callAtFunctionBoundary(() => v2(...args))
5379
6600
  });
5380
6601
  }
5381
6602
  return $lit(v2);
5382
6603
  }
5383
- function $fnVal(params, impl) {
5384
- return absFunction(params, { body: noBody, apply: (args) => impl(...args) });
6604
+ function callAtFunctionBoundary(body) {
6605
+ return runWithLoopExits(() => {
6606
+ try {
6607
+ return body();
6608
+ } catch (e) {
6609
+ if (isNudoReturn(e)) return e.absValue;
6610
+ throw e;
6611
+ }
6612
+ });
6613
+ }
6614
+ function $fnVal(params, impl, opts) {
6615
+ return absFunction(params, {
6616
+ body: noBody,
6617
+ apply: (args) => callAtFunctionBoundary(() => impl(...args)),
6618
+ ...opts?.bindThis ? { bindThis: true } : {}
6619
+ });
5385
6620
  }
5386
6621
  function $lit(v2) {
5387
6622
  if (v2 && typeof v2 === "object" && "shape" in v2 && "conf" in v2) {
@@ -5436,12 +6671,163 @@ function isDefinitelyFalse(a) {
5436
6671
  function undef() {
5437
6672
  return abs({ k: "unknown" }, { op: "lit", value: void 0 }, pTrue, "exact");
5438
6673
  }
6674
+ var loopExitsAls = new AsyncLocalStorage2();
6675
+ var throwExitsAls = new AsyncLocalStorage2();
6676
+ var tryMarksAls = new AsyncLocalStorage2();
6677
+ function runWithLoopExits(body) {
6678
+ return loopExitsAls.run(
6679
+ [],
6680
+ () => throwExitsAls.run([], () => tryMarksAls.run([], body))
6681
+ );
6682
+ }
6683
+ function takeLoopExits() {
6684
+ return loopExitsAls.getStore() ?? [];
6685
+ }
6686
+ function takeThrowExits() {
6687
+ return throwExitsAls.getStore() ?? [];
6688
+ }
6689
+ function pushLoopExit(v2) {
6690
+ loopExitsAls.getStore()?.push(v2);
6691
+ }
6692
+ function pushThrowExit(v2) {
6693
+ throwExitsAls.getStore()?.push(v2);
6694
+ }
6695
+ function $pushLoopExit(v2) {
6696
+ pushLoopExit(v2);
6697
+ }
6698
+ function $tryMark() {
6699
+ const store = throwExitsAls.getStore();
6700
+ const m = store?.length ?? 0;
6701
+ tryMarksAls.getStore()?.push(m);
6702
+ return m;
6703
+ }
6704
+ function $tryCurrentMark() {
6705
+ const stack = tryMarksAls.getStore();
6706
+ return stack && stack.length > 0 ? stack[stack.length - 1] : 0;
6707
+ }
6708
+ function $tryPopMark() {
6709
+ tryMarksAls.getStore()?.pop();
6710
+ }
6711
+ function $tryTakeSince(mark) {
6712
+ const store = throwExitsAls.getStore();
6713
+ if (!store) return [];
6714
+ return store.splice(Math.min(mark, store.length));
6715
+ }
6716
+ var yieldStack = [];
6717
+ var genPathSensitive = 0;
6718
+ var genJoinOverride = null;
6719
+ function withIsolatedYields(fn) {
6720
+ const top = yieldStack[yieldStack.length - 1];
6721
+ if (!top) return { v: fn(), ys: null };
6722
+ const armYs = [];
6723
+ yieldStack[yieldStack.length - 1] = armYs;
6724
+ try {
6725
+ return { v: fn(), ys: armYs };
6726
+ } finally {
6727
+ yieldStack[yieldStack.length - 1] = top;
6728
+ }
6729
+ }
6730
+ function mergeArmYields(armYsList) {
6731
+ const top = yieldStack[yieldStack.length - 1];
6732
+ if (!top || armYsList.length === 0) return;
6733
+ const concrete = armYsList.filter((x) => x !== null);
6734
+ if (concrete.length === 0) return;
6735
+ if (concrete.length === 1) {
6736
+ top.push(...concrete[0]);
6737
+ return;
6738
+ }
6739
+ let joined = null;
6740
+ for (const ys of concrete) {
6741
+ joined = joined ? joinAbs(joined, $arr(ys)) : $arr(ys);
6742
+ }
6743
+ genPathSensitive++;
6744
+ if (joined) genJoinOverride = joined;
6745
+ for (const ys of concrete) top.push(...ys);
6746
+ }
6747
+ function runForkArm(arm, exits) {
6748
+ try {
6749
+ return { kind: "val", v: asAbsVal(arm()) };
6750
+ } catch (e) {
6751
+ if (isNudoReturn(e)) {
6752
+ exits?.push(e.absValue);
6753
+ return { kind: "ret", v: e.absValue };
6754
+ }
6755
+ if (isNudoThrow(e)) {
6756
+ pushThrowExit(e.absValue);
6757
+ return { kind: "throw", v: e.absValue };
6758
+ }
6759
+ throw e;
6760
+ }
6761
+ }
6762
+ function settleForkArms(a, b, exits) {
6763
+ const throws = [a, b].filter((r) => r.kind === "throw");
6764
+ const nonThrow = [a, b].filter((r) => r.kind !== "throw");
6765
+ if (nonThrow.length === 0) {
6766
+ throw new NudoThrow(throws.map((t) => t.v).reduce((x, y) => joinAbs(x, y)));
6767
+ }
6768
+ const first = nonThrow[0];
6769
+ const second = nonThrow[1] ?? first;
6770
+ if (first.kind === "ret" && second.kind === "ret") {
6771
+ throw new NudoReturn(joinAbs(first.v, second.v));
6772
+ }
6773
+ if (nonThrow.length === 1) {
6774
+ if (first.kind === "ret") {
6775
+ if (!exits) throw new NudoReturn(first.v);
6776
+ return undef();
6777
+ }
6778
+ return first.v;
6779
+ }
6780
+ if (first.kind === "ret") {
6781
+ if (!exits) throw new NudoReturn(first.v);
6782
+ return second.kind === "val" ? second.v : undef();
6783
+ }
6784
+ if (second.kind === "ret") {
6785
+ if (!exits) throw new NudoReturn(second.v);
6786
+ return first.v;
6787
+ }
6788
+ return joinAbs(first.v, second.v);
6789
+ }
5439
6790
  function $fork(test, consequent, alternate) {
5440
6791
  if (isDefinitelyTrue(test)) return asAbsVal(consequent());
5441
6792
  if (isDefinitelyFalse(test)) return alternate ? asAbsVal(alternate()) : undef();
5442
- const a = asAbsVal(consequent());
5443
- const b = alternate ? asAbsVal(alternate()) : undef();
5444
- return joinAbs(a, b);
6793
+ const exits = loopExitsAls.getStore();
6794
+ beginCollectionFork();
6795
+ const arms = [];
6796
+ const armYsList = [];
6797
+ let a;
6798
+ let b;
6799
+ try {
6800
+ pushCollectionArm();
6801
+ try {
6802
+ const r = withIsolatedYields(() => runForkArm(consequent, exits));
6803
+ a = r.v;
6804
+ armYsList.push(r.ys);
6805
+ } finally {
6806
+ arms.push(popCollectionArm());
6807
+ }
6808
+ if (alternate) {
6809
+ pushCollectionArm();
6810
+ try {
6811
+ const r = withIsolatedYields(() => runForkArm(alternate, exits));
6812
+ b = r.v;
6813
+ armYsList.push(r.ys);
6814
+ } finally {
6815
+ arms.push(popCollectionArm());
6816
+ }
6817
+ } else {
6818
+ pushCollectionArm();
6819
+ try {
6820
+ b = { kind: "val", v: undef() };
6821
+ armYsList.push(null);
6822
+ } finally {
6823
+ arms.push(popCollectionArm());
6824
+ }
6825
+ }
6826
+ } finally {
6827
+ endCollectionFork(arms);
6828
+ if (yieldStack.length > 0) mergeArmYields(armYsList);
6829
+ }
6830
+ return settleForkArms(a, b, exits);
5445
6831
  }
5446
6832
  var DEFAULT_MAX_LOOP_ITERS = 8;
5447
6833
  function* $forIter(init, test, step, body, maxIters = DEFAULT_MAX_LOOP_ITERS) {
@@ -5457,30 +6843,67 @@ function* $forIter(init, test, step, body, maxIters = DEFAULT_MAX_LOOP_ITERS) {
5457
6843
  s = step(afterBody);
5458
6844
  }
5459
6845
  }
5460
- function $for(init, test, step, body, maxIters = DEFAULT_MAX_LOOP_ITERS) {
6846
+ function $for(init, test, step, body, maxIters = DEFAULT_MAX_LOOP_ITERS, opts) {
5461
6847
  let state = init;
5462
6848
  let exitJoin;
6849
+ let extJoin;
6850
+ const pack = opts?.pack;
6851
+ const unpack = opts?.unpack;
6852
+ const snapCounter = () => {
6853
+ exitJoin = exitJoin ? joinAbs(exitJoin, state) : state;
6854
+ };
6855
+ const snapExt = () => {
6856
+ if (!pack) return;
6857
+ const p = pack();
6858
+ extJoin = extJoin ? joinAbs(extJoin, p) : p;
6859
+ };
6860
+ const applyExtJoin = () => {
6861
+ if (!extJoin || !pack || !unpack) return;
6862
+ unpack(joinAbs(extJoin, pack()));
6863
+ };
5463
6864
  for (let i = 0; i < maxIters; i++) {
5464
6865
  const t = test(state);
5465
6866
  if (isDefinitelyFalse(t)) {
5466
- return exitJoin ? joinAbs(exitJoin, state) : state;
6867
+ snapCounter();
6868
+ snapExt();
6869
+ applyExtJoin();
6870
+ return exitJoin ?? state;
5467
6871
  }
5468
- if (!isDefinitelyTrue(t)) {
5469
- exitJoin = exitJoin ? joinAbs(exitJoin, state) : state;
6872
+ const abstractTest = !isDefinitelyTrue(t);
6873
+ if (abstractTest) {
6874
+ snapCounter();
6875
+ snapExt();
6876
+ }
6877
+ let afterBody;
6878
+ try {
6879
+ afterBody = body(state);
6880
+ } catch (e) {
6881
+ if (isNudoReturn(e) || isNudoThrow(e)) throw e;
6882
+ throw e;
5470
6883
  }
5471
- const afterBody = body(state);
5472
6884
  const next = step(afterBody);
6885
+ if (abstractTest) {
6886
+ state = afterBody;
6887
+ snapExt();
6888
+ }
5473
6889
  if (i > 0) {
5474
6890
  const nv = litValue(next);
5475
6891
  const sv = litValue(state);
5476
6892
  const stuck = nv !== void 0 && sv !== void 0 && nv === sv || nv === void 0 && sv === void 0 && leqAbs(next, state).ok;
5477
6893
  if (stuck) {
5478
- return exitJoin ? joinAbs(exitJoin, next) : next;
6894
+ state = next;
6895
+ snapCounter();
6896
+ snapExt();
6897
+ applyExtJoin();
6898
+ return exitJoin ?? next;
5479
6899
  }
5480
6900
  }
5481
6901
  state = next;
5482
6902
  }
5483
- return exitJoin ? joinAbs(exitJoin, state) : state;
6903
+ snapCounter();
6904
+ snapExt();
6905
+ applyExtJoin();
6906
+ return exitJoin ?? state;
5484
6907
  }
5485
6908
  function tupleOrWiden(els, conf) {
5486
6909
  if (shouldWidenArrayLiteral(els.length)) {
@@ -5496,6 +6919,99 @@ function tupleOrWiden(els, conf) {
5496
6919
  function $arr(items) {
5497
6920
  return tupleOrWiden(items.map(asAbsVal), "exact");
5498
6921
  }
6922
+ var ARR_MUTATORS = /* @__PURE__ */ new Set([
6923
+ "push",
6924
+ "unshift",
6925
+ "pop",
6926
+ "shift",
6927
+ "splice",
6928
+ "reverse",
6929
+ "sort"
6930
+ ]);
6931
+ function isArrMutator(name) {
6932
+ return ARR_MUTATORS.has(name);
6933
+ }
6934
+ function $arrMutContainer(arr, method, args) {
6935
+ const shape = arr.shape;
6936
+ if (shape.k !== "tuple" && shape.k !== "arr") return arr;
6937
+ const vals = args.map((a) => asAbsVal(a));
6938
+ const asArrEl = (els) => els.length > 0 ? els.reduce((x, y) => joinAbs(x, y)) : unknown;
6939
+ if (method === "push" || method === "unshift") {
6940
+ if (shape.k === "tuple") {
6941
+ const els = method === "push" ? [...shape.elements, ...vals] : [...vals, ...shape.elements];
6942
+ const conf = vals.reduce(
6943
+ (acc, v2) => confJoin(acc, v2.conf),
6944
+ arr.conf
6945
+ );
6946
+ return abs(
6947
+ { k: "tuple", elements: els },
6948
+ void 0,
6949
+ void 0,
6950
+ conf
6951
+ );
6952
+ }
6953
+ const el = vals.reduce((acc, v2) => joinAbs(acc, v2), shape.element);
6954
+ return abs({ k: "arr", element: el }, void 0, void 0, confJoin(arr.conf, "path"));
6955
+ }
6956
+ if (method === "pop") {
6957
+ if (shape.k === "tuple") {
6958
+ if (shape.elements.length === 0) return arr;
6959
+ return abs(
6960
+ { k: "tuple", elements: shape.elements.slice(0, -1) },
6961
+ void 0,
6962
+ void 0,
6963
+ arr.conf
6964
+ );
6965
+ }
6966
+ return arr;
6967
+ }
6968
+ if (method === "shift") {
6969
+ if (shape.k === "tuple") {
6970
+ if (shape.elements.length === 0) return arr;
6971
+ return abs(
6972
+ { k: "tuple", elements: shape.elements.slice(1) },
6973
+ void 0,
6974
+ void 0,
6975
+ arr.conf
6976
+ );
6977
+ }
6978
+ return arr;
6979
+ }
6980
+ if (method === "splice") {
6981
+ if (shape.k === "tuple") {
6982
+ return abs(
6983
+ { k: "arr", element: asArrEl(shape.elements) },
6984
+ void 0,
6985
+ void 0,
6986
+ confJoin(arr.conf, "path")
6987
+ );
6988
+ }
6989
+ return arr;
6990
+ }
6991
+ if (method === "reverse") {
6992
+ if (shape.k === "tuple") {
6993
+ return abs(
6994
+ { k: "tuple", elements: [...shape.elements].reverse() },
6995
+ void 0,
6996
+ void 0,
6997
+ arr.conf
6998
+ );
6999
+ }
7000
+ return arr;
7001
+ }
7002
+ if (method === "sort") {
7003
+ if (shape.k === "tuple") {
7004
+ return abs(
7005
+ { k: "arr", element: asArrEl(shape.elements) },
7006
+ void 0,
7007
+ void 0,
7008
+ confJoin(arr.conf, "path")
7009
+ );
7010
+ }
7011
+ return arr;
7012
+ }
7013
+ return arr;
7014
+ }
5499
7015
  function $idx(a, i) {
5500
7016
  const iv = litValue(i);
5501
7017
  if (a.shape.k === "tuple") {
@@ -5511,6 +7027,22 @@ function $idx(a, i) {
5511
7027
  if (a.shape.k === "sum") {
5512
7028
  return a.shape.members.map((m) => $idx(m, i)).reduce((x, y) => joinAbs(x, y));
5513
7029
  }
7030
+ if (a.shape.k === "obj" || a.shape.k === "brand" && a.shape.shape.shape.k === "obj") {
7031
+ const objShape = a.shape.k === "obj" ? a.shape : a.shape.shape.shape;
7032
+ const slots = Object.values(objShape.slots).map((s) => s.value);
7033
+ if (slots.length === 0) return objShape.open ? unknown : undef();
7034
+ const joinSlotsWithUndef = () => joinAbs(slots.reduce((x, y) => joinAbs(x, y)), undef());
7035
+ if (typeof iv === "string" || typeof iv === "number" || typeof iv === "boolean") {
7036
+ const slot = objShape.slots[String(iv)];
7037
+ if (slot) return slot.value;
7038
+ if (objShape.open) return unknown;
7039
+ return undef();
7040
+ }
7041
+ if (objShape.open && slots.length > 0) {
7042
+ return joinAbs(slots.reduce((x, y) => joinAbs(x, y)), unknown);
7043
+ }
7044
+ return joinSlotsWithUndef();
7045
+ }
5514
7046
  const sv = litValue(a);
5515
7047
  if (typeof sv === "string") {
5516
7048
  if (typeof iv === "number" && Number.isInteger(iv)) {
@@ -5570,6 +7102,35 @@ function $obj(slots) {
5570
7102
  function $spread(a, b) {
5571
7103
  return spread(asAbsVal(a), asAbsVal(b));
5572
7104
  }
7105
+ function $objRest(o, keys) {
7106
+ o = asAbsVal(o);
7107
+ if (o.shape.k === "sum") {
7108
+ return o.shape.members.map((m) => $objRest(m, keys)).reduce((a, b) => joinAbs(a, b));
7109
+ }
7110
+ if (!isObj(o)) return unknown;
7111
+ const drop = new Set(keys);
7112
+ const slots = {};
7113
+ let openRest = o.shape.open === true;
7114
+ for (const [k, s] of Object.entries(o.shape.slots)) {
7115
+ if (drop.has(k)) continue;
7116
+ slots[k] = s;
7117
+ }
7118
+ if (o.shape.open) openRest = true;
7119
+ const shape = { k: "obj", slots };
7120
+ if (openRest) shape.open = true;
7121
+ return { shape, conf: o.conf === "exact" ? "exact" : confJoin(o.conf, "partial") };
7122
+ }
7123
+ function $arrRest(a, start) {
7124
+ a = asAbsVal(a);
7125
+ if (a.shape.k === "sum") {
7126
+ return a.shape.members.map((m) => $arrRest(m, start)).reduce((x, y) => joinAbs(x, y));
7127
+ }
7128
+ if (a.shape.k === "tuple") {
7129
+ return tupleOrWiden(a.shape.elements.slice(start), a.conf);
7130
+ }
7131
+ if (a.shape.k === "arr") return a;
7132
+ return unknown;
7133
+ }
5573
7134
  function $concat(a, b) {
5574
7135
  a = asAbsVal(a);
5575
7136
  b = asAbsVal(b);
@@ -5604,20 +7165,49 @@ function $concat(a, b) {
5604
7165
  function $elems(a) {
5605
7166
  if (a.shape.k === "tuple") return [...a.shape.elements];
5606
7167
  if (a.shape.k === "arr") return [a.shape.element];
7168
+ if (isSetAbs(a)) return setElementsAbs(a);
7169
+ if (isMapAbs(a)) return mapEntriesAbs(a);
5607
7170
  return [unknown];
5608
7171
  }
5609
- function $forOf(iterable, body, maxIters = DEFAULT_MAX_LOOP_ITERS) {
7172
+ function $forOf(iterable, body, maxIters = DEFAULT_MAX_LOOP_ITERS, opts) {
7173
+ const pack = opts?.pack;
7174
+ const unpack = opts?.unpack;
7175
+ let exitJoin;
7176
+ const snapExit = () => {
7177
+ if (!pack) return;
7178
+ const s = pack();
7179
+ exitJoin = exitJoin ? joinAbs(exitJoin, s) : s;
7180
+ };
7181
+ const applyExitJoin = () => {
7182
+ if (!exitJoin || !pack || !unpack) return;
7183
+ unpack(joinAbs(exitJoin, pack()));
7184
+ };
7185
+ const shape = iterable.shape;
5610
7186
  const items = $elems(iterable);
5611
- const n = Math.min(items.length || maxIters, maxIters);
7187
+ const knownLen = shape.k === "tuple" ? shape.elements.length : collectionExactLen(iterable);
7188
+ const unbounded = knownLen === void 0;
7189
+ if (unbounded) snapExit();
7190
+ const n = knownLen !== void 0 ? Math.min(knownLen, maxIters) : items.length > 0 ? maxIters : 0;
5612
7191
  for (let i = 0; i < n; i++) {
5613
7192
  const item = items.length > 0 ? items[Math.min(i, items.length - 1)] : unknown;
5614
- body(item, abs(
5615
- { k: "prim", type: "number" },
5616
- { op: "lit", value: i },
5617
- pTrue,
5618
- "exact"
5619
- ));
7193
+ try {
7194
+ body(
7195
+ item,
7196
+ abs(
7197
+ { k: "prim", type: "number" },
7198
+ { op: "lit", value: i },
7199
+ pTrue,
7200
+ "exact"
7201
+ )
7202
+ );
7203
+ } catch (e) {
7204
+ if (isNudoReturn(e) || isNudoThrow(e)) throw e;
7205
+ throw e;
7206
+ }
7207
+ if (unbounded) snapExit();
5620
7208
  }
7209
+ if (unbounded && n === 0) snapExit();
7210
+ applyExitJoin();
5621
7211
  }
5622
7212
  function namespaceNameOf(v2) {
5623
7213
  if (typeof v2 !== "object" && typeof v2 !== "function") return void 0;
@@ -5665,11 +7255,19 @@ function $get(o, key, opts) {
5665
7255
  }
5666
7256
  return unknown;
5667
7257
  }
5668
- if (o.shape.k === "brand") return $get(o.shape.shape, key, opts);
7258
+ if (o.shape.k === "brand") {
7259
+ if (key === "size" && o.shape.name === "Map") return mapSizeAbs(o);
7260
+ if (key === "size" && o.shape.name === "Set") return setSizeAbs(o);
7261
+ return $get(o.shape.shape, key, opts);
7262
+ }
5669
7263
  if (isObj(o)) {
5670
7264
  const slot = o.shape.slots[key];
5671
- if (slot) return slot.value;
7265
+ if (slot) {
7266
+ if (slot.optional) return joinAbs(slot.value, undef());
7267
+ return slot.value;
7268
+ }
5672
7269
  if (o.shape.open) return unknown;
7270
+ noteObjSlotMissing(o, key);
5673
7271
  return undef();
5674
7272
  }
5675
7273
  if (o.shape.k === "sum") {
@@ -5678,6 +7276,7 @@ function $get(o, key, opts) {
5678
7276
  }
5679
7277
  if (!opts?.silent) {
5680
7278
  noteUnknownMemberMissing(o, key, "property");
7279
+ noteObjSlotMissing(o, key);
5681
7280
  }
5682
7281
  return unknown;
5683
7282
  }
@@ -5725,12 +7324,52 @@ function $while(init, test, step, maxIters = DEFAULT_MAX_LOOP_ITERS) {
5725
7324
  }
5726
7325
  return exitJoin ? joinAbs(exitJoin, state) : state;
5727
7326
  }
5728
- function $whileSeq(test, body, maxIters = DEFAULT_MAX_LOOP_ITERS) {
7327
+ function $whileSeq(test, body, maxIters = DEFAULT_MAX_LOOP_ITERS, opts) {
7328
+ const pack = opts?.pack;
7329
+ const unpack = opts?.unpack;
7330
+ let exitJoin;
7331
+ const snapExit = () => {
7332
+ if (!pack) return;
7333
+ const s = pack();
7334
+ exitJoin = exitJoin ? joinAbs(exitJoin, s) : s;
7335
+ };
7336
+ const applyExitJoin = () => {
7337
+ if (!exitJoin || !pack || !unpack) return;
7338
+ unpack(joinAbs(exitJoin, pack()));
7339
+ };
5729
7340
  for (let i = 0; i < maxIters; i++) {
5730
7341
  const t = test();
5731
- if (isDefinitelyFalse(t)) return;
5732
- body();
7342
+ if (isDefinitelyFalse(t)) {
7343
+ applyExitJoin();
7344
+ return;
7345
+ }
7346
+ if (!isDefinitelyTrue(t)) snapExit();
7347
+ try {
7348
+ body();
7349
+ } catch (e) {
7350
+ if (isNudoReturn(e) || isNudoThrow(e)) throw e;
7351
+ throw e;
7352
+ }
7353
+ }
7354
+ snapExit();
7355
+ applyExitJoin();
7356
+ }
7357
+ var NudoReturn = class extends Error {
7358
+ absValue;
7359
+ constructor(absValue) {
7360
+ super("nudo:return");
7361
+ this.name = "NudoReturn";
7362
+ this.absValue = absValue;
5733
7363
  }
7364
+ };
7365
+ function $loopReturn(v2) {
7366
+ throw new NudoReturn(v2);
7367
+ }
7368
+ function isNudoReturn(e) {
7369
+ return e instanceof NudoReturn;
7370
+ }
7371
+ function $rethrowIfNudoReturn(e) {
7372
+ if (isNudoReturn(e)) throw e;
5734
7373
  }
5735
7374
  var NudoThrow = class extends Error {
5736
7375
  absValue;
@@ -5746,11 +7385,35 @@ function $throw(v2) {
5746
7385
  function isNudoThrow(e) {
5747
7386
  return e instanceof NudoThrow;
5748
7387
  }
7388
+ function $isForkExit(e) {
7389
+ return isNudoReturn(e) || isNudoThrow(e);
7390
+ }
5749
7391
  function $catchVal(e) {
5750
7392
  if (isNudoThrow(e)) return e.absValue;
5751
7393
  if (e instanceof Error) {
7394
+ const name = e.name || "Error";
7395
+ const msgAbs = typeof e.message === "string" ? abs(
7396
+ { k: "prim", type: "string" },
7397
+ { op: "lit", value: e.message },
7398
+ pTrue,
7399
+ "exact"
7400
+ ) : abs({ k: "prim", type: "string" }, void 0, void 0, "path");
5752
7401
  return abs(
5753
- { k: "brand", name: e.name || "Error", shape: objOf({}) },
7402
+ {
7403
+ k: "brand",
7404
+ name,
7405
+ shape: objOf({
7406
+ name: {
7407
+ value: abs(
7408
+ { k: "prim", type: "string" },
7409
+ { op: "lit", value: name },
7410
+ pTrue,
7411
+ "exact"
7412
+ )
7413
+ },
7414
+ message: { value: msgAbs }
7415
+ })
7416
+ },
5754
7417
  void 0,
5755
7418
  void 0,
5756
7419
  "path"
@@ -5781,16 +7444,28 @@ function $asyncReturn(v2) {
5781
7444
  if (v2.shape.k === "eff") return v2;
5782
7445
  return wrapPromiseAbs(v2);
5783
7446
  }
5784
- var yieldStack = [];
5785
7447
  function $gen(body) {
5786
7448
  const ys = [];
7449
+ const marker = genPathSensitive;
7450
+ const prevOverride = genJoinOverride;
7451
+ genJoinOverride = null;
5787
7452
  yieldStack.push(ys);
5788
7453
  try {
5789
7454
  body();
5790
7455
  } finally {
5791
7456
  yieldStack.pop();
5792
7457
  }
5793
- return $arr(ys);
7458
+ if (genJoinOverride) {
7459
+ const joined = genJoinOverride;
7460
+ genJoinOverride = prevOverride;
7461
+ return { ...joined, conf: joined.conf === "exact" ? "path" : joined.conf };
7462
+ }
7463
+ genJoinOverride = prevOverride;
7464
+ const arr = $arr(ys);
7465
+ if (genPathSensitive > marker) {
7466
+ return { ...arr, conf: arr.conf === "exact" ? "path" : arr.conf };
7467
+ }
7468
+ return arr;
5794
7469
  }
5795
7470
  function $yield(v2) {
5796
7471
  const top = yieldStack[yieldStack.length - 1];
@@ -5806,10 +7481,63 @@ function $switch(disc, cases, dflt) {
5806
7481
  }
5807
7482
  return dflt ? asAbsVal(dflt()) : undef();
5808
7483
  }
5809
- const parts = cases.map((c) => asAbsVal(c.run()));
5810
- if (dflt) parts.push(asAbsVal(dflt()));
5811
- if (parts.length === 0) return undef();
5812
- return parts.reduce((a, b) => joinAbs(a, b));
7484
+ const exits = loopExitsAls.getStore();
7485
+ beginCollectionFork();
7486
+ const armOverlays2 = [];
7487
+ const armYsList = [];
7488
+ const runArm = (fn) => {
7489
+ pushCollectionArm();
7490
+ try {
7491
+ const r = withIsolatedYields(() => runForkArm(fn, exits));
7492
+ armYsList.push(r.ys);
7493
+ return r.v;
7494
+ } finally {
7495
+ armOverlays2.push(popCollectionArm());
7496
+ }
7497
+ };
7498
+ const results = [];
7499
+ try {
7500
+ const seenRuns = /* @__PURE__ */ new Set();
7501
+ for (const c of cases) {
7502
+ if (seenRuns.has(c.run)) continue;
7503
+ seenRuns.add(c.run);
7504
+ results.push(runArm(c.run));
7505
+ }
7506
+ if (dflt) {
7507
+ if (!seenRuns.has(dflt)) results.push(runArm(dflt));
7508
+ } else {
7509
+ pushCollectionArm();
7510
+ try {
7511
+ results.push({ kind: "val", v: undef() });
7512
+ armYsList.push(null);
7513
+ } finally {
7514
+ armOverlays2.push(popCollectionArm());
7515
+ }
7516
+ }
7517
+ } finally {
7518
+ endCollectionFork(armOverlays2);
7519
+ if (yieldStack.length > 0) mergeArmYields(armYsList);
7520
+ }
7521
+ if (results.length === 0) return undef();
7522
+ const throws = results.filter((r) => r.kind === "throw");
7523
+ const nonThrow = results.filter((r) => r.kind !== "throw");
7524
+ if (nonThrow.length === 0) {
7525
+ throw new NudoThrow(throws.map((t) => t.v).reduce((x, y) => joinAbs(x, y)));
7526
+ }
7527
+ const allRet = nonThrow.every((r) => r.kind === "ret");
7528
+ if (allRet) {
7529
+ throw new NudoReturn(nonThrow.map((r) => r.v).reduce((a, b) => joinAbs(a, b)));
7530
+ }
7531
+ const valParts = nonThrow.filter((r) => r.kind === "val").map((r) => r.v);
7532
+ if (valParts.length === 0) return undef();
7533
+ return valParts.reduce((a, b) => joinAbs(a, b));
7534
+ }
7535
+ function $nullishTest(v2) {
7536
+ if (definitelyNotNullishShape(v2.shape)) return boolLit(false);
7537
+ if (isNullishLitAbs(v2)) return boolLit(true);
7538
+ const t = v2.term;
7539
+ if (t?.op === "lit" && t.value !== null && t.value !== void 0) return boolLit(false);
7540
+ return bool();
5813
7541
  }
5814
7542
 
5815
7543
  // src/algebra/exec/transpile.ts
@@ -5824,6 +7552,7 @@ function matchAsOverride(stmt, opts) {
5824
7552
  function normWs(s) {
5825
7553
  return s.replace(/\s+/g, "");
5826
7554
  }
7555
+ var switchBodySeq = 0;
5827
7556
  function matchReplacement(node, opts) {
5828
7557
  if (!opts.source || !opts.replacements?.length) return null;
5829
7558
  if (node.start == null || node.end == null || !node.loc) return null;
@@ -5848,7 +7577,9 @@ var BIN_OPS = {
5848
7577
  ">": "$gt",
5849
7578
  ">=": "$ge",
5850
7579
  "===": "$eq",
5851
- "!==": "$ne"
7580
+ "!==": "$ne",
7581
+ "==": "$eqLoose",
7582
+ "!=": "$neLoose"
5852
7583
  };
5853
7584
  var COMPOUND_OPS = {
5854
7585
  "+=": "$add",
@@ -5921,6 +7652,65 @@ function setPathSrc(p, valSrc) {
5921
7652
  function readPrefix(p, j) {
5922
7653
  return p.layers.slice(0, j + 1).reduce((acc, l) => l.get(acc), p.rootSrc);
5923
7654
  }
7655
+ var ARR_MUTATOR_NAMES = /* @__PURE__ */ new Set([
7656
+ "push",
7657
+ "unshift",
7658
+ "splice",
7659
+ "pop",
7660
+ "shift",
7661
+ "reverse",
7662
+ "sort"
7663
+ ]);
7664
+ function emitArrMutatorRebinds(expr, opts, pad) {
7665
+ const lines = [];
7666
+ if (!expr || typeof expr !== "object") return lines;
7667
+ const visit = (n) => {
7668
+ if (!n || typeof n !== "object") return;
7669
+ const node = n;
7670
+ if (node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression" || node.type === "ObjectMethod" || node.type === "ClassMethod") {
7671
+ return;
7672
+ }
7673
+ if (node.type === "LogicalExpression" || node.type === "ConditionalExpression") {
7674
+ return;
7675
+ }
7676
+ if (node.type === "AssignmentExpression" && (node.operator === "||=" || node.operator === "&&=" || node.operator === "??=")) {
7677
+ visit(node.left);
7678
+ return;
7679
+ }
7680
+ 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)) {
7681
+ const methodName = node.callee.property.name;
7682
+ const argSrcs = (node.arguments ?? []).map(
7683
+ (a) => a.type === "SpreadElement" ? "$lit(undefined)" : isExpression(a) ? transpileExpression(a, opts) : "$lit(undefined)"
7684
+ ).join(", ");
7685
+ const objNode = node.callee.object;
7686
+ if (objNode.type === "Identifier") {
7687
+ const name = objNode.name;
7688
+ lines.push(
7689
+ `${pad}${name} = $arrMutContainer(${name}, ${JSON.stringify(methodName)}, [${argSrcs}]);`
7690
+ );
7691
+ } else if (objNode.type === "MemberExpression" || objNode.type === "ThisExpression") {
7692
+ const path = objNode.type === "MemberExpression" ? memberPathOf(
7693
+ objNode,
7694
+ opts
7695
+ ) : null;
7696
+ if (path) {
7697
+ const recvSrc = readPathSrc(path);
7698
+ const mutSrc = `$arrMutContainer(${recvSrc}, ${JSON.stringify(methodName)}, [${argSrcs}])`;
7699
+ lines.push(`${pad}${path.rootSrc} = ${setPathSrc(path, mutSrc)};`);
7700
+ }
7701
+ }
7702
+ }
7703
+ for (const key of Object.keys(node)) {
7704
+ if (key === "loc" || key === "start" || key === "end" || key === "range") continue;
7705
+ if (key === "callee" || key === "property") continue;
7706
+ const child = node[key];
7707
+ if (Array.isArray(child)) child.forEach(visit);
7708
+ else if (child && typeof child === "object") visit(child);
7709
+ }
7710
+ };
7711
+ visit(expr);
7712
+ return lines;
7713
+ }
5924
7714
  function transpileSource(source, opts = {}) {
5925
7715
  const file = parseSource(source);
5926
7716
  return transpileFile(file, { ...opts, source: opts.source ?? source });
@@ -5929,7 +7719,7 @@ function transpileFile(file, opts = {}) {
5929
7719
  const runtime = opts.runtimeImport ?? "@nudojs/core/exec";
5930
7720
  const lines = [
5931
7721
  `// nudo B-path transpile \u2014 values are Abs; operators are overloaded calls`,
5932
- `import { $add, $sub, $mul, $div, $mod, $neg, $typeof, $not, $eq, $ne, $lt, $le, $gt, $ge, $join, $lit, $fork, $for, $forIter, $obj, $get, $set, $while, $whileSeq, $arr, $idx, $idxSet, $len, $call, $throw, $class, $new, $invoke, $invokeSuper, $super, $async, $await, $asyncReturn, $orDefault, $callNamed, $optionalGet, $optionalInvoke, $spread, $concat, $forOf, $catchVal, $switch, $staticInvoke, $setKey, $gen, $yield, $fnVal, $regex } from ${JSON.stringify(runtime)};`,
7722
+ `import { $add, $sub, $mul, $div, $mod, $neg, $typeof, $not, $eq, $ne, $eqLoose, $neLoose, $lt, $le, $gt, $ge, $join, $lit, $fork, $for, $forIter, $obj, $get, $set, $while, $whileSeq, $arr, $arrMutContainer, $idx, $idxSet, $len, $call, $throw, $loopReturn, $class, $new, $invoke, $invokeSuper, $super, $async, $await, $asyncReturn, $orDefault, $callNamed, $optionalGet, $optionalInvoke, $spread, $concat, $forOf, $catchVal, $switch, $staticInvoke, $setKey, $gen, $yield, $fnVal, $regex, $rethrowIfNudoReturn, $nullishTest, $tryMark, $tryTakeSince, $tryCurrentMark, $tryPopMark, $pushLoopExit, $objRest, $arrRest, $isForkExit } from ${JSON.stringify(runtime)};`,
5933
7723
  ``
5934
7724
  ];
5935
7725
  for (const stmt of file.program.body) {
@@ -5940,12 +7730,226 @@ function transpileFile(file, opts = {}) {
5940
7730
  function indent(n) {
5941
7731
  return " ".repeat(n);
5942
7732
  }
7733
+ function collectAssignedIds(node, acc) {
7734
+ if (!node || typeof node !== "object") return;
7735
+ const n = node;
7736
+ if (n.type === "AssignmentExpression" && n.left?.type === "Identifier" && n.left.name) {
7737
+ acc.add(n.left.name);
7738
+ }
7739
+ if (n.type === "AssignmentExpression" && n.left?.type === "MemberExpression") {
7740
+ let cur = n.left;
7741
+ while (cur?.type === "MemberExpression") cur = cur.object;
7742
+ if (cur?.type === "Identifier" && cur.name) acc.add(cur.name);
7743
+ }
7744
+ if (n.type === "UpdateExpression" && n.argument?.type === "Identifier" && n.argument.name) {
7745
+ acc.add(n.argument.name);
7746
+ }
7747
+ for (const key of Object.keys(n)) {
7748
+ if (key === "loc" || key === "start" || key === "end" || key === "range") continue;
7749
+ const child = n[key];
7750
+ if (Array.isArray(child)) child.forEach((c) => collectAssignedIds(c, acc));
7751
+ else if (child && typeof child === "object") collectAssignedIds(child, acc);
7752
+ }
7753
+ }
7754
+ var FUNCTION_SCOPE_TYPES = /* @__PURE__ */ new Set([
7755
+ "FunctionDeclaration",
7756
+ "FunctionExpression",
7757
+ "ArrowFunctionExpression",
7758
+ "ObjectMethod",
7759
+ "ClassMethod",
7760
+ "ClassPrivateMethod"
7761
+ ]);
7762
+ var BINDING_SCOPE_TYPES = /* @__PURE__ */ new Set([
7763
+ ...FUNCTION_SCOPE_TYPES,
7764
+ "CatchClause",
7765
+ "ForOfStatement",
7766
+ "ForInStatement"
7767
+ ]);
7768
+ function collectPatternNames(id, acc) {
7769
+ if (!id || typeof id !== "object") return;
7770
+ const n = id;
7771
+ if (n.type === "Identifier" && n.name) acc.add(n.name);
7772
+ else if (n.type === "RestElement") collectPatternNames(n.argument, acc);
7773
+ else if (n.type === "AssignmentPattern") collectPatternNames(n.left, acc);
7774
+ else if (n.type === "ObjectPattern") {
7775
+ for (const p of n.properties ?? []) {
7776
+ const prop = p;
7777
+ if (prop?.type === "RestElement") collectPatternNames(prop.argument, acc);
7778
+ else collectPatternNames(prop?.value, acc);
7779
+ }
7780
+ } else if (n.type === "ArrayPattern") {
7781
+ for (const el of n.elements ?? []) collectPatternNames(el, acc);
7782
+ }
7783
+ }
7784
+ var freeAssignedCache = /* @__PURE__ */ new WeakMap();
7785
+ var mutatorRecvCache = /* @__PURE__ */ new WeakMap();
7786
+ function collectFreeAssignedNames(...nodes) {
7787
+ const cachedParts = [];
7788
+ const pending = [];
7789
+ for (const node of nodes) {
7790
+ if (node && typeof node === "object") {
7791
+ const hit = freeAssignedCache.get(node);
7792
+ if (hit) {
7793
+ cachedParts.push(hit);
7794
+ continue;
7795
+ }
7796
+ pending.push(node);
7797
+ }
7798
+ }
7799
+ if (pending.length === 0) {
7800
+ const merged2 = /* @__PURE__ */ new Set();
7801
+ for (const p of cachedParts) for (const n of p) merged2.add(n);
7802
+ return [...merged2];
7803
+ }
7804
+ const free = /* @__PURE__ */ new Set();
7805
+ const markFree = (name, shadowed) => {
7806
+ if (name && name !== "undefined" && !shadowed.has(name)) free.add(name);
7807
+ };
7808
+ const walk = (node, shadowed) => {
7809
+ if (!node || typeof node !== "object") return;
7810
+ const n = node;
7811
+ let nextShadowed = shadowed;
7812
+ const pushShadow = (names) => {
7813
+ const add2 = [];
7814
+ for (const name of names) {
7815
+ if (name && !nextShadowed.has(name)) add2.push(name);
7816
+ }
7817
+ if (add2.length === 0) return;
7818
+ nextShadowed = new Set(nextShadowed);
7819
+ for (const name of add2) nextShadowed.add(name);
7820
+ };
7821
+ if (FUNCTION_SCOPE_TYPES.has(n.type)) {
7822
+ const bound = /* @__PURE__ */ new Set();
7823
+ collectPatternNames(n.id, bound);
7824
+ for (const p of n.params ?? []) collectPatternNames(p, bound);
7825
+ pushShadow(bound);
7826
+ } else if (n.type === "CatchClause") {
7827
+ const bound = /* @__PURE__ */ new Set();
7828
+ collectPatternNames(n.param, bound);
7829
+ pushShadow(bound);
7830
+ } else if (n.type === "ForOfStatement" || n.type === "ForInStatement") {
7831
+ const bound = /* @__PURE__ */ new Set();
7832
+ const left = n.left;
7833
+ if (left?.type === "VariableDeclaration") {
7834
+ for (const d of left.declarations ?? []) collectPatternNames(d.id, bound);
7835
+ } else {
7836
+ collectPatternNames(left, bound);
7837
+ }
7838
+ pushShadow(bound);
7839
+ }
7840
+ if (n.type === "AssignmentExpression") {
7841
+ const left = n.left;
7842
+ if (left?.type === "Identifier") markFree(left.name, nextShadowed);
7843
+ else if (left?.type === "MemberExpression") {
7844
+ let cur = left;
7845
+ while (cur?.type === "MemberExpression") {
7846
+ cur = cur.object;
7847
+ }
7848
+ if (cur?.type === "Identifier") markFree(cur.name, nextShadowed);
7849
+ }
7850
+ }
7851
+ if (n.type === "UpdateExpression") {
7852
+ const arg = n.argument;
7853
+ if (arg?.type === "Identifier") markFree(arg.name, nextShadowed);
7854
+ }
7855
+ if (n.type === "CallExpression" && n.callee?.type === "MemberExpression" && n.callee.computed !== true && n.callee.property?.type === "Identifier" && ARR_MUTATOR_NAMES.has(n.callee.property.name)) {
7856
+ const obj2 = n.callee.object;
7857
+ if (obj2?.type === "Identifier") markFree(obj2.name, nextShadowed);
7858
+ else if (obj2?.type === "MemberExpression" || obj2?.type === "ThisExpression") {
7859
+ let cur = obj2;
7860
+ while (cur?.type === "MemberExpression") {
7861
+ cur = cur.object;
7862
+ }
7863
+ if (cur?.type === "Identifier") markFree(cur.name, nextShadowed);
7864
+ }
7865
+ }
7866
+ for (const key of Object.keys(n)) {
7867
+ if (key === "loc" || key === "start" || key === "end" || key === "range") continue;
7868
+ if (key === "callee" || key === "property" || key === "param" || key === "params") continue;
7869
+ const child = n[key];
7870
+ if (Array.isArray(child)) {
7871
+ if (n.type === "BlockStatement" || n.type === "Program" || n.type === "StaticBlock" || n.type === "SwitchCase") {
7872
+ let blockShadow = nextShadowed;
7873
+ for (const stmt of child) {
7874
+ walk(stmt, blockShadow);
7875
+ const stmtNode = stmt;
7876
+ if (!stmtNode) continue;
7877
+ const declared = /* @__PURE__ */ new Set();
7878
+ if (stmtNode.type === "VariableDeclaration") {
7879
+ for (const d of stmtNode.declarations ?? []) collectPatternNames(d.id, declared);
7880
+ } else if (stmtNode.type === "FunctionDeclaration" || stmtNode.type === "ClassDeclaration") {
7881
+ collectPatternNames(stmtNode.id, declared);
7882
+ }
7883
+ if (declared.size > 0) {
7884
+ if (blockShadow === nextShadowed) blockShadow = new Set(blockShadow);
7885
+ for (const name of declared) blockShadow.add(name);
7886
+ }
7887
+ }
7888
+ continue;
7889
+ }
7890
+ for (const item of child) walk(item, nextShadowed);
7891
+ } else if (child && typeof child === "object") {
7892
+ walk(child, nextShadowed);
7893
+ }
7894
+ }
7895
+ if (FUNCTION_SCOPE_TYPES.has(n.type) && n.body) {
7896
+ walk(n.body, nextShadowed);
7897
+ }
7898
+ };
7899
+ for (const node of pending) {
7900
+ walk(node, /* @__PURE__ */ new Set());
7901
+ }
7902
+ const computed = [...free];
7903
+ for (const node of pending) freeAssignedCache.set(node, computed);
7904
+ const merged = new Set(computed);
7905
+ for (const p of cachedParts) for (const n of p) merged.add(n);
7906
+ return [...merged];
7907
+ }
7908
+ function collectForkBindingNames(...nodes) {
7909
+ return collectFreeAssignedNames(...nodes);
7910
+ }
7911
+ function stmtCompletesControl(stmt) {
7912
+ if (!stmt) return false;
7913
+ switch (stmt.type) {
7914
+ case "BreakStatement":
7915
+ case "ReturnStatement":
7916
+ case "ThrowStatement":
7917
+ case "ContinueStatement":
7918
+ return true;
7919
+ case "BlockStatement":
7920
+ return stmtCompletesControl(stmt.body[stmt.body.length - 1]);
7921
+ case "IfStatement":
7922
+ return stmt.alternate != null && stmtCompletesControl(stmt.consequent) && stmtCompletesControl(stmt.alternate);
7923
+ default:
7924
+ return false;
7925
+ }
7926
+ }
5943
7927
  function stmtReturns(stmt) {
5944
7928
  if (stmt.type === "ReturnStatement" || stmt.type === "ThrowStatement") return true;
5945
7929
  if (stmt.type === "BlockStatement") return stmt.body.some(stmtReturns);
5946
7930
  if (stmt.type === "IfStatement") {
5947
7931
  return stmtReturns(stmt.consequent) && stmt.alternate != null && stmtReturns(stmt.alternate);
5948
7932
  }
7933
+ if (stmt.type === "SwitchStatement") {
7934
+ const arms = [];
7935
+ for (const c of stmt.cases) {
7936
+ const testIsDefault = c.test === null || c.test === void 0;
7937
+ const last = arms[arms.length - 1];
7938
+ if (last && !last.isDefault && last.stmts.length === 0 && !testIsDefault) {
7939
+ last.stmts = c.consequent;
7940
+ continue;
7941
+ }
7942
+ if (last && !last.isDefault && !testIsDefault && last.stmts.length > 0 && c.consequent.length === 0) {
7943
+ continue;
7944
+ }
7945
+ arms.push({ stmts: c.consequent, isDefault: testIsDefault });
7946
+ }
7947
+ const armOk = (a) => a.stmts.length > 0 && a.stmts.every(stmtReturns);
7948
+ const nonDefault = arms.filter((a) => !a.isDefault);
7949
+ const dflt = arms.find((a) => a.isDefault);
7950
+ if (dflt === void 0) return false;
7951
+ return nonDefault.length > 0 && nonDefault.every(armOk) && armOk(dflt);
7952
+ }
5949
7953
  return false;
5950
7954
  }
5951
7955
  function transpileFnBodyStmts(stmts, depth, opts) {
@@ -5957,11 +7961,61 @@ function transpileFnBodyStmts(stmts, depth, opts) {
5957
7961
  if (rest.length === 0) continue;
5958
7962
  const head = stmts.slice(0, i).map((s) => transpileStatement(s, depth, opts)).join("\n");
5959
7963
  const test = transpileExpression(stmt.test, opts);
5960
- const cons = transpileBlockAsThunk(stmt.consequent, depth, opts);
5961
- const altBody = transpileFnBodyStmts(rest, depth + 1, opts);
5962
- const promoted = `${indent(depth)}return $fork(${test}, ${cons}, () => {
7964
+ const recvSet = /* @__PURE__ */ new Set([
7965
+ ...collectForkBindingNames(stmt.consequent),
7966
+ ...collectForkBindingNames(stmt.test),
7967
+ ...rest.flatMap((r) => collectForkBindingNames(r))
7968
+ ]);
7969
+ const names = [...recvSet];
7970
+ const pad = indent(depth);
7971
+ const padIn = indent(depth + 1);
7972
+ const wrapArm = (thunk, outPrefix) => {
7973
+ if (names.length === 0) return thunk;
7974
+ return [
7975
+ `() => {`,
7976
+ ...names.map((n) => `${padIn}${n} = __fk0_${n};`),
7977
+ `${padIn}let __cont = true;`,
7978
+ `${padIn}try {`,
7979
+ `${padIn} return (${thunk})();`,
7980
+ `${padIn}} catch (e) {`,
7981
+ `${padIn} if ($isForkExit(e)) __cont = false;`,
7982
+ `${padIn} throw e;`,
7983
+ `${padIn}} finally {`,
7984
+ `${padIn} if (__cont) {`,
7985
+ ...names.map((n) => `${padIn} __${outPrefix}${n} = ${n};`),
7986
+ ...names.map((n) => `${padIn} __${outPrefix}set_${n} = true;`),
7987
+ `${padIn} }`,
7988
+ `${padIn}}`,
7989
+ `}`
7990
+ ].join("\n");
7991
+ };
7992
+ const testRecvs = collectArrMutatorReceivers(stmt.test);
7993
+ const testRebinds = testRecvs.size ? emitArrMutatorRebinds(stmt.test, opts, pad) : [];
7994
+ const cons = wrapArm(transpileBlockAsThunk(stmt.consequent, depth, opts), "fk1_");
7995
+ const altBody = transpileFnBodyStmts(rest, depth + 1, { ...opts, inLoop: opts.inLoop });
7996
+ const altThunk = `() => {
5963
7997
  ${altBody}
5964
- ${indent(depth)}});`;
7998
+ ${pad}}`;
7999
+ const alt = wrapArm(altThunk, "fk2_");
8000
+ const inCtrl = (opts.inLoop ?? 0) > 0 || (opts.inTry ?? 0) > 0;
8001
+ const applyJoin = names.length ? forkJoinBindings(names, pad).join("\n") : "";
8002
+ if (names.length === 0) {
8003
+ const promoted2 = [
8004
+ ...testRebinds,
8005
+ inCtrl ? `${pad}$loopReturn($fork(${test}, ${cons}, ${alt}));` : `${pad}return $fork(${test}, ${cons}, ${alt});`
8006
+ ].join("\n");
8007
+ return head ? `${head}
8008
+ ${promoted2}` : promoted2;
8009
+ }
8010
+ const promoted = [
8011
+ `${pad}{`,
8012
+ ...testRebinds,
8013
+ ...forkBindingDecls(names, padIn),
8014
+ `${padIn}const __fkR = $fork(${test}, ${cons}, ${alt});`,
8015
+ applyJoin.split("\n").map((l) => l.replace(/^\s*/, padIn)).join("\n"),
8016
+ inCtrl ? `${padIn}$loopReturn(__fkR);` : `${padIn}return __fkR;`,
8017
+ `${pad}}`
8018
+ ].join("\n");
5965
8019
  return head ? `${head}
5966
8020
  ${promoted}` : promoted;
5967
8021
  }
@@ -5973,11 +8027,18 @@ function emitDestructure(pattern, fromSrc, kw, pad, opts, out, tmpSeq) {
5973
8027
  return;
5974
8028
  }
5975
8029
  if (pattern.type === "ObjectPattern") {
8030
+ const namedKeys = [];
8031
+ let restName;
5976
8032
  for (const prop of pattern.properties) {
8033
+ if (prop.type === "RestElement") {
8034
+ if (prop.argument.type === "Identifier") restName = prop.argument.name;
8035
+ continue;
8036
+ }
5977
8037
  if (prop.type !== "ObjectProperty") continue;
5978
8038
  if (prop.key.type !== "Identifier" && prop.key.type !== "StringLiteral") continue;
5979
8039
  const key = prop.key.type === "Identifier" ? prop.key.name : String(prop.key.value);
5980
8040
  const keyLit = JSON.stringify(key);
8041
+ namedKeys.push(key);
5981
8042
  if (prop.value.type === "AssignmentPattern") {
5982
8043
  const def = transpileExpression(prop.value.right, opts);
5983
8044
  const left = prop.value.left;
@@ -6002,11 +8063,25 @@ function emitDestructure(pattern, fromSrc, kw, pad, opts, out, tmpSeq) {
6002
8063
  out.push(`${pad}${kw} ${prop.value.name} = $get(${fromSrc}, ${keyLit});`);
6003
8064
  }
6004
8065
  }
8066
+ if (restName) {
8067
+ out.push(
8068
+ `${pad}${kw} ${restName} = $objRest(${fromSrc}, ${JSON.stringify(namedKeys)});`
8069
+ );
8070
+ }
6005
8071
  return;
6006
8072
  }
6007
8073
  if (pattern.type === "ArrayPattern") {
8074
+ let restName;
8075
+ let restAt = 0;
6008
8076
  pattern.elements.forEach((el, i) => {
6009
8077
  if (!el) return;
8078
+ if (el.type === "RestElement") {
8079
+ if (el.argument.type === "Identifier") {
8080
+ restName = el.argument.name;
8081
+ restAt = i;
8082
+ }
8083
+ return;
8084
+ }
6010
8085
  if (el.type === "AssignmentPattern") {
6011
8086
  const def = transpileExpression(el.right, opts);
6012
8087
  const idx = `$idx(${fromSrc}, $lit(${i}))`;
@@ -6029,6 +8104,9 @@ function emitDestructure(pattern, fromSrc, kw, pad, opts, out, tmpSeq) {
6029
8104
  out.push(`${pad}${kw} ${el.name} = $idx(${fromSrc}, $lit(${i}));`);
6030
8105
  }
6031
8106
  });
8107
+ if (restName) {
8108
+ out.push(`${pad}${kw} ${restName} = $arrRest(${fromSrc}, ${restAt});`);
8109
+ }
6032
8110
  }
6033
8111
  }
6034
8112
  function emitParamBinding(params, pad, opts) {
@@ -6069,6 +8147,122 @@ function emitParamBinding(params, pad, opts) {
6069
8147
  });
6070
8148
  return { sig, rest, prologue };
6071
8149
  }
8150
+ function collectArrMutatorReceivers(node, acc = /* @__PURE__ */ new Set()) {
8151
+ if (!node || typeof node !== "object") return acc;
8152
+ const hit = mutatorRecvCache.get(node);
8153
+ if (hit) {
8154
+ for (const n of hit) acc.add(n);
8155
+ return acc;
8156
+ }
8157
+ const local = /* @__PURE__ */ new Set();
8158
+ collectArrMutatorReceiversUncached(node, local);
8159
+ mutatorRecvCache.set(node, local);
8160
+ for (const n of local) acc.add(n);
8161
+ return acc;
8162
+ }
8163
+ function collectArrMutatorReceiversUncached(node, acc = /* @__PURE__ */ new Set()) {
8164
+ if (!node || typeof node !== "object") return acc;
8165
+ const n = node;
8166
+ if (n.type === "FunctionExpression" || n.type === "ArrowFunctionExpression" || n.type === "ObjectMethod" || n.type === "ClassMethod" || n.type === "FunctionDeclaration") {
8167
+ return acc;
8168
+ }
8169
+ if (n.type === "CallExpression" && n.callee?.type === "MemberExpression") {
8170
+ const callee = n.callee;
8171
+ const propName = !callee.computed && callee.property?.type === "Identifier" ? callee.property.name : void 0;
8172
+ if (propName && ARR_MUTATOR_NAMES.has(propName)) {
8173
+ const obj2 = callee.object;
8174
+ if (obj2?.type === "Identifier") {
8175
+ acc.add(obj2.name);
8176
+ } else if (obj2?.type === "MemberExpression") {
8177
+ let cur = obj2;
8178
+ while (cur?.type === "MemberExpression") {
8179
+ cur = cur.object;
8180
+ }
8181
+ if (cur?.type === "Identifier") {
8182
+ acc.add(cur.name);
8183
+ }
8184
+ }
8185
+ }
8186
+ }
8187
+ for (const key of Object.keys(n)) {
8188
+ if (key === "loc" || key === "start" || key === "end" || key === "range") continue;
8189
+ const child = n[key];
8190
+ if (Array.isArray(child)) child.forEach((c) => collectArrMutatorReceiversUncached(c, acc));
8191
+ else if (child && typeof child === "object") collectArrMutatorReceiversUncached(child, acc);
8192
+ }
8193
+ return acc;
8194
+ }
8195
+ function forkArmThunk(bodyLines, outPrefix, names) {
8196
+ return [
8197
+ `() => {`,
8198
+ ...names.map((n) => ` ${n} = __fk0_${n};`),
8199
+ ` let __cont = true;`,
8200
+ ` try {`,
8201
+ ...bodyLines.map((l) => ` ${l}`),
8202
+ ` } catch (e) {`,
8203
+ ` if ($isForkExit(e)) __cont = false;`,
8204
+ ` throw e;`,
8205
+ ` } finally {`,
8206
+ ` if (__cont) {`,
8207
+ ...names.map((n) => ` __${outPrefix}${n} = ${n};`),
8208
+ ...names.map((n) => ` __${outPrefix}set_${n} = true;`),
8209
+ ` }`,
8210
+ ` }`,
8211
+ `}`
8212
+ ].join("\n");
8213
+ }
8214
+ function forkBindingDecls(names, pad = "") {
8215
+ return names.flatMap((n) => [
8216
+ `${pad}const __fk0_${n} = ${n};`,
8217
+ `${pad}let __fk1_${n}; let __fk2_${n};`,
8218
+ `${pad}let __fk1_set_${n} = false; let __fk2_set_${n} = false;`
8219
+ ]);
8220
+ }
8221
+ function forkJoinBindings(names, pad = "") {
8222
+ return names.map(
8223
+ (n) => `${pad}${n} = (__fk1_set_${n} && __fk2_set_${n}) ? $join(__fk1_${n}, __fk2_${n}) : (__fk1_set_${n} ? __fk1_${n} : (__fk2_set_${n} ? __fk2_${n} : ${n}));`
8224
+ );
8225
+ }
8226
+ function transpileShortCircuitExpr(opts, parts) {
8227
+ const alwaysNames = new Set(collectForkBindingNames(...parts.alwaysNodes));
8228
+ const branchNames = new Set(alwaysNames);
8229
+ for (const n of parts.consNodes) for (const id of collectForkBindingNames(n)) branchNames.add(id);
8230
+ for (const n of parts.altNodes) for (const id of collectForkBindingNames(n)) branchNames.add(id);
8231
+ const names = [...branchNames];
8232
+ const alwaysRebinds = [];
8233
+ for (const n of parts.alwaysNodes) {
8234
+ alwaysRebinds.push(...emitArrMutatorRebinds(n, opts, ""));
8235
+ }
8236
+ const consRebinds = [];
8237
+ for (const n of parts.consNodes) {
8238
+ if (parts.alwaysNodes.includes(n)) continue;
8239
+ consRebinds.push(...emitArrMutatorRebinds(n, opts, ""));
8240
+ }
8241
+ const altRebinds = [];
8242
+ for (const n of parts.altNodes) {
8243
+ if (parts.alwaysNodes.includes(n)) continue;
8244
+ altRebinds.push(...emitArrMutatorRebinds(n, opts, ""));
8245
+ }
8246
+ if (alwaysNames.size === 0 && branchNames.size === 0) {
8247
+ const forkTest2 = parts.testSrc ?? parts.alwaysSrc;
8248
+ const consExpr = parts.consSrc === "__test" ? parts.alwaysSrc : parts.consSrc;
8249
+ const altExpr = parts.altSrc === "__test" ? parts.alwaysSrc : parts.altSrc;
8250
+ return `$fork(${forkTest2}, () => ${consExpr}, () => ${altExpr})`;
8251
+ }
8252
+ const consLines = parts.consSrc === "__test" ? [`return __test;`] : consRebinds.length === 0 ? [`return (${parts.consSrc});`] : [`const __v = (${parts.consSrc});`, ...consRebinds, `return __v;`];
8253
+ const altLines = parts.altSrc === "__test" ? [`return __test;`] : altRebinds.length === 0 ? [`return (${parts.altSrc});`] : [`const __v = (${parts.altSrc});`, ...altRebinds, `return __v;`];
8254
+ const forkTest = parts.testSrc ?? "__test";
8255
+ return [
8256
+ `(() => {`,
8257
+ ` const __test = (${parts.alwaysSrc});`,
8258
+ ...alwaysRebinds.map((l) => ` ${l}`),
8259
+ ...names.length ? forkBindingDecls(names, " ") : [],
8260
+ ` const __r = $fork(${forkTest}, ${forkArmThunk(consLines, "fk1_", names)}, ${forkArmThunk(altLines, "fk2_", names)});`,
8261
+ ...forkJoinBindings(names, " "),
8262
+ ` return __r;`,
8263
+ `})()`
8264
+ ].join("\n");
8265
+ }
6072
8266
  function transpileStatement(stmt, depth, opts) {
6073
8267
  const pad = indent(depth);
6074
8268
  switch (stmt.type) {
@@ -6106,20 +8300,22 @@ function transpileStatement(stmt, depth, opts) {
6106
8300
  }
6107
8301
  case "FunctionDeclaration": {
6108
8302
  if (!stmt.id) return `${pad}// <anonymous fn skipped>`;
8303
+ const exportKw = depth === 0 ? "export " : "";
8304
+ const fnOpts = { ...opts, inLoop: 0 };
6109
8305
  const { sig, rest, prologue } = emitParamBinding(
6110
8306
  stmt.params,
6111
8307
  indent(depth + 2),
6112
- opts
8308
+ fnOpts
6113
8309
  );
6114
8310
  const named = sig;
6115
8311
  const paramsSig = rest ? [...named, `...${rest}`] : named;
6116
8312
  const params = paramsSig.join(", ");
6117
- const bodyStmts = stmt.body.type === "BlockStatement" ? [...prologue, transpileFnBodyStmts(stmt.body.body, depth + 2, opts)].join("\n") : `${indent(depth + 2)}return ${transpileExpression(stmt.body, opts)};`;
8313
+ const bodyStmts = stmt.body.type === "BlockStatement" ? [...prologue, transpileFnBodyStmts(stmt.body.body, depth + 2, fnOpts)].join("\n") : `${indent(depth + 2)}return ${transpileExpression(stmt.body, fnOpts)};`;
6118
8314
  const restBind = rest ? `${indent(depth + 1)}const ${rest} = arguments.length > ${named.length} ? $arr(Array.from(arguments).slice(${named.length})) : $arr([]);
6119
8315
  ` : "";
6120
8316
  if (stmt.generator) {
6121
8317
  return [
6122
- `${pad}export function ${stmt.id.name}(${named.join(", ")}) {`,
8318
+ `${pad}${exportKw}function ${stmt.id.name}(${named.join(", ")}) {`,
6123
8319
  restBind,
6124
8320
  `${indent(depth + 1)}return $gen(() => {`,
6125
8321
  bodyStmts,
@@ -6129,7 +8325,7 @@ function transpileStatement(stmt, depth, opts) {
6129
8325
  }
6130
8326
  if (stmt.async) {
6131
8327
  return [
6132
- `${pad}export function ${stmt.id.name}(${named.join(", ")}) {`,
8328
+ `${pad}${exportKw}function ${stmt.id.name}(${named.join(", ")}) {`,
6133
8329
  restBind,
6134
8330
  `${indent(depth + 1)}return $async(() => {`,
6135
8331
  bodyStmts,
@@ -6138,7 +8334,7 @@ function transpileStatement(stmt, depth, opts) {
6138
8334
  ].join("\n");
6139
8335
  }
6140
8336
  return [
6141
- `${pad}export function ${stmt.id.name}(${named.join(", ")}) {`,
8337
+ `${pad}${exportKw}function ${stmt.id.name}(${named.join(", ")}) {`,
6142
8338
  restBind,
6143
8339
  bodyStmts,
6144
8340
  `${pad}}`
@@ -6146,16 +8342,73 @@ function transpileStatement(stmt, depth, opts) {
6146
8342
  }
6147
8343
  case "ReturnStatement": {
6148
8344
  const asVar = matchAsOverride(stmt, opts);
6149
- if (asVar) return `${pad}return ${asVar};`;
6150
- if (!stmt.argument) return `${pad}return $lit(undefined);`;
6151
- return `${pad}return ${transpileExpression(stmt.argument, opts)};`;
8345
+ const prefix = (opts.inLoop ?? 0) > 0 ? "$loopReturn" : "return";
8346
+ const markExpr = opts.tryMarkName ?? "$tryCurrentMark()";
8347
+ const emitRet = (src, mutNodes) => {
8348
+ const retRebinds = mutNodes ? emitArrMutatorRebinds(mutNodes, opts, pad) : [];
8349
+ if ((opts.inTry ?? 0) > 0) {
8350
+ return [
8351
+ `${pad}const __nudoRet = ${src};`,
8352
+ ...retRebinds,
8353
+ `${pad}{`,
8354
+ `${indent(depth + 1)}const __xs = $tryTakeSince(${markExpr});`,
8355
+ `${indent(depth + 1)}if (__xs.length) {`,
8356
+ `${indent(depth + 2)}$pushLoopExit(__nudoRet);`,
8357
+ `${indent(depth + 2)}$throw(__xs.reduce((a, b) => $join(a, b)));`,
8358
+ `${indent(depth + 1)}}`,
8359
+ `${pad}}`,
8360
+ `${pad}${prefix}(__nudoRet);`
8361
+ ].join("\n");
8362
+ }
8363
+ if (retRebinds.length === 0) return `${pad}${prefix}(${src});`;
8364
+ return [
8365
+ `${pad}let __mutRet = ${src};`,
8366
+ ...retRebinds,
8367
+ `${pad}${prefix}(__mutRet);`
8368
+ ].join("\n");
8369
+ };
8370
+ if (asVar) return emitRet(asVar);
8371
+ if (!stmt.argument) return emitRet(`$lit(undefined)`);
8372
+ const retSrc = transpileExpression(stmt.argument, opts);
8373
+ return emitRet(retSrc, stmt.argument);
6152
8374
  }
6153
8375
  case "ThrowStatement": {
6154
8376
  const arg = stmt.argument ? transpileExpression(stmt.argument, opts) : "$lit(undefined)";
6155
8377
  return `${pad}$throw(${arg});`;
6156
8378
  }
6157
- case "ExpressionStatement":
8379
+ case "ExpressionStatement": {
8380
+ const expr = stmt.expression;
8381
+ const exprRebinds = emitArrMutatorRebinds(expr, opts, pad);
8382
+ if (expr.type === "CallExpression" && expr.callee.type === "MemberExpression" && !expr.callee.computed && expr.callee.property.type === "Identifier") {
8383
+ const methodName = expr.callee.property.name;
8384
+ if (["push", "unshift", "splice", "pop", "shift", "reverse", "sort"].includes(methodName)) {
8385
+ const argSrcs = expr.arguments.map(
8386
+ (a) => a.type === "SpreadElement" ? "$lit(undefined)" : transpileExpression(a, opts)
8387
+ ).join(", ");
8388
+ const objNode = expr.callee.object;
8389
+ if (objNode.type === "Identifier") {
8390
+ const name = objNode.name;
8391
+ return `${pad}${name} = $arrMutContainer(${name}, ${JSON.stringify(methodName)}, [${argSrcs}]);`;
8392
+ }
8393
+ if (objNode.type === "MemberExpression" || objNode.type === "ThisExpression") {
8394
+ const path = objNode.type === "MemberExpression" ? memberPathOf(objNode, opts) : null;
8395
+ if (path) {
8396
+ const recvSrc = readPathSrc(path);
8397
+ const mutSrc = `$arrMutContainer(${recvSrc}, ${JSON.stringify(methodName)}, [${argSrcs}])`;
8398
+ return `${pad}${path.rootSrc} = ${setPathSrc(path, mutSrc)};`;
8399
+ }
8400
+ return `${pad}${transpileExpression(stmt.expression, opts)};`;
8401
+ }
8402
+ }
8403
+ }
8404
+ if (exprRebinds.length > 0) {
8405
+ return [
8406
+ `${pad}${transpileExpression(expr, opts)};`,
8407
+ ...exprRebinds
8408
+ ].join("\n");
8409
+ }
6158
8410
  return `${pad}${transpileExpression(stmt.expression, opts)};`;
8411
+ }
6159
8412
  case "VariableDeclaration": {
6160
8413
  const kw = "let";
6161
8414
  const asVar = matchAsOverride(stmt, opts);
@@ -6165,6 +8418,9 @@ function transpileStatement(stmt, depth, opts) {
6165
8418
  if (d.id.type === "Identifier") {
6166
8419
  const init = asVar ? asVar : d.init ? transpileExpression(d.init, opts) : "$lit(undefined)";
6167
8420
  lines.push(`${pad}${kw} ${d.id.name} = ${init};`);
8421
+ if (d.init && !asVar) {
8422
+ lines.push(...emitArrMutatorRebinds(d.init, opts, pad));
8423
+ }
6168
8424
  continue;
6169
8425
  }
6170
8426
  if (!d.init) {
@@ -6174,18 +8430,74 @@ function transpileStatement(stmt, depth, opts) {
6174
8430
  const initSrc = transpileExpression(d.init, opts);
6175
8431
  const tmp = `_d${tmpSeq++}_${stmt.loc?.start.line ?? 0}`;
6176
8432
  lines.push(`${pad}const ${tmp} = ${initSrc};`);
8433
+ lines.push(...emitArrMutatorRebinds(d.init, opts, pad));
6177
8434
  emitDestructure(d.id, tmp, kw, pad, opts, lines, { n: 0 });
6178
8435
  }
6179
8436
  return lines.join("\n");
6180
8437
  }
6181
8438
  case "IfStatement": {
6182
8439
  const test = transpileExpression(stmt.test, opts);
6183
- const cons = transpileBlockAsThunk(stmt.consequent, depth, opts);
6184
- const alt = stmt.alternate ? transpileBlockAsThunk(stmt.alternate, depth, opts) : "undefined";
8440
+ const recvSet = /* @__PURE__ */ new Set([
8441
+ ...collectForkBindingNames(stmt.consequent),
8442
+ ...collectForkBindingNames(stmt.alternate)
8443
+ ]);
8444
+ const testRecvs = collectArrMutatorReceivers(stmt.test);
8445
+ const testRebinds = testRecvs.size ? emitArrMutatorRebinds(stmt.test, opts, pad) : [];
8446
+ const names = [...recvSet];
8447
+ const padIn = indent(depth + 1);
8448
+ const padDecl = names.length > 0 ? padIn : pad;
8449
+ const wrapArm = (thunk, outPrefix) => {
8450
+ if (names.length === 0) return thunk;
8451
+ return [
8452
+ `() => {`,
8453
+ ...names.map((n) => `${padIn}${n} = __fk0_${n};`),
8454
+ `${padIn}let __cont = true;`,
8455
+ `${padIn}try {`,
8456
+ `${padIn} return (${thunk})();`,
8457
+ `${padIn}} catch (e) {`,
8458
+ `${padIn} if ($isForkExit(e)) __cont = false;`,
8459
+ `${padIn} throw e;`,
8460
+ `${padIn}} finally {`,
8461
+ `${padIn} if (__cont) {`,
8462
+ ...names.map((n) => `${padIn} __${outPrefix}${n} = ${n};`),
8463
+ ...names.map((n) => `${padIn} __${outPrefix}set_${n} = true;`),
8464
+ `${padIn} }`,
8465
+ `${padIn}}`,
8466
+ `}`
8467
+ ].join("\n");
8468
+ };
8469
+ const consRaw = transpileBlockAsThunk(stmt.consequent, depth, opts);
8470
+ const altRaw = stmt.alternate ? transpileBlockAsThunk(stmt.alternate, depth, opts) : "undefined";
8471
+ const cons = wrapArm(consRaw, "fk1_");
8472
+ const alt = names.length ? wrapArm(altRaw === "undefined" ? "() => $lit(undefined)" : altRaw, "fk2_") : altRaw;
8473
+ const joinLines = names.length ? [...testRebinds, ...forkBindingDecls(names, padDecl)] : testRebinds;
8474
+ const applyJoin = names.length ? forkJoinBindings(names, padDecl).join("\n") : "";
8475
+ const inCtrl = (opts.inLoop ?? 0) > 0;
8476
+ const openBlock = names.length > 0 ? `${pad}{` : null;
8477
+ const closeBlock = names.length > 0 ? `${pad}}` : null;
6185
8478
  if (stmtReturns(stmt.consequent) && stmt.alternate !== void 0 && stmt.alternate !== null && stmtReturns(stmt.alternate)) {
6186
- return `${pad}return $fork(${test}, ${cons}, ${alt});`;
8479
+ if (names.length === 0) {
8480
+ return [
8481
+ ...joinLines,
8482
+ inCtrl ? `${pad}$loopReturn($fork(${test}, ${cons}, ${alt}));` : `${pad}return $fork(${test}, ${cons}, ${alt});`
8483
+ ].join("\n");
8484
+ }
8485
+ return [
8486
+ openBlock,
8487
+ ...joinLines,
8488
+ `${padDecl}const __fkR = $fork(${test}, ${cons}, ${alt});`,
8489
+ applyJoin,
8490
+ inCtrl ? `${padDecl}$loopReturn(__fkR);` : `${padDecl}return __fkR;`,
8491
+ closeBlock
8492
+ ].join("\n");
6187
8493
  }
6188
- return `${pad}$fork(${test}, ${cons}, ${alt});`;
8494
+ return [
8495
+ openBlock,
8496
+ ...joinLines,
8497
+ `${padDecl}$fork(${test}, ${cons}, ${alt});`,
8498
+ applyJoin,
8499
+ closeBlock
8500
+ ].filter((l) => l !== null && l !== "").join("\n");
6189
8501
  }
6190
8502
  case "ForStatement": {
6191
8503
  const initName = extractForInitName(stmt.init);
@@ -6193,8 +8505,21 @@ function transpileStatement(stmt, depth, opts) {
6193
8505
  const initExpr = stmt.init && stmt.init.type === "VariableDeclaration" && stmt.init.declarations[0]?.init ? transpileExpression(stmt.init.declarations[0].init, opts) : "$lit(undefined)";
6194
8506
  const testSrc = stmt.test ? transpileExpression(stmt.test, opts) : "$lit(true)";
6195
8507
  const updateSrc = stmt.update ? transpileExpression(stmt.update, opts) : `$lit(undefined)`;
6196
- const bodyStmts = stmt.body.type === "BlockStatement" ? stmt.body.body.map((s) => transpileStatement(s, depth + 2, opts)).join("\n") : transpileStatement(stmt.body, depth + 2, opts);
8508
+ const forBodyOpts = {
8509
+ ...opts,
8510
+ inLoop: (opts.inLoop ?? 0) + 1
8511
+ };
8512
+ const bodyStmts = stmt.body.type === "BlockStatement" ? stmt.body.body.map((s) => transpileStatement(s, depth + 2, forBodyOpts)).join("\n") : transpileStatement(stmt.body, depth + 2, forBodyOpts);
6197
8513
  const max = opts.maxLoopIters ?? 8;
8514
+ const assigned = /* @__PURE__ */ new Set();
8515
+ collectAssignedIds(stmt.body, assigned);
8516
+ collectAssignedIds(stmt.test, assigned);
8517
+ collectAssignedIds(stmt.update, assigned);
8518
+ collectArrMutatorReceivers(stmt.body, assigned);
8519
+ const names = [...assigned].filter((n) => n !== initName && n !== "undefined");
8520
+ const packSrc = names.length === 0 ? null : `$obj({ ${names.map((n) => `${JSON.stringify(n)}: ${n}`).join(", ")} })`;
8521
+ const unpackSrc = names.length === 0 ? null : `(__lp) => { ${names.map((n) => `${n} = $get(__lp, ${JSON.stringify(n)});`).join(" ")} }`;
8522
+ const optsSrc = packSrc && unpackSrc ? `, { pack: () => ${packSrc}, unpack: ${unpackSrc} }` : "";
6198
8523
  return [
6199
8524
  `${pad}// for \u2192 $for (bounded unroll, max=${max})`,
6200
8525
  `${pad}$for(`,
@@ -6205,7 +8530,7 @@ function transpileStatement(stmt, depth, opts) {
6205
8530
  bodyStmts,
6206
8531
  `${indent(depth + 1)} return ${initName};`,
6207
8532
  `${indent(depth + 1)}},`,
6208
- `${indent(depth + 1)}${max}`,
8533
+ `${indent(depth + 1)}${max}${optsSrc}`,
6209
8534
  `${pad});`
6210
8535
  ].join("\n");
6211
8536
  }
@@ -6213,58 +8538,172 @@ function transpileStatement(stmt, depth, opts) {
6213
8538
  return transpileFnBodyStmts(stmt.body, depth, opts);
6214
8539
  case "SwitchStatement": {
6215
8540
  const disc = transpileExpression(stmt.discriminant, opts);
6216
- const arms = [];
8541
+ const pre = [];
8542
+ let pendingTests = [];
6217
8543
  for (const c of stmt.cases) {
6218
8544
  const testSrc = c.test ? transpileExpression(c.test, opts) : null;
6219
8545
  if (testSrc === null) {
6220
- arms.push({ tests: [], stmts: c.consequent, isDefault: true });
6221
- } else if (arms.length > 0 && !arms[arms.length - 1].isDefault && arms[arms.length - 1].stmts.length === 0) {
6222
- const last = arms[arms.length - 1];
6223
- last.tests.push(testSrc);
6224
- last.stmts = c.consequent;
6225
- } else {
6226
- arms.push({ tests: [testSrc], stmts: c.consequent, isDefault: false });
8546
+ if (pendingTests.length > 0 && c.consequent.length > 0) {
8547
+ pre.push({ tests: pendingTests, stmts: c.consequent, isDefault: false });
8548
+ pendingTests = [];
8549
+ }
8550
+ pre.push({ tests: [], stmts: c.consequent, isDefault: true });
8551
+ continue;
6227
8552
  }
6228
- }
6229
- const merged = [];
6230
- for (const arm of arms) {
6231
- if (merged.length > 0 && merged[merged.length - 1].stmts === arm.stmts && !arm.isDefault) {
6232
- merged[merged.length - 1].tests.push(...arm.tests);
6233
- } else {
6234
- merged.push({ ...arm, tests: [...arm.tests] });
8553
+ if (c.consequent.length === 0) {
8554
+ pendingTests.push(testSrc);
8555
+ continue;
6235
8556
  }
8557
+ pre.push({ tests: [...pendingTests, testSrc], stmts: c.consequent, isDefault: false });
8558
+ pendingTests = [];
8559
+ }
8560
+ if (pendingTests.length > 0) {
8561
+ pre.push({ tests: pendingTests, stmts: [], isDefault: false });
8562
+ }
8563
+ const merged = pre.map((arm) => ({ ...arm, tests: [...arm.tests], stmts: [...arm.stmts] }));
8564
+ for (let i = 0; i < merged.length; i++) {
8565
+ const arm = merged[i];
8566
+ const body = [...arm.stmts];
8567
+ let j = i + 1;
8568
+ while (j < merged.length && !stmtCompletesControl(body[body.length - 1])) {
8569
+ body.push(...merged[j].stmts);
8570
+ if (stmtCompletesControl(body[body.length - 1])) break;
8571
+ j++;
8572
+ }
8573
+ arm.stmts = body;
6236
8574
  }
8575
+ const armReturns = (arm) => arm.stmts.length > 0 && arm.stmts.every(stmtReturns);
8576
+ const nonDefaultArms = merged.filter((a) => !a.isDefault);
8577
+ const defaultArm = merged.find((a) => a.isDefault);
8578
+ const allReturn = defaultArm !== void 0 && nonDefaultArms.length > 0 && nonDefaultArms.every(armReturns) && armReturns(defaultArm);
6237
8579
  const caseLines = [];
8580
+ const sharedBodyDecls = [];
6238
8581
  let defaultSrc = null;
8582
+ const bodyIdxBase = switchBodySeq;
8583
+ let bodyIdx = 0;
8584
+ const armOpts = {
8585
+ ...opts,
8586
+ inLoop: (opts.inLoop ?? 0) + 1
8587
+ };
8588
+ const recvSet = /* @__PURE__ */ new Set([
8589
+ ...merged.flatMap((a) => collectForkBindingNames(...a.stmts)),
8590
+ ...collectForkBindingNames(stmt.discriminant)
8591
+ ]);
8592
+ const names = [...recvSet];
8593
+ const nArms = merged.filter((a) => !a.isDefault).length + (defaultArm ? 1 : 0) + (defaultArm ? 0 : 1);
8594
+ const wrapArmThunk = (thunk, outIdx) => {
8595
+ if (names.length === 0) return thunk;
8596
+ return [
8597
+ `() => {`,
8598
+ ...names.map((n) => `${indent(depth + 1)}${n} = __sw0_${n};`),
8599
+ `${indent(depth + 1)}let __cont = true;`,
8600
+ `${indent(depth + 1)}try {`,
8601
+ `${indent(depth + 2)}return (${thunk})();`,
8602
+ `${indent(depth + 1)}} catch (e) {`,
8603
+ `${indent(depth + 2)}if ($isForkExit(e)) __cont = false;`,
8604
+ `${indent(depth + 2)}throw e;`,
8605
+ `${indent(depth + 1)}} finally {`,
8606
+ `${indent(depth + 2)}if (__cont) {`,
8607
+ ...names.map((n) => `${indent(depth + 3)}__sw${outIdx + 1}_${n} = ${n};`),
8608
+ ...names.map((n) => `${indent(depth + 3)}__sw${outIdx + 1}set_${n} = true;`),
8609
+ `${indent(depth + 2)}}`,
8610
+ `${indent(depth + 1)}}`,
8611
+ `}`
8612
+ ].join("\n");
8613
+ };
8614
+ let armSeq = 0;
6239
8615
  for (const arm of merged) {
6240
- const body = arm.stmts.map((s) => transpileStatement(s, depth + 2, opts)).join("\n") || `${indent(depth + 2)}return $lit(undefined);`;
6241
- const thunk = `() => {
8616
+ const body = arm.stmts.length === 0 ? "" : arm.stmts.map((s) => transpileStatement(s, depth + 2, armOpts)).join("\n");
8617
+ const rawThunk = `() => {
6242
8618
  ${body}
6243
8619
  ${indent(depth + 1)}}`;
8620
+ const thunk = wrapArmThunk(rawThunk, armSeq);
8621
+ armSeq++;
8622
+ const shared = arm.tests.length > 1 && !arm.isDefault;
8623
+ const runRef = shared ? `__swBody${bodyIdxBase + bodyIdx++}` : thunk;
8624
+ if (shared) {
8625
+ sharedBodyDecls.push(`${pad}const ${runRef} = ${thunk};`);
8626
+ }
6244
8627
  if (arm.isDefault) {
6245
8628
  defaultSrc = thunk;
6246
8629
  } else {
6247
8630
  for (const t of arm.tests) {
6248
- caseLines.push(`{ test: ${t}, run: ${thunk} },`);
8631
+ caseLines.push(`{ test: ${t}, run: ${runRef} },`);
6249
8632
  }
6250
8633
  }
6251
8634
  }
8635
+ if (!defaultArm && names.length > 0) {
8636
+ defaultSrc = wrapArmThunk(`() => {
8637
+ ${indent(depth + 2)}return $lit(undefined);
8638
+ ${indent(depth + 1)}}`, armSeq);
8639
+ }
8640
+ switchBodySeq += Math.max(bodyIdx, 1);
6252
8641
  const dflt = defaultSrc ? `, ${defaultSrc}` : "";
8642
+ const discRebinds = collectArrMutatorReceivers(stmt.discriminant).size ? emitArrMutatorRebinds(stmt.discriminant, opts, pad) : [];
8643
+ const switchCall = `$switch(${disc}, [
8644
+ ${caseLines.map((l) => indent(depth + 1) + l).join("\n")}
8645
+ ${indent(depth + 1)}]${dflt})`;
8646
+ if (names.length === 0) {
8647
+ return [
8648
+ ...discRebinds,
8649
+ ...sharedBodyDecls,
8650
+ allReturn ? `${pad}return ${switchCall};` : `${pad}${switchCall};`
8651
+ ].join("\n");
8652
+ }
8653
+ const decls = names.flatMap((n) => [
8654
+ `${pad}const __sw0_${n} = ${n};`,
8655
+ ...Array.from(
8656
+ { length: Math.max(nArms, armSeq + (defaultArm ? 0 : 1)) },
8657
+ (_, i) => `${pad}let __sw${i + 1}_${n}; let __sw${i + 1}set_${n} = false;`
8658
+ )
8659
+ ]);
8660
+ const slotCount = Math.max(nArms, armSeq + (defaultArm ? 0 : 1));
8661
+ const joins = names.map((n) => {
8662
+ const slots = Array.from(
8663
+ { length: slotCount },
8664
+ (_, i) => `(__sw${i + 1}set_${n} ? __sw${i + 1}_${n} : null)`
8665
+ );
8666
+ return `${pad}${n} = (() => { const __p = [${slots.join(",")}].filter((x) => x !== null); return __p.length === 0 ? ${n} : __p.reduce((a, b) => $join(a, b)); })();`;
8667
+ });
6253
8668
  return [
6254
- `${pad}return $switch(${disc}, [`,
6255
- ...caseLines.map((l) => indent(depth + 1) + l),
6256
- `${indent(depth + 1)}]${dflt});`
6257
- ].join("\n");
8669
+ ...discRebinds,
8670
+ `${pad}{`,
8671
+ ...decls.map((l) => l.replace(new RegExp(`^${pad}`), `${pad}`)),
8672
+ ...sharedBodyDecls.map(
8673
+ (l) => l.startsWith(pad) ? `${pad}${l.slice(pad.length)}` : `${pad}${l}`
8674
+ ),
8675
+ `${pad}const __swR = ${switchCall};`,
8676
+ ...joins,
8677
+ allReturn ? `${pad}return __swR;` : null,
8678
+ `${pad}}`
8679
+ ].filter((l) => l !== null).join("\n");
6258
8680
  }
6259
8681
  case "TryStatement": {
6260
- const tryBody = stmt.block.type === "BlockStatement" ? stmt.block.body.map((s) => transpileStatement(s, depth + 1, opts)).join("\n") : transpileStatement(stmt.block, depth + 1, opts);
6261
- const lines = [`${pad}try {`, tryBody, `${pad}}`];
8682
+ const markName = `__nudoTm_${stmt.loc?.start.line ?? 0}`;
8683
+ const tryOpts = {
8684
+ ...opts,
8685
+ inTry: (opts.inTry ?? 0) + 1,
8686
+ tryMarkName: markName
8687
+ };
8688
+ const tryBody = stmt.block.type === "BlockStatement" ? stmt.block.body.map((s) => transpileStatement(s, depth + 1, tryOpts)).join("\n") : transpileStatement(stmt.block, depth + 1, tryOpts);
8689
+ const lines = [
8690
+ `${pad}const ${markName} = $tryMark();`,
8691
+ `${pad}try {`,
8692
+ tryBody,
8693
+ `${pad}}`
8694
+ ];
8695
+ const catchParam = stmt.handler?.param?.type === "Identifier" ? stmt.handler.param.name : "e";
8696
+ const catchTmp = `__nudoE_${stmt.loc?.start.line ?? 0}`;
8697
+ const transpileCatchBody = (d, o) => !stmt.handler ? "" : stmt.handler.body.type === "BlockStatement" ? stmt.handler.body.body.map((s) => transpileStatement(s, d, o)).join("\n") : transpileStatement(stmt.handler.body, d, o);
6262
8698
  if (stmt.handler) {
6263
- const param = stmt.handler.param?.type === "Identifier" ? stmt.handler.param.name : "e";
6264
- const catchTmp = `__nudoE_${stmt.loc?.start.line ?? 0}`;
6265
- const catchBody = stmt.handler.body.type === "BlockStatement" ? stmt.handler.body.body.map((s) => transpileStatement(s, depth + 1, opts)).join("\n") : transpileStatement(stmt.handler.body, depth + 1, opts);
8699
+ const catchBody = transpileCatchBody(depth + 1, opts);
6266
8700
  lines.push(`${pad}catch (${catchTmp}) {`);
6267
- lines.push(`${indent(depth + 1)}const ${param} = $catchVal(${catchTmp});`);
8701
+ lines.push(`${indent(depth + 1)}$rethrowIfNudoReturn(${catchTmp});`);
8702
+ lines.push(`${indent(depth + 1)}const __xs_${markName} = $tryTakeSince(${markName});`);
8703
+ lines.push(`${indent(depth + 1)}__xs_${markName}.push($catchVal(${catchTmp}));`);
8704
+ lines.push(
8705
+ `${indent(depth + 1)}const ${catchParam} = __xs_${markName}.reduce((a, b) => $join(a, b));`
8706
+ );
6268
8707
  lines.push(catchBody);
6269
8708
  lines.push(`${pad}}`);
6270
8709
  }
@@ -6272,6 +8711,30 @@ ${indent(depth + 1)}}`;
6272
8711
  const finBody = stmt.finalizer.type === "BlockStatement" ? stmt.finalizer.body.map((s) => transpileStatement(s, depth + 1, opts)).join("\n") : transpileStatement(stmt.finalizer, depth + 1, opts);
6273
8712
  lines.push(`${pad}finally {`);
6274
8713
  lines.push(finBody);
8714
+ lines.push(`${pad}$tryPopMark();`);
8715
+ lines.push(`${pad}}`);
8716
+ } else {
8717
+ lines.push(`${pad}$tryPopMark();`);
8718
+ }
8719
+ if (stmt.handler) {
8720
+ const catchBody = transpileCatchBody(depth + 2, opts);
8721
+ lines.push(`${pad}{`);
8722
+ lines.push(`${indent(depth + 1)}const __post_${markName} = $tryTakeSince(${markName});`);
8723
+ lines.push(`${indent(depth + 1)}if (__post_${markName}.length) {`);
8724
+ lines.push(
8725
+ `${indent(depth + 2)}const ${catchParam} = __post_${markName}.reduce((a, b) => $join(a, b));`
8726
+ );
8727
+ lines.push(
8728
+ catchBody.split("\n").map((l) => l ? `${indent(depth + 2)}${l.trimStart()}` : l).join("\n")
8729
+ );
8730
+ lines.push(`${indent(depth + 1)}}`);
8731
+ lines.push(`${pad}}`);
8732
+ } else {
8733
+ lines.push(`${pad}{`);
8734
+ lines.push(`${indent(depth + 1)}const __post_${markName} = $tryTakeSince(${markName});`);
8735
+ lines.push(`${indent(depth + 1)}if (__post_${markName}.length) {`);
8736
+ lines.push(`${indent(depth + 2)}$throw(__post_${markName}.reduce((a, b) => $join(a, b)));`);
8737
+ lines.push(`${indent(depth + 1)}}`);
6275
8738
  lines.push(`${pad}}`);
6276
8739
  }
6277
8740
  return lines.join("\n");
@@ -6300,24 +8763,77 @@ ${indent(depth + 1)}}`;
6300
8763
  { n: 0 }
6301
8764
  );
6302
8765
  }
6303
- const bodyStmts = stmt.body.type === "BlockStatement" ? stmt.body.body.map((s) => transpileStatement(s, depth + 2, opts)).join("\n") : transpileStatement(stmt.body, depth + 2, opts);
8766
+ const bodyOpts = {
8767
+ ...opts,
8768
+ inLoop: (opts.inLoop ?? 0) + 1
8769
+ };
8770
+ const bodyStmts = stmt.body.type === "BlockStatement" ? stmt.body.body.map((s) => transpileStatement(s, depth + 2, bodyOpts)).join("\n") : transpileStatement(stmt.body, depth + 2, bodyOpts);
6304
8771
  const max = opts.maxLoopIters ?? 8;
8772
+ const assigned = /* @__PURE__ */ new Set();
8773
+ collectAssignedIds(stmt.body, assigned);
8774
+ collectArrMutatorReceivers(stmt.body, assigned);
8775
+ const names = [...assigned].filter((n) => n !== bindName && n !== "undefined");
8776
+ const optsSrc = names.length === 0 ? "" : `, { pack: () => $obj({ ${names.map((n) => `${JSON.stringify(n)}: ${n}`).join(", ")} }), unpack: (__lp) => { ${names.map((n) => `${n} = $get(__lp, ${JSON.stringify(n)});`).join(" ")} } }`;
6305
8777
  return [
6306
8778
  `${pad}$forOf(${iter}, (${bindName}, _i) => {`,
6307
8779
  ...bodyLines,
6308
8780
  bodyStmts,
6309
- `${pad}}, ${max});`
8781
+ `${pad}}, ${max}${optsSrc});`
6310
8782
  ].join("\n");
6311
8783
  }
6312
8784
  case "WhileStatement": {
6313
8785
  const test = transpileExpression(stmt.test, opts);
6314
- const body = stmt.body.type === "BlockStatement" ? stmt.body.body.map((s) => transpileStatement(s, depth + 1, opts)).join("\n") : transpileStatement(stmt.body, depth + 1, opts);
8786
+ const bodyOpts = {
8787
+ ...opts,
8788
+ inLoop: (opts.inLoop ?? 0) + 1
8789
+ };
8790
+ const body = stmt.body.type === "BlockStatement" ? stmt.body.body.map((s) => transpileStatement(s, depth + 1, bodyOpts)).join("\n") : transpileStatement(stmt.body, depth + 1, bodyOpts);
6315
8791
  const max = opts.maxLoopIters ?? 8;
8792
+ const assigned = /* @__PURE__ */ new Set();
8793
+ collectAssignedIds(stmt.body, assigned);
8794
+ collectAssignedIds(stmt.test, assigned);
8795
+ const names = [...assigned].filter((n) => n !== "undefined");
8796
+ if (names.length === 0) {
8797
+ return [
8798
+ `${pad}// while \u2192 $whileSeq (bounded, max=${max})`,
8799
+ `${pad}$whileSeq(() => ${test}, () => {`,
8800
+ body,
8801
+ `${pad}}, ${max});`
8802
+ ].join("\n");
8803
+ }
8804
+ const packSrc = `$obj({ ${names.map((n) => `${JSON.stringify(n)}: ${n}`).join(", ")} })`;
8805
+ const unpackSrc = `(__lp) => { ${names.map((n) => `${n} = $get(__lp, ${JSON.stringify(n)});`).join(" ")} }`;
6316
8806
  return [
6317
- `${pad}// while \u2192 $whileSeq (bounded, max=${max})`,
8807
+ `${pad}// while \u2192 $whileSeq (instrumented bindings: ${names.join(", ")})`,
6318
8808
  `${pad}$whileSeq(() => ${test}, () => {`,
6319
8809
  body,
6320
- `${pad}}, ${max});`
8810
+ `${pad}}, ${max}, { pack: () => ${packSrc}, unpack: ${unpackSrc} });`
8811
+ ].join("\n");
8812
+ }
8813
+ case "DoWhileStatement": {
8814
+ const test = transpileExpression(stmt.test, opts);
8815
+ const bodyOpts = {
8816
+ ...opts,
8817
+ inLoop: (opts.inLoop ?? 0) + 1
8818
+ };
8819
+ const bodyStmts = stmt.body.type === "BlockStatement" ? stmt.body.body.map((s) => transpileStatement(s, depth + 1, bodyOpts)).join("\n") : transpileStatement(stmt.body, depth + 1, bodyOpts);
8820
+ const max = opts.maxLoopIters ?? 8;
8821
+ const assigned = /* @__PURE__ */ new Set();
8822
+ collectAssignedIds(stmt.body, assigned);
8823
+ collectAssignedIds(stmt.test, assigned);
8824
+ collectArrMutatorReceivers(stmt.body, assigned);
8825
+ const names = [...assigned].filter((n) => n !== "undefined");
8826
+ const packSrc = names.length === 0 ? null : `$obj({ ${names.map((n) => `${JSON.stringify(n)}: ${n}`).join(", ")} })`;
8827
+ const unpackSrc = names.length === 0 ? null : `(__lp) => { ${names.map((n) => `${n} = $get(__lp, ${JSON.stringify(n)});`).join(" ")} }`;
8828
+ const optsSrc = packSrc && unpackSrc ? `, { pack: () => ${packSrc}, unpack: ${unpackSrc} }` : "";
8829
+ return [
8830
+ `${pad}// do-while \u2192 body + $whileSeq (bounded, max=${max})`,
8831
+ `{`,
8832
+ bodyStmts,
8833
+ `${indent(depth + 1)}$whileSeq(() => ${test}, () => {`,
8834
+ bodyStmts,
8835
+ `${indent(depth + 1)}}, ${max}${optsSrc});`,
8836
+ `${pad}}`
6321
8837
  ].join("\n");
6322
8838
  }
6323
8839
  case "ClassDeclaration": {
@@ -6342,6 +8858,8 @@ function transpileClass(stmt, depth, opts) {
6342
8858
  });
6343
8859
  const methodOpts = {
6344
8860
  ...opts,
8861
+ inLoop: 0,
8862
+ inTry: 0,
6345
8863
  thisParam: "__this",
6346
8864
  className: name
6347
8865
  };
@@ -6425,6 +8943,9 @@ ${indent(depth)}}`;
6425
8943
  }
6426
8944
  if (stmt.type === "ReturnStatement") {
6427
8945
  const v2 = stmt.argument ? transpileExpression(stmt.argument, opts) : "$lit(undefined)";
8946
+ if ((opts.inLoop ?? 0) > 0) {
8947
+ return `() => { $loopReturn(${v2}); }`;
8948
+ }
6428
8949
  return `() => ${v2}`;
6429
8950
  }
6430
8951
  const one = transpileStatement(stmt, depth + 1, opts);
@@ -6466,15 +8987,53 @@ function transpileExpression(expr, opts = {}) {
6466
8987
  }
6467
8988
  case "LogicalExpression": {
6468
8989
  const op = expr.operator;
8990
+ const lNode = expr.left;
8991
+ const rNode = expr.right;
6469
8992
  const l = transpileExpression(expr.left, opts);
6470
8993
  const r = transpileExpression(expr.right, opts);
6471
- return op === "&&" ? `$fork(${l}, () => ${r}, () => ${l})` : `$fork(${l}, () => ${l}, () => ${r})`;
8994
+ if (op === "??") {
8995
+ return transpileShortCircuitExpr(opts, {
8996
+ alwaysNodes: [lNode],
8997
+ alwaysSrc: l,
8998
+ // 测试用 nullish;返回侧:nullish → right,否则 → left
8999
+ consSrc: r,
9000
+ consNodes: [rNode],
9001
+ altSrc: l,
9002
+ altNodes: [lNode],
9003
+ testSrc: `$nullishTest(${l})`
9004
+ });
9005
+ }
9006
+ return op === "&&" ? transpileShortCircuitExpr(opts, {
9007
+ alwaysNodes: [lNode],
9008
+ alwaysSrc: l,
9009
+ consSrc: r,
9010
+ consNodes: [rNode],
9011
+ altSrc: "__test",
9012
+ altNodes: []
9013
+ }) : transpileShortCircuitExpr(opts, {
9014
+ alwaysNodes: [lNode],
9015
+ alwaysSrc: l,
9016
+ consSrc: "__test",
9017
+ consNodes: [],
9018
+ altSrc: r,
9019
+ altNodes: [rNode]
9020
+ });
6472
9021
  }
6473
9022
  case "ConditionalExpression": {
9023
+ const testNode = expr.test;
9024
+ const consNode = expr.consequent;
9025
+ const altNode = expr.alternate;
6474
9026
  const test = transpileExpression(expr.test, opts);
6475
9027
  const c = transpileExpression(expr.consequent, opts);
6476
9028
  const a = transpileExpression(expr.alternate, opts);
6477
- return `$fork(${test}, () => ${c}, () => ${a})`;
9029
+ return transpileShortCircuitExpr(opts, {
9030
+ alwaysNodes: [testNode],
9031
+ alwaysSrc: test,
9032
+ consSrc: c,
9033
+ consNodes: [consNode],
9034
+ altSrc: a,
9035
+ altNodes: [altNode]
9036
+ });
6478
9037
  }
6479
9038
  case "RegExpLiteral": {
6480
9039
  return `$regex(${JSON.stringify(expr.pattern)}${expr.flags ? `, ${JSON.stringify(expr.flags)}` : ""})`;
@@ -6543,6 +9102,22 @@ function transpileExpression(expr, opts = {}) {
6543
9102
  acc = acc === null ? arg : `$spread(${acc}, ${arg})`;
6544
9103
  continue;
6545
9104
  }
9105
+ if (prop.type === "ObjectMethod") {
9106
+ flushProps();
9107
+ const mkey = prop.key.type === "Identifier" ? JSON.stringify(prop.key.name) : prop.key.type === "StringLiteral" ? JSON.stringify(prop.key.value) : null;
9108
+ if (mkey === null) continue;
9109
+ const paramNames = prop.params.map(
9110
+ (p) => p.type === "Identifier" && p.name ? p.name : "_a"
9111
+ );
9112
+ const methodOpts = { ...opts, inLoop: 0, inTry: 0, thisParam: "__this" };
9113
+ const bodySrc = prop.body.type === "BlockStatement" ? `{
9114
+ ${prop.body.body.map((s) => transpileStatement(s, 1, methodOpts)).join("\n")}
9115
+ }` : transpileExpression(prop.body, methodOpts);
9116
+ const bindParams = ["__this", ...paramNames];
9117
+ const fnValSrc = `$fnVal([${paramNames.map((p) => JSON.stringify(p)).join(", ")}], (${bindParams.join(", ")}) => ${bodySrc}, { bindThis: true })`;
9118
+ props.push(`${mkey}: ${fnValSrc}`);
9119
+ continue;
9120
+ }
6546
9121
  if (prop.type !== "ObjectProperty") continue;
6547
9122
  if (prop.computed) {
6548
9123
  flushProps();
@@ -6554,6 +9129,23 @@ function transpileExpression(expr, opts = {}) {
6554
9129
  }
6555
9130
  const key = prop.key.type === "Identifier" ? JSON.stringify(prop.key.name) : prop.key.type === "StringLiteral" ? JSON.stringify(prop.key.value) : null;
6556
9131
  if (key === null) continue;
9132
+ if (prop.value.type === "FunctionExpression" && !prop.value.async) {
9133
+ const fn = prop.value;
9134
+ if (!fn.generator) {
9135
+ const paramNames = fn.params.map(
9136
+ (p) => p.type === "Identifier" && p.name ? p.name : "_a"
9137
+ );
9138
+ const methodOpts = { ...opts, inLoop: 0, thisParam: "__this" };
9139
+ const bodySrc = fn.body.type === "BlockStatement" ? `{
9140
+ ${fn.body.body.map((s) => transpileStatement(s, 1, methodOpts)).join("\n")}
9141
+ }` : transpileExpression(fn.body, methodOpts);
9142
+ const bindParams = ["__this", ...paramNames];
9143
+ props.push(
9144
+ `${key}: $fnVal([${paramNames.map((p) => JSON.stringify(p)).join(", ")}], (${bindParams.join(", ")}) => ${bodySrc}, { bindThis: true })`
9145
+ );
9146
+ continue;
9147
+ }
9148
+ }
6557
9149
  const valSrc = transpileExpression(prop.value, opts);
6558
9150
  props.push(`${key}: ${valSrc}`);
6559
9151
  }
@@ -6605,6 +9197,58 @@ function transpileExpression(expr, opts = {}) {
6605
9197
  case "AssignmentExpression": {
6606
9198
  const compoundFn = COMPOUND_OPS[expr.operator];
6607
9199
  const right = transpileExpression(expr.right, opts);
9200
+ const op = expr.operator;
9201
+ if (op === "||=" || op === "&&=" || op === "??=") {
9202
+ const rNode = expr.right;
9203
+ const emitLogicalAssign = (targetSrc, setSrc) => {
9204
+ if (op === "||=") {
9205
+ const sc2 = transpileShortCircuitExpr(opts, {
9206
+ alwaysNodes: [],
9207
+ alwaysSrc: targetSrc,
9208
+ consSrc: "__test",
9209
+ consNodes: [],
9210
+ altSrc: right,
9211
+ altNodes: [rNode]
9212
+ });
9213
+ return setSrc(sc2);
9214
+ }
9215
+ if (op === "&&=") {
9216
+ const sc2 = transpileShortCircuitExpr(opts, {
9217
+ alwaysNodes: [],
9218
+ alwaysSrc: targetSrc,
9219
+ consSrc: right,
9220
+ consNodes: [rNode],
9221
+ altSrc: "__test",
9222
+ altNodes: []
9223
+ });
9224
+ return setSrc(sc2);
9225
+ }
9226
+ const sc = transpileShortCircuitExpr(opts, {
9227
+ alwaysNodes: [],
9228
+ alwaysSrc: targetSrc,
9229
+ consSrc: right,
9230
+ consNodes: [rNode],
9231
+ altSrc: targetSrc,
9232
+ altNodes: [],
9233
+ testSrc: `$nullishTest(${targetSrc})`
9234
+ });
9235
+ return setSrc(sc);
9236
+ };
9237
+ if (expr.left.type === "Identifier") {
9238
+ return emitLogicalAssign(expr.left.name, (val) => `${expr.left.type === "Identifier" ? expr.left.name : ""} = ${val}`);
9239
+ }
9240
+ if (expr.left.type === "MemberExpression") {
9241
+ const m = expr.left;
9242
+ const path = memberPathOf(m, opts);
9243
+ if (path) {
9244
+ return emitLogicalAssign(readPathSrc(path), (val) => {
9245
+ const writeSrc = setPathSrc(path, val);
9246
+ return `${path.rootSrc} = ${writeSrc}`;
9247
+ });
9248
+ }
9249
+ }
9250
+ return `/* assign ${op} */ $lit(undefined)`;
9251
+ }
6608
9252
  if (expr.left.type === "MemberExpression") {
6609
9253
  const m = expr.left;
6610
9254
  const path = memberPathOf(m, opts);
@@ -6694,10 +9338,11 @@ function transpileExpression(expr, opts = {}) {
6694
9338
  case "FunctionExpression": {
6695
9339
  const fn = expr;
6696
9340
  const { sig, rest, prologue } = emitParamBinding(fn.params, indent(1), opts);
9341
+ const fnBodyOpts = { ...opts, inLoop: 0 };
6697
9342
  const paramParts = rest ? [...sig, `...${rest}`] : sig;
6698
9343
  const nameList = `[${sig.map((p) => JSON.stringify(p)).join(", ")}]`;
6699
9344
  if (fn.body.type === "BlockStatement") {
6700
- const inner = [...prologue, transpileFnBodyStmts(fn.body.body, 1, opts)].join("\n");
9345
+ const inner = [...prologue, transpileFnBodyStmts(fn.body.body, 1, fnBodyOpts)].join("\n");
6701
9346
  if (fn.async) {
6702
9347
  return `$fnVal(${nameList}, (${paramParts.join(", ")}) => $async(() => {
6703
9348
  ${inner}
@@ -6707,7 +9352,7 @@ ${inner}
6707
9352
  ${inner}
6708
9353
  })`;
6709
9354
  }
6710
- const bodySrc = transpileExpression(fn.body, opts);
9355
+ const bodySrc = transpileExpression(fn.body, fnBodyOpts);
6711
9356
  if (prologue.length > 0) {
6712
9357
  const thunk = fn.async ? `$async(() => ${bodySrc})` : bodySrc;
6713
9358
  return `$fnVal(${nameList}, (${paramParts.join(", ")}) => {
@@ -6807,7 +9452,7 @@ function $new(cls, args) {
6807
9452
  if (args.length === 1) {
6808
9453
  const n = litValue(args[0]);
6809
9454
  if (typeof n === "number" && Number.isInteger(n) && n >= 0 && n <= 4096) {
6810
- const els = Array.from({ length: n }, () => undefAbs());
9455
+ const els = Array.from({ length: n }, () => undefAbs2());
6811
9456
  return abs({ k: "tuple", elements: els }, void 0, void 0, "exact");
6812
9457
  }
6813
9458
  return abs({ k: "arr", element: unknown }, void 0, void 0, "partial");
@@ -6818,9 +9463,14 @@ function $new(cls, args) {
6818
9463
  const p = args[0] ? litValue(args[0]) : void 0;
6819
9464
  if (typeof p === "string") return $regex(p, args[1] ? String(litValue(args[1]) ?? "") : "");
6820
9465
  }
6821
- const name = cls.name || "Object";
9466
+ const clsName = cls.name || "Object";
9467
+ if (isErrorCtorName(clsName)) {
9468
+ return errorBrandAbs(clsName, args[0]);
9469
+ }
9470
+ if (clsName === "Map") return makeMapAbs(args[0]);
9471
+ if (clsName === "Set") return makeSetAbs(args[0]);
6822
9472
  const shape = objOf({});
6823
- return abs({ k: "brand", name, shape }, void 0, void 0, "path");
9473
+ return abs({ k: "brand", name: clsName, shape }, void 0, void 0, "path");
6824
9474
  }
6825
9475
  const spec = specOf(cls);
6826
9476
  if (!spec) {
@@ -6884,7 +9534,7 @@ function execRegexBrand(re, method, args) {
6884
9534
  if (!m) {
6885
9535
  return abs({ k: "unknown" }, { op: "lit", value: null }, void 0, "exact");
6886
9536
  }
6887
- const els = m.map((g) => g === void 0 ? undefAbs() : strLit(g));
9537
+ const els = m.map((g) => g === void 0 ? undefAbs2() : strLit(g));
6888
9538
  return abs({ k: "tuple", elements: els }, void 0, void 0, "exact");
6889
9539
  }
6890
9540
  function stringRegexMethod(recv, method, args) {
@@ -6917,10 +9567,69 @@ function stringRegexMethod(recv, method, args) {
6917
9567
  if (!m) {
6918
9568
  return abs({ k: "unknown" }, { op: "lit", value: null }, void 0, "exact");
6919
9569
  }
6920
- const els = m.map((g) => g === void 0 ? undefAbs() : strLit(g));
9570
+ const els = m.map((g) => g === void 0 ? undefAbs2() : strLit(g));
6921
9571
  return abs({ k: "tuple", elements: els }, void 0, void 0, "exact");
6922
9572
  }
6923
9573
  function $invoke(thisVal, method, args, loc) {
9574
+ if (method === "call" || method === "apply" || method === "bind") {
9575
+ const expandApplyArgs = (list) => {
9576
+ if (list === null || list === void 0) return [];
9577
+ if (Array.isArray(list)) {
9578
+ return list.map(
9579
+ (x) => x && typeof x === "object" && "shape" in x ? x : unknown
9580
+ );
9581
+ }
9582
+ if (typeof list === "object" && "shape" in list) {
9583
+ const s = list.shape;
9584
+ if (s.k === "tuple") return [...s.elements];
9585
+ if (s.k === "arr") return [s.element];
9586
+ }
9587
+ return [unknown];
9588
+ };
9589
+ const boundFnParams = (fnVal, boundCount) => {
9590
+ if (fnVal && typeof fnVal === "object" && "shape" in fnVal) {
9591
+ const s = fnVal.shape;
9592
+ if (s.k === "fn" && Array.isArray(s.params)) {
9593
+ return s.params.slice(boundCount);
9594
+ }
9595
+ }
9596
+ if (typeof fnVal === "function") {
9597
+ const arity = fnVal.length ?? 0;
9598
+ const rem = Math.max(0, arity - boundCount);
9599
+ return Array.from({ length: rem }, (_, i) => `_a${boundCount + i}`);
9600
+ }
9601
+ return ["_rest"];
9602
+ };
9603
+ if (typeof thisVal === "function") {
9604
+ const fn = thisVal;
9605
+ if (method === "call") {
9606
+ return callAtFunctionBoundary(() => fn(...args.slice(1)));
9607
+ }
9608
+ if (method === "apply") {
9609
+ return callAtFunctionBoundary(() => fn(...expandApplyArgs(args[1])));
9610
+ }
9611
+ const bound = args.slice(1);
9612
+ return absFunction(boundFnParams(thisVal, bound.length), {
9613
+ apply: (callArgs) => callAtFunctionBoundary(() => fn(...bound, ...callArgs))
9614
+ });
9615
+ }
9616
+ if (thisVal && typeof thisVal === "object" && "shape" in thisVal) {
9617
+ const fnImpl = getFnImpl(thisVal);
9618
+ const isCallable = thisVal.shape.k === "fn" || fnImpl !== void 0;
9619
+ if (isCallable) {
9620
+ if (method === "call") {
9621
+ return $call(thisVal, args.slice(1));
9622
+ }
9623
+ if (method === "apply") {
9624
+ return $call(thisVal, expandApplyArgs(args[1]));
9625
+ }
9626
+ const bound = args.slice(1);
9627
+ return absFunction(boundFnParams(thisVal, bound.length), {
9628
+ apply: (callArgs) => callAtFunctionBoundary(() => $call(thisVal, [...bound, ...callArgs]))
9629
+ });
9630
+ }
9631
+ }
9632
+ }
6924
9633
  if (!thisVal || typeof thisVal !== "object" || !("shape" in thisVal)) {
6925
9634
  const ns = namespaceNameOf(thisVal);
6926
9635
  return (ns ? evalNamespaceCall(ns, method, args) : void 0) ?? unknown;
@@ -6936,6 +9645,10 @@ function $invoke(thisVal, method, args, loc) {
6936
9645
  }
6937
9646
  const brandName = thisVal.shape.k === "brand" ? thisVal.shape.name : void 0;
6938
9647
  if (brandName) {
9648
+ if (brandName === "Map" || brandName === "Set") {
9649
+ const viaCol = evalBuiltinInstanceMethod(brandName, method, thisVal, args);
9650
+ if (viaCol !== void 0) return viaCol;
9651
+ }
6939
9652
  const m = findMethod(brandName, method);
6940
9653
  if (m) return m(thisVal, ...args);
6941
9654
  const spec = getBClass(brandName);
@@ -6957,6 +9670,7 @@ function $invoke(thisVal, method, args, loc) {
6957
9670
  const prop = $get(thisVal, method, { silent: true });
6958
9671
  const impl = prop && typeof prop === "object" && "shape" in prop ? getFnImpl(prop) : void 0;
6959
9672
  if (impl) {
9673
+ if (impl.bindThis) return $call(prop, [thisVal, ...args]);
6960
9674
  return $call(prop, args);
6961
9675
  }
6962
9676
  if (notePrimMemberMissing(thisVal, method, "method", loc)) return unknown;
@@ -6974,8 +9688,21 @@ function memberLikelyHasMethod(m, method) {
6974
9688
  function invokeArrMethod(arr, method, args) {
6975
9689
  const shape = arr.shape;
6976
9690
  const callFn = (fn, ...fnArgs) => {
9691
+ const sumIdx = fnArgs.findIndex(
9692
+ (a) => a && typeof a === "object" && "shape" in a && a.shape.k === "sum"
9693
+ );
9694
+ if (sumIdx >= 0) {
9695
+ const members = fnArgs[sumIdx].shape.members;
9696
+ let acc;
9697
+ for (const m of members) {
9698
+ const next = fnArgs.map((a, i) => i === sumIdx ? m : a);
9699
+ const r = callFn(fn, ...next);
9700
+ acc = acc === void 0 ? r : joinAbs(acc, r);
9701
+ }
9702
+ return acc ?? unknown;
9703
+ }
6977
9704
  if (typeof fn === "function") {
6978
- const r = fn(...fnArgs);
9705
+ const r = callAtFunctionBoundary(() => fn(...fnArgs));
6979
9706
  if (r && typeof r === "object" && "shape" in r) return r;
6980
9707
  return unknown;
6981
9708
  }
@@ -7033,7 +9760,7 @@ function invokeArrMethod(arr, method, args) {
7033
9760
  if (method === "forEach" && args[0]) {
7034
9761
  const list = shape.k === "tuple" ? shape.elements : [shape.element];
7035
9762
  for (const el of list) callFn(args[0], el);
7036
- return undefAbs();
9763
+ return undefAbs2();
7037
9764
  }
7038
9765
  if ((method === "some" || method === "every") && args[0]) {
7039
9766
  const list = shape.k === "tuple" ? shape.elements : [shape.element];
@@ -7043,7 +9770,7 @@ function invokeArrMethod(arr, method, args) {
7043
9770
  if (method === "find" && args[0]) {
7044
9771
  const el = shape.k === "tuple" ? shape.elements[0] ?? unknown : shape.element;
7045
9772
  callFn(args[0], el);
7046
- return joinAbs(el, undefAbs());
9773
+ return joinAbs(el, undefAbs2());
7047
9774
  }
7048
9775
  if (method === "join") {
7049
9776
  return abs({ k: "prim", type: "string" }, void 0, void 0, "path");
@@ -7063,11 +9790,35 @@ function invokeArrMethod(arr, method, args) {
7063
9790
  if (method === "includes") {
7064
9791
  return abs({ k: "prim", type: "boolean" }, void 0, void 0, "partial");
7065
9792
  }
7066
- if (method === "at" || method === "pop" || method === "shift") {
9793
+ if (method === "push" || method === "unshift") {
9794
+ return abs({ k: "prim", type: "number" }, void 0, void 0, "path");
9795
+ }
9796
+ if (method === "pop") {
9797
+ if (shape.k === "tuple") {
9798
+ return shape.elements.length > 0 ? shape.elements[shape.elements.length - 1] ?? unknown : undefAbs2();
9799
+ }
9800
+ if (shape.k === "arr") return joinAbs(shape.element, undefAbs2());
9801
+ }
9802
+ if (method === "shift") {
7067
9803
  if (shape.k === "tuple" && shape.elements.length > 0) {
7068
9804
  return shape.elements[0] ?? unknown;
7069
9805
  }
7070
- if (shape.k === "arr") return shape.element;
9806
+ if (shape.k === "arr") return joinAbs(shape.element, undefAbs2());
9807
+ }
9808
+ if (method === "at") {
9809
+ const raw = args[0] !== void 0 ? litValue(args[0]) : void 0;
9810
+ const iv = typeof raw === "number" && Number.isInteger(raw) ? raw : void 0;
9811
+ if (shape.k === "tuple") {
9812
+ const els = shape.elements;
9813
+ if (iv === void 0) {
9814
+ if (els.length === 0) return undefAbs2();
9815
+ return joinAbs(els.reduce((a, b) => joinAbs(a, b)), undefAbs2());
9816
+ }
9817
+ const idx = iv < 0 ? els.length + iv : iv;
9818
+ if (idx >= 0 && idx < els.length) return els[idx] ?? unknown;
9819
+ return undefAbs2();
9820
+ }
9821
+ if (shape.k === "arr") return joinAbs(shape.element, undefAbs2());
7071
9822
  }
7072
9823
  return void 0;
7073
9824
  }
@@ -7109,13 +9860,32 @@ function $thisSet(thisVal, key, value) {
7109
9860
  }
7110
9861
  function $orDefault(v2, dflt) {
7111
9862
  if (v2 === void 0) return asAbsVal(dflt());
7112
- if (litValue(v2) === void 0 && v2.shape.k !== "never") {
7113
- if (v2.term?.op === "lit" && v2.term.value === void 0) return asAbsVal(dflt());
7114
- if (v2.shape.k === "unknown" && v2.term?.op === "lit") return asAbsVal(dflt());
9863
+ if (isDefinitelyUndefinedAbs(v2)) return asAbsVal(dflt());
9864
+ if (v2.shape.k === "sum") {
9865
+ const d = asAbsVal(dflt());
9866
+ const parts = [];
9867
+ let sawUndef = false;
9868
+ for (const m of v2.shape.members) {
9869
+ if (isDefinitelyUndefinedAbs(m)) {
9870
+ sawUndef = true;
9871
+ continue;
9872
+ }
9873
+ parts.push(m);
9874
+ }
9875
+ if (!sawUndef) return v2;
9876
+ if (parts.length === 0) return d;
9877
+ let joined = parts[0];
9878
+ for (let i = 1; i < parts.length; i++) joined = joinAbs(joined, parts[i]);
9879
+ return joinAbs(joined, d);
7115
9880
  }
7116
- if (v2.term?.op === "lit" && v2.term.value === void 0) return asAbsVal(dflt());
7117
9881
  return v2;
7118
9882
  }
9883
+ function isDefinitelyUndefinedAbs(v2) {
9884
+ if (!v2) return false;
9885
+ if (v2.term?.op === "lit" && v2.term.value === void 0) return true;
9886
+ if (v2.shape.k === "unknown" && v2.term?.op === "lit" && litValue(v2) === void 0) return true;
9887
+ return false;
9888
+ }
7119
9889
  function isNullishAbs(v2) {
7120
9890
  if (!v2 || v2.term?.op !== "lit") return false;
7121
9891
  const lv = v2.term.value;
@@ -7154,11 +9924,47 @@ function $setKey(o, key, value) {
7154
9924
  if (typeof k === "string" || typeof k === "number") {
7155
9925
  return $set(o, String(k), value);
7156
9926
  }
7157
- return $set(o, "?", value);
9927
+ const val = asAbsVal(value);
9928
+ if (o.shape.k === "brand") {
9929
+ const inner = $setKey(o.shape.shape, key, value);
9930
+ return abs(
9931
+ { k: "brand", name: o.shape.name, shape: inner },
9932
+ o.term,
9933
+ o.pred,
9934
+ confJoin(o.conf, value.conf)
9935
+ );
9936
+ }
9937
+ if (o.shape.k !== "obj") {
9938
+ return abs(
9939
+ {
9940
+ k: "obj",
9941
+ slots: {},
9942
+ index: { key: unknown, value: val },
9943
+ open: true
9944
+ },
9945
+ void 0,
9946
+ void 0,
9947
+ confJoin("path", value.conf)
9948
+ );
9949
+ }
9950
+ const shape = o.shape;
9951
+ const prevIndex = shape.index?.value;
9952
+ const indexVal = prevIndex ? joinAbs(prevIndex, val) : val;
9953
+ const next = objOf({ ...shape.slots }, {
9954
+ index: { key: shape.index?.key ?? unknown, value: indexVal },
9955
+ open: true
9956
+ });
9957
+ next.conf = confJoin(o.conf, value.conf);
9958
+ return next;
7158
9959
  }
7159
9960
 
7160
9961
  // src/algebra/exec/run.ts
7161
9962
  var rtAll = { ...runtime_exports, ...class_exports, ...calls_exports };
9963
+ rtAll.isNudoReturn = isNudoReturn;
9964
+ rtAll.isNudoThrow = isNudoThrow;
9965
+ rtAll.$isForkExit = $isForkExit;
9966
+ rtAll.runWithLoopExits = runWithLoopExits;
9967
+ rtAll.takeLoopExits = takeLoopExits;
7162
9968
  var RUNTIME_IMPORT_RE = /^import\s*\{[^}]+\}\s*from\s*"[^"]+";\s*$/m;
7163
9969
  function rewriteUserImports(js) {
7164
9970
  js = js.replace(
@@ -7364,33 +10170,59 @@ function isAbsVal(v2) {
7364
10170
  function callTranspiledExportFull(exports, name, args) {
7365
10171
  const fn = exports[name];
7366
10172
  if (typeof fn === "function") {
7367
- try {
7368
- const r = fn(...args);
7369
- if (!isAbsVal(r)) return { result: unknown, throws: never };
7370
- return { result: r, throws: never };
7371
- } catch (e) {
7372
- if (isNudoThrow(e)) {
7373
- return { result: never, throws: e.absValue };
7374
- }
7375
- return { result: unknown, throws: never };
7376
- }
7377
- }
7378
- if (isAbsVal(fn)) {
7379
- if (fn.shape.k === "fn") {
10173
+ return runWithLoopExits(() => {
7380
10174
  try {
7381
- const r = $call(fn, args);
7382
- return { result: r, throws: never };
10175
+ const r = fn(...args);
10176
+ if (!isAbsVal(r)) return joinControlExits(unknown);
10177
+ return joinControlExits(r);
7383
10178
  } catch (e) {
10179
+ if (isNudoReturn(e)) {
10180
+ return joinControlExits(e.absValue);
10181
+ }
7384
10182
  if (isNudoThrow(e)) {
7385
- return { result: never, throws: e.absValue };
10183
+ const result = joinLoopExits(never);
10184
+ const throws = joinThrowExits(e.absValue);
10185
+ return { result, throws };
7386
10186
  }
7387
- return { result: unknown, throws: never };
10187
+ return joinControlExits(unknown);
7388
10188
  }
10189
+ });
10190
+ }
10191
+ if (isAbsVal(fn)) {
10192
+ if (fn.shape.k === "fn") {
10193
+ return runWithLoopExits(() => {
10194
+ try {
10195
+ const r = $call(fn, args);
10196
+ return joinControlExits(r);
10197
+ } catch (e) {
10198
+ if (isNudoReturn(e)) {
10199
+ return joinControlExits(e.absValue);
10200
+ }
10201
+ if (isNudoThrow(e)) {
10202
+ return { result: joinLoopExits(never), throws: joinThrowExits(e.absValue) };
10203
+ }
10204
+ return joinControlExits(unknown);
10205
+ }
10206
+ });
7389
10207
  }
7390
10208
  return { result: fn, throws: never };
7391
10209
  }
7392
10210
  return { result: unknown, throws: never };
7393
10211
  }
10212
+ function joinLoopExits(normal) {
10213
+ const exits = takeLoopExits();
10214
+ if (exits.length === 0) return normal;
10215
+ return exits.reduce((acc, x) => joinAbs(acc, x), normal);
10216
+ }
10217
+ function joinThrowExits(base) {
10218
+ const exits = takeThrowExits();
10219
+ let t = base;
10220
+ for (const x of exits) t = t ? joinAbs(t, x) : x;
10221
+ return t ?? never;
10222
+ }
10223
+ function joinControlExits(normal) {
10224
+ return { result: joinLoopExits(normal), throws: joinThrowExits(void 0) };
10225
+ }
7394
10226
  function callTranspiledExport(exports, name, args) {
7395
10227
  return callTranspiledExportFull(exports, name, args).result;
7396
10228
  }
@@ -7494,7 +10326,7 @@ export {
7494
10326
  instantiateReturn,
7495
10327
  setApplyCallbackHost,
7496
10328
  applyCallbackAbs,
7497
- undefAbs,
10329
+ undefAbs2 as undefAbs,
7498
10330
  mapElementFallback,
7499
10331
  projectFlatMapResult,
7500
10332
  asAbs,
@@ -7530,6 +10362,34 @@ export {
7530
10362
  definitelyNotNullishShape,
7531
10363
  isNullishLitAbs,
7532
10364
  strictEqAbs,
10365
+ looseEqAbs,
10366
+ pushCollectionArm,
10367
+ popCollectionArm,
10368
+ mergeCollectionArms,
10369
+ beginCollectionFork,
10370
+ noteCollectionWrite,
10371
+ endCollectionFork,
10372
+ isMapAbs,
10373
+ isSetAbs,
10374
+ makeMapAbs,
10375
+ makeSetAbs,
10376
+ mapSetEntry,
10377
+ mapDeleteEntry,
10378
+ mapClearEntries,
10379
+ mapGetEntry,
10380
+ mapHasEntry,
10381
+ mapSizeAbs,
10382
+ mapValuesAbs,
10383
+ mapEntriesAbs,
10384
+ setAddEntry,
10385
+ setDeleteEntry,
10386
+ setClearEntries,
10387
+ setHasEntry,
10388
+ setSizeAbs,
10389
+ setElementsAbs,
10390
+ collectionExactLen,
10391
+ collectionElementJoin,
10392
+ clearCollectionTables,
7533
10393
  evalMathMethod,
7534
10394
  evalObjectMethod,
7535
10395
  evalJsonMethod,
@@ -7544,6 +10404,8 @@ export {
7544
10404
  evalPromiseCtor,
7545
10405
  evalPromiseStatic,
7546
10406
  evalNamespaceCall,
10407
+ isErrorCtorName,
10408
+ errorBrandAbs,
7547
10409
  evalBuiltinNew,
7548
10410
  evalBuiltinInstanceMethod,
7549
10411
  callAbsMethod,
@@ -7569,6 +10431,7 @@ export {
7569
10431
  awaitAbs,
7570
10432
  coerceAsyncReturn,
7571
10433
  classFromMethods,
10434
+ requiredFnArity,
7572
10435
  leqAbs,
7573
10436
  tagAbsOrigin,
7574
10437
  getAbsOrigin,
@@ -7577,6 +10440,10 @@ export {
7577
10440
  notePrimMemberMissing,
7578
10441
  noteUnknownMemberMissing,
7579
10442
  noteMemberDispatchMiss,
10443
+ setEvalMissingSlotEnabled,
10444
+ isEvalMissingSlotEnabled,
10445
+ runWithEvalMissingSlot,
10446
+ noteObjSlotMissing,
7580
10447
  registerBClass,
7581
10448
  getBClass,
7582
10449
  clearBClasses,
@@ -7618,27 +10485,44 @@ export {
7618
10485
  $not,
7619
10486
  $eq,
7620
10487
  $ne,
10488
+ $eqLoose,
10489
+ $neLoose,
7621
10490
  $lt,
7622
10491
  $le,
7623
10492
  $gt,
7624
10493
  $ge,
7625
10494
  $join,
7626
10495
  asAbsVal,
10496
+ callAtFunctionBoundary,
7627
10497
  $fnVal,
7628
10498
  $lit,
7629
10499
  litTruth,
7630
10500
  isDefinitelyTrue,
7631
10501
  isDefinitelyFalse,
10502
+ runWithLoopExits,
10503
+ takeLoopExits,
10504
+ takeThrowExits,
10505
+ pushLoopExit,
10506
+ pushThrowExit,
10507
+ $pushLoopExit,
10508
+ $tryMark,
10509
+ $tryCurrentMark,
10510
+ $tryPopMark,
10511
+ $tryTakeSince,
7632
10512
  $fork,
7633
10513
  DEFAULT_MAX_LOOP_ITERS,
7634
10514
  $forIter,
7635
10515
  $for,
7636
10516
  $arr,
10517
+ isArrMutator,
10518
+ $arrMutContainer,
7637
10519
  $idx,
7638
10520
  $idxSet,
7639
10521
  $len,
7640
10522
  $obj,
7641
10523
  $spread,
10524
+ $objRest,
10525
+ $arrRest,
7642
10526
  $concat,
7643
10527
  $elems,
7644
10528
  $forOf,
@@ -7648,9 +10532,14 @@ export {
7648
10532
  $set,
7649
10533
  $while,
7650
10534
  $whileSeq,
10535
+ NudoReturn,
10536
+ $loopReturn,
10537
+ isNudoReturn,
10538
+ $rethrowIfNudoReturn,
7651
10539
  NudoThrow,
7652
10540
  $throw,
7653
10541
  isNudoThrow,
10542
+ $isForkExit,
7654
10543
  $catchVal,
7655
10544
  $async,
7656
10545
  $await,
@@ -7658,6 +10547,7 @@ export {
7658
10547
  $gen,
7659
10548
  $yield,
7660
10549
  $switch,
10550
+ $nullishTest,
7661
10551
  transpileSource,
7662
10552
  transpileFile,
7663
10553
  transpileExpression,