@nudojs/core 0.4.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -703,6 +703,86 @@ function shapeOnlyFn(paramTypes, returnType, opts) {
703
703
  }
704
704
 
705
705
  // src/algebra/template.ts
706
+ function viewTemplateParts(parts, describe) {
707
+ return parts.map((p) => {
708
+ const d = describe(p);
709
+ return "fixed" in d ? { fixed: d.fixed, render: d.fixed, part: p } : { fixed: void 0, render: d.render, part: p };
710
+ });
711
+ }
712
+ function knownPrefixOfViews(views) {
713
+ let s = "";
714
+ for (const v2 of views) {
715
+ if (v2.fixed !== void 0) s += v2.fixed;
716
+ else break;
717
+ }
718
+ return s;
719
+ }
720
+ function knownSuffixOfViews(views) {
721
+ let s = "";
722
+ for (let i = views.length - 1; i >= 0; i--) {
723
+ const v2 = views[i];
724
+ if (v2.fixed !== void 0) s = v2.fixed + s;
725
+ else break;
726
+ }
727
+ return s;
728
+ }
729
+ function allFixedTextOfViews(views) {
730
+ return views.filter((v2) => v2.fixed !== void 0).map((v2) => v2.fixed).join("");
731
+ }
732
+ function fixedLengthOfViews(views) {
733
+ if (views.some((v2) => v2.fixed === void 0)) return void 0;
734
+ return allFixedTextOfViews(views).length;
735
+ }
736
+ function formatTemplateNameViews(views) {
737
+ const inner = views.map((v2) => v2.fixed !== void 0 ? v2.fixed : `\${${v2.render}}`).join("");
738
+ return `\`${inner}\``;
739
+ }
740
+ function mergeAdjacentFixedViews(views, rebuildFixed) {
741
+ const out = [];
742
+ for (const v2 of views) {
743
+ const last = out[out.length - 1];
744
+ if (last && last.fixed !== void 0 && v2.fixed !== void 0) {
745
+ out[out.length - 1] = rebuildFixed(last.fixed + v2.fixed);
746
+ } else {
747
+ out.push(v2);
748
+ }
749
+ }
750
+ return out;
751
+ }
752
+ function templateMatchesValue(value, views) {
753
+ let pos = 0;
754
+ for (let i = 0; i < views.length; i++) {
755
+ const v2 = views[i];
756
+ if (v2.fixed !== void 0) {
757
+ if (!value.startsWith(v2.fixed, pos)) return false;
758
+ pos += v2.fixed.length;
759
+ } else {
760
+ if (i === views.length - 1) return true;
761
+ const next = views[i + 1];
762
+ if (next?.fixed !== void 0) {
763
+ const idx = value.indexOf(next.fixed, pos);
764
+ if (idx === -1) return false;
765
+ pos = idx;
766
+ } else {
767
+ return true;
768
+ }
769
+ }
770
+ }
771
+ return pos === value.length;
772
+ }
773
+ function decideStartsWith(prefix, search) {
774
+ if (prefix.length >= search.length) return prefix.startsWith(search);
775
+ if (search.startsWith(prefix)) return "unknown";
776
+ return false;
777
+ }
778
+ function decideEndsWith(suffix, search) {
779
+ if (suffix.length >= search.length) return suffix.endsWith(search);
780
+ if (search.endsWith(suffix)) return "unknown";
781
+ return false;
782
+ }
783
+ function decideIncludes(fixedText, search) {
784
+ return fixedText.includes(search) ? true : "unknown";
785
+ }
706
786
  function isStrLit(a) {
707
787
  return a.shape.k === "prim" && a.shape.type === "string" && a.term?.op === "lit" && typeof a.term.value === "string";
708
788
  }
@@ -712,6 +792,13 @@ function isStrPrim2(a) {
712
792
  function isTemplateAbs(a) {
713
793
  return a.shape.k === "prim" && a.shape.type === "string" && !!a.pred && a.pred.name?.startsWith("`") === true && Array.isArray(a.pred.meta?.templateParts);
714
794
  }
795
+ function describeAbsPart(p) {
796
+ if (isStrLit(p)) return { fixed: String(litValue(p)) };
797
+ return { render: p.term ? termToString(p.term) : "string" };
798
+ }
799
+ function absTemplateViews(parts) {
800
+ return viewTemplateParts(parts, describeAbsPart);
801
+ }
715
802
  function templatePartsOf(a) {
716
803
  if (isTemplateAbs(a)) {
717
804
  const meta = a.pred.meta;
@@ -719,29 +806,18 @@ function templatePartsOf(a) {
719
806
  }
720
807
  return [a];
721
808
  }
809
+ function rebuildAbsFixedView(text) {
810
+ return {
811
+ fixed: text,
812
+ render: text,
813
+ part: abs({ k: "prim", type: "string" }, lit(text), void 0, "exact")
814
+ };
815
+ }
722
816
  function normalizeParts(parts) {
723
- const out = [];
724
- for (const p of parts) {
725
- const last = out[out.length - 1];
726
- if (last && isStrLit(last) && isStrLit(p)) {
727
- out[out.length - 1] = abs(
728
- { k: "prim", type: "string" },
729
- lit(String(litValue(last)) + String(litValue(p))),
730
- void 0,
731
- "exact"
732
- );
733
- } else {
734
- out.push(p);
735
- }
736
- }
737
- return out;
817
+ return mergeAdjacentFixedViews(absTemplateViews(parts), rebuildAbsFixedView).map((v2) => v2.part);
738
818
  }
739
819
  function formatTemplateName(parts) {
740
- const inner = parts.map((p) => {
741
- if (isStrLit(p)) return String(litValue(p));
742
- return `\${${p.term ? termToString(p.term) : "string"}}`;
743
- }).join("");
744
- return `\`${inner}\``;
820
+ return formatTemplateNameViews(absTemplateViews(parts));
745
821
  }
746
822
  function createTemplateAbs(parts) {
747
823
  const normalized = normalizeParts(parts);
@@ -793,6 +869,157 @@ function coerceToStringParts(a) {
793
869
  return void 0;
794
870
  }
795
871
 
872
+ // src/algebra/objects.ts
873
+ function objOf(slots, opts) {
874
+ const shape = { k: "obj", slots };
875
+ if (opts?.index) shape.index = opts.index;
876
+ if (opts?.open) shape.open = true;
877
+ return { shape, conf: "exact" };
878
+ }
879
+ function isObj(a) {
880
+ return a.shape.k === "obj";
881
+ }
882
+ function getSlot(slots, key) {
883
+ return Object.prototype.hasOwnProperty.call(slots, key) ? slots[key] : void 0;
884
+ }
885
+ function spread(base, over) {
886
+ if (!isObj(base) && !isObj(over)) {
887
+ if (isObj(over)) return { shape: { ...over.shape, open: true }, conf: confJoin(base.conf, over.conf) };
888
+ if (isObj(base)) return { shape: { ...base.shape, open: true }, conf: confJoin(base.conf, over.conf) };
889
+ return unknown;
890
+ }
891
+ if (!isObj(over)) {
892
+ if (!isObj(base)) return unknown;
893
+ return {
894
+ shape: { ...base.shape, open: true },
895
+ conf: confJoin(base.conf, "partial")
896
+ };
897
+ }
898
+ if (!isObj(base)) {
899
+ return { shape: { ...over.shape, open: true }, conf: confJoin(base.conf, over.conf) };
900
+ }
901
+ const slots = { ...base.shape.slots };
902
+ for (const [k, s] of Object.entries(over.shape.slots)) {
903
+ slots[k] = s;
904
+ }
905
+ const open = base.shape.open || over.shape.open || false;
906
+ const shape = { k: "obj", slots };
907
+ if (open) shape.open = true;
908
+ if (base.shape.index || over.shape.index) {
909
+ shape.index = over.shape.index ?? base.shape.index;
910
+ }
911
+ return { shape, conf: confJoin(base.conf, over.conf) };
912
+ }
913
+ function joinObjects(a, b) {
914
+ if (a.shape.k === "never") return b;
915
+ if (b.shape.k === "never") return a;
916
+ if (!isObj(a) || !isObj(b)) {
917
+ return makeSum(a, b);
918
+ }
919
+ const ka = Object.keys(a.shape.slots).sort();
920
+ const kb = Object.keys(b.shape.slots).sort();
921
+ const sameKeys = ka.length === kb.length && ka.every((k, i) => k === kb[i]);
922
+ if (!sameKeys) {
923
+ return makeSum(a, b);
924
+ }
925
+ const slots = {};
926
+ let conf = confJoin(a.conf, b.conf);
927
+ for (const k of ka) {
928
+ const sa = a.shape.slots[k];
929
+ const sb = b.shape.slots[k];
930
+ const optional = sa.optional || sb.optional;
931
+ const jv = joinValues(sa.value, sb.value);
932
+ conf = confJoin(conf, jv.conf);
933
+ slots[k] = { value: jv, optional };
934
+ }
935
+ return { shape: { k: "obj", slots }, conf };
936
+ }
937
+ function joinValues(a, b) {
938
+ if (a.shape.k === "never") return b;
939
+ if (b.shape.k === "never") return a;
940
+ const va = litValue(a);
941
+ const vb = litValue(b);
942
+ if (va !== void 0 && Object.is(va, vb)) return a;
943
+ if (a.shape.k === "prim" && b.shape.k === "prim" && a.shape.type === b.shape.type) {
944
+ if (va !== void 0 && vb !== void 0) {
945
+ return abs(
946
+ a.shape,
947
+ void 0,
948
+ void 0,
949
+ confJoin(a.conf, "path")
950
+ );
951
+ }
952
+ return abs(a.shape, void 0, void 0, confJoin(confJoin(a.conf, b.conf), "path"));
953
+ }
954
+ return makeSum(a, b);
955
+ }
956
+ function makeSum(a, b) {
957
+ const members = flattenSum([a, b]);
958
+ if (members.length === 1) return members[0];
959
+ return {
960
+ shape: { k: "sum", members },
961
+ conf: confJoin(a.conf, b.conf)
962
+ };
963
+ }
964
+ function flattenSum(xs) {
965
+ const out = [];
966
+ for (const x of xs) {
967
+ if (x.shape.k === "sum") out.push(...x.shape.members);
968
+ else out.push(x);
969
+ }
970
+ const seen = /* @__PURE__ */ new Set();
971
+ const deduped = [];
972
+ for (const x of out) {
973
+ const key = shapeKey(x);
974
+ if (seen.has(key)) continue;
975
+ seen.add(key);
976
+ deduped.push(x);
977
+ }
978
+ return deduped;
979
+ }
980
+ function shapeKey(a) {
981
+ const s = a.shape;
982
+ if (s.k === "prim") {
983
+ const lv = litValue(a);
984
+ if (lv !== void 0) return `prim:${s.type}:${String(lv)}`;
985
+ const t = a.term ? termToString(a.term) : "";
986
+ const p = a.pred && a.pred.op !== "true" ? predToString(a.pred) : "";
987
+ return `prim:${s.type}:${t}:${p}`;
988
+ }
989
+ if (s.k === "never") return "never";
990
+ if (s.k === "any") return "any";
991
+ if (s.k === "unknown") return "unknown";
992
+ if (s.k === "obj") return `obj:${Object.keys(s.slots).sort().join(",")}`;
993
+ if (s.k === "fn") return `fn:${s.params.length}`;
994
+ if (s.k === "sum") return `sum:${s.members.length}`;
995
+ return "other";
996
+ }
997
+ function fnOf(params, name) {
998
+ const shape = { k: "fn", params };
999
+ if (name) shape.name = name;
1000
+ return { shape, conf: "exact" };
1001
+ }
1002
+ function joinFunctions(a, b) {
1003
+ const sa = a.shape;
1004
+ const sb = b.shape;
1005
+ if (sa.k !== "fn" || sb.k !== "fn") return makeSum(a, b);
1006
+ const an = sa.name;
1007
+ const bn = sb.name;
1008
+ if (an && an === bn) {
1009
+ if (sa.params.length === sb.params.length && sa.params.every((p, i) => p === sb.params[i])) {
1010
+ return a;
1011
+ }
1012
+ }
1013
+ return makeSum(a, b);
1014
+ }
1015
+ function joinAbs(a, b) {
1016
+ if (a.shape.k === "never") return b;
1017
+ if (b.shape.k === "never") return a;
1018
+ if (isObj(a) && isObj(b)) return joinObjects(a, b);
1019
+ if (a.shape.k === "fn" && b.shape.k === "fn") return joinFunctions(a, b);
1020
+ return joinValues(a, b);
1021
+ }
1022
+
796
1023
  // src/algebra/arithmetic.ts
797
1024
  function add(a, b, phi2 = pTrue) {
798
1025
  const va = litValue(a);
@@ -1220,6 +1447,20 @@ function compareLits(op, a, b) {
1220
1447
  return a >= b;
1221
1448
  }
1222
1449
  }
1450
+ if (op === "lt" || op === "le" || op === "gt" || op === "ge") {
1451
+ const x = a;
1452
+ const y = b;
1453
+ switch (op) {
1454
+ case "lt":
1455
+ return x < y;
1456
+ case "le":
1457
+ return x <= y;
1458
+ case "gt":
1459
+ return x > y;
1460
+ case "ge":
1461
+ return x >= y;
1462
+ }
1463
+ }
1223
1464
  return void 0;
1224
1465
  }
1225
1466
  function decideByBounds(op, a, b, phi2) {
@@ -1258,6 +1499,34 @@ function trueConstraint(c) {
1258
1499
  if (c.term?.op === "lit" && c.term.value === false) return void 0;
1259
1500
  return c.pred;
1260
1501
  }
1502
+ function refineAbsForRelTrue(a, op, k) {
1503
+ const bound = (t) => op === "gt" ? gt(t, lit(k)) : op === "ge" ? ge(t, lit(k)) : op === "lt" ? lt(t, lit(k)) : le(t, lit(k));
1504
+ if (isNumPrim(a) && a.term) {
1505
+ const pred = a.pred && a.pred.op !== "true" ? and(a.pred, bound(a.term)) : bound(a.term);
1506
+ return abs(a.shape, a.term, pred, a.conf);
1507
+ }
1508
+ if (isStrPrim(a)) return a;
1509
+ if ((a.shape.k === "any" || a.shape.k === "unknown") && a.term) {
1510
+ const numArm = abs({ k: "prim", type: "number" }, a.term, bound(a.term), "path");
1511
+ const strArm = abs({ k: "prim", type: "string" }, a.term, void 0, "path");
1512
+ return makeSum(numArm, strArm);
1513
+ }
1514
+ return a;
1515
+ }
1516
+ function matchRelIdentLit(test) {
1517
+ const t = test;
1518
+ if (t?.type !== "BinaryExpression") return void 0;
1519
+ const rel = t.operator === ">" ? "gt" : t.operator === ">=" ? "ge" : t.operator === "<" ? "lt" : t.operator === "<=" ? "le" : void 0;
1520
+ if (!rel) return void 0;
1521
+ if (t.left?.type === "Identifier" && t.left.name && t.right?.type === "NumericLiteral" && typeof t.right.value === "number") {
1522
+ return { name: t.left.name, op: rel, k: t.right.value };
1523
+ }
1524
+ if (t.right?.type === "Identifier" && t.right.name && t.left?.type === "NumericLiteral" && typeof t.left.value === "number") {
1525
+ const flipped = rel === "gt" ? "lt" : rel === "ge" ? "le" : rel === "lt" ? "gt" : "ge";
1526
+ return { name: t.right.name, op: flipped, k: t.left.value };
1527
+ }
1528
+ return void 0;
1529
+ }
1261
1530
  function falseConstraint(c) {
1262
1531
  if (c.term?.op === "lit" && c.term.value === true) return void 0;
1263
1532
  if (c.term?.op === "lit" && c.term.value === false) return pTrue;
@@ -1450,169 +1719,13 @@ function strictEqAbs(a, b) {
1450
1719
  return void 0;
1451
1720
  }
1452
1721
 
1453
- // src/algebra/objects.ts
1454
- function objOf(slots, opts) {
1455
- const shape = { k: "obj", slots };
1456
- if (opts?.index) shape.index = opts.index;
1457
- if (opts?.open) shape.open = true;
1458
- return { shape, conf: "exact" };
1459
- }
1460
- function isObj(a) {
1461
- return a.shape.k === "obj";
1462
- }
1463
- function spread(base, over) {
1464
- if (!isObj(base) && !isObj(over)) {
1465
- if (isObj(over)) return { shape: { ...over.shape, open: true }, conf: confJoin(base.conf, over.conf) };
1466
- if (isObj(base)) return { shape: { ...base.shape, open: true }, conf: confJoin(base.conf, over.conf) };
1467
- return unknown;
1468
- }
1469
- if (!isObj(over)) {
1470
- if (!isObj(base)) return unknown;
1471
- return {
1472
- shape: { ...base.shape, open: true },
1473
- conf: confJoin(base.conf, "partial")
1474
- };
1475
- }
1476
- if (!isObj(base)) {
1477
- return { shape: { ...over.shape, open: true }, conf: confJoin(base.conf, over.conf) };
1478
- }
1479
- const slots = { ...base.shape.slots };
1480
- for (const [k, s] of Object.entries(over.shape.slots)) {
1481
- slots[k] = s;
1482
- }
1483
- const open = base.shape.open || over.shape.open || false;
1484
- const shape = { k: "obj", slots };
1485
- if (open) shape.open = true;
1486
- if (base.shape.index || over.shape.index) {
1487
- shape.index = over.shape.index ?? base.shape.index;
1488
- }
1489
- return { shape, conf: confJoin(base.conf, over.conf) };
1490
- }
1491
- function joinObjects(a, b) {
1492
- if (a.shape.k === "never") return b;
1493
- if (b.shape.k === "never") return a;
1494
- if (!isObj(a) || !isObj(b)) {
1495
- return makeSum(a, b);
1496
- }
1497
- const ka = Object.keys(a.shape.slots).sort();
1498
- const kb = Object.keys(b.shape.slots).sort();
1499
- const sameKeys = ka.length === kb.length && ka.every((k, i) => k === kb[i]);
1500
- if (!sameKeys) {
1501
- return makeSum(a, b);
1502
- }
1503
- const slots = {};
1504
- let conf = confJoin(a.conf, b.conf);
1505
- for (const k of ka) {
1506
- const sa = a.shape.slots[k];
1507
- const sb = b.shape.slots[k];
1508
- const optional = sa.optional || sb.optional;
1509
- const jv = joinValues(sa.value, sb.value);
1510
- conf = confJoin(conf, jv.conf);
1511
- slots[k] = { value: jv, optional };
1512
- }
1513
- return { shape: { k: "obj", slots }, conf };
1722
+ // src/algebra/containers.ts
1723
+ var TUPLE_LITERAL_CAP = 8;
1724
+ function shouldWidenArrayLiteral(n) {
1725
+ return n > TUPLE_LITERAL_CAP;
1514
1726
  }
1515
- function joinValues(a, b) {
1516
- if (a.shape.k === "never") return b;
1517
- if (b.shape.k === "never") return a;
1518
- const va = litValue(a);
1519
- const vb = litValue(b);
1520
- if (va !== void 0 && va === vb) return a;
1521
- if (a.shape.k === "prim" && b.shape.k === "prim" && a.shape.type === b.shape.type) {
1522
- if (va !== void 0 && vb !== void 0) {
1523
- return abs(
1524
- a.shape,
1525
- void 0,
1526
- void 0,
1527
- confJoin(a.conf, "path")
1528
- );
1529
- }
1530
- return abs(a.shape, void 0, void 0, confJoin(confJoin(a.conf, b.conf), "path"));
1531
- }
1532
- return makeSum(a, b);
1533
- }
1534
- function makeSum(a, b) {
1535
- const members = flattenSum([a, b]);
1536
- if (members.length === 1) return members[0];
1537
- return {
1538
- shape: { k: "sum", members },
1539
- conf: confJoin(a.conf, b.conf)
1540
- };
1541
- }
1542
- function flattenSum(xs) {
1543
- const out = [];
1544
- for (const x of xs) {
1545
- if (x.shape.k === "sum") out.push(...x.shape.members);
1546
- else out.push(x);
1547
- }
1548
- const seen = /* @__PURE__ */ new Set();
1549
- const deduped = [];
1550
- for (const x of out) {
1551
- const key = shapeKey(x);
1552
- if (seen.has(key)) continue;
1553
- seen.add(key);
1554
- deduped.push(x);
1555
- }
1556
- return deduped;
1557
- }
1558
- function shapeKey(a) {
1559
- const s = a.shape;
1560
- if (s.k === "prim") return `prim:${s.type}`;
1561
- if (s.k === "never") return "never";
1562
- if (s.k === "any") return "any";
1563
- if (s.k === "unknown") return "unknown";
1564
- if (s.k === "obj") return `obj:${Object.keys(s.slots).sort().join(",")}`;
1565
- if (s.k === "fn") return `fn:${s.params.length}`;
1566
- if (s.k === "sum") return `sum:${s.members.length}`;
1567
- return "other";
1568
- }
1569
- function collapseToOptional(sum) {
1570
- if (sum.shape.k !== "sum") {
1571
- if (isObj(sum)) return { ...sum, conf: confJoin(sum.conf, "widened") };
1572
- return sum;
1573
- }
1574
- const objs = sum.shape.members.filter(isObj);
1575
- if (objs.length === 0) {
1576
- return abs({ k: "unknown" }, void 0, void 0, "widened");
1577
- }
1578
- const allKeys = /* @__PURE__ */ new Set();
1579
- for (const o of objs) {
1580
- for (const k of Object.keys(o.shape.slots)) allKeys.add(k);
1581
- }
1582
- const slots = {};
1583
- for (const k of allKeys) {
1584
- const present = objs.filter((o) => k in o.shape.slots);
1585
- const values = present.map((o) => o.shape.slots[k].value);
1586
- const joined = values.reduce((acc, v2) => joinValues(acc, v2));
1587
- const optional = present.length < objs.length;
1588
- slots[k] = { value: joined, optional };
1589
- }
1590
- return { shape: { k: "obj", slots }, conf: "widened" };
1591
- }
1592
- function fnOf(params, name) {
1593
- const shape = { k: "fn", params };
1594
- if (name) shape.name = name;
1595
- return { shape, conf: "exact" };
1596
- }
1597
- function joinFunctions(a, b) {
1598
- const sa = a.shape;
1599
- const sb = b.shape;
1600
- if (sa.k !== "fn" || sb.k !== "fn") return makeSum(a, b);
1601
- const an = sa.name;
1602
- const bn = sb.name;
1603
- if (an && an === bn) {
1604
- if (sa.params.length === sb.params.length && sa.params.every((p, i) => p === sb.params[i])) {
1605
- return a;
1606
- }
1607
- }
1608
- return makeSum(a, b);
1609
- }
1610
- function joinAbs(a, b) {
1611
- if (a.shape.k === "never") return b;
1612
- if (b.shape.k === "never") return a;
1613
- if (isObj(a) && isObj(b)) return joinObjects(a, b);
1614
- if (a.shape.k === "fn" && b.shape.k === "fn") return joinFunctions(a, b);
1615
- return joinValues(a, b);
1727
+ function widenedArrayConf() {
1728
+ return "path";
1616
1729
  }
1617
1730
 
1618
1731
  // src/algebra/language.ts
@@ -1728,8 +1841,8 @@ function litFalse() {
1728
1841
  function projectBrand(self, key) {
1729
1842
  if (self.shape.k !== "brand") return unknown;
1730
1843
  const inner = self.shape.shape;
1731
- if (inner.shape.k === "obj") {
1732
- const slot = inner.shape.slots[key];
1844
+ if (inner && inner.shape.k === "obj") {
1845
+ const slot = getSlot(inner.shape.slots, key);
1733
1846
  if (slot) return slot.value;
1734
1847
  }
1735
1848
  return unknown;
@@ -1918,7 +2031,7 @@ function leqShape(src, tgt, phi2, env, depth) {
1918
2031
  const srcObj = s.k === "obj" ? s : s.k === "brand" ? s.shape.shape.k === "obj" ? s.shape.shape : null : null;
1919
2032
  if (!srcObj || srcObj.k !== "obj") return fail(`shape ${s.k} \u22AD obj`);
1920
2033
  for (const [key, slot] of Object.entries(t.slots)) {
1921
- const srcSlot = srcObj.slots[key];
2034
+ const srcSlot = getSlot(srcObj.slots, key);
1922
2035
  if (!srcSlot) {
1923
2036
  if (slot.optional) continue;
1924
2037
  return fail(`missing slot ${key}`);
@@ -2164,9 +2277,29 @@ function evalArrayStatic(name, args) {
2164
2277
  const k = a0.shape.k;
2165
2278
  return boolLit(k === "arr" || k === "tuple");
2166
2279
  }
2167
- case "from":
2168
2280
  case "of":
2169
2281
  return abs({ k: "arr", element: a0 ?? unknown }, void 0, void 0, "path");
2282
+ case "from": {
2283
+ if (!a0) return unknown;
2284
+ const k = a0.shape.k;
2285
+ if (k === "arr") return a0;
2286
+ if (k === "tuple") {
2287
+ const els = a0.shape.elements;
2288
+ if (els.length === 0) return abs({ k: "arr", element: unknown }, void 0, void 0, "path");
2289
+ let el = els[0];
2290
+ for (let i = 1; i < els.length; i++) el = joinAbs(el, els[i]);
2291
+ return abs({ k: "arr", element: el }, void 0, void 0, "path");
2292
+ }
2293
+ if (k === "prim" && a0.shape.type === "string") {
2294
+ return abs(
2295
+ { k: "arr", element: abs({ k: "prim", type: "string" }, void 0, void 0, "path") },
2296
+ void 0,
2297
+ void 0,
2298
+ "path"
2299
+ );
2300
+ }
2301
+ return unknown;
2302
+ }
2170
2303
  default:
2171
2304
  return void 0;
2172
2305
  }
@@ -2518,10 +2651,10 @@ function parseUncached(source, opts) {
2518
2651
  attachComment: true,
2519
2652
  errorRecovery: opts?.errorRecovery === true
2520
2653
  });
2521
- return stripTypes(ast);
2654
+ return opts?.keepTs === true ? ast : stripTypes(ast);
2522
2655
  }
2523
2656
  function parseSource(source, opts) {
2524
- if (opts?.errorRecovery === true) {
2657
+ if (opts?.keepTs === true || opts?.errorRecovery === true) {
2525
2658
  return parseUncached(source, opts);
2526
2659
  }
2527
2660
  if (source.length > MAX_AST_SOURCE_CHARS) {
@@ -3127,29 +3260,6 @@ function numPrim2(conf = "path") {
3127
3260
  function strArr(conf = "path") {
3128
3261
  return abs({ k: "arr", element: strPrim2("path") }, void 0, void 0, conf);
3129
3262
  }
3130
- function knownPrefix(parts) {
3131
- let s = "";
3132
- for (const p of parts) {
3133
- if (p.term?.op === "lit" && typeof p.term.value === "string") s += p.term.value;
3134
- else break;
3135
- }
3136
- return s;
3137
- }
3138
- function knownSuffix(parts) {
3139
- let s = "";
3140
- for (let i = parts.length - 1; i >= 0; i--) {
3141
- const p = parts[i];
3142
- if (p.term?.op === "lit" && typeof p.term.value === "string") s = p.term.value + s;
3143
- else break;
3144
- }
3145
- return s;
3146
- }
3147
- function fixedLength(parts) {
3148
- if (parts.some((p) => !(p.term?.op === "lit" && typeof p.term.value === "string"))) {
3149
- return void 0;
3150
- }
3151
- return parts.reduce((n, p) => n + String(p.term && p.term.op === "lit" ? p.term.value : "").length, 0);
3152
- }
3153
3263
  function isStrRecv(recv) {
3154
3264
  return isTemplateLike(recv) || recv.shape.k === "prim" && recv.shape.type === "string" || recv.term?.op === "lit" && typeof recv.term.value === "string";
3155
3265
  }
@@ -3158,27 +3268,24 @@ function callAbsMethod(recv, name, args) {
3158
3268
  const a0 = args[0] ? litValue(args[0]) : void 0;
3159
3269
  const lit3 = recv.term?.op === "lit" && typeof recv.term.value === "string" ? recv.term.value : void 0;
3160
3270
  if (isTemplateLike(recv)) {
3161
- const parts = templatePartsOf(recv);
3162
- const prefix = knownPrefix(parts);
3163
- const suffix = knownSuffix(parts);
3271
+ const views = absTemplateViews(templatePartsOf(recv));
3272
+ const prefix = knownPrefixOfViews(views);
3273
+ const suffix = knownSuffixOfViews(views);
3164
3274
  switch (name) {
3165
3275
  case "startsWith": {
3166
3276
  if (typeof a0 !== "string") return boolPrim2();
3167
- if (prefix.length >= a0.length) return boolLit(prefix.startsWith(a0));
3168
- if (a0.startsWith(prefix)) return boolPrim2();
3169
- return boolLit(false);
3277
+ const d = decideStartsWith(prefix, a0);
3278
+ return d === "unknown" ? boolPrim2() : boolLit(d);
3170
3279
  }
3171
3280
  case "endsWith": {
3172
3281
  if (typeof a0 !== "string") return boolPrim2();
3173
- if (suffix.length >= a0.length) return boolLit(suffix.endsWith(a0));
3174
- if (a0.startsWith(prefix)) return boolPrim2();
3175
- return boolLit(false);
3282
+ const d = decideEndsWith(suffix, a0);
3283
+ return d === "unknown" ? boolPrim2() : boolLit(d);
3176
3284
  }
3177
3285
  case "includes": {
3178
3286
  if (typeof a0 !== "string") return boolPrim2();
3179
- const fixed = parts.filter((p) => p.term?.op === "lit" && typeof p.term.value === "string").map((p) => String(p.term && p.term.op === "lit" ? p.term.value : "")).join("");
3180
- if (fixed.includes(a0)) return boolLit(true);
3181
- return boolPrim2();
3287
+ const d = decideIncludes(allFixedTextOfViews(views), a0);
3288
+ return d === "unknown" ? boolPrim2() : boolLit(d);
3182
3289
  }
3183
3290
  case "toUpperCase":
3184
3291
  case "toLowerCase":
@@ -3264,8 +3371,7 @@ function callAbsMethod(recv, name, args) {
3264
3371
  function getAbsProperty(recv, name) {
3265
3372
  if (name === "length") {
3266
3373
  if (isTemplateLike(recv)) {
3267
- const parts = templatePartsOf(recv);
3268
- const n = fixedLength(parts);
3374
+ const n = fixedLengthOfViews(absTemplateViews(templatePartsOf(recv)));
3269
3375
  if (n !== void 0) return numLit(n);
3270
3376
  return numPrim2("path");
3271
3377
  }
@@ -3581,9 +3687,18 @@ function recordAbsNode(node, value) {
3581
3687
  }
3582
3688
  }
3583
3689
  var absAssignCollector = null;
3690
+ var assignFlowDepth = 0;
3584
3691
  function setAbsAssignCollector(collector) {
3585
3692
  absAssignCollector = collector;
3586
3693
  }
3694
+ function evalInConditionalFlow(body) {
3695
+ assignFlowDepth++;
3696
+ try {
3697
+ return body();
3698
+ } finally {
3699
+ assignFlowDepth--;
3700
+ }
3701
+ }
3587
3702
  function recordAbsAssign(name, prev, next, loc) {
3588
3703
  if (!absAssignCollector) return;
3589
3704
  try {
@@ -3592,7 +3707,8 @@ function recordAbsAssign(name, prev, next, loc) {
3592
3707
  prev,
3593
3708
  next,
3594
3709
  line: loc?.start.line,
3595
- column: loc?.start.column
3710
+ column: loc?.start.column,
3711
+ conditional: assignFlowDepth > 0
3596
3712
  });
3597
3713
  } catch {
3598
3714
  }
@@ -3970,14 +4086,14 @@ function evalNodeInner(node, env, phi2, budget) {
3970
4086
  }
3971
4087
  if (!m.computed && m.property.type === "Identifier" && obj2.shape.k === "obj") {
3972
4088
  const key = m.property.name;
3973
- const slot = obj2.shape.slots[key];
4089
+ const slot = getSlot(obj2.shape.slots, key);
3974
4090
  if (slot) return ok2(slot.value, phi2, env);
3975
4091
  }
3976
4092
  if (m.computed) {
3977
4093
  const key = evalNode(m.property, env, phi2, budget).value;
3978
4094
  const kl = litValue(key);
3979
4095
  if (typeof kl === "string" && obj2.shape.k === "obj") {
3980
- const slot = obj2.shape.slots[kl];
4096
+ const slot = getSlot(obj2.shape.slots, kl);
3981
4097
  if (slot) return ok2(slot.value, phi2, env);
3982
4098
  }
3983
4099
  if (typeof kl === "number") {
@@ -4029,11 +4145,11 @@ function evalNodeInner(node, env, phi2, budget) {
4029
4145
  if (els.length === 0) {
4030
4146
  return ok2(abs({ k: "arr", element: unknown }, void 0, void 0, "exact"), phi2, env);
4031
4147
  }
4032
- if (els.length <= 8) {
4148
+ if (!shouldWidenArrayLiteral(els.length)) {
4033
4149
  return ok2(abs({ k: "tuple", elements: els }, void 0, void 0, "exact"), phi2, env);
4034
4150
  }
4035
4151
  const elem = els.reduce((x, y) => joinAbs(x, y));
4036
- return ok2(abs({ k: "arr", element: elem }, void 0, void 0, "path"), phi2, env);
4152
+ return ok2(abs({ k: "arr", element: elem }, void 0, void 0, widenedArrayConf()), phi2, env);
4037
4153
  }
4038
4154
  default:
4039
4155
  return ok2(unknown, phi2, env);
@@ -4553,7 +4669,7 @@ function evalFor(node, env, phi2, budget) {
4553
4669
  const lv = litValue(t.value);
4554
4670
  if (lv === false || lv === null || lv === void 0) break;
4555
4671
  }
4556
- const bodyR = evalNode(node.body, local, phi2, budget);
4672
+ const bodyR = evalInConditionalFlow(() => evalNode(node.body, local, phi2, budget));
4557
4673
  if (bodyR.returned) return bodyR;
4558
4674
  if (bodyR.threw) return bodyR;
4559
4675
  if (bodyR.brk) {
@@ -4576,7 +4692,7 @@ function evalWhile(node, env, phi2, budget) {
4576
4692
  const t = evalNode(node.test, local, phi2, budget);
4577
4693
  const lv = litValue(t.value);
4578
4694
  if (lv === false || lv === null || lv === void 0) break;
4579
- const bodyR = evalNode(node.body, local, phi2, budget);
4695
+ const bodyR = evalInConditionalFlow(() => evalNode(node.body, local, phi2, budget));
4580
4696
  if (bodyR.returned || bodyR.threw) return bodyR;
4581
4697
  if (bodyR.brk) {
4582
4698
  local = bodyR.env;
@@ -4591,7 +4707,7 @@ function evalDoWhile(node, env, phi2, budget) {
4591
4707
  let local = env;
4592
4708
  let acc = unknown;
4593
4709
  for (let i = 0; i < MAX_LOOP_ITERS; i++) {
4594
- const bodyR = evalNode(node.body, local, phi2, budget);
4710
+ const bodyR = evalInConditionalFlow(() => evalNode(node.body, local, phi2, budget));
4595
4711
  if (bodyR.returned || bodyR.threw) return bodyR;
4596
4712
  if (bodyR.brk) {
4597
4713
  local = bodyR.env;
@@ -4628,7 +4744,7 @@ function evalForOf(node, env, phi2, budget) {
4628
4744
  const n = Math.min(elements.length, MAX_LOOP_ITERS);
4629
4745
  for (let i = 0; i < n; i++) {
4630
4746
  local = withVar(local, bindName, elements[i]);
4631
- const bodyR = evalNode(node.body, local, phi2, budget);
4747
+ const bodyR = evalInConditionalFlow(() => evalNode(node.body, local, phi2, budget));
4632
4748
  if (bodyR.returned || bodyR.threw) return bodyR;
4633
4749
  if (bodyR.brk) {
4634
4750
  local = bodyR.env;
@@ -4687,8 +4803,15 @@ function evalVarDecl(node, env, phi2, budget) {
4687
4803
  function evalIf(node, env, phi2, budget) {
4688
4804
  const t = evalNode(node.test, env, phi2, budget).value;
4689
4805
  const tv = litValue(t);
4806
+ const refineEnv = (branch) => {
4807
+ const m = matchRelIdentLit(node.test);
4808
+ if (!m || branch !== "true") return env;
4809
+ const cur = env.vars.get(m.name);
4810
+ if (!cur) return env;
4811
+ return withVar(env, m.name, refineAbsForRelTrue(cur, m.op, m.k));
4812
+ };
4690
4813
  if (tv === true) {
4691
- return evalNode(node.consequent, env, phi2, budget);
4814
+ return evalNode(node.consequent, refineEnv("true"), phi2, budget);
4692
4815
  }
4693
4816
  if (tv === false) {
4694
4817
  if (node.alternate) return evalNode(node.alternate, env, phi2, budget);
@@ -4696,9 +4819,15 @@ function evalIf(node, env, phi2, budget) {
4696
4819
  }
4697
4820
  const tCons = trueConstraint(t);
4698
4821
  const fCons = falseConstraint(t);
4699
- const a = evalNode(node.consequent, env, tCons ? and(phi2, tCons) : phi2, budget);
4700
- if (node.alternate) {
4701
- const b = evalNode(node.alternate, env, fCons ? and(phi2, fCons) : phi2, budget);
4822
+ const envT = refineEnv("true");
4823
+ const a = evalInConditionalFlow(
4824
+ () => evalNode(node.consequent, envT, tCons ? and(phi2, tCons) : phi2, budget)
4825
+ );
4826
+ const alt = node.alternate;
4827
+ if (alt) {
4828
+ const b = evalInConditionalFlow(
4829
+ () => evalNode(alt, env, fCons ? and(phi2, fCons) : phi2, budget)
4830
+ );
4702
4831
  return { value: joinAbs(a.value, b.value), phi: phi2, env, returned: a.returned || b.returned };
4703
4832
  }
4704
4833
  if (a.returned || a.threw) {
@@ -5062,8 +5191,19 @@ function $for(init, test, step, body, maxIters = DEFAULT_MAX_LOOP_ITERS) {
5062
5191
  }
5063
5192
  return exitJoin ? joinAbs(exitJoin, state) : state;
5064
5193
  }
5194
+ function tupleOrWiden(els, conf) {
5195
+ if (shouldWidenArrayLiteral(els.length)) {
5196
+ return abs(
5197
+ { k: "arr", element: els.reduce((x, y) => joinAbs(x, y)) },
5198
+ void 0,
5199
+ void 0,
5200
+ widenedArrayConf()
5201
+ );
5202
+ }
5203
+ return abs({ k: "tuple", elements: els }, void 0, void 0, conf);
5204
+ }
5065
5205
  function $arr(items) {
5066
- return abs({ k: "tuple", elements: items.map(asAbsVal) }, void 0, void 0, "exact");
5206
+ return tupleOrWiden(items.map(asAbsVal), "exact");
5067
5207
  }
5068
5208
  function $idx(a, i) {
5069
5209
  const iv = litValue(i);
@@ -5142,33 +5282,33 @@ function $spread(a, b) {
5142
5282
  function $concat(a, b) {
5143
5283
  a = asAbsVal(a);
5144
5284
  b = asAbsVal(b);
5145
- if (a.shape.k === "tuple" && b.shape.k === "tuple") {
5146
- return abs(
5147
- { k: "tuple", elements: [...a.shape.elements, ...b.shape.elements] },
5148
- void 0,
5149
- void 0,
5150
- confJoin(a.conf, b.conf)
5151
- );
5285
+ const as = a.shape;
5286
+ const bs = b.shape;
5287
+ if (as.k === "tuple" && bs.k === "tuple") {
5288
+ return tupleOrWiden([...as.elements, ...bs.elements], confJoin(a.conf, b.conf));
5289
+ }
5290
+ if (as.k === "arr" || bs.k === "arr") {
5291
+ const ea = as.k === "tuple" ? as.elements.reduce((x, y) => joinAbs(x, y)) : as.k === "arr" ? as.element : a;
5292
+ const eb = bs.k === "tuple" ? bs.elements.reduce((x, y) => joinAbs(x, y)) : bs.k === "arr" ? bs.element : b;
5293
+ return abs({ k: "arr", element: joinAbs(ea, eb) }, void 0, void 0, "path");
5152
5294
  }
5153
- if (a.shape.k === "tuple" && b.shape.k !== "tuple") {
5295
+ if (as.k === "tuple") {
5154
5296
  return abs(
5155
- { k: "tuple", elements: [...a.shape.elements, b] },
5297
+ { k: "tuple", elements: [...as.elements, b] },
5156
5298
  void 0,
5157
5299
  void 0,
5158
5300
  confJoin(a.conf, b.conf)
5159
5301
  );
5160
5302
  }
5161
- if (a.shape.k !== "tuple" && b.shape.k === "tuple") {
5303
+ if (bs.k === "tuple") {
5162
5304
  return abs(
5163
- { k: "tuple", elements: [a, ...b.shape.elements] },
5305
+ { k: "tuple", elements: [a, ...bs.elements] },
5164
5306
  void 0,
5165
5307
  void 0,
5166
5308
  confJoin(a.conf, b.conf)
5167
5309
  );
5168
5310
  }
5169
- const ea = a.shape.k === "arr" ? a.shape.element : a;
5170
- const eb = b.shape.k === "arr" ? b.shape.element : b;
5171
- return abs({ k: "arr", element: joinAbs(ea, eb) }, void 0, void 0, "path");
5311
+ return abs({ k: "arr", element: joinAbs(a, b) }, void 0, void 0, "path");
5172
5312
  }
5173
5313
  function $elems(a) {
5174
5314
  if (a.shape.k === "tuple") return [...a.shape.elements];
@@ -6961,10 +7101,6 @@ function callTranspiledExport(exports, name, args) {
6961
7101
  }
6962
7102
 
6963
7103
  export {
6964
- stripTypes,
6965
- resetParseSourceCache,
6966
- getParseSourceCacheSize,
6967
- parseSource,
6968
7104
  lit,
6969
7105
  v,
6970
7106
  app,
@@ -7014,6 +7150,26 @@ export {
7014
7150
  isStrPrim,
7015
7151
  isExactLit,
7016
7152
  litValue,
7153
+ viewTemplateParts,
7154
+ knownPrefixOfViews,
7155
+ knownSuffixOfViews,
7156
+ allFixedTextOfViews,
7157
+ fixedLengthOfViews,
7158
+ formatTemplateNameViews,
7159
+ mergeAdjacentFixedViews,
7160
+ templateMatchesValue,
7161
+ decideStartsWith,
7162
+ decideEndsWith,
7163
+ decideIncludes,
7164
+ absTemplateViews,
7165
+ templatePartsOf,
7166
+ createTemplateAbs,
7167
+ isTemplateLike,
7168
+ concatString,
7169
+ stripTypes,
7170
+ resetParseSourceCache,
7171
+ getParseSourceCacheSize,
7172
+ parseSource,
7017
7173
  attachFnImpl,
7018
7174
  getFnImpl,
7019
7175
  absFunction,
@@ -7022,11 +7178,11 @@ export {
7022
7178
  shapeOnlyFn,
7023
7179
  objOf,
7024
7180
  isObj,
7181
+ getSlot,
7025
7182
  spread,
7026
7183
  joinObjects,
7027
7184
  joinValues,
7028
7185
  makeSum,
7029
- collapseToOptional,
7030
7186
  fnOf,
7031
7187
  joinFunctions,
7032
7188
  joinAbs,
@@ -7049,18 +7205,15 @@ export {
7049
7205
  mapElementFallback,
7050
7206
  projectFlatMapResult,
7051
7207
  asAbs,
7052
- templatePartsOf,
7053
- createTemplateAbs,
7054
- isTemplateLike,
7055
- concatString,
7056
7208
  add,
7057
- numericBounds,
7058
7209
  sub,
7059
7210
  mul,
7060
7211
  div,
7061
7212
  mod,
7062
7213
  cmp,
7063
7214
  trueConstraint,
7215
+ refineAbsForRelTrue,
7216
+ matchRelIdentLit,
7064
7217
  falseConstraint,
7065
7218
  typeofAbs,
7066
7219
  negAbs,