@nudojs/core 0.4.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-N7E2A7IK.js → chunk-P3G2TODS.js} +760 -296
- package/dist/exec.d.ts +1 -1
- package/dist/exec.js +1 -1
- package/dist/{index-DgyudAkw.d.ts → index-FITqyJ8v.d.ts} +22 -172
- package/dist/index.d.ts +727 -236
- package/dist/index.js +3788 -2676
- package/package.json +14 -2
|
@@ -309,11 +309,18 @@ var phiAnd = and;
|
|
|
309
309
|
function implies(phi2, pred) {
|
|
310
310
|
if (pred.op === "true") return true;
|
|
311
311
|
if (pred.op === "false") return false;
|
|
312
|
+
if (phi2.op === "false") return true;
|
|
313
|
+
if (predEquals(phi2, pred)) return true;
|
|
314
|
+
if (phi2.op === "and" && phi2.args.some((c) => predEquals(c, pred))) return true;
|
|
315
|
+
if (phi2.op === "or") {
|
|
316
|
+
return phi2.args.every((a) => implies(a, pred));
|
|
317
|
+
}
|
|
318
|
+
if (pred.op === "or") {
|
|
319
|
+
return pred.args.some((b) => implies(phi2, b));
|
|
320
|
+
}
|
|
312
321
|
if (phi2.op === "true") {
|
|
313
322
|
return decideLiteralPred(pred) === true;
|
|
314
323
|
}
|
|
315
|
-
if (predEquals(phi2, pred)) return true;
|
|
316
|
-
if (phi2.op === "and" && phi2.args.some((c) => predEquals(c, pred))) return true;
|
|
317
324
|
const bounds = extractBounds(phi2);
|
|
318
325
|
const implied = impliesViaBounds(pred, bounds);
|
|
319
326
|
if (implied !== void 0) return implied;
|
|
@@ -703,6 +710,86 @@ function shapeOnlyFn(paramTypes, returnType, opts) {
|
|
|
703
710
|
}
|
|
704
711
|
|
|
705
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
|
+
}
|
|
706
793
|
function isStrLit(a) {
|
|
707
794
|
return a.shape.k === "prim" && a.shape.type === "string" && a.term?.op === "lit" && typeof a.term.value === "string";
|
|
708
795
|
}
|
|
@@ -712,6 +799,13 @@ function isStrPrim2(a) {
|
|
|
712
799
|
function isTemplateAbs(a) {
|
|
713
800
|
return a.shape.k === "prim" && a.shape.type === "string" && !!a.pred && a.pred.name?.startsWith("`") === true && Array.isArray(a.pred.meta?.templateParts);
|
|
714
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
|
+
}
|
|
715
809
|
function templatePartsOf(a) {
|
|
716
810
|
if (isTemplateAbs(a)) {
|
|
717
811
|
const meta = a.pred.meta;
|
|
@@ -719,29 +813,18 @@ function templatePartsOf(a) {
|
|
|
719
813
|
}
|
|
720
814
|
return [a];
|
|
721
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
|
+
}
|
|
722
823
|
function normalizeParts(parts) {
|
|
723
|
-
|
|
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;
|
|
824
|
+
return mergeAdjacentFixedViews(absTemplateViews(parts), rebuildAbsFixedView).map((v2) => v2.part);
|
|
738
825
|
}
|
|
739
826
|
function formatTemplateName(parts) {
|
|
740
|
-
|
|
741
|
-
if (isStrLit(p)) return String(litValue(p));
|
|
742
|
-
return `\${${p.term ? termToString(p.term) : "string"}}`;
|
|
743
|
-
}).join("");
|
|
744
|
-
return `\`${inner}\``;
|
|
827
|
+
return formatTemplateNameViews(absTemplateViews(parts));
|
|
745
828
|
}
|
|
746
829
|
function createTemplateAbs(parts) {
|
|
747
830
|
const normalized = normalizeParts(parts);
|
|
@@ -793,6 +876,324 @@ function coerceToStringParts(a) {
|
|
|
793
876
|
return void 0;
|
|
794
877
|
}
|
|
795
878
|
|
|
879
|
+
// src/algebra/derivation.ts
|
|
880
|
+
var collector = null;
|
|
881
|
+
var nextId = 1;
|
|
882
|
+
var byAbs = /* @__PURE__ */ new WeakMap();
|
|
883
|
+
var sessionNodes = null;
|
|
884
|
+
function setDerivationCollector(fn) {
|
|
885
|
+
collector = fn;
|
|
886
|
+
}
|
|
887
|
+
function hasDerivationSession() {
|
|
888
|
+
return sessionNodes !== null;
|
|
889
|
+
}
|
|
890
|
+
function beginDerivationSession() {
|
|
891
|
+
sessionNodes = /* @__PURE__ */ new Map();
|
|
892
|
+
nextId = 1;
|
|
893
|
+
}
|
|
894
|
+
function endDerivationSession() {
|
|
895
|
+
const nodes = sessionNodes ? [...sessionNodes.values()] : [];
|
|
896
|
+
sessionNodes = null;
|
|
897
|
+
collector = null;
|
|
898
|
+
return nodes;
|
|
899
|
+
}
|
|
900
|
+
function abortDerivationSession() {
|
|
901
|
+
sessionNodes = null;
|
|
902
|
+
collector = null;
|
|
903
|
+
}
|
|
904
|
+
function note(node) {
|
|
905
|
+
const full = { ...node, id: nextId++ };
|
|
906
|
+
if (sessionNodes) sessionNodes.set(full.id, full);
|
|
907
|
+
collector?.(full);
|
|
908
|
+
return full;
|
|
909
|
+
}
|
|
910
|
+
function tagDerivationRoot(abs2, meta) {
|
|
911
|
+
const node = note({
|
|
912
|
+
kind: "root",
|
|
913
|
+
expr: meta.expr,
|
|
914
|
+
...meta.importFrom !== void 0 ? { importFrom: meta.importFrom } : {},
|
|
915
|
+
...meta.importName !== void 0 ? { importName: meta.importName } : {},
|
|
916
|
+
parents: []
|
|
917
|
+
});
|
|
918
|
+
byAbs.set(abs2, node);
|
|
919
|
+
return node;
|
|
920
|
+
}
|
|
921
|
+
function getDerivation(abs2) {
|
|
922
|
+
return byAbs.get(abs2);
|
|
923
|
+
}
|
|
924
|
+
function setDerivation(abs2, node) {
|
|
925
|
+
byAbs.set(abs2, node);
|
|
926
|
+
}
|
|
927
|
+
function derivationChain(node) {
|
|
928
|
+
const chain = [node];
|
|
929
|
+
const seen = /* @__PURE__ */ new Set([node.id]);
|
|
930
|
+
let cur = node;
|
|
931
|
+
while (cur.kind !== "root" && cur.parents.length > 0) {
|
|
932
|
+
const pid = cur.parents[0];
|
|
933
|
+
if (seen.has(pid) || !sessionNodes) break;
|
|
934
|
+
const parent = sessionNodes.get(pid);
|
|
935
|
+
if (!parent) break;
|
|
936
|
+
seen.add(pid);
|
|
937
|
+
chain.push(parent);
|
|
938
|
+
cur = parent;
|
|
939
|
+
}
|
|
940
|
+
return chain;
|
|
941
|
+
}
|
|
942
|
+
function noteDerivationAdd(a, b, result) {
|
|
943
|
+
if (!sessionNodes) return;
|
|
944
|
+
const vb = litValue(b);
|
|
945
|
+
const va = litValue(a);
|
|
946
|
+
let parent;
|
|
947
|
+
let offset;
|
|
948
|
+
if (typeof vb === "number" && Number.isFinite(vb)) {
|
|
949
|
+
parent = byAbs.get(a);
|
|
950
|
+
offset = vb;
|
|
951
|
+
} else if (typeof va === "number" && Number.isFinite(va)) {
|
|
952
|
+
parent = byAbs.get(b);
|
|
953
|
+
offset = va;
|
|
954
|
+
}
|
|
955
|
+
if (!parent || offset === void 0) return;
|
|
956
|
+
const node = note({
|
|
957
|
+
kind: "shift",
|
|
958
|
+
offset,
|
|
959
|
+
parents: [parent.id]
|
|
960
|
+
});
|
|
961
|
+
byAbs.set(result, node);
|
|
962
|
+
}
|
|
963
|
+
function noteDerivationJoin(inputs, result) {
|
|
964
|
+
if (!sessionNodes) return;
|
|
965
|
+
const parents = [];
|
|
966
|
+
for (const a of inputs) {
|
|
967
|
+
const n = byAbs.get(a);
|
|
968
|
+
if (n && !parents.includes(n.id)) parents.push(n.id);
|
|
969
|
+
}
|
|
970
|
+
if (parents.length === 0) return;
|
|
971
|
+
const node = note({ kind: "join", parents });
|
|
972
|
+
byAbs.set(result, node);
|
|
973
|
+
}
|
|
974
|
+
function projectDerivationDsl(node, localName) {
|
|
975
|
+
const chain = derivationChain(node);
|
|
976
|
+
const root = chain[chain.length - 1];
|
|
977
|
+
if (!root || root.kind !== "root" || root.expr === void 0) return void 0;
|
|
978
|
+
if (chain.some((n) => n.kind === "join" || n.kind === "opaque")) return void 0;
|
|
979
|
+
const shifts = [];
|
|
980
|
+
for (let i = chain.length - 2; i >= 0; i--) {
|
|
981
|
+
const n = chain[i];
|
|
982
|
+
if (n.kind !== "shift" || n.offset === void 0) return void 0;
|
|
983
|
+
shifts.push(n.offset);
|
|
984
|
+
}
|
|
985
|
+
const rootExpr = root.expr;
|
|
986
|
+
const imports = [];
|
|
987
|
+
if (root.importFrom !== void 0) {
|
|
988
|
+
imports.push({
|
|
989
|
+
name: root.importName ?? rootExpr,
|
|
990
|
+
from: root.importFrom
|
|
991
|
+
});
|
|
992
|
+
}
|
|
993
|
+
if (shifts.length === 0) {
|
|
994
|
+
return { prelude: [], expr: rootExpr, imports };
|
|
995
|
+
}
|
|
996
|
+
let current = rootExpr;
|
|
997
|
+
const prelude = [];
|
|
998
|
+
for (let i = 0; i < shifts.length; i++) {
|
|
999
|
+
const step = `${current}.shift(${shifts[i]})`;
|
|
1000
|
+
if (i === shifts.length - 1) {
|
|
1001
|
+
prelude.push(`const ${localName} = ${step};`);
|
|
1002
|
+
return { prelude, expr: localName, imports };
|
|
1003
|
+
}
|
|
1004
|
+
const tmp = `${localName}_${i}`;
|
|
1005
|
+
prelude.push(`const ${tmp} = ${step};`);
|
|
1006
|
+
current = tmp;
|
|
1007
|
+
}
|
|
1008
|
+
return void 0;
|
|
1009
|
+
}
|
|
1010
|
+
function termKey3(t) {
|
|
1011
|
+
return t === void 0 ? "<none>" : termToString(t);
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
// src/algebra/objects.ts
|
|
1015
|
+
function objOf(slots, opts) {
|
|
1016
|
+
const shape = { k: "obj", slots };
|
|
1017
|
+
if (opts?.index) shape.index = opts.index;
|
|
1018
|
+
if (opts?.open) shape.open = true;
|
|
1019
|
+
return { shape, conf: "exact" };
|
|
1020
|
+
}
|
|
1021
|
+
function isObj(a) {
|
|
1022
|
+
return a.shape.k === "obj";
|
|
1023
|
+
}
|
|
1024
|
+
function getSlot(slots, key) {
|
|
1025
|
+
return Object.prototype.hasOwnProperty.call(slots, key) ? slots[key] : void 0;
|
|
1026
|
+
}
|
|
1027
|
+
function spread(base, over) {
|
|
1028
|
+
if (!isObj(base) && !isObj(over)) {
|
|
1029
|
+
if (isObj(over)) return { shape: { ...over.shape, open: true }, conf: confJoin(base.conf, over.conf) };
|
|
1030
|
+
if (isObj(base)) return { shape: { ...base.shape, open: true }, conf: confJoin(base.conf, over.conf) };
|
|
1031
|
+
return unknown;
|
|
1032
|
+
}
|
|
1033
|
+
if (!isObj(over)) {
|
|
1034
|
+
if (!isObj(base)) return unknown;
|
|
1035
|
+
return {
|
|
1036
|
+
shape: { ...base.shape, open: true },
|
|
1037
|
+
conf: confJoin(base.conf, "partial")
|
|
1038
|
+
};
|
|
1039
|
+
}
|
|
1040
|
+
if (!isObj(base)) {
|
|
1041
|
+
return { shape: { ...over.shape, open: true }, conf: confJoin(base.conf, over.conf) };
|
|
1042
|
+
}
|
|
1043
|
+
const slots = { ...base.shape.slots };
|
|
1044
|
+
for (const [k, s] of Object.entries(over.shape.slots)) {
|
|
1045
|
+
slots[k] = s;
|
|
1046
|
+
}
|
|
1047
|
+
const open = base.shape.open || over.shape.open || false;
|
|
1048
|
+
const shape = { k: "obj", slots };
|
|
1049
|
+
if (open) shape.open = true;
|
|
1050
|
+
if (base.shape.index || over.shape.index) {
|
|
1051
|
+
shape.index = over.shape.index ?? base.shape.index;
|
|
1052
|
+
}
|
|
1053
|
+
return { shape, conf: confJoin(base.conf, over.conf) };
|
|
1054
|
+
}
|
|
1055
|
+
function joinObjects(a, b) {
|
|
1056
|
+
if (a.shape.k === "never") return b;
|
|
1057
|
+
if (b.shape.k === "never") return a;
|
|
1058
|
+
if (!isObj(a) || !isObj(b)) {
|
|
1059
|
+
return makeSum(a, b);
|
|
1060
|
+
}
|
|
1061
|
+
const ka = Object.keys(a.shape.slots).sort();
|
|
1062
|
+
const kb = Object.keys(b.shape.slots).sort();
|
|
1063
|
+
const sameKeys = ka.length === kb.length && ka.every((k, i) => k === kb[i]);
|
|
1064
|
+
if (!sameKeys) {
|
|
1065
|
+
return makeSum(a, b);
|
|
1066
|
+
}
|
|
1067
|
+
const slots = {};
|
|
1068
|
+
let conf = confJoin(a.conf, b.conf);
|
|
1069
|
+
for (const k of ka) {
|
|
1070
|
+
const sa = a.shape.slots[k];
|
|
1071
|
+
const sb = b.shape.slots[k];
|
|
1072
|
+
const optional = sa.optional || sb.optional;
|
|
1073
|
+
const jv = joinValues(sa.value, sb.value);
|
|
1074
|
+
conf = confJoin(conf, jv.conf);
|
|
1075
|
+
slots[k] = { value: jv, optional };
|
|
1076
|
+
}
|
|
1077
|
+
return { shape: { k: "obj", slots }, conf };
|
|
1078
|
+
}
|
|
1079
|
+
function joinValues(a, b) {
|
|
1080
|
+
if (a.shape.k === "never") return b;
|
|
1081
|
+
if (b.shape.k === "never") return a;
|
|
1082
|
+
const va = litValue(a);
|
|
1083
|
+
const vb = litValue(b);
|
|
1084
|
+
if (va !== void 0 && Object.is(va, vb)) return a;
|
|
1085
|
+
if (a.shape.k === "prim" && b.shape.k === "prim" && a.shape.type === b.shape.type) {
|
|
1086
|
+
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
|
+
);
|
|
1093
|
+
}
|
|
1094
|
+
return abs(a.shape, void 0, void 0, confJoin(confJoin(a.conf, b.conf), "path"));
|
|
1095
|
+
}
|
|
1096
|
+
return makeSum(a, b);
|
|
1097
|
+
}
|
|
1098
|
+
function makeSum(a, b) {
|
|
1099
|
+
const members = flattenSum([a, b]);
|
|
1100
|
+
if (members.length === 1) return members[0];
|
|
1101
|
+
return {
|
|
1102
|
+
shape: { k: "sum", members },
|
|
1103
|
+
conf: confJoin(a.conf, b.conf)
|
|
1104
|
+
};
|
|
1105
|
+
}
|
|
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;
|
|
1121
|
+
}
|
|
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);
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
function fnOf(params, name) {
|
|
1170
|
+
const shape = { k: "fn", params };
|
|
1171
|
+
if (name) shape.name = name;
|
|
1172
|
+
return { shape, conf: "exact" };
|
|
1173
|
+
}
|
|
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
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
return makeSum(a, b);
|
|
1186
|
+
}
|
|
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;
|
|
1195
|
+
}
|
|
1196
|
+
|
|
796
1197
|
// src/algebra/arithmetic.ts
|
|
797
1198
|
function add(a, b, phi2 = pTrue) {
|
|
798
1199
|
const va = litValue(a);
|
|
@@ -815,7 +1216,9 @@ function add(a, b, phi2 = pTrue) {
|
|
|
815
1216
|
const term = simplifyTerm(app("+", [a.term, b.term]));
|
|
816
1217
|
const pred = addPred(a, b, term, phi2);
|
|
817
1218
|
const conf = term.op === "lit" ? "exact" : confJoin(confJoin(a.conf, b.conf), "path");
|
|
818
|
-
|
|
1219
|
+
const result = abs({ k: "prim", type: "number" }, term, pred, conf);
|
|
1220
|
+
noteDerivationAdd(a, b, result);
|
|
1221
|
+
return result;
|
|
819
1222
|
}
|
|
820
1223
|
if (isAnyLike(a) || isAnyLike(b)) {
|
|
821
1224
|
const term = a.term && b.term ? simplifyTerm(app("+", [a.term, b.term])) : void 0;
|
|
@@ -854,7 +1257,7 @@ function dedupAbsMembers(ms) {
|
|
|
854
1257
|
const seen = /* @__PURE__ */ new Set();
|
|
855
1258
|
const out = [];
|
|
856
1259
|
for (const m of ms) {
|
|
857
|
-
const key = m
|
|
1260
|
+
const key = absShapeKey(m);
|
|
858
1261
|
if (seen.has(key)) continue;
|
|
859
1262
|
seen.add(key);
|
|
860
1263
|
out.push(m);
|
|
@@ -934,7 +1337,7 @@ function collectBoundsFromPred(pred, term, acc) {
|
|
|
934
1337
|
}
|
|
935
1338
|
if (p.op === "gt" && match(p.a) && p.b.op === "lit" && typeof p.b.value === "number") {
|
|
936
1339
|
const n = p.b.value;
|
|
937
|
-
if (acc.lo === void 0 || n > acc.lo.value || n === acc.lo.value &&
|
|
1340
|
+
if (acc.lo === void 0 || n > acc.lo.value || n === acc.lo.value && !acc.lo.strict) {
|
|
938
1341
|
acc.lo = { value: n, strict: true };
|
|
939
1342
|
}
|
|
940
1343
|
return;
|
|
@@ -948,7 +1351,7 @@ function collectBoundsFromPred(pred, term, acc) {
|
|
|
948
1351
|
}
|
|
949
1352
|
if (p.op === "lt" && match(p.a) && p.b.op === "lit" && typeof p.b.value === "number") {
|
|
950
1353
|
const n = p.b.value;
|
|
951
|
-
if (acc.hi === void 0 || n < acc.hi.value) {
|
|
1354
|
+
if (acc.hi === void 0 || n < acc.hi.value || n === acc.hi.value && !acc.hi.strict) {
|
|
952
1355
|
acc.hi = { value: n, strict: true };
|
|
953
1356
|
}
|
|
954
1357
|
return;
|
|
@@ -967,7 +1370,7 @@ function collectBoundsFromPhi(phi2, id, acc) {
|
|
|
967
1370
|
for (const p of conjs) {
|
|
968
1371
|
if (p.op === "gt" && p.a.op === "var" && p.a.id === id && p.b.op === "lit" && typeof p.b.value === "number") {
|
|
969
1372
|
const n = p.b.value;
|
|
970
|
-
if (acc.lo === void 0 || n > acc.lo.value) {
|
|
1373
|
+
if (acc.lo === void 0 || n > acc.lo.value || n === acc.lo.value && !acc.lo.strict) {
|
|
971
1374
|
acc.lo = { value: n, strict: true };
|
|
972
1375
|
}
|
|
973
1376
|
}
|
|
@@ -979,7 +1382,7 @@ function collectBoundsFromPhi(phi2, id, acc) {
|
|
|
979
1382
|
}
|
|
980
1383
|
if (p.op === "lt" && p.a.op === "var" && p.a.id === id && p.b.op === "lit" && typeof p.b.value === "number") {
|
|
981
1384
|
const n = p.b.value;
|
|
982
|
-
if (acc.hi === void 0 || n < acc.hi.value) {
|
|
1385
|
+
if (acc.hi === void 0 || n < acc.hi.value || n === acc.hi.value && !acc.hi.strict) {
|
|
983
1386
|
acc.hi = { value: n, strict: true };
|
|
984
1387
|
}
|
|
985
1388
|
}
|
|
@@ -1220,6 +1623,20 @@ function compareLits(op, a, b) {
|
|
|
1220
1623
|
return a >= b;
|
|
1221
1624
|
}
|
|
1222
1625
|
}
|
|
1626
|
+
if (op === "lt" || op === "le" || op === "gt" || op === "ge") {
|
|
1627
|
+
const x = a;
|
|
1628
|
+
const y = b;
|
|
1629
|
+
switch (op) {
|
|
1630
|
+
case "lt":
|
|
1631
|
+
return x < y;
|
|
1632
|
+
case "le":
|
|
1633
|
+
return x <= y;
|
|
1634
|
+
case "gt":
|
|
1635
|
+
return x > y;
|
|
1636
|
+
case "ge":
|
|
1637
|
+
return x >= y;
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1223
1640
|
return void 0;
|
|
1224
1641
|
}
|
|
1225
1642
|
function decideByBounds(op, a, b, phi2) {
|
|
@@ -1258,6 +1675,34 @@ function trueConstraint(c) {
|
|
|
1258
1675
|
if (c.term?.op === "lit" && c.term.value === false) return void 0;
|
|
1259
1676
|
return c.pred;
|
|
1260
1677
|
}
|
|
1678
|
+
function refineAbsForRelTrue(a, op, k) {
|
|
1679
|
+
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));
|
|
1680
|
+
if (isNumPrim(a) && a.term) {
|
|
1681
|
+
const pred = a.pred && a.pred.op !== "true" ? and(a.pred, bound(a.term)) : bound(a.term);
|
|
1682
|
+
return abs(a.shape, a.term, pred, a.conf);
|
|
1683
|
+
}
|
|
1684
|
+
if (isStrPrim(a)) return a;
|
|
1685
|
+
if ((a.shape.k === "any" || a.shape.k === "unknown") && a.term) {
|
|
1686
|
+
const numArm = abs({ k: "prim", type: "number" }, a.term, bound(a.term), "path");
|
|
1687
|
+
const strArm = abs({ k: "prim", type: "string" }, a.term, void 0, "path");
|
|
1688
|
+
return makeSum(numArm, strArm);
|
|
1689
|
+
}
|
|
1690
|
+
return a;
|
|
1691
|
+
}
|
|
1692
|
+
function matchRelIdentLit(test) {
|
|
1693
|
+
const t = test;
|
|
1694
|
+
if (t?.type !== "BinaryExpression") return void 0;
|
|
1695
|
+
const rel = t.operator === ">" ? "gt" : t.operator === ">=" ? "ge" : t.operator === "<" ? "lt" : t.operator === "<=" ? "le" : void 0;
|
|
1696
|
+
if (!rel) return void 0;
|
|
1697
|
+
if (t.left?.type === "Identifier" && t.left.name && t.right?.type === "NumericLiteral" && typeof t.right.value === "number") {
|
|
1698
|
+
return { name: t.left.name, op: rel, k: t.right.value };
|
|
1699
|
+
}
|
|
1700
|
+
if (t.right?.type === "Identifier" && t.right.name && t.left?.type === "NumericLiteral" && typeof t.left.value === "number") {
|
|
1701
|
+
const flipped = rel === "gt" ? "lt" : rel === "ge" ? "le" : rel === "lt" ? "gt" : "ge";
|
|
1702
|
+
return { name: t.right.name, op: flipped, k: t.left.value };
|
|
1703
|
+
}
|
|
1704
|
+
return void 0;
|
|
1705
|
+
}
|
|
1261
1706
|
function falseConstraint(c) {
|
|
1262
1707
|
if (c.term?.op === "lit" && c.term.value === true) return void 0;
|
|
1263
1708
|
if (c.term?.op === "lit" && c.term.value === false) return pTrue;
|
|
@@ -1371,7 +1816,7 @@ function flipBounds(pred, src, dst, out) {
|
|
|
1371
1816
|
if (p.op !== "gt" && p.op !== "ge" && p.op !== "lt" && p.op !== "le") {
|
|
1372
1817
|
return;
|
|
1373
1818
|
}
|
|
1374
|
-
if (
|
|
1819
|
+
if (termKey4(p.a) !== termKey4(src)) return;
|
|
1375
1820
|
if (p.b.op !== "lit" || typeof p.b.value !== "number") return;
|
|
1376
1821
|
const n = p.b.value;
|
|
1377
1822
|
if (p.op === "gt") out.push(lt(dst, lit(-n)));
|
|
@@ -1381,7 +1826,7 @@ function flipBounds(pred, src, dst, out) {
|
|
|
1381
1826
|
};
|
|
1382
1827
|
apply(pred);
|
|
1383
1828
|
}
|
|
1384
|
-
function
|
|
1829
|
+
function termKey4(t) {
|
|
1385
1830
|
if (t.op === "lit") return `lit:${JSON.stringify(t.value)}`;
|
|
1386
1831
|
if (t.op === "var") return `var:${t.id}`;
|
|
1387
1832
|
return `app:${t.fn}`;
|
|
@@ -1450,169 +1895,13 @@ function strictEqAbs(a, b) {
|
|
|
1450
1895
|
return void 0;
|
|
1451
1896
|
}
|
|
1452
1897
|
|
|
1453
|
-
// src/algebra/
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
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 };
|
|
1514
|
-
}
|
|
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;
|
|
1898
|
+
// src/algebra/containers.ts
|
|
1899
|
+
var TUPLE_LITERAL_CAP = 8;
|
|
1900
|
+
function shouldWidenArrayLiteral(n) {
|
|
1901
|
+
return n > TUPLE_LITERAL_CAP;
|
|
1557
1902
|
}
|
|
1558
|
-
function
|
|
1559
|
-
|
|
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);
|
|
1903
|
+
function widenedArrayConf() {
|
|
1904
|
+
return "path";
|
|
1616
1905
|
}
|
|
1617
1906
|
|
|
1618
1907
|
// src/algebra/language.ts
|
|
@@ -1728,8 +2017,8 @@ function litFalse() {
|
|
|
1728
2017
|
function projectBrand(self, key) {
|
|
1729
2018
|
if (self.shape.k !== "brand") return unknown;
|
|
1730
2019
|
const inner = self.shape.shape;
|
|
1731
|
-
if (inner.shape.k === "obj") {
|
|
1732
|
-
const slot = inner.shape.slots
|
|
2020
|
+
if (inner && inner.shape.k === "obj") {
|
|
2021
|
+
const slot = getSlot(inner.shape.slots, key);
|
|
1733
2022
|
if (slot) return slot.value;
|
|
1734
2023
|
}
|
|
1735
2024
|
return unknown;
|
|
@@ -1918,7 +2207,7 @@ function leqShape(src, tgt, phi2, env, depth) {
|
|
|
1918
2207
|
const srcObj = s.k === "obj" ? s : s.k === "brand" ? s.shape.shape.k === "obj" ? s.shape.shape : null : null;
|
|
1919
2208
|
if (!srcObj || srcObj.k !== "obj") return fail(`shape ${s.k} \u22AD obj`);
|
|
1920
2209
|
for (const [key, slot] of Object.entries(t.slots)) {
|
|
1921
|
-
const srcSlot = srcObj.slots
|
|
2210
|
+
const srcSlot = getSlot(srcObj.slots, key);
|
|
1922
2211
|
if (!srcSlot) {
|
|
1923
2212
|
if (slot.optional) continue;
|
|
1924
2213
|
return fail(`missing slot ${key}`);
|
|
@@ -2025,6 +2314,8 @@ function evalMathMethod(name, args) {
|
|
|
2025
2314
|
case "round":
|
|
2026
2315
|
if (typeof a0 === "number") return numLit(Math.round(a0));
|
|
2027
2316
|
return numPrim();
|
|
2317
|
+
case "random":
|
|
2318
|
+
return numPrim("path");
|
|
2028
2319
|
case "sqrt":
|
|
2029
2320
|
if (typeof a0 === "number") return numLit(Math.sqrt(a0));
|
|
2030
2321
|
return numPrim();
|
|
@@ -2104,6 +2395,12 @@ function evalJsonMethod(name, args) {
|
|
|
2104
2395
|
if (name === "parse") return unknown;
|
|
2105
2396
|
return void 0;
|
|
2106
2397
|
}
|
|
2398
|
+
function foldParseInt(s, radix) {
|
|
2399
|
+
const str2 = String(s);
|
|
2400
|
+
if (radix === void 0) return numLit(parseInt(str2));
|
|
2401
|
+
if (!Number.isInteger(radix) || radix < 2 || radix > 36) return numLit(NaN);
|
|
2402
|
+
return numLit(parseInt(str2, radix));
|
|
2403
|
+
}
|
|
2107
2404
|
function evalNumberStatic(name, args) {
|
|
2108
2405
|
const a0 = args[0] ? litValue(args[0]) : void 0;
|
|
2109
2406
|
switch (name) {
|
|
@@ -2117,12 +2414,16 @@ function evalNumberStatic(name, args) {
|
|
|
2117
2414
|
if (typeof a0 === "number") return boolLit(Number.isFinite(a0));
|
|
2118
2415
|
return boolPrim();
|
|
2119
2416
|
case "parseInt":
|
|
2120
|
-
case "parseFloat":
|
|
2121
2417
|
if (typeof a0 === "string" || typeof a0 === "number") {
|
|
2122
|
-
const
|
|
2123
|
-
return
|
|
2418
|
+
const radix = args[1] ? litValue(args[1]) : void 0;
|
|
2419
|
+
if (radix === void 0) return foldParseInt(a0, void 0);
|
|
2420
|
+
if (typeof radix === "number") return foldParseInt(a0, radix);
|
|
2421
|
+
return numPrim();
|
|
2124
2422
|
}
|
|
2125
2423
|
return numPrim();
|
|
2424
|
+
case "parseFloat":
|
|
2425
|
+
if (typeof a0 === "string" || typeof a0 === "number") return numLit(parseFloat(String(a0)));
|
|
2426
|
+
return numPrim();
|
|
2126
2427
|
case "MAX_SAFE_INTEGER":
|
|
2127
2428
|
return numLit(Number.MAX_SAFE_INTEGER);
|
|
2128
2429
|
default:
|
|
@@ -2133,7 +2434,12 @@ function evalGlobalFn(name, args) {
|
|
|
2133
2434
|
const a0 = args[0] ? litValue(args[0]) : void 0;
|
|
2134
2435
|
switch (name) {
|
|
2135
2436
|
case "parseInt":
|
|
2136
|
-
if (typeof a0 === "string" || typeof a0 === "number")
|
|
2437
|
+
if (typeof a0 === "string" || typeof a0 === "number") {
|
|
2438
|
+
const radix = args[1] ? litValue(args[1]) : void 0;
|
|
2439
|
+
if (radix === void 0) return foldParseInt(a0, void 0);
|
|
2440
|
+
if (typeof radix === "number") return foldParseInt(a0, radix);
|
|
2441
|
+
return numPrim();
|
|
2442
|
+
}
|
|
2137
2443
|
return numPrim();
|
|
2138
2444
|
case "parseFloat":
|
|
2139
2445
|
if (typeof a0 === "string" || typeof a0 === "number") return numLit(parseFloat(String(a0)));
|
|
@@ -2156,17 +2462,44 @@ function evalGlobalFn(name, args) {
|
|
|
2156
2462
|
return void 0;
|
|
2157
2463
|
}
|
|
2158
2464
|
}
|
|
2465
|
+
function peelBrand(shape) {
|
|
2466
|
+
let s = shape;
|
|
2467
|
+
while (s.k === "brand") s = s.shape.shape;
|
|
2468
|
+
return s;
|
|
2469
|
+
}
|
|
2159
2470
|
function evalArrayStatic(name, args) {
|
|
2160
2471
|
const a0 = args[0];
|
|
2161
2472
|
switch (name) {
|
|
2162
2473
|
case "isArray": {
|
|
2163
2474
|
if (!a0) return boolLit(false);
|
|
2164
|
-
const
|
|
2165
|
-
|
|
2475
|
+
const s = peelBrand(a0.shape);
|
|
2476
|
+
if (s.k === "arr" || s.k === "tuple") return boolLit(true);
|
|
2477
|
+
if (s.k === "any" || s.k === "unknown" || s.k === "sum") return boolPrim();
|
|
2478
|
+
return boolLit(false);
|
|
2166
2479
|
}
|
|
2167
|
-
case "from":
|
|
2168
2480
|
case "of":
|
|
2169
2481
|
return abs({ k: "arr", element: a0 ?? unknown }, void 0, void 0, "path");
|
|
2482
|
+
case "from": {
|
|
2483
|
+
if (!a0) return unknown;
|
|
2484
|
+
const k = a0.shape.k;
|
|
2485
|
+
if (k === "arr") return a0;
|
|
2486
|
+
if (k === "tuple") {
|
|
2487
|
+
const els = a0.shape.elements;
|
|
2488
|
+
if (els.length === 0) return abs({ k: "arr", element: unknown }, void 0, void 0, "path");
|
|
2489
|
+
let el = els[0];
|
|
2490
|
+
for (let i = 1; i < els.length; i++) el = joinAbs(el, els[i]);
|
|
2491
|
+
return abs({ k: "arr", element: el }, void 0, void 0, "path");
|
|
2492
|
+
}
|
|
2493
|
+
if (k === "prim" && a0.shape.type === "string") {
|
|
2494
|
+
return abs(
|
|
2495
|
+
{ k: "arr", element: abs({ k: "prim", type: "string" }, void 0, void 0, "path") },
|
|
2496
|
+
void 0,
|
|
2497
|
+
void 0,
|
|
2498
|
+
"path"
|
|
2499
|
+
);
|
|
2500
|
+
}
|
|
2501
|
+
return unknown;
|
|
2502
|
+
}
|
|
2170
2503
|
default:
|
|
2171
2504
|
return void 0;
|
|
2172
2505
|
}
|
|
@@ -2180,7 +2513,7 @@ function evalDateCtor(args) {
|
|
|
2180
2513
|
);
|
|
2181
2514
|
}
|
|
2182
2515
|
function evalDateStatic(name, _args) {
|
|
2183
|
-
if (name === "now") return
|
|
2516
|
+
if (name === "now") return numPrim("path");
|
|
2184
2517
|
return void 0;
|
|
2185
2518
|
}
|
|
2186
2519
|
function evalDateMethod(name, _recv, _args) {
|
|
@@ -2518,10 +2851,10 @@ function parseUncached(source, opts) {
|
|
|
2518
2851
|
attachComment: true,
|
|
2519
2852
|
errorRecovery: opts?.errorRecovery === true
|
|
2520
2853
|
});
|
|
2521
|
-
return stripTypes(ast);
|
|
2854
|
+
return opts?.keepTs === true ? ast : stripTypes(ast);
|
|
2522
2855
|
}
|
|
2523
2856
|
function parseSource(source, opts) {
|
|
2524
|
-
if (opts?.errorRecovery === true) {
|
|
2857
|
+
if (opts?.keepTs === true || opts?.errorRecovery === true) {
|
|
2525
2858
|
return parseUncached(source, opts);
|
|
2526
2859
|
}
|
|
2527
2860
|
if (source.length > MAX_AST_SOURCE_CHARS) {
|
|
@@ -3127,29 +3460,6 @@ function numPrim2(conf = "path") {
|
|
|
3127
3460
|
function strArr(conf = "path") {
|
|
3128
3461
|
return abs({ k: "arr", element: strPrim2("path") }, void 0, void 0, conf);
|
|
3129
3462
|
}
|
|
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
3463
|
function isStrRecv(recv) {
|
|
3154
3464
|
return isTemplateLike(recv) || recv.shape.k === "prim" && recv.shape.type === "string" || recv.term?.op === "lit" && typeof recv.term.value === "string";
|
|
3155
3465
|
}
|
|
@@ -3158,27 +3468,24 @@ function callAbsMethod(recv, name, args) {
|
|
|
3158
3468
|
const a0 = args[0] ? litValue(args[0]) : void 0;
|
|
3159
3469
|
const lit3 = recv.term?.op === "lit" && typeof recv.term.value === "string" ? recv.term.value : void 0;
|
|
3160
3470
|
if (isTemplateLike(recv)) {
|
|
3161
|
-
const
|
|
3162
|
-
const prefix =
|
|
3163
|
-
const suffix =
|
|
3471
|
+
const views = absTemplateViews(templatePartsOf(recv));
|
|
3472
|
+
const prefix = knownPrefixOfViews(views);
|
|
3473
|
+
const suffix = knownSuffixOfViews(views);
|
|
3164
3474
|
switch (name) {
|
|
3165
3475
|
case "startsWith": {
|
|
3166
3476
|
if (typeof a0 !== "string") return boolPrim2();
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
return boolLit(false);
|
|
3477
|
+
const d = decideStartsWith(prefix, a0);
|
|
3478
|
+
return d === "unknown" ? boolPrim2() : boolLit(d);
|
|
3170
3479
|
}
|
|
3171
3480
|
case "endsWith": {
|
|
3172
3481
|
if (typeof a0 !== "string") return boolPrim2();
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
return boolLit(false);
|
|
3482
|
+
const d = decideEndsWith(suffix, a0);
|
|
3483
|
+
return d === "unknown" ? boolPrim2() : boolLit(d);
|
|
3176
3484
|
}
|
|
3177
3485
|
case "includes": {
|
|
3178
3486
|
if (typeof a0 !== "string") return boolPrim2();
|
|
3179
|
-
const
|
|
3180
|
-
|
|
3181
|
-
return boolPrim2();
|
|
3487
|
+
const d = decideIncludes(allFixedTextOfViews(views), a0);
|
|
3488
|
+
return d === "unknown" ? boolPrim2() : boolLit(d);
|
|
3182
3489
|
}
|
|
3183
3490
|
case "toUpperCase":
|
|
3184
3491
|
case "toLowerCase":
|
|
@@ -3248,7 +3555,7 @@ function callAbsMethod(recv, name, args) {
|
|
|
3248
3555
|
const parts = lit3.split(sep).map((s) => strLit(s));
|
|
3249
3556
|
return abs({ k: "tuple", elements: parts }, void 0, void 0, "exact");
|
|
3250
3557
|
}
|
|
3251
|
-
return
|
|
3558
|
+
return strArr("path");
|
|
3252
3559
|
}
|
|
3253
3560
|
return strArr("path");
|
|
3254
3561
|
}
|
|
@@ -3264,8 +3571,7 @@ function callAbsMethod(recv, name, args) {
|
|
|
3264
3571
|
function getAbsProperty(recv, name) {
|
|
3265
3572
|
if (name === "length") {
|
|
3266
3573
|
if (isTemplateLike(recv)) {
|
|
3267
|
-
const
|
|
3268
|
-
const n = fixedLength(parts);
|
|
3574
|
+
const n = fixedLengthOfViews(absTemplateViews(templatePartsOf(recv)));
|
|
3269
3575
|
if (n !== void 0) return numLit(n);
|
|
3270
3576
|
return numPrim2("path");
|
|
3271
3577
|
}
|
|
@@ -3534,8 +3840,8 @@ function callBudgetKey(kind, id, args) {
|
|
|
3534
3840
|
return `${kind}|${id}|${parts.join(",")}`;
|
|
3535
3841
|
}
|
|
3536
3842
|
var absTruncCollector = null;
|
|
3537
|
-
function setAbsTruncationCollector(
|
|
3538
|
-
absTruncCollector =
|
|
3843
|
+
function setAbsTruncationCollector(collector2) {
|
|
3844
|
+
absTruncCollector = collector2;
|
|
3539
3845
|
}
|
|
3540
3846
|
function noteTruncation(label) {
|
|
3541
3847
|
if (!absTruncCollector) return;
|
|
@@ -3559,8 +3865,10 @@ function exitCall() {
|
|
|
3559
3865
|
_activeCallKeys.pop();
|
|
3560
3866
|
}
|
|
3561
3867
|
var absCallCollector = null;
|
|
3562
|
-
function setAbsCallCollector(
|
|
3563
|
-
|
|
3868
|
+
function setAbsCallCollector(collector2) {
|
|
3869
|
+
const prev = absCallCollector;
|
|
3870
|
+
absCallCollector = collector2;
|
|
3871
|
+
return prev;
|
|
3564
3872
|
}
|
|
3565
3873
|
function recordAbsCall(fnName, args, result, callLoc, threw) {
|
|
3566
3874
|
if (!absCallCollector) return;
|
|
@@ -3570,8 +3878,8 @@ function recordAbsCall(fnName, args, result, callLoc, threw) {
|
|
|
3570
3878
|
}
|
|
3571
3879
|
}
|
|
3572
3880
|
var absNodeCollector = null;
|
|
3573
|
-
function setAbsNodeCollector(
|
|
3574
|
-
absNodeCollector =
|
|
3881
|
+
function setAbsNodeCollector(collector2) {
|
|
3882
|
+
absNodeCollector = collector2;
|
|
3575
3883
|
}
|
|
3576
3884
|
function recordAbsNode(node, value) {
|
|
3577
3885
|
if (!absNodeCollector || !value) return;
|
|
@@ -3581,8 +3889,17 @@ function recordAbsNode(node, value) {
|
|
|
3581
3889
|
}
|
|
3582
3890
|
}
|
|
3583
3891
|
var absAssignCollector = null;
|
|
3584
|
-
|
|
3585
|
-
|
|
3892
|
+
var assignFlowDepth = 0;
|
|
3893
|
+
function setAbsAssignCollector(collector2) {
|
|
3894
|
+
absAssignCollector = collector2;
|
|
3895
|
+
}
|
|
3896
|
+
function evalInConditionalFlow(body) {
|
|
3897
|
+
assignFlowDepth++;
|
|
3898
|
+
try {
|
|
3899
|
+
return body();
|
|
3900
|
+
} finally {
|
|
3901
|
+
assignFlowDepth--;
|
|
3902
|
+
}
|
|
3586
3903
|
}
|
|
3587
3904
|
function recordAbsAssign(name, prev, next, loc) {
|
|
3588
3905
|
if (!absAssignCollector) return;
|
|
@@ -3592,7 +3909,8 @@ function recordAbsAssign(name, prev, next, loc) {
|
|
|
3592
3909
|
prev,
|
|
3593
3910
|
next,
|
|
3594
3911
|
line: loc?.start.line,
|
|
3595
|
-
column: loc?.start.column
|
|
3912
|
+
column: loc?.start.column,
|
|
3913
|
+
conditional: assignFlowDepth > 0
|
|
3596
3914
|
});
|
|
3597
3915
|
} catch {
|
|
3598
3916
|
}
|
|
@@ -3602,6 +3920,16 @@ function evalSource(source, entry, opts = {}) {
|
|
|
3602
3920
|
const file = opts.file ?? parseSource(source);
|
|
3603
3921
|
const env = emptyEnv();
|
|
3604
3922
|
let phi2 = opts.phi ?? pTrue;
|
|
3923
|
+
if (opts.seedVars) {
|
|
3924
|
+
for (const [k, v2] of Object.entries(opts.seedVars)) {
|
|
3925
|
+
env.vars.set(k, v2);
|
|
3926
|
+
}
|
|
3927
|
+
}
|
|
3928
|
+
if (opts.seedFns) {
|
|
3929
|
+
for (const [k, fn] of Object.entries(opts.seedFns)) {
|
|
3930
|
+
env.fns.set(k, fn);
|
|
3931
|
+
}
|
|
3932
|
+
}
|
|
3605
3933
|
if (opts.modules) {
|
|
3606
3934
|
for (const stmt of file.program.body) {
|
|
3607
3935
|
if (stmt.type === "ImportDeclaration") {
|
|
@@ -3635,8 +3963,13 @@ function evalSource(source, entry, opts = {}) {
|
|
|
3635
3963
|
}
|
|
3636
3964
|
}
|
|
3637
3965
|
}
|
|
3638
|
-
const
|
|
3639
|
-
return {
|
|
3966
|
+
const full = callFunctionFull(env, entry.fn, entry.args, phi2, opts.budget);
|
|
3967
|
+
return {
|
|
3968
|
+
value: full.result,
|
|
3969
|
+
phi: phi2,
|
|
3970
|
+
env,
|
|
3971
|
+
...full.throws.shape.k !== "never" ? { threw: true, ...full.throwLoc ? { throwLoc: full.throwLoc } : {} } : {}
|
|
3972
|
+
};
|
|
3640
3973
|
}
|
|
3641
3974
|
function registerClassDecl(env, node) {
|
|
3642
3975
|
const cls = node;
|
|
@@ -3692,6 +4025,37 @@ function registerFunction(env, decl) {
|
|
|
3692
4025
|
async: decl.async === true
|
|
3693
4026
|
});
|
|
3694
4027
|
}
|
|
4028
|
+
function callFunctionFull(env, name, args, phi2 = pTrue, budget = defaultLeakBudget) {
|
|
4029
|
+
const fn = env.fns.get(name);
|
|
4030
|
+
const neverAbs = abs({ k: "never" }, void 0, void 0, "exact");
|
|
4031
|
+
if (!fn) return { result: unknown, throws: neverAbs };
|
|
4032
|
+
const key = callBudgetKey("fn", name, args);
|
|
4033
|
+
if (!enterCall(key, name)) {
|
|
4034
|
+
return { result: truncatedAbs(), throws: neverAbs };
|
|
4035
|
+
}
|
|
4036
|
+
try {
|
|
4037
|
+
let local = { vars: new Map(env.vars), fns: env.fns, hofCollect: env.hofCollect };
|
|
4038
|
+
const cls = env.classes;
|
|
4039
|
+
if (cls) local.classes = cls;
|
|
4040
|
+
fn.params.forEach((p, i) => {
|
|
4041
|
+
local.vars.set(p, args[i] ?? unknown);
|
|
4042
|
+
});
|
|
4043
|
+
const result = evalNode(fn.body, local, phi2, budget);
|
|
4044
|
+
if (result.threw) {
|
|
4045
|
+
return {
|
|
4046
|
+
result: neverAbs,
|
|
4047
|
+
throws: result.value,
|
|
4048
|
+
...result.throwLoc ? { throwLoc: result.throwLoc } : {}
|
|
4049
|
+
};
|
|
4050
|
+
}
|
|
4051
|
+
if (fn.async) {
|
|
4052
|
+
return { result: coerceAsyncReturn(result.value), throws: neverAbs };
|
|
4053
|
+
}
|
|
4054
|
+
return { result: result.value, throws: neverAbs };
|
|
4055
|
+
} finally {
|
|
4056
|
+
exitCall();
|
|
4057
|
+
}
|
|
4058
|
+
}
|
|
3695
4059
|
function callFunction(env, name, args, phi2 = pTrue, budget = defaultLeakBudget) {
|
|
3696
4060
|
const fn = env.fns.get(name);
|
|
3697
4061
|
if (!fn) return unknown;
|
|
@@ -3858,7 +4222,18 @@ function evalNodeInner(node, env, phi2, budget) {
|
|
|
3858
4222
|
case "ThrowStatement": {
|
|
3859
4223
|
const arg = node.argument;
|
|
3860
4224
|
const v2 = arg ? evalNode(arg, env, phi2, budget).value : unknown;
|
|
3861
|
-
|
|
4225
|
+
const loc = node.loc ? { line: node.loc.start.line, column: node.loc.start.column } : void 0;
|
|
4226
|
+
return { value: v2, phi: phi2, env, threw: true, ...loc ? { throwLoc: loc } : {} };
|
|
4227
|
+
}
|
|
4228
|
+
case "ConditionalExpression": {
|
|
4229
|
+
const cond = node;
|
|
4230
|
+
const t = evalNode(cond.test, env, phi2, budget).value;
|
|
4231
|
+
const tv = litValue(t);
|
|
4232
|
+
if (tv === true) return evalNode(cond.consequent, env, phi2, budget);
|
|
4233
|
+
if (tv === false) return evalNode(cond.alternate, env, phi2, budget);
|
|
4234
|
+
const a = evalNode(cond.consequent, env, phi2, budget);
|
|
4235
|
+
const b = evalNode(cond.alternate, env, phi2, budget);
|
|
4236
|
+
return { value: joinAbs(a.value, b.value), phi: phi2, env };
|
|
3862
4237
|
}
|
|
3863
4238
|
case "ForStatement":
|
|
3864
4239
|
return evalFor(node, env, phi2, budget);
|
|
@@ -3970,14 +4345,14 @@ function evalNodeInner(node, env, phi2, budget) {
|
|
|
3970
4345
|
}
|
|
3971
4346
|
if (!m.computed && m.property.type === "Identifier" && obj2.shape.k === "obj") {
|
|
3972
4347
|
const key = m.property.name;
|
|
3973
|
-
const slot = obj2.shape.slots
|
|
4348
|
+
const slot = getSlot(obj2.shape.slots, key);
|
|
3974
4349
|
if (slot) return ok2(slot.value, phi2, env);
|
|
3975
4350
|
}
|
|
3976
4351
|
if (m.computed) {
|
|
3977
4352
|
const key = evalNode(m.property, env, phi2, budget).value;
|
|
3978
4353
|
const kl = litValue(key);
|
|
3979
4354
|
if (typeof kl === "string" && obj2.shape.k === "obj") {
|
|
3980
|
-
const slot = obj2.shape.slots
|
|
4355
|
+
const slot = getSlot(obj2.shape.slots, kl);
|
|
3981
4356
|
if (slot) return ok2(slot.value, phi2, env);
|
|
3982
4357
|
}
|
|
3983
4358
|
if (typeof kl === "number") {
|
|
@@ -4029,11 +4404,11 @@ function evalNodeInner(node, env, phi2, budget) {
|
|
|
4029
4404
|
if (els.length === 0) {
|
|
4030
4405
|
return ok2(abs({ k: "arr", element: unknown }, void 0, void 0, "exact"), phi2, env);
|
|
4031
4406
|
}
|
|
4032
|
-
if (els.length
|
|
4407
|
+
if (!shouldWidenArrayLiteral(els.length)) {
|
|
4033
4408
|
return ok2(abs({ k: "tuple", elements: els }, void 0, void 0, "exact"), phi2, env);
|
|
4034
4409
|
}
|
|
4035
4410
|
const elem = els.reduce((x, y) => joinAbs(x, y));
|
|
4036
|
-
return ok2(abs({ k: "arr", element: elem }, void 0, void 0,
|
|
4411
|
+
return ok2(abs({ k: "arr", element: elem }, void 0, void 0, widenedArrayConf()), phi2, env);
|
|
4037
4412
|
}
|
|
4038
4413
|
default:
|
|
4039
4414
|
return ok2(unknown, phi2, env);
|
|
@@ -4309,18 +4684,27 @@ function evalCall(node, env, phi2, budget) {
|
|
|
4309
4684
|
}
|
|
4310
4685
|
if (obj2.shape.k === "tuple") {
|
|
4311
4686
|
const kept = [];
|
|
4312
|
-
|
|
4313
|
-
|
|
4687
|
+
let anyUncertain = false;
|
|
4688
|
+
for (const el2 of obj2.shape.elements) {
|
|
4689
|
+
const p = applyUnaryCallback(fnNode, el2, env, phi2, budget);
|
|
4314
4690
|
const lv = litValue(p);
|
|
4315
4691
|
if (lv === false) continue;
|
|
4316
|
-
|
|
4692
|
+
if (lv !== true) anyUncertain = true;
|
|
4693
|
+
kept.push(el2);
|
|
4317
4694
|
}
|
|
4318
4695
|
if (kept.length === 0) {
|
|
4319
4696
|
return ok2(abs({ k: "arr", element: unknown }, void 0, void 0, "path"), phi2, env);
|
|
4320
4697
|
}
|
|
4321
|
-
if (
|
|
4698
|
+
if (!anyUncertain) {
|
|
4699
|
+
return ok2(
|
|
4700
|
+
abs({ k: "tuple", elements: kept }, void 0, void 0, confJoin(obj2.conf, "path")),
|
|
4701
|
+
phi2,
|
|
4702
|
+
env
|
|
4703
|
+
);
|
|
4704
|
+
}
|
|
4705
|
+
const el = kept.reduce((a, b) => joinAbs(a, b));
|
|
4322
4706
|
return ok2(
|
|
4323
|
-
abs({ k: "
|
|
4707
|
+
abs({ k: "arr", element: el }, void 0, void 0, confJoin(obj2.conf, "path")),
|
|
4324
4708
|
phi2,
|
|
4325
4709
|
env
|
|
4326
4710
|
);
|
|
@@ -4531,7 +4915,16 @@ function evalBlock(node, env, phi2, budget) {
|
|
|
4531
4915
|
pendingPartial = void 0;
|
|
4532
4916
|
}
|
|
4533
4917
|
if (r.returned || r.brk || r.cont || r.threw) {
|
|
4534
|
-
return {
|
|
4918
|
+
return {
|
|
4919
|
+
value: last,
|
|
4920
|
+
phi: curPhi,
|
|
4921
|
+
env: local,
|
|
4922
|
+
returned: r.returned,
|
|
4923
|
+
brk: r.brk,
|
|
4924
|
+
cont: r.cont,
|
|
4925
|
+
threw: r.threw,
|
|
4926
|
+
...r.throwLoc ? { throwLoc: r.throwLoc } : {}
|
|
4927
|
+
};
|
|
4535
4928
|
}
|
|
4536
4929
|
}
|
|
4537
4930
|
if (pendingPartial !== void 0) {
|
|
@@ -4553,7 +4946,7 @@ function evalFor(node, env, phi2, budget) {
|
|
|
4553
4946
|
const lv = litValue(t.value);
|
|
4554
4947
|
if (lv === false || lv === null || lv === void 0) break;
|
|
4555
4948
|
}
|
|
4556
|
-
const bodyR = evalNode(node.body, local, phi2, budget);
|
|
4949
|
+
const bodyR = evalInConditionalFlow(() => evalNode(node.body, local, phi2, budget));
|
|
4557
4950
|
if (bodyR.returned) return bodyR;
|
|
4558
4951
|
if (bodyR.threw) return bodyR;
|
|
4559
4952
|
if (bodyR.brk) {
|
|
@@ -4576,7 +4969,7 @@ function evalWhile(node, env, phi2, budget) {
|
|
|
4576
4969
|
const t = evalNode(node.test, local, phi2, budget);
|
|
4577
4970
|
const lv = litValue(t.value);
|
|
4578
4971
|
if (lv === false || lv === null || lv === void 0) break;
|
|
4579
|
-
const bodyR = evalNode(node.body, local, phi2, budget);
|
|
4972
|
+
const bodyR = evalInConditionalFlow(() => evalNode(node.body, local, phi2, budget));
|
|
4580
4973
|
if (bodyR.returned || bodyR.threw) return bodyR;
|
|
4581
4974
|
if (bodyR.brk) {
|
|
4582
4975
|
local = bodyR.env;
|
|
@@ -4591,7 +4984,7 @@ function evalDoWhile(node, env, phi2, budget) {
|
|
|
4591
4984
|
let local = env;
|
|
4592
4985
|
let acc = unknown;
|
|
4593
4986
|
for (let i = 0; i < MAX_LOOP_ITERS; i++) {
|
|
4594
|
-
const bodyR = evalNode(node.body, local, phi2, budget);
|
|
4987
|
+
const bodyR = evalInConditionalFlow(() => evalNode(node.body, local, phi2, budget));
|
|
4595
4988
|
if (bodyR.returned || bodyR.threw) return bodyR;
|
|
4596
4989
|
if (bodyR.brk) {
|
|
4597
4990
|
local = bodyR.env;
|
|
@@ -4628,7 +5021,7 @@ function evalForOf(node, env, phi2, budget) {
|
|
|
4628
5021
|
const n = Math.min(elements.length, MAX_LOOP_ITERS);
|
|
4629
5022
|
for (let i = 0; i < n; i++) {
|
|
4630
5023
|
local = withVar(local, bindName, elements[i]);
|
|
4631
|
-
const bodyR = evalNode(node.body, local, phi2, budget);
|
|
5024
|
+
const bodyR = evalInConditionalFlow(() => evalNode(node.body, local, phi2, budget));
|
|
4632
5025
|
if (bodyR.returned || bodyR.threw) return bodyR;
|
|
4633
5026
|
if (bodyR.brk) {
|
|
4634
5027
|
local = bodyR.env;
|
|
@@ -4687,8 +5080,15 @@ function evalVarDecl(node, env, phi2, budget) {
|
|
|
4687
5080
|
function evalIf(node, env, phi2, budget) {
|
|
4688
5081
|
const t = evalNode(node.test, env, phi2, budget).value;
|
|
4689
5082
|
const tv = litValue(t);
|
|
5083
|
+
const refineEnv = (branch) => {
|
|
5084
|
+
const m = matchRelIdentLit(node.test);
|
|
5085
|
+
if (!m || branch !== "true") return env;
|
|
5086
|
+
const cur = env.vars.get(m.name);
|
|
5087
|
+
if (!cur) return env;
|
|
5088
|
+
return withVar(env, m.name, refineAbsForRelTrue(cur, m.op, m.k));
|
|
5089
|
+
};
|
|
4690
5090
|
if (tv === true) {
|
|
4691
|
-
return evalNode(node.consequent,
|
|
5091
|
+
return evalNode(node.consequent, refineEnv("true"), phi2, budget);
|
|
4692
5092
|
}
|
|
4693
5093
|
if (tv === false) {
|
|
4694
5094
|
if (node.alternate) return evalNode(node.alternate, env, phi2, budget);
|
|
@@ -4696,9 +5096,15 @@ function evalIf(node, env, phi2, budget) {
|
|
|
4696
5096
|
}
|
|
4697
5097
|
const tCons = trueConstraint(t);
|
|
4698
5098
|
const fCons = falseConstraint(t);
|
|
4699
|
-
const
|
|
4700
|
-
|
|
4701
|
-
|
|
5099
|
+
const envT = refineEnv("true");
|
|
5100
|
+
const a = evalInConditionalFlow(
|
|
5101
|
+
() => evalNode(node.consequent, envT, tCons ? and(phi2, tCons) : phi2, budget)
|
|
5102
|
+
);
|
|
5103
|
+
const alt = node.alternate;
|
|
5104
|
+
if (alt) {
|
|
5105
|
+
const b = evalInConditionalFlow(
|
|
5106
|
+
() => evalNode(alt, env, fCons ? and(phi2, fCons) : phi2, budget)
|
|
5107
|
+
);
|
|
4702
5108
|
return { value: joinAbs(a.value, b.value), phi: phi2, env, returned: a.returned || b.returned };
|
|
4703
5109
|
}
|
|
4704
5110
|
if (a.returned || a.threw) {
|
|
@@ -4709,6 +5115,20 @@ function evalIf(node, env, phi2, budget) {
|
|
|
4709
5115
|
function analyzeFn(source, fnName, args, phi2 = pTrue, budget, file, modules) {
|
|
4710
5116
|
return evalSource(source, { fn: fnName, args }, { phi: phi2, budget, file, modules }).value;
|
|
4711
5117
|
}
|
|
5118
|
+
function analyzeFnFull(source, fnName, args, opts = {}) {
|
|
5119
|
+
const r = evalSource(source, { fn: fnName, args }, opts);
|
|
5120
|
+
if (r.threw) {
|
|
5121
|
+
return {
|
|
5122
|
+
result: abs({ k: "never" }, void 0, void 0, "exact"),
|
|
5123
|
+
throws: r.value,
|
|
5124
|
+
...r.throwLoc ? { throwLoc: r.throwLoc } : {}
|
|
5125
|
+
};
|
|
5126
|
+
}
|
|
5127
|
+
return {
|
|
5128
|
+
result: r.value,
|
|
5129
|
+
throws: abs({ k: "never" }, void 0, void 0, "exact")
|
|
5130
|
+
};
|
|
5131
|
+
}
|
|
4712
5132
|
function evalProgramAbs(source, opts = {}) {
|
|
4713
5133
|
resetAbsCallBudget();
|
|
4714
5134
|
const file = opts.file ?? parseSource(source);
|
|
@@ -4842,8 +5262,8 @@ var GLOBAL_FNS = /* @__PURE__ */ new Set([
|
|
|
4842
5262
|
"String",
|
|
4843
5263
|
"Boolean"
|
|
4844
5264
|
]);
|
|
4845
|
-
function setBCallCollector(
|
|
4846
|
-
bCallCollector =
|
|
5265
|
+
function setBCallCollector(collector2) {
|
|
5266
|
+
bCallCollector = collector2;
|
|
4847
5267
|
}
|
|
4848
5268
|
function getBCallCollector() {
|
|
4849
5269
|
return bCallCollector;
|
|
@@ -5062,8 +5482,19 @@ function $for(init, test, step, body, maxIters = DEFAULT_MAX_LOOP_ITERS) {
|
|
|
5062
5482
|
}
|
|
5063
5483
|
return exitJoin ? joinAbs(exitJoin, state) : state;
|
|
5064
5484
|
}
|
|
5485
|
+
function tupleOrWiden(els, conf) {
|
|
5486
|
+
if (shouldWidenArrayLiteral(els.length)) {
|
|
5487
|
+
return abs(
|
|
5488
|
+
{ k: "arr", element: els.reduce((x, y) => joinAbs(x, y)) },
|
|
5489
|
+
void 0,
|
|
5490
|
+
void 0,
|
|
5491
|
+
widenedArrayConf()
|
|
5492
|
+
);
|
|
5493
|
+
}
|
|
5494
|
+
return abs({ k: "tuple", elements: els }, void 0, void 0, conf);
|
|
5495
|
+
}
|
|
5065
5496
|
function $arr(items) {
|
|
5066
|
-
return
|
|
5497
|
+
return tupleOrWiden(items.map(asAbsVal), "exact");
|
|
5067
5498
|
}
|
|
5068
5499
|
function $idx(a, i) {
|
|
5069
5500
|
const iv = litValue(i);
|
|
@@ -5142,33 +5573,33 @@ function $spread(a, b) {
|
|
|
5142
5573
|
function $concat(a, b) {
|
|
5143
5574
|
a = asAbsVal(a);
|
|
5144
5575
|
b = asAbsVal(b);
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
);
|
|
5576
|
+
const as = a.shape;
|
|
5577
|
+
const bs = b.shape;
|
|
5578
|
+
if (as.k === "tuple" && bs.k === "tuple") {
|
|
5579
|
+
return tupleOrWiden([...as.elements, ...bs.elements], confJoin(a.conf, b.conf));
|
|
5580
|
+
}
|
|
5581
|
+
if (as.k === "arr" || bs.k === "arr") {
|
|
5582
|
+
const ea = as.k === "tuple" ? as.elements.reduce((x, y) => joinAbs(x, y)) : as.k === "arr" ? as.element : a;
|
|
5583
|
+
const eb = bs.k === "tuple" ? bs.elements.reduce((x, y) => joinAbs(x, y)) : bs.k === "arr" ? bs.element : b;
|
|
5584
|
+
return abs({ k: "arr", element: joinAbs(ea, eb) }, void 0, void 0, "path");
|
|
5152
5585
|
}
|
|
5153
|
-
if (
|
|
5586
|
+
if (as.k === "tuple") {
|
|
5154
5587
|
return abs(
|
|
5155
|
-
{ k: "tuple", elements: [...
|
|
5588
|
+
{ k: "tuple", elements: [...as.elements, b] },
|
|
5156
5589
|
void 0,
|
|
5157
5590
|
void 0,
|
|
5158
5591
|
confJoin(a.conf, b.conf)
|
|
5159
5592
|
);
|
|
5160
5593
|
}
|
|
5161
|
-
if (
|
|
5594
|
+
if (bs.k === "tuple") {
|
|
5162
5595
|
return abs(
|
|
5163
|
-
{ k: "tuple", elements: [a, ...
|
|
5596
|
+
{ k: "tuple", elements: [a, ...bs.elements] },
|
|
5164
5597
|
void 0,
|
|
5165
5598
|
void 0,
|
|
5166
5599
|
confJoin(a.conf, b.conf)
|
|
5167
5600
|
);
|
|
5168
5601
|
}
|
|
5169
|
-
|
|
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");
|
|
5602
|
+
return abs({ k: "arr", element: joinAbs(a, b) }, void 0, void 0, "path");
|
|
5172
5603
|
}
|
|
5173
5604
|
function $elems(a) {
|
|
5174
5605
|
if (a.shape.k === "tuple") return [...a.shape.elements];
|
|
@@ -6585,6 +7016,10 @@ function invokeArrMethod(arr, method, args) {
|
|
|
6585
7016
|
return acc;
|
|
6586
7017
|
}
|
|
6587
7018
|
if (method === "filter" && args[0]) {
|
|
7019
|
+
if (shape.k === "tuple") {
|
|
7020
|
+
const el = shape.elements.length > 0 ? shape.elements.reduce((a, b) => joinAbs(a, b)) : unknown;
|
|
7021
|
+
return abs({ k: "arr", element: el }, void 0, void 0, confJoin(arr.conf, "path"));
|
|
7022
|
+
}
|
|
6588
7023
|
return arr;
|
|
6589
7024
|
}
|
|
6590
7025
|
if (method === "flatMap" && args[0]) {
|
|
@@ -6961,10 +7396,6 @@ function callTranspiledExport(exports, name, args) {
|
|
|
6961
7396
|
}
|
|
6962
7397
|
|
|
6963
7398
|
export {
|
|
6964
|
-
stripTypes,
|
|
6965
|
-
resetParseSourceCache,
|
|
6966
|
-
getParseSourceCacheSize,
|
|
6967
|
-
parseSource,
|
|
6968
7399
|
lit,
|
|
6969
7400
|
v,
|
|
6970
7401
|
app,
|
|
@@ -7014,19 +7445,37 @@ export {
|
|
|
7014
7445
|
isStrPrim,
|
|
7015
7446
|
isExactLit,
|
|
7016
7447
|
litValue,
|
|
7448
|
+
stripTypes,
|
|
7449
|
+
resetParseSourceCache,
|
|
7450
|
+
getParseSourceCacheSize,
|
|
7451
|
+
parseSource,
|
|
7017
7452
|
attachFnImpl,
|
|
7018
7453
|
getFnImpl,
|
|
7019
7454
|
absFunction,
|
|
7020
7455
|
relationFingerprint,
|
|
7021
7456
|
relationFn,
|
|
7022
7457
|
shapeOnlyFn,
|
|
7458
|
+
setDerivationCollector,
|
|
7459
|
+
hasDerivationSession,
|
|
7460
|
+
beginDerivationSession,
|
|
7461
|
+
endDerivationSession,
|
|
7462
|
+
abortDerivationSession,
|
|
7463
|
+
tagDerivationRoot,
|
|
7464
|
+
getDerivation,
|
|
7465
|
+
setDerivation,
|
|
7466
|
+
derivationChain,
|
|
7467
|
+
noteDerivationAdd,
|
|
7468
|
+
noteDerivationJoin,
|
|
7469
|
+
projectDerivationDsl,
|
|
7470
|
+
termKey3 as termKey,
|
|
7023
7471
|
objOf,
|
|
7024
7472
|
isObj,
|
|
7473
|
+
getSlot,
|
|
7025
7474
|
spread,
|
|
7026
7475
|
joinObjects,
|
|
7027
7476
|
joinValues,
|
|
7028
7477
|
makeSum,
|
|
7029
|
-
|
|
7478
|
+
absShapeKey,
|
|
7030
7479
|
fnOf,
|
|
7031
7480
|
joinFunctions,
|
|
7032
7481
|
joinAbs,
|
|
@@ -7049,18 +7498,31 @@ export {
|
|
|
7049
7498
|
mapElementFallback,
|
|
7050
7499
|
projectFlatMapResult,
|
|
7051
7500
|
asAbs,
|
|
7501
|
+
viewTemplateParts,
|
|
7502
|
+
knownPrefixOfViews,
|
|
7503
|
+
knownSuffixOfViews,
|
|
7504
|
+
allFixedTextOfViews,
|
|
7505
|
+
fixedLengthOfViews,
|
|
7506
|
+
formatTemplateNameViews,
|
|
7507
|
+
mergeAdjacentFixedViews,
|
|
7508
|
+
templateMatchesValue,
|
|
7509
|
+
decideStartsWith,
|
|
7510
|
+
decideEndsWith,
|
|
7511
|
+
decideIncludes,
|
|
7512
|
+
absTemplateViews,
|
|
7052
7513
|
templatePartsOf,
|
|
7053
7514
|
createTemplateAbs,
|
|
7054
7515
|
isTemplateLike,
|
|
7055
7516
|
concatString,
|
|
7056
7517
|
add,
|
|
7057
|
-
numericBounds,
|
|
7058
7518
|
sub,
|
|
7059
7519
|
mul,
|
|
7060
7520
|
div,
|
|
7061
7521
|
mod,
|
|
7062
7522
|
cmp,
|
|
7063
7523
|
trueConstraint,
|
|
7524
|
+
refineAbsForRelTrue,
|
|
7525
|
+
matchRelIdentLit,
|
|
7064
7526
|
falseConstraint,
|
|
7065
7527
|
typeofAbs,
|
|
7066
7528
|
negAbs,
|
|
@@ -7130,11 +7592,13 @@ export {
|
|
|
7130
7592
|
setAbsNodeCollector,
|
|
7131
7593
|
setAbsAssignCollector,
|
|
7132
7594
|
evalSource,
|
|
7595
|
+
callFunctionFull,
|
|
7133
7596
|
callFunction,
|
|
7134
7597
|
evalMethodBody,
|
|
7135
7598
|
evalNode,
|
|
7136
7599
|
applyAbsFn,
|
|
7137
7600
|
analyzeFn,
|
|
7601
|
+
analyzeFnFull,
|
|
7138
7602
|
evalProgramAbs,
|
|
7139
7603
|
collectAbsNodeTypes,
|
|
7140
7604
|
findAbsAtPosition,
|