@nudojs/core 0.3.1 → 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.
- package/dist/{chunk-BU4A6XJ3.js → chunk-RZOQL6PT.js} +1865 -1352
- package/dist/exec.d.ts +1 -1
- package/dist/exec.js +7 -1
- package/dist/{index-CVYjXnwU.d.ts → index-OfNo5qlN.d.ts} +34 -175
- package/dist/index.d.ts +580 -42
- package/dist/index.js +5103 -3032
- package/package.json +14 -2
|
@@ -39,6 +39,7 @@ __export(runtime_exports, {
|
|
|
39
39
|
$neg: () => $neg,
|
|
40
40
|
$not: () => $not,
|
|
41
41
|
$obj: () => $obj,
|
|
42
|
+
$regex: () => $regex,
|
|
42
43
|
$set: () => $set,
|
|
43
44
|
$spread: () => $spread,
|
|
44
45
|
$sub: () => $sub,
|
|
@@ -55,6 +56,8 @@ __export(runtime_exports, {
|
|
|
55
56
|
isDefinitelyFalse: () => isDefinitelyFalse,
|
|
56
57
|
isDefinitelyTrue: () => isDefinitelyTrue,
|
|
57
58
|
isNudoThrow: () => isNudoThrow,
|
|
59
|
+
litTruth: () => litTruth,
|
|
60
|
+
namespaceNameOf: () => namespaceNameOf,
|
|
58
61
|
withExecPhi: () => withExecPhi
|
|
59
62
|
});
|
|
60
63
|
|
|
@@ -700,6 +703,86 @@ function shapeOnlyFn(paramTypes, returnType, opts) {
|
|
|
700
703
|
}
|
|
701
704
|
|
|
702
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
|
+
}
|
|
703
786
|
function isStrLit(a) {
|
|
704
787
|
return a.shape.k === "prim" && a.shape.type === "string" && a.term?.op === "lit" && typeof a.term.value === "string";
|
|
705
788
|
}
|
|
@@ -709,6 +792,13 @@ function isStrPrim2(a) {
|
|
|
709
792
|
function isTemplateAbs(a) {
|
|
710
793
|
return a.shape.k === "prim" && a.shape.type === "string" && !!a.pred && a.pred.name?.startsWith("`") === true && Array.isArray(a.pred.meta?.templateParts);
|
|
711
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
|
+
}
|
|
712
802
|
function templatePartsOf(a) {
|
|
713
803
|
if (isTemplateAbs(a)) {
|
|
714
804
|
const meta = a.pred.meta;
|
|
@@ -716,29 +806,18 @@ function templatePartsOf(a) {
|
|
|
716
806
|
}
|
|
717
807
|
return [a];
|
|
718
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
|
+
}
|
|
719
816
|
function normalizeParts(parts) {
|
|
720
|
-
|
|
721
|
-
for (const p of parts) {
|
|
722
|
-
const last = out[out.length - 1];
|
|
723
|
-
if (last && isStrLit(last) && isStrLit(p)) {
|
|
724
|
-
out[out.length - 1] = abs(
|
|
725
|
-
{ k: "prim", type: "string" },
|
|
726
|
-
lit(String(litValue(last)) + String(litValue(p))),
|
|
727
|
-
void 0,
|
|
728
|
-
"exact"
|
|
729
|
-
);
|
|
730
|
-
} else {
|
|
731
|
-
out.push(p);
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
return out;
|
|
817
|
+
return mergeAdjacentFixedViews(absTemplateViews(parts), rebuildAbsFixedView).map((v2) => v2.part);
|
|
735
818
|
}
|
|
736
819
|
function formatTemplateName(parts) {
|
|
737
|
-
|
|
738
|
-
if (isStrLit(p)) return String(litValue(p));
|
|
739
|
-
return `\${${p.term ? termToString(p.term) : "string"}}`;
|
|
740
|
-
}).join("");
|
|
741
|
-
return `\`${inner}\``;
|
|
820
|
+
return formatTemplateNameViews(absTemplateViews(parts));
|
|
742
821
|
}
|
|
743
822
|
function createTemplateAbs(parts) {
|
|
744
823
|
const normalized = normalizeParts(parts);
|
|
@@ -790,6 +869,157 @@ function coerceToStringParts(a) {
|
|
|
790
869
|
return void 0;
|
|
791
870
|
}
|
|
792
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
|
+
|
|
793
1023
|
// src/algebra/arithmetic.ts
|
|
794
1024
|
function add(a, b, phi2 = pTrue) {
|
|
795
1025
|
const va = litValue(a);
|
|
@@ -873,6 +1103,9 @@ function isAnyLike(a) {
|
|
|
873
1103
|
if (a.shape.k === "unknown") return true;
|
|
874
1104
|
return false;
|
|
875
1105
|
}
|
|
1106
|
+
function coercibleLit(v2) {
|
|
1107
|
+
return v2 !== void 0 && (typeof v2 === "number" || typeof v2 === "string" || typeof v2 === "boolean" || v2 === null);
|
|
1108
|
+
}
|
|
876
1109
|
function toNumberResult(a, b, op) {
|
|
877
1110
|
const term = a.term && b.term ? simplifyTerm(app(op, [a.term, b.term])) : void 0;
|
|
878
1111
|
return abs(
|
|
@@ -991,6 +1224,9 @@ function sub(a, b, phi2 = pTrue) {
|
|
|
991
1224
|
if (typeof va === "number" && typeof vb === "number") {
|
|
992
1225
|
return numLit(va - vb);
|
|
993
1226
|
}
|
|
1227
|
+
if (coercibleLit(va) && coercibleLit(vb)) {
|
|
1228
|
+
return numLit(Number(va) - Number(vb));
|
|
1229
|
+
}
|
|
994
1230
|
if (isNumericLike(a) && isNumericLike(b) && a.term && b.term) {
|
|
995
1231
|
const term = simplifyTerm(app("-", [a.term, b.term]));
|
|
996
1232
|
const ab = numericBounds(a, phi2);
|
|
@@ -1023,6 +1259,9 @@ function mul(a, b, phi2 = pTrue) {
|
|
|
1023
1259
|
if (typeof va === "number" && typeof vb === "number") {
|
|
1024
1260
|
return numLit(va * vb);
|
|
1025
1261
|
}
|
|
1262
|
+
if (coercibleLit(va) && coercibleLit(vb)) {
|
|
1263
|
+
return numLit(Number(va) * Number(vb));
|
|
1264
|
+
}
|
|
1026
1265
|
if (isNumericLike(a) && isNumericLike(b) && a.term && b.term) {
|
|
1027
1266
|
const term = simplifyTerm(app("*", [a.term, b.term]));
|
|
1028
1267
|
if (b.term.op === "lit" && b.term.value === 0 || a.term.op === "lit" && a.term.value === 0) {
|
|
@@ -1089,6 +1328,9 @@ function div(a, b, phi2 = pTrue) {
|
|
|
1089
1328
|
}
|
|
1090
1329
|
return numLit(va / vb);
|
|
1091
1330
|
}
|
|
1331
|
+
if (coercibleLit(va) && coercibleLit(vb)) {
|
|
1332
|
+
return numLit(Number(va) / Number(vb));
|
|
1333
|
+
}
|
|
1092
1334
|
if (isNumericLike(a) && isNumericLike(b) && a.term && b.term) {
|
|
1093
1335
|
const term = simplifyTerm(app("/", [a.term, b.term]));
|
|
1094
1336
|
if (b.term.op === "lit" && typeof b.term.value === "number" && b.term.value !== 0) {
|
|
@@ -1131,6 +1373,9 @@ function mod(a, b, phi2 = pTrue) {
|
|
|
1131
1373
|
}
|
|
1132
1374
|
return numLit(va % vb);
|
|
1133
1375
|
}
|
|
1376
|
+
if (coercibleLit(va) && coercibleLit(vb)) {
|
|
1377
|
+
return numLit(Number(va) % Number(vb));
|
|
1378
|
+
}
|
|
1134
1379
|
if (isNumericLike(a) && isNumericLike(b) && a.term && b.term) {
|
|
1135
1380
|
const term = simplifyTerm(app("%", [a.term, b.term]));
|
|
1136
1381
|
if (b.term.op === "lit" && typeof b.term.value === "number" && b.term.value !== 0) {
|
|
@@ -1202,6 +1447,20 @@ function compareLits(op, a, b) {
|
|
|
1202
1447
|
return a >= b;
|
|
1203
1448
|
}
|
|
1204
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
|
+
}
|
|
1205
1464
|
return void 0;
|
|
1206
1465
|
}
|
|
1207
1466
|
function decideByBounds(op, a, b, phi2) {
|
|
@@ -1240,6 +1499,34 @@ function trueConstraint(c) {
|
|
|
1240
1499
|
if (c.term?.op === "lit" && c.term.value === false) return void 0;
|
|
1241
1500
|
return c.pred;
|
|
1242
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
|
+
}
|
|
1243
1530
|
function falseConstraint(c) {
|
|
1244
1531
|
if (c.term?.op === "lit" && c.term.value === true) return void 0;
|
|
1245
1532
|
if (c.term?.op === "lit" && c.term.value === false) return pTrue;
|
|
@@ -1432,176 +1719,20 @@ function strictEqAbs(a, b) {
|
|
|
1432
1719
|
return void 0;
|
|
1433
1720
|
}
|
|
1434
1721
|
|
|
1435
|
-
// src/algebra/
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
if (opts?.open) shape.open = true;
|
|
1440
|
-
return { shape, conf: "exact" };
|
|
1722
|
+
// src/algebra/containers.ts
|
|
1723
|
+
var TUPLE_LITERAL_CAP = 8;
|
|
1724
|
+
function shouldWidenArrayLiteral(n) {
|
|
1725
|
+
return n > TUPLE_LITERAL_CAP;
|
|
1441
1726
|
}
|
|
1442
|
-
function
|
|
1443
|
-
return
|
|
1727
|
+
function widenedArrayConf() {
|
|
1728
|
+
return "path";
|
|
1444
1729
|
}
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
if (!isObj(over)) {
|
|
1452
|
-
if (!isObj(base)) return unknown;
|
|
1453
|
-
return {
|
|
1454
|
-
shape: { ...base.shape, open: true },
|
|
1455
|
-
conf: confJoin(base.conf, "partial")
|
|
1456
|
-
};
|
|
1457
|
-
}
|
|
1458
|
-
if (!isObj(base)) {
|
|
1459
|
-
return { shape: { ...over.shape, open: true }, conf: confJoin(base.conf, over.conf) };
|
|
1460
|
-
}
|
|
1461
|
-
const slots = { ...base.shape.slots };
|
|
1462
|
-
for (const [k, s] of Object.entries(over.shape.slots)) {
|
|
1463
|
-
slots[k] = s;
|
|
1464
|
-
}
|
|
1465
|
-
const open = base.shape.open || over.shape.open || false;
|
|
1466
|
-
const shape = { k: "obj", slots };
|
|
1467
|
-
if (open) shape.open = true;
|
|
1468
|
-
if (base.shape.index || over.shape.index) {
|
|
1469
|
-
shape.index = over.shape.index ?? base.shape.index;
|
|
1470
|
-
}
|
|
1471
|
-
return { shape, conf: confJoin(base.conf, over.conf) };
|
|
1472
|
-
}
|
|
1473
|
-
function joinObjects(a, b) {
|
|
1474
|
-
if (a.shape.k === "never") return b;
|
|
1475
|
-
if (b.shape.k === "never") return a;
|
|
1476
|
-
if (!isObj(a) || !isObj(b)) {
|
|
1477
|
-
return makeSum(a, b);
|
|
1478
|
-
}
|
|
1479
|
-
const ka = Object.keys(a.shape.slots).sort();
|
|
1480
|
-
const kb = Object.keys(b.shape.slots).sort();
|
|
1481
|
-
const sameKeys = ka.length === kb.length && ka.every((k, i) => k === kb[i]);
|
|
1482
|
-
if (!sameKeys) {
|
|
1483
|
-
return makeSum(a, b);
|
|
1484
|
-
}
|
|
1485
|
-
const slots = {};
|
|
1486
|
-
let conf = confJoin(a.conf, b.conf);
|
|
1487
|
-
for (const k of ka) {
|
|
1488
|
-
const sa = a.shape.slots[k];
|
|
1489
|
-
const sb = b.shape.slots[k];
|
|
1490
|
-
const optional = sa.optional || sb.optional;
|
|
1491
|
-
const jv = joinValues(sa.value, sb.value);
|
|
1492
|
-
conf = confJoin(conf, jv.conf);
|
|
1493
|
-
slots[k] = { value: jv, optional };
|
|
1494
|
-
}
|
|
1495
|
-
return { shape: { k: "obj", slots }, conf };
|
|
1496
|
-
}
|
|
1497
|
-
function joinValues(a, b) {
|
|
1498
|
-
if (a.shape.k === "never") return b;
|
|
1499
|
-
if (b.shape.k === "never") return a;
|
|
1500
|
-
const va = litValue(a);
|
|
1501
|
-
const vb = litValue(b);
|
|
1502
|
-
if (va !== void 0 && va === vb) return a;
|
|
1503
|
-
if (a.shape.k === "prim" && b.shape.k === "prim" && a.shape.type === b.shape.type) {
|
|
1504
|
-
if (va !== void 0 && vb !== void 0) {
|
|
1505
|
-
return abs(
|
|
1506
|
-
a.shape,
|
|
1507
|
-
void 0,
|
|
1508
|
-
void 0,
|
|
1509
|
-
confJoin(a.conf, "path")
|
|
1510
|
-
);
|
|
1511
|
-
}
|
|
1512
|
-
return abs(a.shape, void 0, void 0, confJoin(confJoin(a.conf, b.conf), "path"));
|
|
1513
|
-
}
|
|
1514
|
-
return makeSum(a, b);
|
|
1515
|
-
}
|
|
1516
|
-
function makeSum(a, b) {
|
|
1517
|
-
const members = flattenSum([a, b]);
|
|
1518
|
-
if (members.length === 1) return members[0];
|
|
1519
|
-
return {
|
|
1520
|
-
shape: { k: "sum", members },
|
|
1521
|
-
conf: confJoin(a.conf, b.conf)
|
|
1522
|
-
};
|
|
1523
|
-
}
|
|
1524
|
-
function flattenSum(xs) {
|
|
1525
|
-
const out = [];
|
|
1526
|
-
for (const x of xs) {
|
|
1527
|
-
if (x.shape.k === "sum") out.push(...x.shape.members);
|
|
1528
|
-
else out.push(x);
|
|
1529
|
-
}
|
|
1530
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1531
|
-
const deduped = [];
|
|
1532
|
-
for (const x of out) {
|
|
1533
|
-
const key = shapeKey(x);
|
|
1534
|
-
if (seen.has(key)) continue;
|
|
1535
|
-
seen.add(key);
|
|
1536
|
-
deduped.push(x);
|
|
1537
|
-
}
|
|
1538
|
-
return deduped;
|
|
1539
|
-
}
|
|
1540
|
-
function shapeKey(a) {
|
|
1541
|
-
const s = a.shape;
|
|
1542
|
-
if (s.k === "prim") return `prim:${s.type}`;
|
|
1543
|
-
if (s.k === "never") return "never";
|
|
1544
|
-
if (s.k === "any") return "any";
|
|
1545
|
-
if (s.k === "unknown") return "unknown";
|
|
1546
|
-
if (s.k === "obj") return `obj:${Object.keys(s.slots).sort().join(",")}`;
|
|
1547
|
-
if (s.k === "fn") return `fn:${s.params.length}`;
|
|
1548
|
-
if (s.k === "sum") return `sum:${s.members.length}`;
|
|
1549
|
-
return "other";
|
|
1550
|
-
}
|
|
1551
|
-
function collapseToOptional(sum) {
|
|
1552
|
-
if (sum.shape.k !== "sum") {
|
|
1553
|
-
if (isObj(sum)) return { ...sum, conf: confJoin(sum.conf, "widened") };
|
|
1554
|
-
return sum;
|
|
1555
|
-
}
|
|
1556
|
-
const objs = sum.shape.members.filter(isObj);
|
|
1557
|
-
if (objs.length === 0) {
|
|
1558
|
-
return abs({ k: "unknown" }, void 0, void 0, "widened");
|
|
1559
|
-
}
|
|
1560
|
-
const allKeys = /* @__PURE__ */ new Set();
|
|
1561
|
-
for (const o of objs) {
|
|
1562
|
-
for (const k of Object.keys(o.shape.slots)) allKeys.add(k);
|
|
1563
|
-
}
|
|
1564
|
-
const slots = {};
|
|
1565
|
-
for (const k of allKeys) {
|
|
1566
|
-
const present = objs.filter((o) => k in o.shape.slots);
|
|
1567
|
-
const values = present.map((o) => o.shape.slots[k].value);
|
|
1568
|
-
const joined = values.reduce((acc, v2) => joinValues(acc, v2));
|
|
1569
|
-
const optional = present.length < objs.length;
|
|
1570
|
-
slots[k] = { value: joined, optional };
|
|
1571
|
-
}
|
|
1572
|
-
return { shape: { k: "obj", slots }, conf: "widened" };
|
|
1573
|
-
}
|
|
1574
|
-
function fnOf(params, name) {
|
|
1575
|
-
const shape = { k: "fn", params };
|
|
1576
|
-
if (name) shape.name = name;
|
|
1577
|
-
return { shape, conf: "exact" };
|
|
1578
|
-
}
|
|
1579
|
-
function joinFunctions(a, b) {
|
|
1580
|
-
const sa = a.shape;
|
|
1581
|
-
const sb = b.shape;
|
|
1582
|
-
if (sa.k !== "fn" || sb.k !== "fn") return makeSum(a, b);
|
|
1583
|
-
const an = sa.name;
|
|
1584
|
-
const bn = sb.name;
|
|
1585
|
-
if (an && an === bn) {
|
|
1586
|
-
if (sa.params.length === sb.params.length && sa.params.every((p, i) => p === sb.params[i])) {
|
|
1587
|
-
return a;
|
|
1588
|
-
}
|
|
1589
|
-
}
|
|
1590
|
-
return makeSum(a, b);
|
|
1591
|
-
}
|
|
1592
|
-
function joinAbs(a, b) {
|
|
1593
|
-
if (a.shape.k === "never") return b;
|
|
1594
|
-
if (b.shape.k === "never") return a;
|
|
1595
|
-
if (isObj(a) && isObj(b)) return joinObjects(a, b);
|
|
1596
|
-
if (a.shape.k === "fn" && b.shape.k === "fn") return joinFunctions(a, b);
|
|
1597
|
-
return joinValues(a, b);
|
|
1598
|
-
}
|
|
1599
|
-
|
|
1600
|
-
// src/algebra/language.ts
|
|
1601
|
-
function classesOf(env) {
|
|
1602
|
-
const e = env;
|
|
1603
|
-
if (!e.classes) e.classes = /* @__PURE__ */ new Map();
|
|
1604
|
-
return e.classes;
|
|
1730
|
+
|
|
1731
|
+
// src/algebra/language.ts
|
|
1732
|
+
function classesOf(env) {
|
|
1733
|
+
const e = env;
|
|
1734
|
+
if (!e.classes) e.classes = /* @__PURE__ */ new Map();
|
|
1735
|
+
return e.classes;
|
|
1605
1736
|
}
|
|
1606
1737
|
function defineClass(env, def) {
|
|
1607
1738
|
classesOf(env).set(def.name, def);
|
|
@@ -1710,8 +1841,8 @@ function litFalse() {
|
|
|
1710
1841
|
function projectBrand(self, key) {
|
|
1711
1842
|
if (self.shape.k !== "brand") return unknown;
|
|
1712
1843
|
const inner = self.shape.shape;
|
|
1713
|
-
if (inner.shape.k === "obj") {
|
|
1714
|
-
const slot = inner.shape.slots
|
|
1844
|
+
if (inner && inner.shape.k === "obj") {
|
|
1845
|
+
const slot = getSlot(inner.shape.slots, key);
|
|
1715
1846
|
if (slot) return slot.value;
|
|
1716
1847
|
}
|
|
1717
1848
|
return unknown;
|
|
@@ -1900,7 +2031,7 @@ function leqShape(src, tgt, phi2, env, depth) {
|
|
|
1900
2031
|
const srcObj = s.k === "obj" ? s : s.k === "brand" ? s.shape.shape.k === "obj" ? s.shape.shape : null : null;
|
|
1901
2032
|
if (!srcObj || srcObj.k !== "obj") return fail(`shape ${s.k} \u22AD obj`);
|
|
1902
2033
|
for (const [key, slot] of Object.entries(t.slots)) {
|
|
1903
|
-
const srcSlot = srcObj.slots
|
|
2034
|
+
const srcSlot = getSlot(srcObj.slots, key);
|
|
1904
2035
|
if (!srcSlot) {
|
|
1905
2036
|
if (slot.optional) continue;
|
|
1906
2037
|
return fail(`missing slot ${key}`);
|
|
@@ -1981,1118 +2112,1138 @@ function primOf(a) {
|
|
|
1981
2112
|
return void 0;
|
|
1982
2113
|
}
|
|
1983
2114
|
|
|
1984
|
-
// src/algebra/
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
if (Array.isArray(value)) {
|
|
2018
|
-
let changed = false;
|
|
2019
|
-
const out = [];
|
|
2020
|
-
for (const el of value) {
|
|
2021
|
-
if (el === null || el === void 0) {
|
|
2022
|
-
out.push(el);
|
|
2023
|
-
continue;
|
|
2115
|
+
// src/algebra/builtins.ts
|
|
2116
|
+
function numPrim(conf = "path") {
|
|
2117
|
+
return abs({ k: "prim", type: "number" }, void 0, void 0, conf);
|
|
2118
|
+
}
|
|
2119
|
+
function strPrim(conf = "path") {
|
|
2120
|
+
return abs({ k: "prim", type: "string" }, void 0, void 0, conf);
|
|
2121
|
+
}
|
|
2122
|
+
function boolPrim(conf = "partial") {
|
|
2123
|
+
return abs({ k: "prim", type: "boolean" }, void 0, void 0, conf);
|
|
2124
|
+
}
|
|
2125
|
+
function evalMathMethod(name, args) {
|
|
2126
|
+
const a0 = args[0] ? litValue(args[0]) : void 0;
|
|
2127
|
+
const a1 = args[1] ? litValue(args[1]) : void 0;
|
|
2128
|
+
switch (name) {
|
|
2129
|
+
case "abs":
|
|
2130
|
+
if (typeof a0 === "number") return numLit(Math.abs(a0));
|
|
2131
|
+
return numPrim();
|
|
2132
|
+
case "floor":
|
|
2133
|
+
if (typeof a0 === "number") return numLit(Math.floor(a0));
|
|
2134
|
+
return numPrim();
|
|
2135
|
+
case "ceil":
|
|
2136
|
+
if (typeof a0 === "number") return numLit(Math.ceil(a0));
|
|
2137
|
+
return numPrim();
|
|
2138
|
+
case "round":
|
|
2139
|
+
if (typeof a0 === "number") return numLit(Math.round(a0));
|
|
2140
|
+
return numPrim();
|
|
2141
|
+
case "sqrt":
|
|
2142
|
+
if (typeof a0 === "number") return numLit(Math.sqrt(a0));
|
|
2143
|
+
return numPrim();
|
|
2144
|
+
case "min": {
|
|
2145
|
+
const lits = args.map(litValue);
|
|
2146
|
+
if (lits.length > 0 && lits.every((x) => typeof x === "number")) {
|
|
2147
|
+
return numLit(Math.min(...lits));
|
|
2024
2148
|
}
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2149
|
+
return numPrim();
|
|
2150
|
+
}
|
|
2151
|
+
case "max": {
|
|
2152
|
+
const lits = args.map(litValue);
|
|
2153
|
+
if (lits.length > 0 && lits.every((x) => typeof x === "number")) {
|
|
2154
|
+
return numLit(Math.max(...lits));
|
|
2031
2155
|
}
|
|
2156
|
+
return numPrim();
|
|
2032
2157
|
}
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
function isTsDeclareLike(node) {
|
|
2040
|
-
return node.declare === true;
|
|
2041
|
-
}
|
|
2042
|
-
function isTypeOnlyDeclaration(decl) {
|
|
2043
|
-
switch (decl.type) {
|
|
2044
|
-
case "TSInterfaceDeclaration":
|
|
2045
|
-
case "TSTypeAliasDeclaration":
|
|
2046
|
-
case "TSEnumDeclaration":
|
|
2047
|
-
case "TSDeclareFunction":
|
|
2048
|
-
return true;
|
|
2049
|
-
case "VariableDeclaration":
|
|
2050
|
-
case "ClassDeclaration":
|
|
2051
|
-
return isTsDeclareLike(decl);
|
|
2158
|
+
case "pow":
|
|
2159
|
+
if (typeof a0 === "number" && typeof a1 === "number") return numLit(Math.pow(a0, a1));
|
|
2160
|
+
return numPrim();
|
|
2161
|
+
case "sign":
|
|
2162
|
+
if (typeof a0 === "number") return numLit(Math.sign(a0));
|
|
2163
|
+
return numPrim();
|
|
2052
2164
|
default:
|
|
2053
|
-
return
|
|
2165
|
+
return void 0;
|
|
2054
2166
|
}
|
|
2055
2167
|
}
|
|
2056
|
-
function
|
|
2057
|
-
const
|
|
2058
|
-
switch (
|
|
2059
|
-
case "
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
return isTsDeclareLike(node);
|
|
2066
|
-
case "VariableDeclaration":
|
|
2067
|
-
case "ClassDeclaration":
|
|
2068
|
-
return isTsDeclareLike(node);
|
|
2069
|
-
case "ImportDeclaration":
|
|
2070
|
-
if (anyNode.importKind === "type") return true;
|
|
2071
|
-
{
|
|
2072
|
-
const specs = anyNode.specifiers;
|
|
2073
|
-
if (specs && specs.length > 0 && specs.every((s) => s.importKind === "type" || s.importKind === "typeof")) {
|
|
2074
|
-
return true;
|
|
2075
|
-
}
|
|
2168
|
+
function evalObjectMethod(name, args) {
|
|
2169
|
+
const a0 = args[0];
|
|
2170
|
+
switch (name) {
|
|
2171
|
+
case "keys": {
|
|
2172
|
+
if (a0?.shape.k === "obj") {
|
|
2173
|
+
const keys = Object.keys(a0.shape.slots).map(
|
|
2174
|
+
(k) => strLit(k)
|
|
2175
|
+
);
|
|
2176
|
+
return abs({ k: "tuple", elements: keys }, void 0, void 0, "exact");
|
|
2076
2177
|
}
|
|
2077
|
-
return
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
if (!decl && specs && specs.length > 0 && specs.every((s) => s.exportKind === "type")) return true;
|
|
2178
|
+
return abs({ k: "arr", element: strPrim("path") }, void 0, void 0, "partial");
|
|
2179
|
+
}
|
|
2180
|
+
case "values": {
|
|
2181
|
+
if (a0?.shape.k === "obj") {
|
|
2182
|
+
const slots = a0.shape.slots;
|
|
2183
|
+
const vals = Object.values(slots).map((s) => s.value);
|
|
2184
|
+
return abs({ k: "tuple", elements: vals }, void 0, void 0, "exact");
|
|
2085
2185
|
}
|
|
2086
|
-
return
|
|
2186
|
+
return abs({ k: "arr", element: unknown }, void 0, void 0, "partial");
|
|
2187
|
+
}
|
|
2188
|
+
case "entries": {
|
|
2189
|
+
if (a0?.shape.k === "obj") {
|
|
2190
|
+
const slots = a0.shape.slots;
|
|
2191
|
+
const entries = Object.entries(slots).map(
|
|
2192
|
+
([, s]) => abs({ k: "tuple", elements: [strPrim("exact"), s.value] }, void 0, void 0, "exact")
|
|
2193
|
+
);
|
|
2194
|
+
return abs({ k: "tuple", elements: entries }, void 0, void 0, "exact");
|
|
2195
|
+
}
|
|
2196
|
+
return abs({ k: "arr", element: unknown }, void 0, void 0, "partial");
|
|
2197
|
+
}
|
|
2198
|
+
case "assign": {
|
|
2199
|
+
if (!args.length) return unknown;
|
|
2200
|
+
let acc = args[0];
|
|
2201
|
+
for (let i = 1; i < args.length; i++) {
|
|
2202
|
+
acc = { ...acc };
|
|
2203
|
+
if (acc.shape.k === "obj" && args[i].shape.k === "obj") {
|
|
2204
|
+
const base = acc.shape.slots;
|
|
2205
|
+
const over = args[i].shape.slots;
|
|
2206
|
+
acc = abs({ k: "obj", slots: { ...base, ...over } }, void 0, void 0, confJoin(acc.conf, args[i].conf));
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
2209
|
+
return acc;
|
|
2087
2210
|
}
|
|
2088
|
-
case "ExportAllDeclaration":
|
|
2089
|
-
return anyNode.exportKind === "type";
|
|
2090
|
-
case "ExportDefaultDeclaration":
|
|
2091
|
-
return isTypeOnlyDeclaration(node.declaration);
|
|
2092
|
-
// ---- 类成员 ----
|
|
2093
|
-
case "TSIndexSignature":
|
|
2094
|
-
case "TSDeclareMethod":
|
|
2095
|
-
return true;
|
|
2096
|
-
case "ClassProperty":
|
|
2097
|
-
case "ClassPrivateProperty":
|
|
2098
|
-
return isTsDeclareLike(node) || node.abstract === true;
|
|
2099
2211
|
default:
|
|
2100
|
-
return
|
|
2212
|
+
return void 0;
|
|
2101
2213
|
}
|
|
2102
2214
|
}
|
|
2103
|
-
function
|
|
2104
|
-
|
|
2105
|
-
if (
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2215
|
+
function evalJsonMethod(name, args) {
|
|
2216
|
+
if (name === "stringify") return strPrim("partial");
|
|
2217
|
+
if (name === "parse") return unknown;
|
|
2218
|
+
return void 0;
|
|
2219
|
+
}
|
|
2220
|
+
function evalNumberStatic(name, args) {
|
|
2221
|
+
const a0 = args[0] ? litValue(args[0]) : void 0;
|
|
2222
|
+
switch (name) {
|
|
2223
|
+
case "isInteger":
|
|
2224
|
+
if (typeof a0 === "number") return boolLit(Number.isInteger(a0));
|
|
2225
|
+
return boolPrim();
|
|
2226
|
+
case "isNaN":
|
|
2227
|
+
if (typeof a0 === "number") return boolLit(Number.isNaN(a0));
|
|
2228
|
+
return boolPrim();
|
|
2229
|
+
case "isFinite":
|
|
2230
|
+
if (typeof a0 === "number") return boolLit(Number.isFinite(a0));
|
|
2231
|
+
return boolPrim();
|
|
2232
|
+
case "parseInt":
|
|
2233
|
+
case "parseFloat":
|
|
2234
|
+
if (typeof a0 === "string" || typeof a0 === "number") {
|
|
2235
|
+
const n = name === "parseInt" ? parseInt(String(a0), 10) : parseFloat(String(a0));
|
|
2236
|
+
return numLit(n);
|
|
2237
|
+
}
|
|
2238
|
+
return numPrim();
|
|
2239
|
+
case "MAX_SAFE_INTEGER":
|
|
2240
|
+
return numLit(Number.MAX_SAFE_INTEGER);
|
|
2241
|
+
default:
|
|
2242
|
+
return void 0;
|
|
2114
2243
|
}
|
|
2115
|
-
if ("implements" in node) delete node.implements;
|
|
2116
|
-
if ("superTypeParameters" in node) delete node.superTypeParameters;
|
|
2117
2244
|
}
|
|
2118
|
-
function
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
case "
|
|
2125
|
-
|
|
2126
|
-
return
|
|
2245
|
+
function evalGlobalFn(name, args) {
|
|
2246
|
+
const a0 = args[0] ? litValue(args[0]) : void 0;
|
|
2247
|
+
switch (name) {
|
|
2248
|
+
case "parseInt":
|
|
2249
|
+
if (typeof a0 === "string" || typeof a0 === "number") return numLit(parseInt(String(a0), 10));
|
|
2250
|
+
return numPrim();
|
|
2251
|
+
case "parseFloat":
|
|
2252
|
+
if (typeof a0 === "string" || typeof a0 === "number") return numLit(parseFloat(String(a0)));
|
|
2253
|
+
return numPrim();
|
|
2254
|
+
case "isNaN":
|
|
2255
|
+
if (typeof a0 === "number") return boolLit(Number.isNaN(a0));
|
|
2256
|
+
return boolPrim();
|
|
2257
|
+
case "Number":
|
|
2258
|
+
if (typeof a0 === "number") return numLit(a0);
|
|
2259
|
+
if (typeof a0 === "string") return numLit(Number(a0));
|
|
2260
|
+
if (typeof a0 === "boolean") return numLit(a0 ? 1 : 0);
|
|
2261
|
+
return numPrim();
|
|
2262
|
+
case "String":
|
|
2263
|
+
if (a0 !== void 0) return strLit(String(a0));
|
|
2264
|
+
return strPrim();
|
|
2265
|
+
case "Boolean":
|
|
2266
|
+
if (a0 !== void 0) return boolLit(Boolean(a0));
|
|
2267
|
+
return boolPrim();
|
|
2127
2268
|
default:
|
|
2128
|
-
return
|
|
2269
|
+
return void 0;
|
|
2129
2270
|
}
|
|
2130
2271
|
}
|
|
2131
|
-
function
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
} else if (node.type === "ExportNamedDeclaration") {
|
|
2139
|
-
if (node.specifiers) {
|
|
2140
|
-
node.specifiers = node.specifiers.filter((s) => s.exportKind !== "type");
|
|
2272
|
+
function evalArrayStatic(name, args) {
|
|
2273
|
+
const a0 = args[0];
|
|
2274
|
+
switch (name) {
|
|
2275
|
+
case "isArray": {
|
|
2276
|
+
if (!a0) return boolLit(false);
|
|
2277
|
+
const k = a0.shape.k;
|
|
2278
|
+
return boolLit(k === "arr" || k === "tuple");
|
|
2141
2279
|
}
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2280
|
+
case "of":
|
|
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;
|
|
2152
2302
|
}
|
|
2303
|
+
default:
|
|
2304
|
+
return void 0;
|
|
2153
2305
|
}
|
|
2154
|
-
return unwrapExpression(node) ?? node;
|
|
2155
2306
|
}
|
|
2156
|
-
function
|
|
2157
|
-
|
|
2158
|
-
|
|
2307
|
+
function evalDateCtor(args) {
|
|
2308
|
+
return abs(
|
|
2309
|
+
{ k: "brand", name: "Date", shape: abs({ k: "obj", slots: {} }, void 0, void 0, "exact") },
|
|
2310
|
+
void 0,
|
|
2311
|
+
void 0,
|
|
2312
|
+
"path"
|
|
2313
|
+
);
|
|
2159
2314
|
}
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
var MAX_AST_SOURCE_CHARS = 1e6;
|
|
2164
|
-
var astCache = /* @__PURE__ */ new Map();
|
|
2165
|
-
function resetParseSourceCache() {
|
|
2166
|
-
astCache.clear();
|
|
2315
|
+
function evalDateStatic(name, _args) {
|
|
2316
|
+
if (name === "now") return numLit(Date.now());
|
|
2317
|
+
return void 0;
|
|
2167
2318
|
}
|
|
2168
|
-
function
|
|
2169
|
-
|
|
2319
|
+
function evalDateMethod(name, _recv, _args) {
|
|
2320
|
+
switch (name) {
|
|
2321
|
+
case "getTime":
|
|
2322
|
+
case "valueOf":
|
|
2323
|
+
return numPrim("path");
|
|
2324
|
+
case "toISOString":
|
|
2325
|
+
case "toString":
|
|
2326
|
+
return strPrim("path");
|
|
2327
|
+
default:
|
|
2328
|
+
return void 0;
|
|
2329
|
+
}
|
|
2170
2330
|
}
|
|
2171
|
-
function
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
return stripTypes(ast);
|
|
2331
|
+
function evalRegExpCtor(_args) {
|
|
2332
|
+
return abs(
|
|
2333
|
+
{ k: "brand", name: "RegExp", shape: abs({ k: "obj", slots: {} }, void 0, void 0, "exact") },
|
|
2334
|
+
void 0,
|
|
2335
|
+
void 0,
|
|
2336
|
+
"path"
|
|
2337
|
+
);
|
|
2179
2338
|
}
|
|
2180
|
-
function
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
if (hit !== void 0) {
|
|
2189
|
-
astCache.delete(source);
|
|
2190
|
-
astCache.set(source, hit);
|
|
2191
|
-
return hit;
|
|
2192
|
-
}
|
|
2193
|
-
const ast = parseUncached(source, opts);
|
|
2194
|
-
if (astCache.size >= MAX_AST_CACHE) {
|
|
2195
|
-
const oldest = astCache.keys().next().value;
|
|
2196
|
-
if (oldest !== void 0) astCache.delete(oldest);
|
|
2339
|
+
function evalRegExpMethod(name, _recv, _args) {
|
|
2340
|
+
switch (name) {
|
|
2341
|
+
case "test":
|
|
2342
|
+
return boolPrim();
|
|
2343
|
+
case "exec":
|
|
2344
|
+
return unknown;
|
|
2345
|
+
default:
|
|
2346
|
+
return void 0;
|
|
2197
2347
|
}
|
|
2198
|
-
astCache.set(source, ast);
|
|
2199
|
-
return ast;
|
|
2200
2348
|
}
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
if (t.op !== "app") return 1;
|
|
2209
|
-
return 1 + Math.max(0, ...t.args.map(termDepth));
|
|
2349
|
+
function evalPromiseCtor(_args) {
|
|
2350
|
+
return abs(
|
|
2351
|
+
{ k: "eff", eff: "promise", inner: unknown },
|
|
2352
|
+
void 0,
|
|
2353
|
+
void 0,
|
|
2354
|
+
"partial"
|
|
2355
|
+
);
|
|
2210
2356
|
}
|
|
2211
|
-
function
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2357
|
+
function evalPromiseStatic(name, args) {
|
|
2358
|
+
switch (name) {
|
|
2359
|
+
case "resolve": {
|
|
2360
|
+
const inner = args[0] ?? unknown;
|
|
2361
|
+
if (inner.shape.k === "eff" && inner.shape.eff === "promise") return inner;
|
|
2362
|
+
return abs({ k: "eff", eff: "promise", inner }, void 0, void 0, "path");
|
|
2363
|
+
}
|
|
2364
|
+
case "reject":
|
|
2365
|
+
return abs({ k: "eff", eff: "promise", inner: unknown }, void 0, void 0, "partial");
|
|
2366
|
+
case "all": {
|
|
2367
|
+
const a0 = args[0];
|
|
2368
|
+
if (a0?.shape.k === "arr" && a0.shape.element.shape.k === "eff") {
|
|
2369
|
+
return abs(
|
|
2370
|
+
{ k: "eff", eff: "promise", inner: abs({ k: "arr", element: a0.shape.element.shape.inner }, void 0, void 0, "path") },
|
|
2371
|
+
void 0,
|
|
2372
|
+
void 0,
|
|
2373
|
+
"path"
|
|
2374
|
+
);
|
|
2375
|
+
}
|
|
2376
|
+
return abs({ k: "eff", eff: "promise", inner: abs({ k: "arr", element: unknown }, void 0, void 0, "partial") }, void 0, void 0, "partial");
|
|
2377
|
+
}
|
|
2378
|
+
default:
|
|
2379
|
+
return void 0;
|
|
2380
|
+
}
|
|
2217
2381
|
}
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2382
|
+
function evalNamespaceCall(ns, method, args) {
|
|
2383
|
+
switch (ns) {
|
|
2384
|
+
case "Math":
|
|
2385
|
+
return evalMathMethod(method, args);
|
|
2386
|
+
case "Object":
|
|
2387
|
+
return evalObjectMethod(method, args);
|
|
2388
|
+
case "JSON":
|
|
2389
|
+
return evalJsonMethod(method, args);
|
|
2390
|
+
case "Number":
|
|
2391
|
+
return evalNumberStatic(method, args);
|
|
2392
|
+
case "Array":
|
|
2393
|
+
return evalArrayStatic(method, args);
|
|
2394
|
+
case "Date":
|
|
2395
|
+
return evalDateStatic(method, args);
|
|
2396
|
+
case "Promise":
|
|
2397
|
+
return evalPromiseStatic(method, args);
|
|
2398
|
+
default:
|
|
2399
|
+
return void 0;
|
|
2400
|
+
}
|
|
2221
2401
|
}
|
|
2222
|
-
function
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2402
|
+
function evalBuiltinNew(className, args) {
|
|
2403
|
+
switch (className) {
|
|
2404
|
+
case "Date":
|
|
2405
|
+
return evalDateCtor(args);
|
|
2406
|
+
case "RegExp":
|
|
2407
|
+
return evalRegExpCtor(args);
|
|
2408
|
+
case "Promise":
|
|
2409
|
+
return evalPromiseCtor(args);
|
|
2410
|
+
case "Map":
|
|
2411
|
+
return abs(
|
|
2412
|
+
{ k: "brand", name: "Map", shape: abs({ k: "obj", slots: {} }, void 0, void 0, "exact") },
|
|
2413
|
+
void 0,
|
|
2414
|
+
void 0,
|
|
2415
|
+
"path"
|
|
2416
|
+
);
|
|
2417
|
+
case "Set":
|
|
2418
|
+
return abs(
|
|
2419
|
+
{ k: "brand", name: "Set", shape: abs({ k: "obj", slots: {} }, void 0, void 0, "exact") },
|
|
2420
|
+
void 0,
|
|
2421
|
+
void 0,
|
|
2422
|
+
"path"
|
|
2423
|
+
);
|
|
2424
|
+
default:
|
|
2425
|
+
return void 0;
|
|
2426
|
+
}
|
|
2230
2427
|
}
|
|
2231
|
-
function
|
|
2232
|
-
return
|
|
2428
|
+
function evalBuiltinInstanceMethod(brandName, method, recv, args) {
|
|
2429
|
+
if (brandName === "Date") return evalDateMethod(method, recv, args);
|
|
2430
|
+
if (brandName === "RegExp") return evalRegExpMethod(method, recv, args);
|
|
2431
|
+
if (brandName === "Map") {
|
|
2432
|
+
switch (method) {
|
|
2433
|
+
case "get":
|
|
2434
|
+
return unknown;
|
|
2435
|
+
case "has":
|
|
2436
|
+
return boolPrim();
|
|
2437
|
+
case "set":
|
|
2438
|
+
return recv;
|
|
2439
|
+
case "size":
|
|
2440
|
+
return numPrim("path");
|
|
2441
|
+
default:
|
|
2442
|
+
return void 0;
|
|
2443
|
+
}
|
|
2444
|
+
}
|
|
2445
|
+
if (brandName === "Set") {
|
|
2446
|
+
switch (method) {
|
|
2447
|
+
case "has":
|
|
2448
|
+
return boolPrim();
|
|
2449
|
+
case "add":
|
|
2450
|
+
return recv;
|
|
2451
|
+
case "size":
|
|
2452
|
+
return numPrim("path");
|
|
2453
|
+
default:
|
|
2454
|
+
return void 0;
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
return void 0;
|
|
2233
2458
|
}
|
|
2234
2459
|
|
|
2235
|
-
// src/algebra/
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2460
|
+
// src/algebra/exec/calls.ts
|
|
2461
|
+
var calls_exports = {};
|
|
2462
|
+
__export(calls_exports, {
|
|
2463
|
+
$callNamed: () => $callNamed,
|
|
2464
|
+
getAbsOrigin: () => getAbsOrigin,
|
|
2465
|
+
getBCallCollector: () => getBCallCollector,
|
|
2466
|
+
noteMemberDispatchMiss: () => noteMemberDispatchMiss,
|
|
2467
|
+
notePrimMemberMissing: () => notePrimMemberMissing,
|
|
2468
|
+
noteUnknownMemberMissing: () => noteUnknownMemberMissing,
|
|
2469
|
+
recordMemberDiag: () => recordMemberDiag,
|
|
2470
|
+
setBCallCollector: () => setBCallCollector,
|
|
2471
|
+
setMemberDiagCollector: () => setMemberDiagCollector,
|
|
2472
|
+
tagAbsOrigin: () => tagAbsOrigin
|
|
2473
|
+
});
|
|
2474
|
+
|
|
2475
|
+
// src/algebra/parse-source.ts
|
|
2476
|
+
import { parse as babelParse } from "@babel/parser";
|
|
2477
|
+
|
|
2478
|
+
// src/strip-types.ts
|
|
2479
|
+
var REMOVE = Symbol("nudo.strip.remove");
|
|
2480
|
+
var SKIP_KEYS = /* @__PURE__ */ new Set([
|
|
2481
|
+
"loc",
|
|
2482
|
+
"start",
|
|
2483
|
+
"end",
|
|
2484
|
+
"range",
|
|
2485
|
+
"leadingComments",
|
|
2486
|
+
"trailingComments",
|
|
2487
|
+
"innerComments",
|
|
2488
|
+
"comments",
|
|
2489
|
+
"tokens",
|
|
2490
|
+
"extra"
|
|
2491
|
+
]);
|
|
2492
|
+
function transformValue(value) {
|
|
2493
|
+
if (Array.isArray(value)) {
|
|
2494
|
+
let changed = false;
|
|
2495
|
+
const out = [];
|
|
2496
|
+
for (const el of value) {
|
|
2497
|
+
if (el === null || el === void 0) {
|
|
2498
|
+
out.push(el);
|
|
2499
|
+
continue;
|
|
2273
2500
|
}
|
|
2274
|
-
|
|
2275
|
-
if (
|
|
2276
|
-
|
|
2501
|
+
const r = transformValue(el);
|
|
2502
|
+
if (r === REMOVE) {
|
|
2503
|
+
changed = true;
|
|
2504
|
+
} else {
|
|
2505
|
+
if (r !== el) changed = true;
|
|
2506
|
+
out.push(r);
|
|
2277
2507
|
}
|
|
2278
2508
|
}
|
|
2279
|
-
|
|
2280
|
-
const result = promotedShape.returnType ?? next;
|
|
2281
|
-
hc.sites.push({
|
|
2282
|
-
param,
|
|
2283
|
-
argTerms: [],
|
|
2284
|
-
result,
|
|
2285
|
-
loc: opts?.loc
|
|
2286
|
-
});
|
|
2287
|
-
}
|
|
2509
|
+
return changed ? out : value;
|
|
2288
2510
|
}
|
|
2289
|
-
return
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
function promoteParamAsArr(env, name, loc) {
|
|
2293
|
-
const hc = env.hofCollect;
|
|
2294
|
-
if (!hc || !hc.paramNames.has(name)) return void 0;
|
|
2295
|
-
const prev = env.vars.get(name);
|
|
2296
|
-
if (!prev) return void 0;
|
|
2297
|
-
if (prev.shape.k !== "any" && prev.shape.k !== "unknown") return void 0;
|
|
2298
|
-
const element = prev.term ? abs(prev.shape, prev.term, prev.pred, "path") : abs({ k: "any" }, void 0, void 0, "path");
|
|
2299
|
-
const arrShape = { k: "arr", element };
|
|
2300
|
-
promoteParamShape(env, name, arrShape, { loc });
|
|
2301
|
-
return env.vars.get(name);
|
|
2511
|
+
if (typeof value !== "object" || value === null) return value;
|
|
2512
|
+
if (typeof value.type !== "string") return value;
|
|
2513
|
+
return transformNode(value);
|
|
2302
2514
|
}
|
|
2303
|
-
function
|
|
2304
|
-
|
|
2305
|
-
return promoteParamAsArr(env, receiverName, loc);
|
|
2515
|
+
function isTsDeclareLike(node) {
|
|
2516
|
+
return node.declare === true;
|
|
2306
2517
|
}
|
|
2307
|
-
function
|
|
2308
|
-
|
|
2518
|
+
function isTypeOnlyDeclaration(decl) {
|
|
2519
|
+
switch (decl.type) {
|
|
2520
|
+
case "TSInterfaceDeclaration":
|
|
2521
|
+
case "TSTypeAliasDeclaration":
|
|
2522
|
+
case "TSEnumDeclaration":
|
|
2523
|
+
case "TSDeclareFunction":
|
|
2524
|
+
return true;
|
|
2525
|
+
case "VariableDeclaration":
|
|
2526
|
+
case "ClassDeclaration":
|
|
2527
|
+
return isTsDeclareLike(decl);
|
|
2528
|
+
default:
|
|
2529
|
+
return false;
|
|
2530
|
+
}
|
|
2309
2531
|
}
|
|
2310
|
-
function
|
|
2311
|
-
const
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
const fnShape = {
|
|
2331
|
-
k: "fn",
|
|
2332
|
-
params: args.map((_, i) => `x${i}`),
|
|
2333
|
-
paramTypes,
|
|
2334
|
-
returnType: ret
|
|
2335
|
-
};
|
|
2336
|
-
promoteParamShape(env, calleeName, fnShape, { loc, recordSite: false });
|
|
2337
|
-
hc.sites.push({
|
|
2338
|
-
param: calleeName,
|
|
2339
|
-
argTerms: args.map((a) => a.term ?? { op: "var", id: "_" }),
|
|
2340
|
-
result: ret,
|
|
2341
|
-
loc
|
|
2342
|
-
});
|
|
2343
|
-
return env.vars.get(calleeName);
|
|
2344
|
-
}
|
|
2345
|
-
function tryPromoteHofCallback(env, cbName, method, argAbses, loc) {
|
|
2346
|
-
const hc = env.hofCollect;
|
|
2347
|
-
if (!hc || !hc.paramNames.has(cbName)) return void 0;
|
|
2348
|
-
const prev = env.vars.get(cbName);
|
|
2349
|
-
if (!prev) return void 0;
|
|
2350
|
-
if (prev.shape.k !== "any" && prev.shape.k !== "unknown") return void 0;
|
|
2351
|
-
let paramTypes;
|
|
2352
|
-
let returnType;
|
|
2353
|
-
if (method === "filter") {
|
|
2354
|
-
paramTypes = argAbses.map(
|
|
2355
|
-
(a) => abs({ k: "any" }, alphaOf(a, hc), void 0, "path")
|
|
2356
|
-
);
|
|
2357
|
-
returnType = abs({ k: "prim", type: "boolean" }, void 0, void 0, "path");
|
|
2358
|
-
} else if (method === "reduce") {
|
|
2359
|
-
paramTypes = argAbses.map(
|
|
2360
|
-
(a) => abs({ k: "any" }, alphaOf(a, hc), void 0, "path")
|
|
2361
|
-
);
|
|
2362
|
-
returnType = abs({ k: "any" }, betaOf(cbName), void 0, "path");
|
|
2363
|
-
} else {
|
|
2364
|
-
paramTypes = argAbses.map(
|
|
2365
|
-
(a) => abs({ k: "any" }, alphaOf(a, hc), void 0, "path")
|
|
2366
|
-
);
|
|
2367
|
-
returnType = abs({ k: "any" }, betaOf(cbName), void 0, "path");
|
|
2368
|
-
}
|
|
2369
|
-
const fnShape = {
|
|
2370
|
-
k: "fn",
|
|
2371
|
-
params: argAbses.map((_, i) => `x${i}`),
|
|
2372
|
-
paramTypes,
|
|
2373
|
-
returnType
|
|
2374
|
-
};
|
|
2375
|
-
promoteParamShape(env, cbName, fnShape, { loc, recordSite: false });
|
|
2376
|
-
hc.sites.push({
|
|
2377
|
-
param: cbName,
|
|
2378
|
-
argTerms: argAbses.map((a) => a.term ?? { op: "var", id: "_" }),
|
|
2379
|
-
result: returnType,
|
|
2380
|
-
loc
|
|
2381
|
-
});
|
|
2382
|
-
return env.vars.get(cbName);
|
|
2383
|
-
}
|
|
2384
|
-
function snapshotAbs(a) {
|
|
2385
|
-
const shape = a.shape;
|
|
2386
|
-
const copyShape = (s) => {
|
|
2387
|
-
switch (s.k) {
|
|
2388
|
-
case "arr":
|
|
2389
|
-
return { ...s, element: snapshotAbs(s.element) };
|
|
2390
|
-
case "tuple": {
|
|
2391
|
-
const next = {
|
|
2392
|
-
k: "tuple",
|
|
2393
|
-
elements: s.elements.map(snapshotAbs)
|
|
2394
|
-
};
|
|
2395
|
-
if (s.rest) next.rest = snapshotAbs(s.rest);
|
|
2396
|
-
return next;
|
|
2397
|
-
}
|
|
2398
|
-
case "fn": {
|
|
2399
|
-
const next = { k: "fn", params: [...s.params] };
|
|
2400
|
-
if (s.name !== void 0) next.name = s.name;
|
|
2401
|
-
if (s.paramTypes) next.paramTypes = s.paramTypes.map(snapshotAbs);
|
|
2402
|
-
if (s.returnType) next.returnType = snapshotAbs(s.returnType);
|
|
2403
|
-
return next;
|
|
2404
|
-
}
|
|
2405
|
-
case "sum":
|
|
2406
|
-
return { ...s, members: s.members.map(snapshotAbs) };
|
|
2407
|
-
case "obj": {
|
|
2408
|
-
const slots = {};
|
|
2409
|
-
for (const [k, slot] of Object.entries(s.slots)) {
|
|
2410
|
-
const nextSlot = { value: snapshotAbs(slot.value) };
|
|
2411
|
-
if (slot.optional) nextSlot.optional = true;
|
|
2412
|
-
if (slot.readonly) nextSlot.readonly = true;
|
|
2413
|
-
slots[k] = nextSlot;
|
|
2414
|
-
}
|
|
2415
|
-
const next = { k: "obj", slots };
|
|
2416
|
-
if (s.index) {
|
|
2417
|
-
next.index = {
|
|
2418
|
-
key: snapshotAbs(s.index.key),
|
|
2419
|
-
value: snapshotAbs(s.index.value)
|
|
2420
|
-
};
|
|
2421
|
-
}
|
|
2422
|
-
if (s.open) next.open = true;
|
|
2423
|
-
return next;
|
|
2424
|
-
}
|
|
2425
|
-
case "brand":
|
|
2426
|
-
return { ...s, shape: snapshotAbs(s.shape) };
|
|
2427
|
-
case "eff":
|
|
2428
|
-
return { ...s, inner: snapshotAbs(s.inner) };
|
|
2429
|
-
default:
|
|
2430
|
-
return s;
|
|
2431
|
-
}
|
|
2432
|
-
};
|
|
2433
|
-
return {
|
|
2434
|
-
shape: copyShape(shape),
|
|
2435
|
-
term: a.term,
|
|
2436
|
-
pred: a.pred,
|
|
2437
|
-
conf: a.conf
|
|
2438
|
-
};
|
|
2439
|
-
}
|
|
2440
|
-
function isRelFn(a) {
|
|
2441
|
-
if (!a || typeof a !== "object") return false;
|
|
2442
|
-
if (getFnImpl(a)) return false;
|
|
2443
|
-
const s = a.shape;
|
|
2444
|
-
if (!s || s.k !== "fn") return false;
|
|
2445
|
-
if (s.returnType === void 0) return false;
|
|
2446
|
-
if (s.paramTypes === void 0) return s.params.length === 0;
|
|
2447
|
-
return s.paramTypes.length === s.params.length;
|
|
2448
|
-
}
|
|
2449
|
-
function litOfTerm(t) {
|
|
2450
|
-
return t.op === "lit" ? t.value : void 0;
|
|
2451
|
-
}
|
|
2452
|
-
function foldCompare(op, a, b) {
|
|
2453
|
-
if (a === void 0 || b === void 0) return void 0;
|
|
2454
|
-
if (typeof a !== typeof b) {
|
|
2455
|
-
if (op === "eq") return pFalse;
|
|
2456
|
-
if (op === "ne") return pTrue;
|
|
2457
|
-
return void 0;
|
|
2458
|
-
}
|
|
2459
|
-
switch (op) {
|
|
2460
|
-
case "eq":
|
|
2461
|
-
return a === b ? pTrue : pFalse;
|
|
2462
|
-
case "ne":
|
|
2463
|
-
return a !== b ? pTrue : pFalse;
|
|
2464
|
-
case "lt":
|
|
2465
|
-
return a < b ? pTrue : pFalse;
|
|
2466
|
-
case "le":
|
|
2467
|
-
return a <= b ? pTrue : pFalse;
|
|
2468
|
-
case "gt":
|
|
2469
|
-
return a > b ? pTrue : pFalse;
|
|
2470
|
-
case "ge":
|
|
2471
|
-
return a >= b ? pTrue : pFalse;
|
|
2472
|
-
default:
|
|
2473
|
-
return void 0;
|
|
2474
|
-
}
|
|
2475
|
-
}
|
|
2476
|
-
function predUsesMappedVars(p, map) {
|
|
2477
|
-
const walkTerm = (t) => {
|
|
2478
|
-
if (t.op === "var") return map.has(t.id);
|
|
2479
|
-
if (t.op === "app") return t.args.some(walkTerm);
|
|
2480
|
-
return false;
|
|
2481
|
-
};
|
|
2482
|
-
const walk = (q) => {
|
|
2483
|
-
switch (q.op) {
|
|
2484
|
-
case "true":
|
|
2485
|
-
case "false":
|
|
2486
|
-
return false;
|
|
2487
|
-
case "eq":
|
|
2488
|
-
case "ne":
|
|
2489
|
-
case "lt":
|
|
2490
|
-
case "le":
|
|
2491
|
-
case "gt":
|
|
2492
|
-
case "ge":
|
|
2493
|
-
return walkTerm(q.a) || walkTerm(q.b);
|
|
2494
|
-
case "and":
|
|
2495
|
-
case "or":
|
|
2496
|
-
return q.args.some(walk);
|
|
2497
|
-
case "not":
|
|
2498
|
-
return walk(q.arg);
|
|
2499
|
-
case "typeof":
|
|
2500
|
-
return walkTerm(q.t);
|
|
2501
|
-
}
|
|
2502
|
-
};
|
|
2503
|
-
return walk(p);
|
|
2504
|
-
}
|
|
2505
|
-
function mapHasShapeOnlyVar(p, map) {
|
|
2506
|
-
const walkTerm = (t) => {
|
|
2507
|
-
if (t.op === "var") {
|
|
2508
|
-
const arg = map.get(t.id);
|
|
2509
|
-
return !!arg && arg.term === void 0;
|
|
2510
|
-
}
|
|
2511
|
-
if (t.op === "app") return t.args.some(walkTerm);
|
|
2512
|
-
return false;
|
|
2513
|
-
};
|
|
2514
|
-
const walk = (q) => {
|
|
2515
|
-
switch (q.op) {
|
|
2516
|
-
case "true":
|
|
2517
|
-
case "false":
|
|
2518
|
-
return false;
|
|
2519
|
-
case "eq":
|
|
2520
|
-
case "ne":
|
|
2521
|
-
case "lt":
|
|
2522
|
-
case "le":
|
|
2523
|
-
case "gt":
|
|
2524
|
-
case "ge":
|
|
2525
|
-
return walkTerm(q.a) || walkTerm(q.b);
|
|
2526
|
-
case "and":
|
|
2527
|
-
case "or":
|
|
2528
|
-
return q.args.some(walk);
|
|
2529
|
-
case "not":
|
|
2530
|
-
return walk(q.arg);
|
|
2531
|
-
case "typeof":
|
|
2532
|
-
return walkTerm(q.t);
|
|
2533
|
-
}
|
|
2534
|
-
};
|
|
2535
|
-
return walk(p);
|
|
2536
|
-
}
|
|
2537
|
-
function substPredAbs(p, map) {
|
|
2538
|
-
if (!predUsesMappedVars(p, map)) return { pred: p, dropped: false };
|
|
2539
|
-
if (mapHasShapeOnlyVar(p, map)) return { pred: pTrue, dropped: true };
|
|
2540
|
-
const substTerm = (t) => {
|
|
2541
|
-
if (t.op === "var") {
|
|
2542
|
-
const arg = map.get(t.id);
|
|
2543
|
-
return arg?.term ?? t;
|
|
2544
|
-
}
|
|
2545
|
-
if (t.op === "app") {
|
|
2546
|
-
return { op: "app", fn: t.fn, args: t.args.map(substTerm) };
|
|
2547
|
-
}
|
|
2548
|
-
return t;
|
|
2549
|
-
};
|
|
2550
|
-
const replaced = substPred(p, substTerm);
|
|
2551
|
-
const fold = (q) => {
|
|
2552
|
-
switch (q.op) {
|
|
2553
|
-
case "true":
|
|
2554
|
-
case "false":
|
|
2555
|
-
return q;
|
|
2556
|
-
case "eq":
|
|
2557
|
-
case "ne":
|
|
2558
|
-
case "lt":
|
|
2559
|
-
case "le":
|
|
2560
|
-
case "gt":
|
|
2561
|
-
case "ge": {
|
|
2562
|
-
const a = litOfTerm(q.a);
|
|
2563
|
-
const b = litOfTerm(q.b);
|
|
2564
|
-
const folded = foldCompare(q.op, a, b);
|
|
2565
|
-
return folded ?? q;
|
|
2566
|
-
}
|
|
2567
|
-
case "and": {
|
|
2568
|
-
const args = q.args.map(fold);
|
|
2569
|
-
if (args.some((x) => x.op === "false")) return pFalse;
|
|
2570
|
-
const rest = args.filter((x) => x.op !== "true");
|
|
2571
|
-
if (rest.length === 0) return pTrue;
|
|
2572
|
-
if (rest.length === 1) return rest[0];
|
|
2573
|
-
return and(...rest);
|
|
2574
|
-
}
|
|
2575
|
-
case "or": {
|
|
2576
|
-
const args = q.args.map(fold);
|
|
2577
|
-
if (args.some((x) => x.op === "true")) return pTrue;
|
|
2578
|
-
const rest = args.filter((x) => x.op !== "false");
|
|
2579
|
-
if (rest.length === 0) return pFalse;
|
|
2580
|
-
if (rest.length === 1) return rest[0];
|
|
2581
|
-
return { op: "or", args: rest };
|
|
2532
|
+
function isTypeOnlyStatement(node) {
|
|
2533
|
+
const anyNode = node;
|
|
2534
|
+
switch (node.type) {
|
|
2535
|
+
case "TSInterfaceDeclaration":
|
|
2536
|
+
case "TSTypeAliasDeclaration":
|
|
2537
|
+
case "TSEnumDeclaration":
|
|
2538
|
+
case "TSDeclareFunction":
|
|
2539
|
+
return true;
|
|
2540
|
+
case "TSModuleDeclaration":
|
|
2541
|
+
return isTsDeclareLike(node);
|
|
2542
|
+
case "VariableDeclaration":
|
|
2543
|
+
case "ClassDeclaration":
|
|
2544
|
+
return isTsDeclareLike(node);
|
|
2545
|
+
case "ImportDeclaration":
|
|
2546
|
+
if (anyNode.importKind === "type") return true;
|
|
2547
|
+
{
|
|
2548
|
+
const specs = anyNode.specifiers;
|
|
2549
|
+
if (specs && specs.length > 0 && specs.every((s) => s.importKind === "type" || s.importKind === "typeof")) {
|
|
2550
|
+
return true;
|
|
2551
|
+
}
|
|
2582
2552
|
}
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2553
|
+
return false;
|
|
2554
|
+
case "ExportNamedDeclaration": {
|
|
2555
|
+
if (anyNode.exportKind === "type") return true;
|
|
2556
|
+
const decl = node.declaration;
|
|
2557
|
+
if (decl && isTypeOnlyDeclaration(decl)) return true;
|
|
2558
|
+
{
|
|
2559
|
+
const specs = anyNode.specifiers;
|
|
2560
|
+
if (!decl && specs && specs.length > 0 && specs.every((s) => s.exportKind === "type")) return true;
|
|
2588
2561
|
}
|
|
2589
|
-
|
|
2590
|
-
return q;
|
|
2562
|
+
return false;
|
|
2591
2563
|
}
|
|
2592
|
-
|
|
2593
|
-
|
|
2564
|
+
case "ExportAllDeclaration":
|
|
2565
|
+
return anyNode.exportKind === "type";
|
|
2566
|
+
case "ExportDefaultDeclaration":
|
|
2567
|
+
return isTypeOnlyDeclaration(node.declaration);
|
|
2568
|
+
// ---- 类成员 ----
|
|
2569
|
+
case "TSIndexSignature":
|
|
2570
|
+
case "TSDeclareMethod":
|
|
2571
|
+
return true;
|
|
2572
|
+
case "ClassProperty":
|
|
2573
|
+
case "ClassPrivateProperty":
|
|
2574
|
+
return isTsDeclareLike(node) || node.abstract === true;
|
|
2575
|
+
default:
|
|
2576
|
+
return false;
|
|
2577
|
+
}
|
|
2594
2578
|
}
|
|
2595
|
-
function
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2579
|
+
function deleteTypeSyntaxFields(node) {
|
|
2580
|
+
const tp = node.typeParameters;
|
|
2581
|
+
if (tp && typeof tp.type === "string" && tp.type.startsWith("TSTypeParameter")) {
|
|
2582
|
+
delete node.typeParameters;
|
|
2599
2583
|
}
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2584
|
+
const ta = node.typeAnnotation;
|
|
2585
|
+
if (ta && ta.type === "TSTypeAnnotation") delete node.typeAnnotation;
|
|
2586
|
+
const rt = node.returnType;
|
|
2587
|
+
if (rt && (rt.type === "TSTypeAnnotation" || rt.type === "TSTypePredicate")) delete node.returnType;
|
|
2588
|
+
if (node.optional === true && (node.type === "Identifier" || node.type === "ObjectPattern" || node.type === "ArrayPattern" || node.type === "RestElement")) {
|
|
2589
|
+
delete node.optional;
|
|
2606
2590
|
}
|
|
2607
|
-
|
|
2591
|
+
if ("implements" in node) delete node.implements;
|
|
2592
|
+
if ("superTypeParameters" in node) delete node.superTypeParameters;
|
|
2608
2593
|
}
|
|
2609
|
-
function
|
|
2610
|
-
switch (
|
|
2611
|
-
case "
|
|
2612
|
-
|
|
2613
|
-
case "
|
|
2614
|
-
case "
|
|
2615
|
-
|
|
2616
|
-
case "
|
|
2617
|
-
return
|
|
2618
|
-
|
|
2619
|
-
return
|
|
2620
|
-
case "arr":
|
|
2621
|
-
return { ...s, element: substAbsInner(s.element, map, cache, visiting) };
|
|
2622
|
-
case "tuple": {
|
|
2623
|
-
const elements = s.elements.map(
|
|
2624
|
-
(e) => substAbsInner(e, map, cache, visiting)
|
|
2625
|
-
);
|
|
2626
|
-
const next = { k: "tuple", elements };
|
|
2627
|
-
if (s.rest) next.rest = substAbsInner(s.rest, map, cache, visiting);
|
|
2628
|
-
return next;
|
|
2629
|
-
}
|
|
2630
|
-
case "fn": {
|
|
2631
|
-
const next = { k: "fn", params: s.params };
|
|
2632
|
-
if (s.name !== void 0) next.name = s.name;
|
|
2633
|
-
if (s.paramTypes) {
|
|
2634
|
-
next.paramTypes = s.paramTypes.map(
|
|
2635
|
-
(p) => substAbsInner(p, map, cache, visiting)
|
|
2636
|
-
);
|
|
2637
|
-
}
|
|
2638
|
-
if (s.returnType !== void 0) {
|
|
2639
|
-
next.returnType = substAbsInner(s.returnType, map, cache, visiting);
|
|
2640
|
-
}
|
|
2641
|
-
return next;
|
|
2642
|
-
}
|
|
2643
|
-
case "sum":
|
|
2644
|
-
return {
|
|
2645
|
-
...s,
|
|
2646
|
-
members: s.members.map((m) => substAbsInner(m, map, cache, visiting))
|
|
2647
|
-
};
|
|
2648
|
-
case "obj": {
|
|
2649
|
-
const slots = {};
|
|
2650
|
-
for (const [k, slot] of Object.entries(s.slots)) {
|
|
2651
|
-
const nextSlot = { value: substAbsInner(slot.value, map, cache, visiting) };
|
|
2652
|
-
if (slot.optional) nextSlot.optional = true;
|
|
2653
|
-
if (slot.readonly) nextSlot.readonly = true;
|
|
2654
|
-
slots[k] = nextSlot;
|
|
2655
|
-
}
|
|
2656
|
-
const next = { k: "obj", slots };
|
|
2657
|
-
if (s.index) {
|
|
2658
|
-
next.index = {
|
|
2659
|
-
key: substAbsInner(s.index.key, map, cache, visiting),
|
|
2660
|
-
value: substAbsInner(s.index.value, map, cache, visiting)
|
|
2661
|
-
};
|
|
2662
|
-
}
|
|
2663
|
-
if (s.open) next.open = true;
|
|
2664
|
-
return next;
|
|
2665
|
-
}
|
|
2594
|
+
function unwrapExpression(node) {
|
|
2595
|
+
switch (node.type) {
|
|
2596
|
+
case "TSAsExpression":
|
|
2597
|
+
// 含 as const
|
|
2598
|
+
case "TSSatisfiesExpression":
|
|
2599
|
+
case "TSTypeAssertion":
|
|
2600
|
+
case "TSNonNullExpression":
|
|
2601
|
+
case "TSInstantiationExpression":
|
|
2602
|
+
return node.expression;
|
|
2603
|
+
default:
|
|
2604
|
+
return null;
|
|
2666
2605
|
}
|
|
2667
2606
|
}
|
|
2668
|
-
function
|
|
2669
|
-
if (
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2607
|
+
function transformNode(node) {
|
|
2608
|
+
if (isTypeOnlyStatement(node)) return REMOVE;
|
|
2609
|
+
deleteTypeSyntaxFields(node);
|
|
2610
|
+
if (node.type === "ImportDeclaration") {
|
|
2611
|
+
node.specifiers = node.specifiers.filter(
|
|
2612
|
+
(s) => !(s.importKind === "type" || s.importKind === "typeof")
|
|
2613
|
+
);
|
|
2614
|
+
} else if (node.type === "ExportNamedDeclaration") {
|
|
2615
|
+
if (node.specifiers) {
|
|
2616
|
+
node.specifiers = node.specifiers.filter((s) => s.exportKind !== "type");
|
|
2617
|
+
}
|
|
2677
2618
|
}
|
|
2678
|
-
const
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
pred = r.pred;
|
|
2689
|
-
if (r.dropped) conf = confJoin(conf, "partial");
|
|
2619
|
+
for (const key of Object.keys(node)) {
|
|
2620
|
+
if (SKIP_KEYS.has(key)) continue;
|
|
2621
|
+
const child = node[key];
|
|
2622
|
+
if (child === null || typeof child !== "object") continue;
|
|
2623
|
+
const r = transformValue(child);
|
|
2624
|
+
if (r === REMOVE) {
|
|
2625
|
+
delete node[key];
|
|
2626
|
+
} else {
|
|
2627
|
+
node[key] = r;
|
|
2628
|
+
}
|
|
2690
2629
|
}
|
|
2691
|
-
|
|
2692
|
-
const result = abs(shape, term, pred, conf);
|
|
2693
|
-
cache.set(a, result);
|
|
2694
|
-
return result;
|
|
2630
|
+
return unwrapExpression(node) ?? node;
|
|
2695
2631
|
}
|
|
2696
|
-
function
|
|
2697
|
-
|
|
2698
|
-
return
|
|
2632
|
+
function stripTypes(ast) {
|
|
2633
|
+
transformValue(ast);
|
|
2634
|
+
return ast;
|
|
2699
2635
|
}
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
const map = /* @__PURE__ */ new Map();
|
|
2708
|
-
src.paramTypes.forEach((p, i) => {
|
|
2709
|
-
if (p.term?.op !== "var") return;
|
|
2710
|
-
const id = p.term.id;
|
|
2711
|
-
if (map.has(id)) return;
|
|
2712
|
-
map.set(id, args[i] ?? unknown);
|
|
2713
|
-
});
|
|
2714
|
-
return substAbs(src.returnType, map);
|
|
2636
|
+
|
|
2637
|
+
// src/algebra/parse-source.ts
|
|
2638
|
+
var MAX_AST_CACHE = 16;
|
|
2639
|
+
var MAX_AST_SOURCE_CHARS = 1e6;
|
|
2640
|
+
var astCache = /* @__PURE__ */ new Map();
|
|
2641
|
+
function resetParseSourceCache() {
|
|
2642
|
+
astCache.clear();
|
|
2715
2643
|
}
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
applyCallbackHost = fn;
|
|
2644
|
+
function getParseSourceCacheSize() {
|
|
2645
|
+
return astCache.size;
|
|
2719
2646
|
}
|
|
2720
|
-
function
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2647
|
+
function parseUncached(source, opts) {
|
|
2648
|
+
const ast = babelParse(source, {
|
|
2649
|
+
sourceType: "module",
|
|
2650
|
+
plugins: ["typescript", "jsx"],
|
|
2651
|
+
attachComment: true,
|
|
2652
|
+
errorRecovery: opts?.errorRecovery === true
|
|
2653
|
+
});
|
|
2654
|
+
return opts?.keepTs === true ? ast : stripTypes(ast);
|
|
2655
|
+
}
|
|
2656
|
+
function parseSource(source, opts) {
|
|
2657
|
+
if (opts?.keepTs === true || opts?.errorRecovery === true) {
|
|
2658
|
+
return parseUncached(source, opts);
|
|
2729
2659
|
}
|
|
2730
|
-
|
|
2660
|
+
if (source.length > MAX_AST_SOURCE_CHARS) {
|
|
2661
|
+
return parseUncached(source, opts);
|
|
2662
|
+
}
|
|
2663
|
+
const hit = astCache.get(source);
|
|
2664
|
+
if (hit !== void 0) {
|
|
2665
|
+
astCache.delete(source);
|
|
2666
|
+
astCache.set(source, hit);
|
|
2667
|
+
return hit;
|
|
2668
|
+
}
|
|
2669
|
+
const ast = parseUncached(source, opts);
|
|
2670
|
+
if (astCache.size >= MAX_AST_CACHE) {
|
|
2671
|
+
const oldest = astCache.keys().next().value;
|
|
2672
|
+
if (oldest !== void 0) astCache.delete(oldest);
|
|
2673
|
+
}
|
|
2674
|
+
astCache.set(source, ast);
|
|
2675
|
+
return ast;
|
|
2676
|
+
}
|
|
2677
|
+
|
|
2678
|
+
// src/algebra/leak.ts
|
|
2679
|
+
var defaultLeakBudget = {
|
|
2680
|
+
maxDepth: 6,
|
|
2681
|
+
maxNodes: 32
|
|
2682
|
+
};
|
|
2683
|
+
function termDepth(t) {
|
|
2684
|
+
if (t.op !== "app") return 1;
|
|
2685
|
+
return 1 + Math.max(0, ...t.args.map(termDepth));
|
|
2686
|
+
}
|
|
2687
|
+
function termNodes(t) {
|
|
2688
|
+
if (t.op !== "app") return 1;
|
|
2689
|
+
return 1 + t.args.reduce((s, x) => s + termNodes(x), 0);
|
|
2731
2690
|
}
|
|
2732
|
-
function
|
|
2733
|
-
return
|
|
2734
|
-
{ k: "unknown" },
|
|
2735
|
-
{ op: "lit", value: void 0 },
|
|
2736
|
-
pTrue,
|
|
2737
|
-
"exact"
|
|
2738
|
-
);
|
|
2691
|
+
function exceedsBudget(t, budget = defaultLeakBudget) {
|
|
2692
|
+
return termDepth(t) > budget.maxDepth || termNodes(t) > budget.maxNodes;
|
|
2739
2693
|
}
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
return slot ?? out;
|
|
2694
|
+
var leakCounter = 0;
|
|
2695
|
+
function resetLeakCounter() {
|
|
2696
|
+
leakCounter = 0;
|
|
2744
2697
|
}
|
|
2745
|
-
function
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
if (anyUnknown || flatEls.length === 0) return unknown;
|
|
2754
|
-
const first = flatEls[0];
|
|
2755
|
-
const sameIdentity = flatEls.every((e) => {
|
|
2756
|
-
if (e.shape.k !== first.shape.k) return false;
|
|
2757
|
-
if (!e.term && !first.term) return true;
|
|
2758
|
-
if (!e.term || !first.term) return false;
|
|
2759
|
-
return termToString(e.term) === termToString(first.term);
|
|
2760
|
-
});
|
|
2761
|
-
const el = sameIdentity ? first : flatEls.reduce((a, b) => joinAbs(a, b));
|
|
2762
|
-
return abs(
|
|
2763
|
-
{ k: "arr", element: el },
|
|
2764
|
-
void 0,
|
|
2765
|
-
void 0,
|
|
2766
|
-
confJoin(arrConf, "path")
|
|
2767
|
-
);
|
|
2698
|
+
function maybeLeak(a, budget = defaultLeakBudget, label = "t") {
|
|
2699
|
+
if (!a.term || a.term.op !== "app") return a;
|
|
2700
|
+
if (!exceedsBudget(a.term, budget)) return a;
|
|
2701
|
+
leakCounter += 1;
|
|
2702
|
+
const id = `${label}$${leakCounter}`;
|
|
2703
|
+
const fresh = v(id);
|
|
2704
|
+
const linkage = eq(fresh, a.term);
|
|
2705
|
+
return abs(a.shape, fresh, linkage, confJoin(a.conf, "path"));
|
|
2768
2706
|
}
|
|
2769
|
-
function
|
|
2770
|
-
|
|
2771
|
-
return void 0;
|
|
2707
|
+
function leakIfNeeded(a, budget, label) {
|
|
2708
|
+
return maybeLeak(a, budget, label);
|
|
2772
2709
|
}
|
|
2773
2710
|
|
|
2774
|
-
// src/algebra/
|
|
2775
|
-
function
|
|
2776
|
-
return
|
|
2711
|
+
// src/algebra/hof.ts
|
|
2712
|
+
function createHofCollectCtx(paramNames, alphaIds) {
|
|
2713
|
+
return {
|
|
2714
|
+
paramNames,
|
|
2715
|
+
alphaIds: new Set(alphaIds),
|
|
2716
|
+
freshSeq: { n: 0 },
|
|
2717
|
+
sites: [],
|
|
2718
|
+
fnRels: /* @__PURE__ */ new Map(),
|
|
2719
|
+
entryShapes: /* @__PURE__ */ new Map()
|
|
2720
|
+
};
|
|
2777
2721
|
}
|
|
2778
|
-
function
|
|
2779
|
-
|
|
2722
|
+
function alphaOf(absOrTerm, ctx) {
|
|
2723
|
+
const t = absOrTerm && typeof absOrTerm === "object" && "shape" in absOrTerm ? absOrTerm.term : absOrTerm;
|
|
2724
|
+
if (t?.op === "var" && ctx.alphaIds.has(t.id)) return t;
|
|
2725
|
+
ctx.freshSeq.n += 1;
|
|
2726
|
+
const id = `T${ctx.freshSeq.n}`;
|
|
2727
|
+
ctx.alphaIds.add(id);
|
|
2728
|
+
return v(id);
|
|
2780
2729
|
}
|
|
2781
|
-
function
|
|
2782
|
-
return
|
|
2730
|
+
function betaOf(param) {
|
|
2731
|
+
return v(`B:${param}`);
|
|
2783
2732
|
}
|
|
2784
|
-
function
|
|
2785
|
-
const
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
if (
|
|
2799
|
-
|
|
2800
|
-
case "sqrt":
|
|
2801
|
-
if (typeof a0 === "number") return numLit(Math.sqrt(a0));
|
|
2802
|
-
return numPrim();
|
|
2803
|
-
case "min": {
|
|
2804
|
-
const lits = args.map(litValue);
|
|
2805
|
-
if (lits.length > 0 && lits.every((x) => typeof x === "number")) {
|
|
2806
|
-
return numLit(Math.min(...lits));
|
|
2733
|
+
function promoteParamShape(env, param, promotedShape, opts) {
|
|
2734
|
+
const prev = env.vars.get(param);
|
|
2735
|
+
if (!prev) return false;
|
|
2736
|
+
if (prev.shape.k !== "any" && prev.shape.k !== "unknown") return false;
|
|
2737
|
+
const next = {
|
|
2738
|
+
shape: promotedShape,
|
|
2739
|
+
term: prev.term,
|
|
2740
|
+
pred: prev.pred,
|
|
2741
|
+
conf: "path"
|
|
2742
|
+
};
|
|
2743
|
+
env.vars.set(param, next);
|
|
2744
|
+
const hc = env.hofCollect;
|
|
2745
|
+
if (hc && hc.paramNames.has(param)) {
|
|
2746
|
+
if (promotedShape.k === "fn") {
|
|
2747
|
+
if (!hc.fnRels.has(param) && !hc.entryShapes.has(param)) {
|
|
2748
|
+
hc.fnRels.set(param, { abs: { ...next }, source: "promote" });
|
|
2807
2749
|
}
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
const lits = args.map(litValue);
|
|
2812
|
-
if (lits.length > 0 && lits.every((x) => typeof x === "number")) {
|
|
2813
|
-
return numLit(Math.max(...lits));
|
|
2750
|
+
} else {
|
|
2751
|
+
if (!hc.fnRels.has(param) && !hc.entryShapes.has(param)) {
|
|
2752
|
+
hc.entryShapes.set(param, { abs: { ...next }, source: "promote" });
|
|
2814
2753
|
}
|
|
2815
|
-
return numPrim();
|
|
2816
2754
|
}
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2755
|
+
if (opts?.recordSite !== false && promotedShape.k === "fn") {
|
|
2756
|
+
const result = promotedShape.returnType ?? next;
|
|
2757
|
+
hc.sites.push({
|
|
2758
|
+
param,
|
|
2759
|
+
argTerms: [],
|
|
2760
|
+
result,
|
|
2761
|
+
loc: opts?.loc
|
|
2762
|
+
});
|
|
2763
|
+
}
|
|
2825
2764
|
}
|
|
2765
|
+
return true;
|
|
2826
2766
|
}
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2767
|
+
var HOF_ARR_METHODS = /* @__PURE__ */ new Set(["map", "filter", "reduce", "flatMap"]);
|
|
2768
|
+
function promoteParamAsArr(env, name, loc) {
|
|
2769
|
+
const hc = env.hofCollect;
|
|
2770
|
+
if (!hc || !hc.paramNames.has(name)) return void 0;
|
|
2771
|
+
const prev = env.vars.get(name);
|
|
2772
|
+
if (!prev) return void 0;
|
|
2773
|
+
if (prev.shape.k !== "any" && prev.shape.k !== "unknown") return void 0;
|
|
2774
|
+
const element = prev.term ? abs(prev.shape, prev.term, prev.pred, "path") : abs({ k: "any" }, void 0, void 0, "path");
|
|
2775
|
+
const arrShape = { k: "arr", element };
|
|
2776
|
+
promoteParamShape(env, name, arrShape, { loc });
|
|
2777
|
+
return env.vars.get(name);
|
|
2778
|
+
}
|
|
2779
|
+
function tryPromoteReceiverAsArr(env, receiverName, method, loc) {
|
|
2780
|
+
if (!HOF_ARR_METHODS.has(method)) return void 0;
|
|
2781
|
+
return promoteParamAsArr(env, receiverName, loc);
|
|
2782
|
+
}
|
|
2783
|
+
function tryPromoteForOfIteratee(env, iterateeName, loc) {
|
|
2784
|
+
return promoteParamAsArr(env, iterateeName, loc);
|
|
2785
|
+
}
|
|
2786
|
+
function tryPromoteDirectCall(env, calleeName, args, loc) {
|
|
2787
|
+
const hc = env.hofCollect;
|
|
2788
|
+
if (!hc || !hc.paramNames.has(calleeName)) return void 0;
|
|
2789
|
+
const prev = env.vars.get(calleeName);
|
|
2790
|
+
if (!prev) return void 0;
|
|
2791
|
+
if (prev.shape.k !== "any" && prev.shape.k !== "unknown") {
|
|
2792
|
+
if (prev.shape.k === "fn") {
|
|
2793
|
+
hc.sites.push({
|
|
2794
|
+
param: calleeName,
|
|
2795
|
+
argTerms: args.map((a) => a.term ?? { op: "var", id: "_" }),
|
|
2796
|
+
result: prev.shape.returnType ?? prev,
|
|
2797
|
+
loc
|
|
2798
|
+
});
|
|
2838
2799
|
}
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2800
|
+
return void 0;
|
|
2801
|
+
}
|
|
2802
|
+
const paramTypes = args.map(
|
|
2803
|
+
(a) => abs({ k: "any" }, alphaOf(a, hc), void 0, "path")
|
|
2804
|
+
);
|
|
2805
|
+
const ret = abs({ k: "any" }, betaOf(calleeName), void 0, "path");
|
|
2806
|
+
const fnShape = {
|
|
2807
|
+
k: "fn",
|
|
2808
|
+
params: args.map((_, i) => `x${i}`),
|
|
2809
|
+
paramTypes,
|
|
2810
|
+
returnType: ret
|
|
2811
|
+
};
|
|
2812
|
+
promoteParamShape(env, calleeName, fnShape, { loc, recordSite: false });
|
|
2813
|
+
hc.sites.push({
|
|
2814
|
+
param: calleeName,
|
|
2815
|
+
argTerms: args.map((a) => a.term ?? { op: "var", id: "_" }),
|
|
2816
|
+
result: ret,
|
|
2817
|
+
loc
|
|
2818
|
+
});
|
|
2819
|
+
return env.vars.get(calleeName);
|
|
2820
|
+
}
|
|
2821
|
+
function tryPromoteHofCallback(env, cbName, method, argAbses, loc) {
|
|
2822
|
+
const hc = env.hofCollect;
|
|
2823
|
+
if (!hc || !hc.paramNames.has(cbName)) return void 0;
|
|
2824
|
+
const prev = env.vars.get(cbName);
|
|
2825
|
+
if (!prev) return void 0;
|
|
2826
|
+
if (prev.shape.k !== "any" && prev.shape.k !== "unknown") return void 0;
|
|
2827
|
+
let paramTypes;
|
|
2828
|
+
let returnType;
|
|
2829
|
+
if (method === "filter") {
|
|
2830
|
+
paramTypes = argAbses.map(
|
|
2831
|
+
(a) => abs({ k: "any" }, alphaOf(a, hc), void 0, "path")
|
|
2832
|
+
);
|
|
2833
|
+
returnType = abs({ k: "prim", type: "boolean" }, void 0, void 0, "path");
|
|
2834
|
+
} else if (method === "reduce") {
|
|
2835
|
+
paramTypes = argAbses.map(
|
|
2836
|
+
(a) => abs({ k: "any" }, alphaOf(a, hc), void 0, "path")
|
|
2837
|
+
);
|
|
2838
|
+
returnType = abs({ k: "any" }, betaOf(cbName), void 0, "path");
|
|
2839
|
+
} else {
|
|
2840
|
+
paramTypes = argAbses.map(
|
|
2841
|
+
(a) => abs({ k: "any" }, alphaOf(a, hc), void 0, "path")
|
|
2842
|
+
);
|
|
2843
|
+
returnType = abs({ k: "any" }, betaOf(cbName), void 0, "path");
|
|
2844
|
+
}
|
|
2845
|
+
const fnShape = {
|
|
2846
|
+
k: "fn",
|
|
2847
|
+
params: argAbses.map((_, i) => `x${i}`),
|
|
2848
|
+
paramTypes,
|
|
2849
|
+
returnType
|
|
2850
|
+
};
|
|
2851
|
+
promoteParamShape(env, cbName, fnShape, { loc, recordSite: false });
|
|
2852
|
+
hc.sites.push({
|
|
2853
|
+
param: cbName,
|
|
2854
|
+
argTerms: argAbses.map((a) => a.term ?? { op: "var", id: "_" }),
|
|
2855
|
+
result: returnType,
|
|
2856
|
+
loc
|
|
2857
|
+
});
|
|
2858
|
+
return env.vars.get(cbName);
|
|
2859
|
+
}
|
|
2860
|
+
function snapshotAbs(a) {
|
|
2861
|
+
const shape = a.shape;
|
|
2862
|
+
const copyShape = (s) => {
|
|
2863
|
+
switch (s.k) {
|
|
2864
|
+
case "arr":
|
|
2865
|
+
return { ...s, element: snapshotAbs(s.element) };
|
|
2866
|
+
case "tuple": {
|
|
2867
|
+
const next = {
|
|
2868
|
+
k: "tuple",
|
|
2869
|
+
elements: s.elements.map(snapshotAbs)
|
|
2870
|
+
};
|
|
2871
|
+
if (s.rest) next.rest = snapshotAbs(s.rest);
|
|
2872
|
+
return next;
|
|
2844
2873
|
}
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
([, s]) => abs({ k: "tuple", elements: [strPrim("exact"), s.value] }, void 0, void 0, "exact")
|
|
2852
|
-
);
|
|
2853
|
-
return abs({ k: "tuple", elements: entries }, void 0, void 0, "exact");
|
|
2874
|
+
case "fn": {
|
|
2875
|
+
const next = { k: "fn", params: [...s.params] };
|
|
2876
|
+
if (s.name !== void 0) next.name = s.name;
|
|
2877
|
+
if (s.paramTypes) next.paramTypes = s.paramTypes.map(snapshotAbs);
|
|
2878
|
+
if (s.returnType) next.returnType = snapshotAbs(s.returnType);
|
|
2879
|
+
return next;
|
|
2854
2880
|
}
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2881
|
+
case "sum":
|
|
2882
|
+
return { ...s, members: s.members.map(snapshotAbs) };
|
|
2883
|
+
case "obj": {
|
|
2884
|
+
const slots = {};
|
|
2885
|
+
for (const [k, slot] of Object.entries(s.slots)) {
|
|
2886
|
+
const nextSlot = { value: snapshotAbs(slot.value) };
|
|
2887
|
+
if (slot.optional) nextSlot.optional = true;
|
|
2888
|
+
if (slot.readonly) nextSlot.readonly = true;
|
|
2889
|
+
slots[k] = nextSlot;
|
|
2890
|
+
}
|
|
2891
|
+
const next = { k: "obj", slots };
|
|
2892
|
+
if (s.index) {
|
|
2893
|
+
next.index = {
|
|
2894
|
+
key: snapshotAbs(s.index.key),
|
|
2895
|
+
value: snapshotAbs(s.index.value)
|
|
2896
|
+
};
|
|
2866
2897
|
}
|
|
2898
|
+
if (s.open) next.open = true;
|
|
2899
|
+
return next;
|
|
2867
2900
|
}
|
|
2868
|
-
|
|
2901
|
+
case "brand":
|
|
2902
|
+
return { ...s, shape: snapshotAbs(s.shape) };
|
|
2903
|
+
case "eff":
|
|
2904
|
+
return { ...s, inner: snapshotAbs(s.inner) };
|
|
2905
|
+
default:
|
|
2906
|
+
return s;
|
|
2869
2907
|
}
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2908
|
+
};
|
|
2909
|
+
return {
|
|
2910
|
+
shape: copyShape(shape),
|
|
2911
|
+
term: a.term,
|
|
2912
|
+
pred: a.pred,
|
|
2913
|
+
conf: a.conf
|
|
2914
|
+
};
|
|
2873
2915
|
}
|
|
2874
|
-
function
|
|
2875
|
-
if (
|
|
2876
|
-
if (
|
|
2877
|
-
|
|
2916
|
+
function isRelFn(a) {
|
|
2917
|
+
if (!a || typeof a !== "object") return false;
|
|
2918
|
+
if (getFnImpl(a)) return false;
|
|
2919
|
+
const s = a.shape;
|
|
2920
|
+
if (!s || s.k !== "fn") return false;
|
|
2921
|
+
if (s.returnType === void 0) return false;
|
|
2922
|
+
if (s.paramTypes === void 0) return s.params.length === 0;
|
|
2923
|
+
return s.paramTypes.length === s.params.length;
|
|
2878
2924
|
}
|
|
2879
|
-
function
|
|
2880
|
-
|
|
2881
|
-
switch (name) {
|
|
2882
|
-
case "isInteger":
|
|
2883
|
-
if (typeof a0 === "number") return boolLit(Number.isInteger(a0));
|
|
2884
|
-
return boolPrim();
|
|
2885
|
-
case "isNaN":
|
|
2886
|
-
if (typeof a0 === "number") return boolLit(Number.isNaN(a0));
|
|
2887
|
-
return boolPrim();
|
|
2888
|
-
case "isFinite":
|
|
2889
|
-
if (typeof a0 === "number") return boolLit(Number.isFinite(a0));
|
|
2890
|
-
return boolPrim();
|
|
2891
|
-
case "parseInt":
|
|
2892
|
-
case "parseFloat":
|
|
2893
|
-
if (typeof a0 === "string" || typeof a0 === "number") {
|
|
2894
|
-
const n = name === "parseInt" ? parseInt(String(a0), 10) : parseFloat(String(a0));
|
|
2895
|
-
return numLit(n);
|
|
2896
|
-
}
|
|
2897
|
-
return numPrim();
|
|
2898
|
-
case "MAX_SAFE_INTEGER":
|
|
2899
|
-
return numLit(Number.MAX_SAFE_INTEGER);
|
|
2900
|
-
default:
|
|
2901
|
-
return void 0;
|
|
2902
|
-
}
|
|
2925
|
+
function litOfTerm(t) {
|
|
2926
|
+
return t.op === "lit" ? t.value : void 0;
|
|
2903
2927
|
}
|
|
2904
|
-
function
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
return
|
|
2916
|
-
case "
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
return
|
|
2924
|
-
case "Boolean":
|
|
2925
|
-
if (a0 !== void 0) return boolLit(Boolean(a0));
|
|
2926
|
-
return boolPrim();
|
|
2928
|
+
function foldCompare(op, a, b) {
|
|
2929
|
+
if (a === void 0 || b === void 0) return void 0;
|
|
2930
|
+
if (typeof a !== typeof b) {
|
|
2931
|
+
if (op === "eq") return pFalse;
|
|
2932
|
+
if (op === "ne") return pTrue;
|
|
2933
|
+
return void 0;
|
|
2934
|
+
}
|
|
2935
|
+
switch (op) {
|
|
2936
|
+
case "eq":
|
|
2937
|
+
return a === b ? pTrue : pFalse;
|
|
2938
|
+
case "ne":
|
|
2939
|
+
return a !== b ? pTrue : pFalse;
|
|
2940
|
+
case "lt":
|
|
2941
|
+
return a < b ? pTrue : pFalse;
|
|
2942
|
+
case "le":
|
|
2943
|
+
return a <= b ? pTrue : pFalse;
|
|
2944
|
+
case "gt":
|
|
2945
|
+
return a > b ? pTrue : pFalse;
|
|
2946
|
+
case "ge":
|
|
2947
|
+
return a >= b ? pTrue : pFalse;
|
|
2927
2948
|
default:
|
|
2928
2949
|
return void 0;
|
|
2929
2950
|
}
|
|
2930
2951
|
}
|
|
2931
|
-
function
|
|
2932
|
-
const
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2952
|
+
function predUsesMappedVars(p, map) {
|
|
2953
|
+
const walkTerm = (t) => {
|
|
2954
|
+
if (t.op === "var") return map.has(t.id);
|
|
2955
|
+
if (t.op === "app") return t.args.some(walkTerm);
|
|
2956
|
+
return false;
|
|
2957
|
+
};
|
|
2958
|
+
const walk = (q) => {
|
|
2959
|
+
switch (q.op) {
|
|
2960
|
+
case "true":
|
|
2961
|
+
case "false":
|
|
2962
|
+
return false;
|
|
2963
|
+
case "eq":
|
|
2964
|
+
case "ne":
|
|
2965
|
+
case "lt":
|
|
2966
|
+
case "le":
|
|
2967
|
+
case "gt":
|
|
2968
|
+
case "ge":
|
|
2969
|
+
return walkTerm(q.a) || walkTerm(q.b);
|
|
2970
|
+
case "and":
|
|
2971
|
+
case "or":
|
|
2972
|
+
return q.args.some(walk);
|
|
2973
|
+
case "not":
|
|
2974
|
+
return walk(q.arg);
|
|
2975
|
+
case "typeof":
|
|
2976
|
+
return walkTerm(q.t);
|
|
2977
|
+
}
|
|
2978
|
+
};
|
|
2979
|
+
return walk(p);
|
|
2980
|
+
}
|
|
2981
|
+
function mapHasShapeOnlyVar(p, map) {
|
|
2982
|
+
const walkTerm = (t) => {
|
|
2983
|
+
if (t.op === "var") {
|
|
2984
|
+
const arg = map.get(t.id);
|
|
2985
|
+
return !!arg && arg.term === void 0;
|
|
2986
|
+
}
|
|
2987
|
+
if (t.op === "app") return t.args.some(walkTerm);
|
|
2988
|
+
return false;
|
|
2989
|
+
};
|
|
2990
|
+
const walk = (q) => {
|
|
2991
|
+
switch (q.op) {
|
|
2992
|
+
case "true":
|
|
2993
|
+
case "false":
|
|
2994
|
+
return false;
|
|
2995
|
+
case "eq":
|
|
2996
|
+
case "ne":
|
|
2997
|
+
case "lt":
|
|
2998
|
+
case "le":
|
|
2999
|
+
case "gt":
|
|
3000
|
+
case "ge":
|
|
3001
|
+
return walkTerm(q.a) || walkTerm(q.b);
|
|
3002
|
+
case "and":
|
|
3003
|
+
case "or":
|
|
3004
|
+
return q.args.some(walk);
|
|
3005
|
+
case "not":
|
|
3006
|
+
return walk(q.arg);
|
|
3007
|
+
case "typeof":
|
|
3008
|
+
return walkTerm(q.t);
|
|
3009
|
+
}
|
|
3010
|
+
};
|
|
3011
|
+
return walk(p);
|
|
3012
|
+
}
|
|
3013
|
+
function substPredAbs(p, map) {
|
|
3014
|
+
if (!predUsesMappedVars(p, map)) return { pred: p, dropped: false };
|
|
3015
|
+
if (mapHasShapeOnlyVar(p, map)) return { pred: pTrue, dropped: true };
|
|
3016
|
+
const substTerm = (t) => {
|
|
3017
|
+
if (t.op === "var") {
|
|
3018
|
+
const arg = map.get(t.id);
|
|
3019
|
+
return arg?.term ?? t;
|
|
3020
|
+
}
|
|
3021
|
+
if (t.op === "app") {
|
|
3022
|
+
return { op: "app", fn: t.fn, args: t.args.map(substTerm) };
|
|
3023
|
+
}
|
|
3024
|
+
return t;
|
|
3025
|
+
};
|
|
3026
|
+
const replaced = substPred(p, substTerm);
|
|
3027
|
+
const fold = (q) => {
|
|
3028
|
+
switch (q.op) {
|
|
3029
|
+
case "true":
|
|
3030
|
+
case "false":
|
|
3031
|
+
return q;
|
|
3032
|
+
case "eq":
|
|
3033
|
+
case "ne":
|
|
3034
|
+
case "lt":
|
|
3035
|
+
case "le":
|
|
3036
|
+
case "gt":
|
|
3037
|
+
case "ge": {
|
|
3038
|
+
const a = litOfTerm(q.a);
|
|
3039
|
+
const b = litOfTerm(q.b);
|
|
3040
|
+
const folded = foldCompare(q.op, a, b);
|
|
3041
|
+
return folded ?? q;
|
|
3042
|
+
}
|
|
3043
|
+
case "and": {
|
|
3044
|
+
const args = q.args.map(fold);
|
|
3045
|
+
if (args.some((x) => x.op === "false")) return pFalse;
|
|
3046
|
+
const rest = args.filter((x) => x.op !== "true");
|
|
3047
|
+
if (rest.length === 0) return pTrue;
|
|
3048
|
+
if (rest.length === 1) return rest[0];
|
|
3049
|
+
return and(...rest);
|
|
3050
|
+
}
|
|
3051
|
+
case "or": {
|
|
3052
|
+
const args = q.args.map(fold);
|
|
3053
|
+
if (args.some((x) => x.op === "true")) return pTrue;
|
|
3054
|
+
const rest = args.filter((x) => x.op !== "false");
|
|
3055
|
+
if (rest.length === 0) return pFalse;
|
|
3056
|
+
if (rest.length === 1) return rest[0];
|
|
3057
|
+
return { op: "or", args: rest };
|
|
3058
|
+
}
|
|
3059
|
+
case "not": {
|
|
3060
|
+
const inner = fold(q.arg);
|
|
3061
|
+
if (inner.op === "true") return pFalse;
|
|
3062
|
+
if (inner.op === "false") return pTrue;
|
|
3063
|
+
return { op: "not", arg: inner };
|
|
3064
|
+
}
|
|
3065
|
+
case "typeof":
|
|
3066
|
+
return q;
|
|
2938
3067
|
}
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
return abs({ k: "arr", element: a0 ?? unknown }, void 0, void 0, "path");
|
|
2942
|
-
default:
|
|
2943
|
-
return void 0;
|
|
2944
|
-
}
|
|
2945
|
-
}
|
|
2946
|
-
function evalDateCtor(args) {
|
|
2947
|
-
return abs(
|
|
2948
|
-
{ k: "brand", name: "Date", shape: abs({ k: "obj", slots: {} }, void 0, void 0, "exact") },
|
|
2949
|
-
void 0,
|
|
2950
|
-
void 0,
|
|
2951
|
-
"path"
|
|
2952
|
-
);
|
|
2953
|
-
}
|
|
2954
|
-
function evalDateStatic(name, _args) {
|
|
2955
|
-
if (name === "now") return numLit(Date.now());
|
|
2956
|
-
return void 0;
|
|
3068
|
+
};
|
|
3069
|
+
return { pred: fold(replaced), dropped: false };
|
|
2957
3070
|
}
|
|
2958
|
-
function
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
return numPrim("path");
|
|
2963
|
-
case "toISOString":
|
|
2964
|
-
case "toString":
|
|
2965
|
-
return strPrim("path");
|
|
2966
|
-
default:
|
|
2967
|
-
return void 0;
|
|
3071
|
+
function substTermAbs(t, map) {
|
|
3072
|
+
if (t.op === "var") {
|
|
3073
|
+
const arg = map.get(t.id);
|
|
3074
|
+
return arg?.term ?? t;
|
|
2968
3075
|
}
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
"path"
|
|
2976
|
-
);
|
|
2977
|
-
}
|
|
2978
|
-
function evalRegExpMethod(name, _recv, _args) {
|
|
2979
|
-
switch (name) {
|
|
2980
|
-
case "test":
|
|
2981
|
-
return boolPrim();
|
|
2982
|
-
case "exec":
|
|
2983
|
-
return unknown;
|
|
2984
|
-
default:
|
|
2985
|
-
return void 0;
|
|
3076
|
+
if (t.op === "app") {
|
|
3077
|
+
return simplifyTerm({
|
|
3078
|
+
op: "app",
|
|
3079
|
+
fn: t.fn,
|
|
3080
|
+
args: t.args.map((x) => substTermAbs(x, map))
|
|
3081
|
+
});
|
|
2986
3082
|
}
|
|
3083
|
+
return t;
|
|
2987
3084
|
}
|
|
2988
|
-
function
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
"
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3085
|
+
function substShape(s, map, cache, visiting) {
|
|
3086
|
+
switch (s.k) {
|
|
3087
|
+
case "never":
|
|
3088
|
+
case "any":
|
|
3089
|
+
case "unknown":
|
|
3090
|
+
case "prim":
|
|
3091
|
+
return s;
|
|
3092
|
+
case "brand":
|
|
3093
|
+
return { ...s, shape: substAbsInner(s.shape, map, cache, visiting) };
|
|
3094
|
+
case "eff":
|
|
3095
|
+
return { ...s, inner: substAbsInner(s.inner, map, cache, visiting) };
|
|
3096
|
+
case "arr":
|
|
3097
|
+
return { ...s, element: substAbsInner(s.element, map, cache, visiting) };
|
|
3098
|
+
case "tuple": {
|
|
3099
|
+
const elements = s.elements.map(
|
|
3100
|
+
(e) => substAbsInner(e, map, cache, visiting)
|
|
3101
|
+
);
|
|
3102
|
+
const next = { k: "tuple", elements };
|
|
3103
|
+
if (s.rest) next.rest = substAbsInner(s.rest, map, cache, visiting);
|
|
3104
|
+
return next;
|
|
3002
3105
|
}
|
|
3003
|
-
case "
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
{ k: "eff", eff: "promise", inner: abs({ k: "arr", element: a0.shape.element.shape.inner }, void 0, void 0, "path") },
|
|
3010
|
-
void 0,
|
|
3011
|
-
void 0,
|
|
3012
|
-
"path"
|
|
3106
|
+
case "fn": {
|
|
3107
|
+
const next = { k: "fn", params: s.params };
|
|
3108
|
+
if (s.name !== void 0) next.name = s.name;
|
|
3109
|
+
if (s.paramTypes) {
|
|
3110
|
+
next.paramTypes = s.paramTypes.map(
|
|
3111
|
+
(p) => substAbsInner(p, map, cache, visiting)
|
|
3013
3112
|
);
|
|
3014
3113
|
}
|
|
3015
|
-
|
|
3114
|
+
if (s.returnType !== void 0) {
|
|
3115
|
+
next.returnType = substAbsInner(s.returnType, map, cache, visiting);
|
|
3116
|
+
}
|
|
3117
|
+
return next;
|
|
3118
|
+
}
|
|
3119
|
+
case "sum":
|
|
3120
|
+
return {
|
|
3121
|
+
...s,
|
|
3122
|
+
members: s.members.map((m) => substAbsInner(m, map, cache, visiting))
|
|
3123
|
+
};
|
|
3124
|
+
case "obj": {
|
|
3125
|
+
const slots = {};
|
|
3126
|
+
for (const [k, slot] of Object.entries(s.slots)) {
|
|
3127
|
+
const nextSlot = { value: substAbsInner(slot.value, map, cache, visiting) };
|
|
3128
|
+
if (slot.optional) nextSlot.optional = true;
|
|
3129
|
+
if (slot.readonly) nextSlot.readonly = true;
|
|
3130
|
+
slots[k] = nextSlot;
|
|
3131
|
+
}
|
|
3132
|
+
const next = { k: "obj", slots };
|
|
3133
|
+
if (s.index) {
|
|
3134
|
+
next.index = {
|
|
3135
|
+
key: substAbsInner(s.index.key, map, cache, visiting),
|
|
3136
|
+
value: substAbsInner(s.index.value, map, cache, visiting)
|
|
3137
|
+
};
|
|
3138
|
+
}
|
|
3139
|
+
if (s.open) next.open = true;
|
|
3140
|
+
return next;
|
|
3016
3141
|
}
|
|
3017
|
-
default:
|
|
3018
|
-
return void 0;
|
|
3019
3142
|
}
|
|
3020
3143
|
}
|
|
3021
|
-
function
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
return evalNumberStatic(method, args);
|
|
3031
|
-
case "Array":
|
|
3032
|
-
return evalArrayStatic(method, args);
|
|
3033
|
-
case "Date":
|
|
3034
|
-
return evalDateStatic(method, args);
|
|
3035
|
-
case "Promise":
|
|
3036
|
-
return evalPromiseStatic(method, args);
|
|
3037
|
-
default:
|
|
3038
|
-
return void 0;
|
|
3144
|
+
function substAbsInner(a, map, cache, visiting) {
|
|
3145
|
+
if (a.term?.op === "var" && map.has(a.term.id)) {
|
|
3146
|
+
const repl = map.get(a.term.id);
|
|
3147
|
+
return {
|
|
3148
|
+
shape: repl.shape,
|
|
3149
|
+
term: repl.term,
|
|
3150
|
+
pred: repl.pred,
|
|
3151
|
+
conf: confJoin(a.conf, repl.conf)
|
|
3152
|
+
};
|
|
3039
3153
|
}
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
void 0,
|
|
3053
|
-
void 0,
|
|
3054
|
-
"path"
|
|
3055
|
-
);
|
|
3056
|
-
case "Set":
|
|
3057
|
-
return abs(
|
|
3058
|
-
{ k: "brand", name: "Set", shape: abs({ k: "obj", slots: {} }, void 0, void 0, "exact") },
|
|
3059
|
-
void 0,
|
|
3060
|
-
void 0,
|
|
3061
|
-
"path"
|
|
3062
|
-
);
|
|
3063
|
-
default:
|
|
3064
|
-
return void 0;
|
|
3154
|
+
const hit = cache.get(a);
|
|
3155
|
+
if (hit !== void 0) return hit;
|
|
3156
|
+
if (visiting.has(a)) return a;
|
|
3157
|
+
visiting.add(a);
|
|
3158
|
+
const shape = substShape(a.shape, map, cache, visiting);
|
|
3159
|
+
const term = a.term ? substTermAbs(a.term, map) : void 0;
|
|
3160
|
+
let pred = a.pred;
|
|
3161
|
+
let conf = a.conf;
|
|
3162
|
+
if (a.pred) {
|
|
3163
|
+
const r = substPredAbs(a.pred, map);
|
|
3164
|
+
pred = r.pred;
|
|
3165
|
+
if (r.dropped) conf = confJoin(conf, "partial");
|
|
3065
3166
|
}
|
|
3167
|
+
visiting.delete(a);
|
|
3168
|
+
const result = abs(shape, term, pred, conf);
|
|
3169
|
+
cache.set(a, result);
|
|
3170
|
+
return result;
|
|
3066
3171
|
}
|
|
3067
|
-
function
|
|
3068
|
-
if (
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3172
|
+
function substAbs(a, map) {
|
|
3173
|
+
if (map.size === 0) return a;
|
|
3174
|
+
return substAbsInner(a, map, /* @__PURE__ */ new Map(), /* @__PURE__ */ new Set());
|
|
3175
|
+
}
|
|
3176
|
+
function instantiateReturn(fn, args) {
|
|
3177
|
+
const shape = fn.shape;
|
|
3178
|
+
if (!shape || shape.k !== "fn") return unknown;
|
|
3179
|
+
const src = getFnImpl(fn)?.relation ?? {
|
|
3180
|
+
paramTypes: shape.paramTypes ?? [],
|
|
3181
|
+
returnType: shape.returnType ?? unknown
|
|
3182
|
+
};
|
|
3183
|
+
const map = /* @__PURE__ */ new Map();
|
|
3184
|
+
src.paramTypes.forEach((p, i) => {
|
|
3185
|
+
if (p.term?.op !== "var") return;
|
|
3186
|
+
const id = p.term.id;
|
|
3187
|
+
if (map.has(id)) return;
|
|
3188
|
+
map.set(id, args[i] ?? unknown);
|
|
3189
|
+
});
|
|
3190
|
+
return substAbs(src.returnType, map);
|
|
3191
|
+
}
|
|
3192
|
+
var applyCallbackHost;
|
|
3193
|
+
function setApplyCallbackHost(fn) {
|
|
3194
|
+
applyCallbackHost = fn;
|
|
3195
|
+
}
|
|
3196
|
+
function applyCallbackAbs(cb, args, env, phi2, budget) {
|
|
3197
|
+
if (!applyCallbackHost) {
|
|
3198
|
+
if (cb && typeof cb === "object" && "shape" in cb) {
|
|
3199
|
+
const a = cb;
|
|
3200
|
+
const impl = getFnImpl(a);
|
|
3201
|
+
if (impl?.relation) return instantiateReturn(a, args);
|
|
3202
|
+
if (isRelFn(a)) return instantiateReturn(a, args);
|
|
3082
3203
|
}
|
|
3204
|
+
return unknown;
|
|
3083
3205
|
}
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3206
|
+
return applyCallbackHost(cb, args, env, phi2, budget);
|
|
3207
|
+
}
|
|
3208
|
+
function undefAbs() {
|
|
3209
|
+
return abs(
|
|
3210
|
+
{ k: "unknown" },
|
|
3211
|
+
{ op: "lit", value: void 0 },
|
|
3212
|
+
pTrue,
|
|
3213
|
+
"exact"
|
|
3214
|
+
);
|
|
3215
|
+
}
|
|
3216
|
+
function mapElementFallback(cbAbs, elem, out) {
|
|
3217
|
+
if (out.shape.k !== "unknown" || elem.term?.op !== "var") return out;
|
|
3218
|
+
const slot = cbAbs?.shape.k === "fn" ? cbAbs.shape.returnType : void 0;
|
|
3219
|
+
return slot ?? out;
|
|
3220
|
+
}
|
|
3221
|
+
function projectFlatMapResult(arrConf, mapped) {
|
|
3222
|
+
const flatEls = [];
|
|
3223
|
+
let anyUnknown = false;
|
|
3224
|
+
for (const m of mapped) {
|
|
3225
|
+
if (m.shape.k === "arr") flatEls.push(m.shape.element);
|
|
3226
|
+
else if (m.shape.k === "tuple") flatEls.push(...m.shape.elements);
|
|
3227
|
+
else anyUnknown = true;
|
|
3095
3228
|
}
|
|
3229
|
+
if (anyUnknown || flatEls.length === 0) return unknown;
|
|
3230
|
+
const first = flatEls[0];
|
|
3231
|
+
const sameIdentity = flatEls.every((e) => {
|
|
3232
|
+
if (e.shape.k !== first.shape.k) return false;
|
|
3233
|
+
if (!e.term && !first.term) return true;
|
|
3234
|
+
if (!e.term || !first.term) return false;
|
|
3235
|
+
return termToString(e.term) === termToString(first.term);
|
|
3236
|
+
});
|
|
3237
|
+
const el = sameIdentity ? first : flatEls.reduce((a, b) => joinAbs(a, b));
|
|
3238
|
+
return abs(
|
|
3239
|
+
{ k: "arr", element: el },
|
|
3240
|
+
void 0,
|
|
3241
|
+
void 0,
|
|
3242
|
+
confJoin(arrConf, "path")
|
|
3243
|
+
);
|
|
3244
|
+
}
|
|
3245
|
+
function asAbs(v2) {
|
|
3246
|
+
if (v2 && typeof v2 === "object" && "shape" in v2) return v2;
|
|
3096
3247
|
return void 0;
|
|
3097
3248
|
}
|
|
3098
3249
|
|
|
@@ -3109,29 +3260,6 @@ function numPrim2(conf = "path") {
|
|
|
3109
3260
|
function strArr(conf = "path") {
|
|
3110
3261
|
return abs({ k: "arr", element: strPrim2("path") }, void 0, void 0, conf);
|
|
3111
3262
|
}
|
|
3112
|
-
function knownPrefix(parts) {
|
|
3113
|
-
let s = "";
|
|
3114
|
-
for (const p of parts) {
|
|
3115
|
-
if (p.term?.op === "lit" && typeof p.term.value === "string") s += p.term.value;
|
|
3116
|
-
else break;
|
|
3117
|
-
}
|
|
3118
|
-
return s;
|
|
3119
|
-
}
|
|
3120
|
-
function knownSuffix(parts) {
|
|
3121
|
-
let s = "";
|
|
3122
|
-
for (let i = parts.length - 1; i >= 0; i--) {
|
|
3123
|
-
const p = parts[i];
|
|
3124
|
-
if (p.term?.op === "lit" && typeof p.term.value === "string") s = p.term.value + s;
|
|
3125
|
-
else break;
|
|
3126
|
-
}
|
|
3127
|
-
return s;
|
|
3128
|
-
}
|
|
3129
|
-
function fixedLength(parts) {
|
|
3130
|
-
if (parts.some((p) => !(p.term?.op === "lit" && typeof p.term.value === "string"))) {
|
|
3131
|
-
return void 0;
|
|
3132
|
-
}
|
|
3133
|
-
return parts.reduce((n, p) => n + String(p.term && p.term.op === "lit" ? p.term.value : "").length, 0);
|
|
3134
|
-
}
|
|
3135
3263
|
function isStrRecv(recv) {
|
|
3136
3264
|
return isTemplateLike(recv) || recv.shape.k === "prim" && recv.shape.type === "string" || recv.term?.op === "lit" && typeof recv.term.value === "string";
|
|
3137
3265
|
}
|
|
@@ -3140,27 +3268,24 @@ function callAbsMethod(recv, name, args) {
|
|
|
3140
3268
|
const a0 = args[0] ? litValue(args[0]) : void 0;
|
|
3141
3269
|
const lit3 = recv.term?.op === "lit" && typeof recv.term.value === "string" ? recv.term.value : void 0;
|
|
3142
3270
|
if (isTemplateLike(recv)) {
|
|
3143
|
-
const
|
|
3144
|
-
const prefix =
|
|
3145
|
-
const suffix =
|
|
3271
|
+
const views = absTemplateViews(templatePartsOf(recv));
|
|
3272
|
+
const prefix = knownPrefixOfViews(views);
|
|
3273
|
+
const suffix = knownSuffixOfViews(views);
|
|
3146
3274
|
switch (name) {
|
|
3147
3275
|
case "startsWith": {
|
|
3148
3276
|
if (typeof a0 !== "string") return boolPrim2();
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
return boolLit(false);
|
|
3277
|
+
const d = decideStartsWith(prefix, a0);
|
|
3278
|
+
return d === "unknown" ? boolPrim2() : boolLit(d);
|
|
3152
3279
|
}
|
|
3153
3280
|
case "endsWith": {
|
|
3154
3281
|
if (typeof a0 !== "string") return boolPrim2();
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
return boolLit(false);
|
|
3282
|
+
const d = decideEndsWith(suffix, a0);
|
|
3283
|
+
return d === "unknown" ? boolPrim2() : boolLit(d);
|
|
3158
3284
|
}
|
|
3159
3285
|
case "includes": {
|
|
3160
3286
|
if (typeof a0 !== "string") return boolPrim2();
|
|
3161
|
-
const
|
|
3162
|
-
|
|
3163
|
-
return boolPrim2();
|
|
3287
|
+
const d = decideIncludes(allFixedTextOfViews(views), a0);
|
|
3288
|
+
return d === "unknown" ? boolPrim2() : boolLit(d);
|
|
3164
3289
|
}
|
|
3165
3290
|
case "toUpperCase":
|
|
3166
3291
|
case "toLowerCase":
|
|
@@ -3246,8 +3371,7 @@ function callAbsMethod(recv, name, args) {
|
|
|
3246
3371
|
function getAbsProperty(recv, name) {
|
|
3247
3372
|
if (name === "length") {
|
|
3248
3373
|
if (isTemplateLike(recv)) {
|
|
3249
|
-
const
|
|
3250
|
-
const n = fixedLength(parts);
|
|
3374
|
+
const n = fixedLengthOfViews(absTemplateViews(templatePartsOf(recv)));
|
|
3251
3375
|
if (n !== void 0) return numLit(n);
|
|
3252
3376
|
return numPrim2("path");
|
|
3253
3377
|
}
|
|
@@ -3563,9 +3687,18 @@ function recordAbsNode(node, value) {
|
|
|
3563
3687
|
}
|
|
3564
3688
|
}
|
|
3565
3689
|
var absAssignCollector = null;
|
|
3690
|
+
var assignFlowDepth = 0;
|
|
3566
3691
|
function setAbsAssignCollector(collector) {
|
|
3567
3692
|
absAssignCollector = collector;
|
|
3568
3693
|
}
|
|
3694
|
+
function evalInConditionalFlow(body) {
|
|
3695
|
+
assignFlowDepth++;
|
|
3696
|
+
try {
|
|
3697
|
+
return body();
|
|
3698
|
+
} finally {
|
|
3699
|
+
assignFlowDepth--;
|
|
3700
|
+
}
|
|
3701
|
+
}
|
|
3569
3702
|
function recordAbsAssign(name, prev, next, loc) {
|
|
3570
3703
|
if (!absAssignCollector) return;
|
|
3571
3704
|
try {
|
|
@@ -3574,7 +3707,8 @@ function recordAbsAssign(name, prev, next, loc) {
|
|
|
3574
3707
|
prev,
|
|
3575
3708
|
next,
|
|
3576
3709
|
line: loc?.start.line,
|
|
3577
|
-
column: loc?.start.column
|
|
3710
|
+
column: loc?.start.column,
|
|
3711
|
+
conditional: assignFlowDepth > 0
|
|
3578
3712
|
});
|
|
3579
3713
|
} catch {
|
|
3580
3714
|
}
|
|
@@ -3952,14 +4086,14 @@ function evalNodeInner(node, env, phi2, budget) {
|
|
|
3952
4086
|
}
|
|
3953
4087
|
if (!m.computed && m.property.type === "Identifier" && obj2.shape.k === "obj") {
|
|
3954
4088
|
const key = m.property.name;
|
|
3955
|
-
const slot = obj2.shape.slots
|
|
4089
|
+
const slot = getSlot(obj2.shape.slots, key);
|
|
3956
4090
|
if (slot) return ok2(slot.value, phi2, env);
|
|
3957
4091
|
}
|
|
3958
4092
|
if (m.computed) {
|
|
3959
4093
|
const key = evalNode(m.property, env, phi2, budget).value;
|
|
3960
4094
|
const kl = litValue(key);
|
|
3961
4095
|
if (typeof kl === "string" && obj2.shape.k === "obj") {
|
|
3962
|
-
const slot = obj2.shape.slots
|
|
4096
|
+
const slot = getSlot(obj2.shape.slots, kl);
|
|
3963
4097
|
if (slot) return ok2(slot.value, phi2, env);
|
|
3964
4098
|
}
|
|
3965
4099
|
if (typeof kl === "number") {
|
|
@@ -4011,11 +4145,11 @@ function evalNodeInner(node, env, phi2, budget) {
|
|
|
4011
4145
|
if (els.length === 0) {
|
|
4012
4146
|
return ok2(abs({ k: "arr", element: unknown }, void 0, void 0, "exact"), phi2, env);
|
|
4013
4147
|
}
|
|
4014
|
-
if (els.length
|
|
4148
|
+
if (!shouldWidenArrayLiteral(els.length)) {
|
|
4015
4149
|
return ok2(abs({ k: "tuple", elements: els }, void 0, void 0, "exact"), phi2, env);
|
|
4016
4150
|
}
|
|
4017
4151
|
const elem = els.reduce((x, y) => joinAbs(x, y));
|
|
4018
|
-
return ok2(abs({ k: "arr", element: elem }, void 0, void 0,
|
|
4152
|
+
return ok2(abs({ k: "arr", element: elem }, void 0, void 0, widenedArrayConf()), phi2, env);
|
|
4019
4153
|
}
|
|
4020
4154
|
default:
|
|
4021
4155
|
return ok2(unknown, phi2, env);
|
|
@@ -4535,7 +4669,7 @@ function evalFor(node, env, phi2, budget) {
|
|
|
4535
4669
|
const lv = litValue(t.value);
|
|
4536
4670
|
if (lv === false || lv === null || lv === void 0) break;
|
|
4537
4671
|
}
|
|
4538
|
-
const bodyR = evalNode(node.body, local, phi2, budget);
|
|
4672
|
+
const bodyR = evalInConditionalFlow(() => evalNode(node.body, local, phi2, budget));
|
|
4539
4673
|
if (bodyR.returned) return bodyR;
|
|
4540
4674
|
if (bodyR.threw) return bodyR;
|
|
4541
4675
|
if (bodyR.brk) {
|
|
@@ -4558,7 +4692,7 @@ function evalWhile(node, env, phi2, budget) {
|
|
|
4558
4692
|
const t = evalNode(node.test, local, phi2, budget);
|
|
4559
4693
|
const lv = litValue(t.value);
|
|
4560
4694
|
if (lv === false || lv === null || lv === void 0) break;
|
|
4561
|
-
const bodyR = evalNode(node.body, local, phi2, budget);
|
|
4695
|
+
const bodyR = evalInConditionalFlow(() => evalNode(node.body, local, phi2, budget));
|
|
4562
4696
|
if (bodyR.returned || bodyR.threw) return bodyR;
|
|
4563
4697
|
if (bodyR.brk) {
|
|
4564
4698
|
local = bodyR.env;
|
|
@@ -4573,7 +4707,7 @@ function evalDoWhile(node, env, phi2, budget) {
|
|
|
4573
4707
|
let local = env;
|
|
4574
4708
|
let acc = unknown;
|
|
4575
4709
|
for (let i = 0; i < MAX_LOOP_ITERS; i++) {
|
|
4576
|
-
const bodyR = evalNode(node.body, local, phi2, budget);
|
|
4710
|
+
const bodyR = evalInConditionalFlow(() => evalNode(node.body, local, phi2, budget));
|
|
4577
4711
|
if (bodyR.returned || bodyR.threw) return bodyR;
|
|
4578
4712
|
if (bodyR.brk) {
|
|
4579
4713
|
local = bodyR.env;
|
|
@@ -4610,7 +4744,7 @@ function evalForOf(node, env, phi2, budget) {
|
|
|
4610
4744
|
const n = Math.min(elements.length, MAX_LOOP_ITERS);
|
|
4611
4745
|
for (let i = 0; i < n; i++) {
|
|
4612
4746
|
local = withVar(local, bindName, elements[i]);
|
|
4613
|
-
const bodyR = evalNode(node.body, local, phi2, budget);
|
|
4747
|
+
const bodyR = evalInConditionalFlow(() => evalNode(node.body, local, phi2, budget));
|
|
4614
4748
|
if (bodyR.returned || bodyR.threw) return bodyR;
|
|
4615
4749
|
if (bodyR.brk) {
|
|
4616
4750
|
local = bodyR.env;
|
|
@@ -4661,6 +4795,7 @@ function evalVarDecl(node, env, phi2, budget) {
|
|
|
4661
4795
|
for (const d of node.declarations) {
|
|
4662
4796
|
if (d.id.type !== "Identifier" || !d.init) continue;
|
|
4663
4797
|
const r = evalNode(d.init, local, phi2, budget);
|
|
4798
|
+
recordAbsNode(d.id, r.value);
|
|
4664
4799
|
local = withVar(local, d.id.name, r.value);
|
|
4665
4800
|
}
|
|
4666
4801
|
return { value: unknown, phi: phi2, env: local };
|
|
@@ -4668,8 +4803,15 @@ function evalVarDecl(node, env, phi2, budget) {
|
|
|
4668
4803
|
function evalIf(node, env, phi2, budget) {
|
|
4669
4804
|
const t = evalNode(node.test, env, phi2, budget).value;
|
|
4670
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
|
+
};
|
|
4671
4813
|
if (tv === true) {
|
|
4672
|
-
return evalNode(node.consequent,
|
|
4814
|
+
return evalNode(node.consequent, refineEnv("true"), phi2, budget);
|
|
4673
4815
|
}
|
|
4674
4816
|
if (tv === false) {
|
|
4675
4817
|
if (node.alternate) return evalNode(node.alternate, env, phi2, budget);
|
|
@@ -4677,9 +4819,15 @@ function evalIf(node, env, phi2, budget) {
|
|
|
4677
4819
|
}
|
|
4678
4820
|
const tCons = trueConstraint(t);
|
|
4679
4821
|
const fCons = falseConstraint(t);
|
|
4680
|
-
const
|
|
4681
|
-
|
|
4682
|
-
|
|
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
|
+
);
|
|
4683
4831
|
return { value: joinAbs(a.value, b.value), phi: phi2, env, returned: a.returned || b.returned };
|
|
4684
4832
|
}
|
|
4685
4833
|
if (a.returned || a.threw) {
|
|
@@ -4814,6 +4962,15 @@ function $call(fn, args) {
|
|
|
4814
4962
|
|
|
4815
4963
|
// src/algebra/exec/calls.ts
|
|
4816
4964
|
var bCallCollector = null;
|
|
4965
|
+
var GLOBAL_FNS = /* @__PURE__ */ new Set([
|
|
4966
|
+
"parseInt",
|
|
4967
|
+
"parseFloat",
|
|
4968
|
+
"isNaN",
|
|
4969
|
+
"isFinite",
|
|
4970
|
+
"Number",
|
|
4971
|
+
"String",
|
|
4972
|
+
"Boolean"
|
|
4973
|
+
]);
|
|
4817
4974
|
function setBCallCollector(collector) {
|
|
4818
4975
|
bCallCollector = collector;
|
|
4819
4976
|
}
|
|
@@ -4832,7 +4989,8 @@ function $callNamed(name, fn, args, loc, argLocs) {
|
|
|
4832
4989
|
if (loc) pushCallLoc({ line: loc[0], column: loc[1] });
|
|
4833
4990
|
try {
|
|
4834
4991
|
if (typeof fn === "function") {
|
|
4835
|
-
|
|
4992
|
+
const g = GLOBAL_FNS.has(name) && fn === globalThis[name] ? evalGlobalFn(name, args) : void 0;
|
|
4993
|
+
result = g ?? fn(...args);
|
|
4836
4994
|
} else if (fn && typeof fn === "object" && "shape" in fn) {
|
|
4837
4995
|
result = $call(fn, args);
|
|
4838
4996
|
}
|
|
@@ -4955,12 +5113,32 @@ function litAbsFromJs(v2) {
|
|
|
4955
5113
|
}
|
|
4956
5114
|
return unknown;
|
|
4957
5115
|
}
|
|
5116
|
+
function litTruth(a) {
|
|
5117
|
+
if (a.term?.op === "lit") {
|
|
5118
|
+
return Boolean(a.term.value);
|
|
5119
|
+
}
|
|
5120
|
+
switch (a.shape.k) {
|
|
5121
|
+
case "obj":
|
|
5122
|
+
case "arr":
|
|
5123
|
+
case "tuple":
|
|
5124
|
+
case "fn":
|
|
5125
|
+
case "brand":
|
|
5126
|
+
case "eff":
|
|
5127
|
+
return true;
|
|
5128
|
+
case "prim":
|
|
5129
|
+
return a.shape.type === "symbol" || a.shape.type === "bigint" ? true : void 0;
|
|
5130
|
+
case "never":
|
|
5131
|
+
return false;
|
|
5132
|
+
default:
|
|
5133
|
+
return void 0;
|
|
5134
|
+
}
|
|
5135
|
+
}
|
|
4958
5136
|
function isDefinitelyTrue(a) {
|
|
4959
|
-
return
|
|
5137
|
+
return litTruth(a) === true;
|
|
4960
5138
|
}
|
|
4961
5139
|
function isDefinitelyFalse(a) {
|
|
4962
|
-
const
|
|
4963
|
-
if (
|
|
5140
|
+
const t = litTruth(a);
|
|
5141
|
+
if (t === false) return true;
|
|
4964
5142
|
if (a.shape.k === "never") return true;
|
|
4965
5143
|
return false;
|
|
4966
5144
|
}
|
|
@@ -5013,8 +5191,19 @@ function $for(init, test, step, body, maxIters = DEFAULT_MAX_LOOP_ITERS) {
|
|
|
5013
5191
|
}
|
|
5014
5192
|
return exitJoin ? joinAbs(exitJoin, state) : state;
|
|
5015
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
|
+
}
|
|
5016
5205
|
function $arr(items) {
|
|
5017
|
-
return
|
|
5206
|
+
return tupleOrWiden(items.map(asAbsVal), "exact");
|
|
5018
5207
|
}
|
|
5019
5208
|
function $idx(a, i) {
|
|
5020
5209
|
const iv = litValue(i);
|
|
@@ -5031,17 +5220,31 @@ function $idx(a, i) {
|
|
|
5031
5220
|
if (a.shape.k === "sum") {
|
|
5032
5221
|
return a.shape.members.map((m) => $idx(m, i)).reduce((x, y) => joinAbs(x, y));
|
|
5033
5222
|
}
|
|
5223
|
+
const sv = litValue(a);
|
|
5224
|
+
if (typeof sv === "string") {
|
|
5225
|
+
if (typeof iv === "number" && Number.isInteger(iv)) {
|
|
5226
|
+
if (iv >= 0 && iv < sv.length) {
|
|
5227
|
+
return abs(
|
|
5228
|
+
{ k: "prim", type: "string" },
|
|
5229
|
+
{ op: "lit", value: sv[iv] },
|
|
5230
|
+
pTrue,
|
|
5231
|
+
"exact"
|
|
5232
|
+
);
|
|
5233
|
+
}
|
|
5234
|
+
return undef();
|
|
5235
|
+
}
|
|
5236
|
+
return unknown;
|
|
5237
|
+
}
|
|
5034
5238
|
return unknown;
|
|
5035
5239
|
}
|
|
5036
5240
|
function $idxSet(a, i, value) {
|
|
5037
5241
|
const iv = litValue(i);
|
|
5038
|
-
if (a.shape.k === "tuple" && typeof iv === "number" && Number.isInteger(iv)) {
|
|
5242
|
+
if (a.shape.k === "tuple" && typeof iv === "number" && Number.isInteger(iv) && iv >= 0) {
|
|
5039
5243
|
const els = [...a.shape.elements];
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
}
|
|
5244
|
+
while (els.length < iv) els.push(undef());
|
|
5245
|
+
els[iv] = asAbsVal(value);
|
|
5246
|
+
const next = abs({ k: "tuple", elements: els }, void 0, void 0, a.conf);
|
|
5247
|
+
return next;
|
|
5045
5248
|
}
|
|
5046
5249
|
return a;
|
|
5047
5250
|
}
|
|
@@ -5057,6 +5260,15 @@ function $len(a) {
|
|
|
5057
5260
|
if (a.shape.k === "arr") {
|
|
5058
5261
|
return abs({ k: "prim", type: "number" }, void 0, void 0, "path");
|
|
5059
5262
|
}
|
|
5263
|
+
const sv = litValue(a);
|
|
5264
|
+
if (typeof sv === "string") {
|
|
5265
|
+
return abs(
|
|
5266
|
+
{ k: "prim", type: "number" },
|
|
5267
|
+
{ op: "lit", value: sv.length },
|
|
5268
|
+
pTrue,
|
|
5269
|
+
"exact"
|
|
5270
|
+
);
|
|
5271
|
+
}
|
|
5060
5272
|
return unknown;
|
|
5061
5273
|
}
|
|
5062
5274
|
function $obj(slots) {
|
|
@@ -5070,33 +5282,33 @@ function $spread(a, b) {
|
|
|
5070
5282
|
function $concat(a, b) {
|
|
5071
5283
|
a = asAbsVal(a);
|
|
5072
5284
|
b = asAbsVal(b);
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
);
|
|
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");
|
|
5080
5294
|
}
|
|
5081
|
-
if (
|
|
5295
|
+
if (as.k === "tuple") {
|
|
5082
5296
|
return abs(
|
|
5083
|
-
{ k: "tuple", elements: [...
|
|
5297
|
+
{ k: "tuple", elements: [...as.elements, b] },
|
|
5084
5298
|
void 0,
|
|
5085
5299
|
void 0,
|
|
5086
5300
|
confJoin(a.conf, b.conf)
|
|
5087
5301
|
);
|
|
5088
5302
|
}
|
|
5089
|
-
if (
|
|
5303
|
+
if (bs.k === "tuple") {
|
|
5090
5304
|
return abs(
|
|
5091
|
-
{ k: "tuple", elements: [a, ...
|
|
5305
|
+
{ k: "tuple", elements: [a, ...bs.elements] },
|
|
5092
5306
|
void 0,
|
|
5093
5307
|
void 0,
|
|
5094
5308
|
confJoin(a.conf, b.conf)
|
|
5095
5309
|
);
|
|
5096
5310
|
}
|
|
5097
|
-
|
|
5098
|
-
const eb = b.shape.k === "arr" ? b.shape.element : b;
|
|
5099
|
-
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");
|
|
5100
5312
|
}
|
|
5101
5313
|
function $elems(a) {
|
|
5102
5314
|
if (a.shape.k === "tuple") return [...a.shape.elements];
|
|
@@ -5116,7 +5328,52 @@ function $forOf(iterable, body, maxIters = DEFAULT_MAX_LOOP_ITERS) {
|
|
|
5116
5328
|
));
|
|
5117
5329
|
}
|
|
5118
5330
|
}
|
|
5331
|
+
function namespaceNameOf(v2) {
|
|
5332
|
+
if (typeof v2 !== "object" && typeof v2 !== "function") return void 0;
|
|
5333
|
+
if (v2 === Math) return "Math";
|
|
5334
|
+
if (v2 === Number) return "Number";
|
|
5335
|
+
if (v2 === JSON) return "JSON";
|
|
5336
|
+
if (v2 === Object) return "Object";
|
|
5337
|
+
if (v2 === Array) return "Array";
|
|
5338
|
+
if (v2 === Date) return "Date";
|
|
5339
|
+
if (v2 === Promise) return "Promise";
|
|
5340
|
+
return void 0;
|
|
5341
|
+
}
|
|
5342
|
+
function $regex(pattern, flags = "") {
|
|
5343
|
+
const litStr = (v2) => abs({ k: "prim", type: "string" }, { op: "lit", value: v2 }, pTrue, "exact");
|
|
5344
|
+
return abs(
|
|
5345
|
+
{
|
|
5346
|
+
k: "brand",
|
|
5347
|
+
name: "RegExp",
|
|
5348
|
+
shape: objOf({
|
|
5349
|
+
source: { value: litStr(pattern) },
|
|
5350
|
+
flags: { value: litStr(flags) }
|
|
5351
|
+
})
|
|
5352
|
+
},
|
|
5353
|
+
void 0,
|
|
5354
|
+
void 0,
|
|
5355
|
+
"exact"
|
|
5356
|
+
);
|
|
5357
|
+
}
|
|
5119
5358
|
function $get(o, key, opts) {
|
|
5359
|
+
if (!o || typeof o !== "object" || !("shape" in o)) {
|
|
5360
|
+
const ns = namespaceNameOf(o);
|
|
5361
|
+
if (ns) {
|
|
5362
|
+
try {
|
|
5363
|
+
const raw = o[key];
|
|
5364
|
+
if (typeof raw === "function") {
|
|
5365
|
+
return absFunction([`${ns}.${key}`], {
|
|
5366
|
+
body: noBody,
|
|
5367
|
+
apply: (args) => evalNamespaceCall(ns, key, args) ?? unknown
|
|
5368
|
+
});
|
|
5369
|
+
}
|
|
5370
|
+
return $lit(raw);
|
|
5371
|
+
} catch {
|
|
5372
|
+
return unknown;
|
|
5373
|
+
}
|
|
5374
|
+
}
|
|
5375
|
+
return unknown;
|
|
5376
|
+
}
|
|
5120
5377
|
if (o.shape.k === "brand") return $get(o.shape.shape, key, opts);
|
|
5121
5378
|
if (isObj(o)) {
|
|
5122
5379
|
const slot = o.shape.slots[key];
|
|
@@ -5302,6 +5559,77 @@ var BIN_OPS = {
|
|
|
5302
5559
|
"===": "$eq",
|
|
5303
5560
|
"!==": "$ne"
|
|
5304
5561
|
};
|
|
5562
|
+
var COMPOUND_OPS = {
|
|
5563
|
+
"+=": "$add",
|
|
5564
|
+
"-=": "$sub",
|
|
5565
|
+
"*=": "$mul",
|
|
5566
|
+
"/=": "$div",
|
|
5567
|
+
"%=": "$mod"
|
|
5568
|
+
};
|
|
5569
|
+
function memberPathOf(m, opts) {
|
|
5570
|
+
const layers = [];
|
|
5571
|
+
let cur = m;
|
|
5572
|
+
let rootSrc = null;
|
|
5573
|
+
while (cur.type === "MemberExpression") {
|
|
5574
|
+
const mm = cur;
|
|
5575
|
+
const k = mm.property;
|
|
5576
|
+
if (mm.computed) {
|
|
5577
|
+
if (k.type === "NumericLiteral") {
|
|
5578
|
+
const key = `$lit(${k.value})`;
|
|
5579
|
+
layers.unshift({
|
|
5580
|
+
get: (b) => `$idx(${b}, ${key})`,
|
|
5581
|
+
set: (b, v2) => `$idxSet(${b}, ${key}, ${v2})`
|
|
5582
|
+
});
|
|
5583
|
+
} else if (k.type === "StringLiteral") {
|
|
5584
|
+
const key = JSON.stringify(k.value);
|
|
5585
|
+
layers.unshift({
|
|
5586
|
+
get: (b) => `$get(${b}, ${key})`,
|
|
5587
|
+
set: (b, v2) => `$set(${b}, ${key}, ${v2})`
|
|
5588
|
+
});
|
|
5589
|
+
} else if (isExpression(k)) {
|
|
5590
|
+
const key = transpileExpression(k, opts);
|
|
5591
|
+
layers.unshift({
|
|
5592
|
+
get: (b) => `$idx(${b}, ${key})`,
|
|
5593
|
+
set: (b, v2) => `$idxSet(${b}, ${key}, ${v2})`
|
|
5594
|
+
});
|
|
5595
|
+
} else {
|
|
5596
|
+
return null;
|
|
5597
|
+
}
|
|
5598
|
+
} else if (k.type === "Identifier") {
|
|
5599
|
+
const key = JSON.stringify(k.name);
|
|
5600
|
+
layers.unshift({
|
|
5601
|
+
get: (b) => `$get(${b}, ${key})`,
|
|
5602
|
+
set: (b, v2) => `$set(${b}, ${key}, ${v2})`
|
|
5603
|
+
});
|
|
5604
|
+
} else {
|
|
5605
|
+
return null;
|
|
5606
|
+
}
|
|
5607
|
+
cur = mm.object;
|
|
5608
|
+
}
|
|
5609
|
+
if (cur.type === "Identifier") {
|
|
5610
|
+
rootSrc = cur.name;
|
|
5611
|
+
} else if (cur.type === "ThisExpression" && opts.thisParam) {
|
|
5612
|
+
rootSrc = opts.thisParam;
|
|
5613
|
+
} else {
|
|
5614
|
+
return null;
|
|
5615
|
+
}
|
|
5616
|
+
return { rootSrc, layers };
|
|
5617
|
+
}
|
|
5618
|
+
function readPathSrc(p) {
|
|
5619
|
+
return p.layers.reduce((acc, l) => l.get(acc), p.rootSrc);
|
|
5620
|
+
}
|
|
5621
|
+
function setPathSrc(p, valSrc) {
|
|
5622
|
+
let acc = valSrc;
|
|
5623
|
+
for (let i = p.layers.length - 1; i >= 0; i--) {
|
|
5624
|
+
const l = p.layers[i];
|
|
5625
|
+
const base = i === 0 ? p.rootSrc : readPrefix(p, i - 1);
|
|
5626
|
+
acc = l.set(base, acc);
|
|
5627
|
+
}
|
|
5628
|
+
return acc;
|
|
5629
|
+
}
|
|
5630
|
+
function readPrefix(p, j) {
|
|
5631
|
+
return p.layers.slice(0, j + 1).reduce((acc, l) => l.get(acc), p.rootSrc);
|
|
5632
|
+
}
|
|
5305
5633
|
function transpileSource(source, opts = {}) {
|
|
5306
5634
|
const file = parseSource(source);
|
|
5307
5635
|
return transpileFile(file, { ...opts, source: opts.source ?? source });
|
|
@@ -5310,7 +5638,7 @@ function transpileFile(file, opts = {}) {
|
|
|
5310
5638
|
const runtime = opts.runtimeImport ?? "@nudojs/core/exec";
|
|
5311
5639
|
const lines = [
|
|
5312
5640
|
`// nudo B-path transpile \u2014 values are Abs; operators are overloaded calls`,
|
|
5313
|
-
`import { $add, $sub, $mul, $div, $mod, $neg, $typeof, $not, $eq, $ne, $lt, $le, $gt, $ge, $join, $lit, $fork, $for, $forIter, $obj, $get, $set, $while, $whileSeq, $arr, $idx, $idxSet, $len, $call, $throw, $class, $new, $invoke, $invokeSuper, $super, $async, $await, $asyncReturn, $orDefault, $callNamed, $optionalGet, $optionalInvoke, $spread, $concat, $forOf, $catchVal, $switch, $staticInvoke, $setKey, $gen, $yield, $fnVal } from ${JSON.stringify(runtime)};`,
|
|
5641
|
+
`import { $add, $sub, $mul, $div, $mod, $neg, $typeof, $not, $eq, $ne, $lt, $le, $gt, $ge, $join, $lit, $fork, $for, $forIter, $obj, $get, $set, $while, $whileSeq, $arr, $idx, $idxSet, $len, $call, $throw, $class, $new, $invoke, $invokeSuper, $super, $async, $await, $asyncReturn, $orDefault, $callNamed, $optionalGet, $optionalInvoke, $spread, $concat, $forOf, $catchVal, $switch, $staticInvoke, $setKey, $gen, $yield, $fnVal, $regex } from ${JSON.stringify(runtime)};`,
|
|
5314
5642
|
``
|
|
5315
5643
|
];
|
|
5316
5644
|
for (const stmt of file.program.body) {
|
|
@@ -5329,34 +5657,24 @@ function stmtReturns(stmt) {
|
|
|
5329
5657
|
}
|
|
5330
5658
|
return false;
|
|
5331
5659
|
}
|
|
5332
|
-
function
|
|
5333
|
-
|
|
5334
|
-
}
|
|
5335
|
-
function foldEarlyReturns(stmts) {
|
|
5336
|
-
for (let i = stmts.length - 2; i >= 0; i--) {
|
|
5660
|
+
function transpileFnBodyStmts(stmts, depth, opts) {
|
|
5661
|
+
for (let i = 0; i < stmts.length; i++) {
|
|
5337
5662
|
const stmt = stmts[i];
|
|
5338
5663
|
if (stmt.type !== "IfStatement" || stmt.alternate != null) continue;
|
|
5339
5664
|
if (!stmtReturns(stmt.consequent)) continue;
|
|
5340
|
-
const
|
|
5341
|
-
if (
|
|
5342
|
-
const
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
}
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
};
|
|
5354
|
-
return foldEarlyReturns([...stmts.slice(0, i), rewritten]);
|
|
5355
|
-
}
|
|
5356
|
-
return stmts;
|
|
5357
|
-
}
|
|
5358
|
-
function transpileFnBodyStmts(stmts, depth, opts) {
|
|
5359
|
-
return foldEarlyReturns(stmts).map((s) => transpileStatement(s, depth, opts)).join("\n");
|
|
5665
|
+
const rest = stmts.slice(i + 1);
|
|
5666
|
+
if (rest.length === 0) continue;
|
|
5667
|
+
const head = stmts.slice(0, i).map((s) => transpileStatement(s, depth, opts)).join("\n");
|
|
5668
|
+
const test = transpileExpression(stmt.test, opts);
|
|
5669
|
+
const cons = transpileBlockAsThunk(stmt.consequent, depth, opts);
|
|
5670
|
+
const altBody = transpileFnBodyStmts(rest, depth + 1, opts);
|
|
5671
|
+
const promoted = `${indent(depth)}return $fork(${test}, ${cons}, () => {
|
|
5672
|
+
${altBody}
|
|
5673
|
+
${indent(depth)}});`;
|
|
5674
|
+
return head ? `${head}
|
|
5675
|
+
${promoted}` : promoted;
|
|
5676
|
+
}
|
|
5677
|
+
return stmts.map((s) => transpileStatement(s, depth, opts)).join("\n");
|
|
5360
5678
|
}
|
|
5361
5679
|
function emitDestructure(pattern, fromSrc, kw, pad, opts, out, tmpSeq) {
|
|
5362
5680
|
if (pattern.type === "Identifier") {
|
|
@@ -5422,13 +5740,55 @@ function emitDestructure(pattern, fromSrc, kw, pad, opts, out, tmpSeq) {
|
|
|
5422
5740
|
});
|
|
5423
5741
|
}
|
|
5424
5742
|
}
|
|
5743
|
+
function emitParamBinding(params, pad, opts) {
|
|
5744
|
+
const sig = [];
|
|
5745
|
+
const prologue = [];
|
|
5746
|
+
let rest;
|
|
5747
|
+
params.forEach((p, i) => {
|
|
5748
|
+
if (p.type === "Identifier") {
|
|
5749
|
+
sig.push(p.name);
|
|
5750
|
+
return;
|
|
5751
|
+
}
|
|
5752
|
+
if (p.type === "RestElement") {
|
|
5753
|
+
if (p.argument.type === "Identifier") {
|
|
5754
|
+
rest = p.argument.name;
|
|
5755
|
+
return;
|
|
5756
|
+
}
|
|
5757
|
+
const ph2 = `_rest${i}`;
|
|
5758
|
+
rest = ph2;
|
|
5759
|
+
emitDestructure(p.argument, ph2, "const", pad, opts, prologue, { n: 0 });
|
|
5760
|
+
return;
|
|
5761
|
+
}
|
|
5762
|
+
const ph = `_p${i}`;
|
|
5763
|
+
sig.push(ph);
|
|
5764
|
+
if (p.type === "AssignmentPattern") {
|
|
5765
|
+
const def = transpileExpression(p.right, opts);
|
|
5766
|
+
if (p.left.type === "Identifier") {
|
|
5767
|
+
prologue.push(`${pad}const ${p.left.name} = $orDefault(${ph}, () => ${def});`);
|
|
5768
|
+
} else {
|
|
5769
|
+
const t = `_pd${i}`;
|
|
5770
|
+
prologue.push(`${pad}const ${t} = $orDefault(${ph}, () => ${def});`);
|
|
5771
|
+
emitDestructure(p.left, t, "const", pad, opts, prologue, { n: 0 });
|
|
5772
|
+
}
|
|
5773
|
+
return;
|
|
5774
|
+
}
|
|
5775
|
+
if (p.type === "ObjectPattern" || p.type === "ArrayPattern") {
|
|
5776
|
+
emitDestructure(p, ph, "const", pad, opts, prologue, { n: 0 });
|
|
5777
|
+
}
|
|
5778
|
+
});
|
|
5779
|
+
return { sig, rest, prologue };
|
|
5780
|
+
}
|
|
5425
5781
|
function transpileStatement(stmt, depth, opts) {
|
|
5426
5782
|
const pad = indent(depth);
|
|
5427
5783
|
switch (stmt.type) {
|
|
5428
5784
|
case "ExportNamedDeclaration": {
|
|
5429
5785
|
const decl = stmt.declaration;
|
|
5430
5786
|
if (!decl) return `${pad}/* export specifiers skipped */`;
|
|
5431
|
-
|
|
5787
|
+
const inner = transpileStatement(decl, depth, opts);
|
|
5788
|
+
if (depth === 0 && decl.type === "VariableDeclaration" && !pad) {
|
|
5789
|
+
return `export ${inner}`;
|
|
5790
|
+
}
|
|
5791
|
+
return inner;
|
|
5432
5792
|
}
|
|
5433
5793
|
case "ImportDeclaration": {
|
|
5434
5794
|
const specs = stmt.specifiers.map((s) => {
|
|
@@ -5455,19 +5815,16 @@ function transpileStatement(stmt, depth, opts) {
|
|
|
5455
5815
|
}
|
|
5456
5816
|
case "FunctionDeclaration": {
|
|
5457
5817
|
if (!stmt.id) return `${pad}// <anonymous fn skipped>`;
|
|
5458
|
-
const
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
}
|
|
5465
|
-
const named = paramParts.filter((p) => p.kind === "id" && p.name !== "_").map((p) => p.name);
|
|
5466
|
-
const rest = paramParts.find((p) => p.kind === "rest");
|
|
5467
|
-
const paramsSig = rest ? [...named, `...${rest.name}`] : named;
|
|
5818
|
+
const { sig, rest, prologue } = emitParamBinding(
|
|
5819
|
+
stmt.params,
|
|
5820
|
+
indent(depth + 2),
|
|
5821
|
+
opts
|
|
5822
|
+
);
|
|
5823
|
+
const named = sig;
|
|
5824
|
+
const paramsSig = rest ? [...named, `...${rest}`] : named;
|
|
5468
5825
|
const params = paramsSig.join(", ");
|
|
5469
|
-
const bodyStmts = stmt.body.type === "BlockStatement" ? transpileFnBodyStmts(stmt.body.body, depth + 2, opts) : `${indent(depth + 2)}return ${transpileExpression(stmt.body, opts)};`;
|
|
5470
|
-
const restBind = rest ? `${indent(depth + 1)}const ${rest
|
|
5826
|
+
const bodyStmts = stmt.body.type === "BlockStatement" ? [...prologue, transpileFnBodyStmts(stmt.body.body, depth + 2, opts)].join("\n") : `${indent(depth + 2)}return ${transpileExpression(stmt.body, opts)};`;
|
|
5827
|
+
const restBind = rest ? `${indent(depth + 1)}const ${rest} = arguments.length > ${named.length} ? $arr(Array.from(arguments).slice(${named.length})) : $arr([]);
|
|
5471
5828
|
` : "";
|
|
5472
5829
|
if (stmt.generator) {
|
|
5473
5830
|
return [
|
|
@@ -5509,7 +5866,7 @@ function transpileStatement(stmt, depth, opts) {
|
|
|
5509
5866
|
case "ExpressionStatement":
|
|
5510
5867
|
return `${pad}${transpileExpression(stmt.expression, opts)};`;
|
|
5511
5868
|
case "VariableDeclaration": {
|
|
5512
|
-
const kw =
|
|
5869
|
+
const kw = "let";
|
|
5513
5870
|
const asVar = matchAsOverride(stmt, opts);
|
|
5514
5871
|
const lines = [];
|
|
5515
5872
|
let tmpSeq = 0;
|
|
@@ -5562,7 +5919,7 @@ function transpileStatement(stmt, depth, opts) {
|
|
|
5562
5919
|
].join("\n");
|
|
5563
5920
|
}
|
|
5564
5921
|
case "BlockStatement":
|
|
5565
|
-
return stmt.body
|
|
5922
|
+
return transpileFnBodyStmts(stmt.body, depth, opts);
|
|
5566
5923
|
case "SwitchStatement": {
|
|
5567
5924
|
const disc = transpileExpression(stmt.discriminant, opts);
|
|
5568
5925
|
const arms = [];
|
|
@@ -5822,6 +6179,15 @@ function transpileExpression(expr, opts = {}) {
|
|
|
5822
6179
|
const r = transpileExpression(expr.right, opts);
|
|
5823
6180
|
return op === "&&" ? `$fork(${l}, () => ${r}, () => ${l})` : `$fork(${l}, () => ${l}, () => ${r})`;
|
|
5824
6181
|
}
|
|
6182
|
+
case "ConditionalExpression": {
|
|
6183
|
+
const test = transpileExpression(expr.test, opts);
|
|
6184
|
+
const c = transpileExpression(expr.consequent, opts);
|
|
6185
|
+
const a = transpileExpression(expr.alternate, opts);
|
|
6186
|
+
return `$fork(${test}, () => ${c}, () => ${a})`;
|
|
6187
|
+
}
|
|
6188
|
+
case "RegExpLiteral": {
|
|
6189
|
+
return `$regex(${JSON.stringify(expr.pattern)}${expr.flags ? `, ${JSON.stringify(expr.flags)}` : ""})`;
|
|
6190
|
+
}
|
|
5825
6191
|
case "BinaryExpression": {
|
|
5826
6192
|
const fn = BIN_OPS[expr.operator];
|
|
5827
6193
|
if (!fn) return `/* unsupported ${expr.operator} */ $lit(undefined)`;
|
|
@@ -5837,6 +6203,14 @@ function transpileExpression(expr, opts = {}) {
|
|
|
5837
6203
|
if (expr.operator === "+") return arg;
|
|
5838
6204
|
return `/* unary ${expr.operator} */ $lit(undefined)`;
|
|
5839
6205
|
}
|
|
6206
|
+
case "UpdateExpression": {
|
|
6207
|
+
const arg = expr.argument;
|
|
6208
|
+
if (arg.type === "Identifier") {
|
|
6209
|
+
const fn = expr.operator === "++" ? "$add" : "$sub";
|
|
6210
|
+
return `${arg.name} = ${fn}(${arg.name}, $lit(1))`;
|
|
6211
|
+
}
|
|
6212
|
+
return `/* update ${expr.operator} */ $lit(undefined)`;
|
|
6213
|
+
}
|
|
5840
6214
|
case "AwaitExpression": {
|
|
5841
6215
|
const arg = transpileExpression(expr.argument, opts);
|
|
5842
6216
|
return `$await(${arg})`;
|
|
@@ -5938,19 +6312,23 @@ function transpileExpression(expr, opts = {}) {
|
|
|
5938
6312
|
return acc ?? `$arr([])`;
|
|
5939
6313
|
}
|
|
5940
6314
|
case "AssignmentExpression": {
|
|
5941
|
-
|
|
6315
|
+
const compoundFn = COMPOUND_OPS[expr.operator];
|
|
5942
6316
|
const right = transpileExpression(expr.right, opts);
|
|
5943
6317
|
if (expr.left.type === "MemberExpression") {
|
|
5944
|
-
|
|
5945
|
-
|
|
6318
|
+
const m = expr.left;
|
|
6319
|
+
const path = memberPathOf(m, opts);
|
|
6320
|
+
if (path) {
|
|
6321
|
+
const valSrc = compoundFn ? `${compoundFn}(${readPathSrc(path)}, ${right})` : right;
|
|
6322
|
+
const writeSrc = setPathSrc(path, valSrc);
|
|
6323
|
+
return `${path.rootSrc} = ${writeSrc}`;
|
|
5946
6324
|
}
|
|
5947
|
-
if (!
|
|
5948
|
-
const obj2 = transpileExpression(
|
|
5949
|
-
return `$set(${obj2}, ${JSON.stringify(
|
|
6325
|
+
if (!m.computed && m.property.type === "Identifier") {
|
|
6326
|
+
const obj2 = transpileExpression(m.object, opts);
|
|
6327
|
+
return `$set(${obj2}, ${JSON.stringify(m.property.name)}, ${right})`;
|
|
5950
6328
|
}
|
|
5951
|
-
if (
|
|
5952
|
-
const obj2 = transpileExpression(
|
|
5953
|
-
const k =
|
|
6329
|
+
if (m.computed) {
|
|
6330
|
+
const obj2 = transpileExpression(m.object, opts);
|
|
6331
|
+
const k = m.property;
|
|
5954
6332
|
if (k.type === "NumericLiteral") {
|
|
5955
6333
|
return `$idxSet(${obj2}, $lit(${k.value}), ${right})`;
|
|
5956
6334
|
}
|
|
@@ -5961,11 +6339,15 @@ function transpileExpression(expr, opts = {}) {
|
|
|
5961
6339
|
return `$idxSet(${obj2}, ${transpileExpression(k, opts)}, ${right})`;
|
|
5962
6340
|
}
|
|
5963
6341
|
}
|
|
6342
|
+
return `/* assign */ $lit(undefined)`;
|
|
5964
6343
|
}
|
|
5965
6344
|
if (expr.left.type === "Identifier") {
|
|
6345
|
+
if (compoundFn) {
|
|
6346
|
+
return `${expr.left.name} = ${compoundFn}(${expr.left.name}, ${right})`;
|
|
6347
|
+
}
|
|
5966
6348
|
return `${expr.left.name} = ${right}`;
|
|
5967
6349
|
}
|
|
5968
|
-
return `/* assign */ $lit(undefined)`;
|
|
6350
|
+
return compoundFn ? `/* assign ${expr.operator} */ $lit(undefined)` : `/* assign */ $lit(undefined)`;
|
|
5969
6351
|
}
|
|
5970
6352
|
case "CallExpression":
|
|
5971
6353
|
case "OptionalCallExpression": {
|
|
@@ -6020,16 +6402,11 @@ function transpileExpression(expr, opts = {}) {
|
|
|
6020
6402
|
case "ArrowFunctionExpression":
|
|
6021
6403
|
case "FunctionExpression": {
|
|
6022
6404
|
const fn = expr;
|
|
6023
|
-
const
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
return `...${p.argument.name}`;
|
|
6027
|
-
}
|
|
6028
|
-
return "_p";
|
|
6029
|
-
});
|
|
6030
|
-
const nameList = `[${paramParts.map((p) => JSON.stringify(p.startsWith("...") ? p.slice(3) : p)).join(", ")}]`;
|
|
6405
|
+
const { sig, rest, prologue } = emitParamBinding(fn.params, indent(1), opts);
|
|
6406
|
+
const paramParts = rest ? [...sig, `...${rest}`] : sig;
|
|
6407
|
+
const nameList = `[${sig.map((p) => JSON.stringify(p)).join(", ")}]`;
|
|
6031
6408
|
if (fn.body.type === "BlockStatement") {
|
|
6032
|
-
const inner = transpileFnBodyStmts(fn.body.body, 1, opts);
|
|
6409
|
+
const inner = [...prologue, transpileFnBodyStmts(fn.body.body, 1, opts)].join("\n");
|
|
6033
6410
|
if (fn.async) {
|
|
6034
6411
|
return `$fnVal(${nameList}, (${paramParts.join(", ")}) => $async(() => {
|
|
6035
6412
|
${inner}
|
|
@@ -6040,6 +6417,13 @@ ${inner}
|
|
|
6040
6417
|
})`;
|
|
6041
6418
|
}
|
|
6042
6419
|
const bodySrc = transpileExpression(fn.body, opts);
|
|
6420
|
+
if (prologue.length > 0) {
|
|
6421
|
+
const thunk = fn.async ? `$async(() => ${bodySrc})` : bodySrc;
|
|
6422
|
+
return `$fnVal(${nameList}, (${paramParts.join(", ")}) => {
|
|
6423
|
+
${prologue.join("\n")}
|
|
6424
|
+
return ${thunk};
|
|
6425
|
+
})`;
|
|
6426
|
+
}
|
|
6043
6427
|
if (fn.async) {
|
|
6044
6428
|
return `$fnVal(${nameList}, (${paramParts.join(", ")}) => $async(() => ${bodySrc}))`;
|
|
6045
6429
|
}
|
|
@@ -6128,6 +6512,21 @@ function findCtor(startName) {
|
|
|
6128
6512
|
}
|
|
6129
6513
|
function $new(cls, args) {
|
|
6130
6514
|
if (typeof cls === "function") {
|
|
6515
|
+
if (cls === Array) {
|
|
6516
|
+
if (args.length === 1) {
|
|
6517
|
+
const n = litValue(args[0]);
|
|
6518
|
+
if (typeof n === "number" && Number.isInteger(n) && n >= 0 && n <= 4096) {
|
|
6519
|
+
const els = Array.from({ length: n }, () => undefAbs());
|
|
6520
|
+
return abs({ k: "tuple", elements: els }, void 0, void 0, "exact");
|
|
6521
|
+
}
|
|
6522
|
+
return abs({ k: "arr", element: unknown }, void 0, void 0, "partial");
|
|
6523
|
+
}
|
|
6524
|
+
return abs({ k: "tuple", elements: args.map((a) => asAbs(a) ?? unknown) }, void 0, void 0, "exact");
|
|
6525
|
+
}
|
|
6526
|
+
if (cls === RegExp) {
|
|
6527
|
+
const p = args[0] ? litValue(args[0]) : void 0;
|
|
6528
|
+
if (typeof p === "string") return $regex(p, args[1] ? String(litValue(args[1]) ?? "") : "");
|
|
6529
|
+
}
|
|
6131
6530
|
const name = cls.name || "Object";
|
|
6132
6531
|
const shape = objOf({});
|
|
6133
6532
|
return abs({ k: "brand", name, shape }, void 0, void 0, "path");
|
|
@@ -6168,12 +6567,82 @@ function $super(thisVal, childName, args) {
|
|
|
6168
6567
|
}
|
|
6169
6568
|
return after ?? thisVal;
|
|
6170
6569
|
}
|
|
6570
|
+
function execRegexBrand(re, method, args) {
|
|
6571
|
+
if (re.shape.k !== "brand" || re.shape.name !== "RegExp") return void 0;
|
|
6572
|
+
if (method !== "exec" && method !== "test" && method !== "toString") return void 0;
|
|
6573
|
+
const inner = re.shape.shape;
|
|
6574
|
+
const patAbs = inner.shape.k === "obj" ? inner.shape.slots["source"]?.value : void 0;
|
|
6575
|
+
const flagsAbs = inner.shape.k === "obj" ? inner.shape.slots["flags"]?.value : void 0;
|
|
6576
|
+
const pat = patAbs ? litValue(patAbs) : void 0;
|
|
6577
|
+
if (typeof pat !== "string") return void 0;
|
|
6578
|
+
const flagsV = flagsAbs ? litValue(flagsAbs) : void 0;
|
|
6579
|
+
const flags = typeof flagsV === "string" ? flagsV : "";
|
|
6580
|
+
if (method === "toString") return strLit(`/${pat}/${flags}`);
|
|
6581
|
+
const subject = args[0] ? litValue(args[0]) : void 0;
|
|
6582
|
+
if (typeof subject !== "string") {
|
|
6583
|
+
return method === "test" ? abs({ k: "prim", type: "boolean" }, void 0, void 0, "partial") : void 0;
|
|
6584
|
+
}
|
|
6585
|
+
let reReal;
|
|
6586
|
+
try {
|
|
6587
|
+
reReal = new RegExp(pat, flags);
|
|
6588
|
+
} catch {
|
|
6589
|
+
return void 0;
|
|
6590
|
+
}
|
|
6591
|
+
const m = reReal.exec(subject);
|
|
6592
|
+
if (method === "test") return boolLit(reReal.test(subject));
|
|
6593
|
+
if (!m) {
|
|
6594
|
+
return abs({ k: "unknown" }, { op: "lit", value: null }, void 0, "exact");
|
|
6595
|
+
}
|
|
6596
|
+
const els = m.map((g) => g === void 0 ? undefAbs() : strLit(g));
|
|
6597
|
+
return abs({ k: "tuple", elements: els }, void 0, void 0, "exact");
|
|
6598
|
+
}
|
|
6599
|
+
function stringRegexMethod(recv, method, args) {
|
|
6600
|
+
if (method !== "match" && method !== "search") return void 0;
|
|
6601
|
+
const re = args[0];
|
|
6602
|
+
if (!re || re.shape.k !== "brand" || re.shape.name !== "RegExp") return void 0;
|
|
6603
|
+
const inner = re.shape.shape;
|
|
6604
|
+
const patAbs = inner.shape.k === "obj" ? inner.shape.slots["source"]?.value : void 0;
|
|
6605
|
+
const flagsAbs = inner.shape.k === "obj" ? inner.shape.slots["flags"]?.value : void 0;
|
|
6606
|
+
const pat = patAbs ? litValue(patAbs) : void 0;
|
|
6607
|
+
const sv = litValue(recv);
|
|
6608
|
+
if (typeof pat !== "string" || typeof sv !== "string") return void 0;
|
|
6609
|
+
const flagsV = flagsAbs ? litValue(flagsAbs) : void 0;
|
|
6610
|
+
const flags = typeof flagsV === "string" ? flagsV : "";
|
|
6611
|
+
let reReal;
|
|
6612
|
+
try {
|
|
6613
|
+
reReal = new RegExp(pat, flags);
|
|
6614
|
+
} catch {
|
|
6615
|
+
return void 0;
|
|
6616
|
+
}
|
|
6617
|
+
if (method === "search") {
|
|
6618
|
+
const idx = sv.search(reReal);
|
|
6619
|
+
return abs({ k: "prim", type: "number" }, { op: "lit", value: idx }, void 0, "exact");
|
|
6620
|
+
}
|
|
6621
|
+
if (flags.includes("g")) {
|
|
6622
|
+
const all = sv.match(reReal) ?? [];
|
|
6623
|
+
return abs({ k: "tuple", elements: all.map((s) => strLit(s)) }, void 0, void 0, "exact");
|
|
6624
|
+
}
|
|
6625
|
+
const m = reReal.exec(sv);
|
|
6626
|
+
if (!m) {
|
|
6627
|
+
return abs({ k: "unknown" }, { op: "lit", value: null }, void 0, "exact");
|
|
6628
|
+
}
|
|
6629
|
+
const els = m.map((g) => g === void 0 ? undefAbs() : strLit(g));
|
|
6630
|
+
return abs({ k: "tuple", elements: els }, void 0, void 0, "exact");
|
|
6631
|
+
}
|
|
6171
6632
|
function $invoke(thisVal, method, args, loc) {
|
|
6633
|
+
if (!thisVal || typeof thisVal !== "object" || !("shape" in thisVal)) {
|
|
6634
|
+
const ns = namespaceNameOf(thisVal);
|
|
6635
|
+
return (ns ? evalNamespaceCall(ns, method, args) : void 0) ?? unknown;
|
|
6636
|
+
}
|
|
6172
6637
|
if (thisVal.shape.k === "sum") {
|
|
6173
6638
|
const results = thisVal.shape.members.filter((m) => memberLikelyHasMethod(m, method)).map((m) => $invoke(m, method, args, loc));
|
|
6174
6639
|
if (results.length === 0) return unknown;
|
|
6175
6640
|
return results.reduce((a, b) => joinAbs(a, b));
|
|
6176
6641
|
}
|
|
6642
|
+
{
|
|
6643
|
+
const reR = execRegexBrand(thisVal, method, args);
|
|
6644
|
+
if (reR !== void 0) return reR;
|
|
6645
|
+
}
|
|
6177
6646
|
const brandName = thisVal.shape.k === "brand" ? thisVal.shape.name : void 0;
|
|
6178
6647
|
if (brandName) {
|
|
6179
6648
|
const m = findMethod(brandName, method);
|
|
@@ -6186,6 +6655,10 @@ function $invoke(thisVal, method, args, loc) {
|
|
|
6186
6655
|
const arrR = invokeArrMethod(thisVal, method, args);
|
|
6187
6656
|
if (arrR !== void 0) return arrR;
|
|
6188
6657
|
}
|
|
6658
|
+
{
|
|
6659
|
+
const sm = stringRegexMethod(thisVal, method, args);
|
|
6660
|
+
if (sm !== void 0) return sm;
|
|
6661
|
+
}
|
|
6189
6662
|
{
|
|
6190
6663
|
const viaTable = callAbsMethod(thisVal, method, args);
|
|
6191
6664
|
if (viaTable) return viaTable;
|
|
@@ -6280,6 +6753,18 @@ function invokeArrMethod(arr, method, args) {
|
|
|
6280
6753
|
if (method === "join") {
|
|
6281
6754
|
return abs({ k: "prim", type: "string" }, void 0, void 0, "path");
|
|
6282
6755
|
}
|
|
6756
|
+
if (method === "fill" && args.length >= 1) {
|
|
6757
|
+
const v2 = asAbs(args[0]) ?? unknown;
|
|
6758
|
+
if (shape.k === "tuple") {
|
|
6759
|
+
return abs(
|
|
6760
|
+
{ k: "tuple", elements: shape.elements.map(() => v2) },
|
|
6761
|
+
void 0,
|
|
6762
|
+
void 0,
|
|
6763
|
+
confJoin(arr.conf, v2.conf)
|
|
6764
|
+
);
|
|
6765
|
+
}
|
|
6766
|
+
return abs({ k: "arr", element: v2 }, void 0, void 0, confJoin(arr.conf, v2.conf));
|
|
6767
|
+
}
|
|
6283
6768
|
if (method === "includes") {
|
|
6284
6769
|
return abs({ k: "prim", type: "boolean" }, void 0, void 0, "partial");
|
|
6285
6770
|
}
|
|
@@ -6328,6 +6813,7 @@ function $thisSet(thisVal, key, value) {
|
|
|
6328
6813
|
return unknown;
|
|
6329
6814
|
}
|
|
6330
6815
|
function $orDefault(v2, dflt) {
|
|
6816
|
+
if (v2 === void 0) return asAbsVal(dflt());
|
|
6331
6817
|
if (litValue(v2) === void 0 && v2.shape.k !== "never") {
|
|
6332
6818
|
if (v2.term?.op === "lit" && v2.term.value === void 0) return asAbsVal(dflt());
|
|
6333
6819
|
if (v2.shape.k === "unknown" && v2.term?.op === "lit") return asAbsVal(dflt());
|
|
@@ -6382,7 +6868,7 @@ var RUNTIME_IMPORT_RE = /^import\s*\{[^}]+\}\s*from\s*"[^"]+";\s*$/m;
|
|
|
6382
6868
|
function rewriteUserImports(js) {
|
|
6383
6869
|
js = js.replace(
|
|
6384
6870
|
/^import\s*\{\s*\*\s+as\s+([A-Za-z_$][\w$]*)\s*\}\s*from\s*["']([^"']+)["'];\s*$/gm,
|
|
6385
|
-
(_all, local, spec) => `
|
|
6871
|
+
(_all, local, spec) => `let ${local} = __nudoBindNamespace(${JSON.stringify(spec)});`
|
|
6386
6872
|
);
|
|
6387
6873
|
js = js.replace(
|
|
6388
6874
|
/^import\s*["']([^"']+)["'];\s*$/gm,
|
|
@@ -6395,7 +6881,7 @@ function rewriteUserImports(js) {
|
|
|
6395
6881
|
return parts.map((p) => {
|
|
6396
6882
|
const [imported, local] = p.split(/\s+as\s+/).map((x) => x.trim());
|
|
6397
6883
|
const bind = local ?? imported;
|
|
6398
|
-
return `
|
|
6884
|
+
return `let ${bind} = __nudoBindImport(${JSON.stringify(spec)}, ${JSON.stringify(imported)});`;
|
|
6399
6885
|
}).join("\n");
|
|
6400
6886
|
}
|
|
6401
6887
|
);
|
|
@@ -6540,8 +7026,8 @@ ${js}`;
|
|
|
6540
7026
|
}
|
|
6541
7027
|
const exportFns = [...js.matchAll(/^export function (\w+)/gm)].map((m) => m[1]);
|
|
6542
7028
|
js = js.replace(/^export function /gm, "function ");
|
|
6543
|
-
const exportConsts = [...js.matchAll(/^export const (\w+)/gm)].map((m) => m[1]);
|
|
6544
|
-
js = js.replace(/^export const /gm, "
|
|
7029
|
+
const exportConsts = [...js.matchAll(/^export (?:const|let) (\w+)/gm)].map((m) => m[1]);
|
|
7030
|
+
js = js.replace(/^export (?:const|let) /gm, "let ");
|
|
6545
7031
|
const names = [.../* @__PURE__ */ new Set([...exportFns, ...exportConsts])];
|
|
6546
7032
|
const argNames = [
|
|
6547
7033
|
...runtimeArgNames(),
|
|
@@ -6595,6 +7081,17 @@ function callTranspiledExportFull(exports, name, args) {
|
|
|
6595
7081
|
}
|
|
6596
7082
|
}
|
|
6597
7083
|
if (isAbsVal(fn)) {
|
|
7084
|
+
if (fn.shape.k === "fn") {
|
|
7085
|
+
try {
|
|
7086
|
+
const r = $call(fn, args);
|
|
7087
|
+
return { result: r, throws: never };
|
|
7088
|
+
} catch (e) {
|
|
7089
|
+
if (isNudoThrow(e)) {
|
|
7090
|
+
return { result: never, throws: e.absValue };
|
|
7091
|
+
}
|
|
7092
|
+
return { result: unknown, throws: never };
|
|
7093
|
+
}
|
|
7094
|
+
}
|
|
6598
7095
|
return { result: fn, throws: never };
|
|
6599
7096
|
}
|
|
6600
7097
|
return { result: unknown, throws: never };
|
|
@@ -6604,10 +7101,6 @@ function callTranspiledExport(exports, name, args) {
|
|
|
6604
7101
|
}
|
|
6605
7102
|
|
|
6606
7103
|
export {
|
|
6607
|
-
stripTypes,
|
|
6608
|
-
resetParseSourceCache,
|
|
6609
|
-
getParseSourceCacheSize,
|
|
6610
|
-
parseSource,
|
|
6611
7104
|
lit,
|
|
6612
7105
|
v,
|
|
6613
7106
|
app,
|
|
@@ -6657,6 +7150,26 @@ export {
|
|
|
6657
7150
|
isStrPrim,
|
|
6658
7151
|
isExactLit,
|
|
6659
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,
|
|
6660
7173
|
attachFnImpl,
|
|
6661
7174
|
getFnImpl,
|
|
6662
7175
|
absFunction,
|
|
@@ -6665,11 +7178,11 @@ export {
|
|
|
6665
7178
|
shapeOnlyFn,
|
|
6666
7179
|
objOf,
|
|
6667
7180
|
isObj,
|
|
7181
|
+
getSlot,
|
|
6668
7182
|
spread,
|
|
6669
7183
|
joinObjects,
|
|
6670
7184
|
joinValues,
|
|
6671
7185
|
makeSum,
|
|
6672
|
-
collapseToOptional,
|
|
6673
7186
|
fnOf,
|
|
6674
7187
|
joinFunctions,
|
|
6675
7188
|
joinAbs,
|
|
@@ -6692,18 +7205,15 @@ export {
|
|
|
6692
7205
|
mapElementFallback,
|
|
6693
7206
|
projectFlatMapResult,
|
|
6694
7207
|
asAbs,
|
|
6695
|
-
templatePartsOf,
|
|
6696
|
-
createTemplateAbs,
|
|
6697
|
-
isTemplateLike,
|
|
6698
|
-
concatString,
|
|
6699
7208
|
add,
|
|
6700
|
-
numericBounds,
|
|
6701
7209
|
sub,
|
|
6702
7210
|
mul,
|
|
6703
7211
|
div,
|
|
6704
7212
|
mod,
|
|
6705
7213
|
cmp,
|
|
6706
7214
|
trueConstraint,
|
|
7215
|
+
refineAbsForRelTrue,
|
|
7216
|
+
matchRelIdentLit,
|
|
6707
7217
|
falseConstraint,
|
|
6708
7218
|
typeofAbs,
|
|
6709
7219
|
negAbs,
|
|
@@ -6805,6 +7315,7 @@ export {
|
|
|
6805
7315
|
asAbsVal,
|
|
6806
7316
|
$fnVal,
|
|
6807
7317
|
$lit,
|
|
7318
|
+
litTruth,
|
|
6808
7319
|
isDefinitelyTrue,
|
|
6809
7320
|
isDefinitelyFalse,
|
|
6810
7321
|
$fork,
|
|
@@ -6820,6 +7331,8 @@ export {
|
|
|
6820
7331
|
$concat,
|
|
6821
7332
|
$elems,
|
|
6822
7333
|
$forOf,
|
|
7334
|
+
namespaceNameOf,
|
|
7335
|
+
$regex,
|
|
6823
7336
|
$get,
|
|
6824
7337
|
$set,
|
|
6825
7338
|
$while,
|