@nudojs/core 1.4.0 → 1.5.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-LFCF6BLE.js → chunk-W2MP6REI.js} +604 -401
- package/dist/{chunk-7QUVTEYZ.js → chunk-YO4GKCNE.js} +1 -1
- package/dist/exec.js +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +79 -34
- package/dist/internal.js +2 -2
- package/package.json +1 -1
|
@@ -1757,6 +1757,10 @@ function joinValues(a, b) {
|
|
|
1757
1757
|
}
|
|
1758
1758
|
return makeSum(a, b);
|
|
1759
1759
|
}
|
|
1760
|
+
const hasPred = (x) => !!x.pred && x.pred.op !== "true";
|
|
1761
|
+
if (hasPred(a) || hasPred(b)) {
|
|
1762
|
+
return makeSum(a, b);
|
|
1763
|
+
}
|
|
1760
1764
|
return abs(a.shape, void 0, void 0, confJoin(confJoin(a.conf, b.conf), "path"));
|
|
1761
1765
|
}
|
|
1762
1766
|
return makeSum(a, b);
|
|
@@ -3734,8 +3738,320 @@ function migrateInvariants(from, to) {
|
|
|
3734
3738
|
if (f) propFlagsTable.set(to, new Map(f));
|
|
3735
3739
|
}
|
|
3736
3740
|
|
|
3737
|
-
// src/algebra/
|
|
3741
|
+
// src/algebra/exec/runtime/state.ts
|
|
3742
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
3743
|
+
|
|
3744
|
+
// src/algebra/containers.ts
|
|
3745
|
+
var TUPLE_LITERAL_CAP = 8;
|
|
3746
|
+
function shouldWidenArrayLiteral(n) {
|
|
3747
|
+
return n > TUPLE_LITERAL_CAP;
|
|
3748
|
+
}
|
|
3749
|
+
var TUPLE_MATERIALIZE_CAP = 4096;
|
|
3750
|
+
function widenedArrayConf() {
|
|
3751
|
+
return "path";
|
|
3752
|
+
}
|
|
3753
|
+
|
|
3754
|
+
// src/algebra/exec/runtime/state.ts
|
|
3755
|
+
function writeInPlace(target, next) {
|
|
3756
|
+
target.shape = next.shape;
|
|
3757
|
+
target.conf = next.conf;
|
|
3758
|
+
target.term = void 0;
|
|
3759
|
+
target.pred = void 0;
|
|
3760
|
+
return target;
|
|
3761
|
+
}
|
|
3762
|
+
function clearStaleTermPred(v2) {
|
|
3763
|
+
v2.term = void 0;
|
|
3764
|
+
v2.pred = void 0;
|
|
3765
|
+
}
|
|
3766
|
+
var phi = pTrue;
|
|
3767
|
+
function currentExecPhi() {
|
|
3768
|
+
return phi;
|
|
3769
|
+
}
|
|
3770
|
+
function withExecPhi(p, body) {
|
|
3771
|
+
const prev = phi;
|
|
3772
|
+
phi = p;
|
|
3773
|
+
try {
|
|
3774
|
+
return body();
|
|
3775
|
+
} finally {
|
|
3776
|
+
phi = prev;
|
|
3777
|
+
}
|
|
3778
|
+
}
|
|
3738
3779
|
var noBody = { type: "BlockStatement", body: [], directives: [] };
|
|
3780
|
+
function asAbsVal(v2) {
|
|
3781
|
+
if (v2 && typeof v2 === "object" && "shape" in v2) return v2;
|
|
3782
|
+
if (typeof v2 === "function") {
|
|
3783
|
+
const n = Math.max(0, v2.length);
|
|
3784
|
+
const params = Array.from({ length: n }, (_, i) => `arg${i}`);
|
|
3785
|
+
return absFunction(params, {
|
|
3786
|
+
body: noBody,
|
|
3787
|
+
// 与 $fnVal / $callNamed 同边界:callee 的 NudoReturn 不得冒泡成 caller
|
|
3788
|
+
apply: (args) => callAtFunctionBoundary(() => v2(...args))
|
|
3789
|
+
});
|
|
3790
|
+
}
|
|
3791
|
+
return $lit(v2);
|
|
3792
|
+
}
|
|
3793
|
+
function callAtFunctionBoundary(body) {
|
|
3794
|
+
let forwarded = [];
|
|
3795
|
+
try {
|
|
3796
|
+
return runWithLoopExits(() => {
|
|
3797
|
+
try {
|
|
3798
|
+
const r = body();
|
|
3799
|
+
forwarded = takeThrowExits();
|
|
3800
|
+
return r;
|
|
3801
|
+
} catch (e) {
|
|
3802
|
+
forwarded = takeThrowExits();
|
|
3803
|
+
if (isNudoReturn(e)) return e.absValue;
|
|
3804
|
+
throw e;
|
|
3805
|
+
}
|
|
3806
|
+
});
|
|
3807
|
+
} finally {
|
|
3808
|
+
for (const x of forwarded) pushThrowExit(x);
|
|
3809
|
+
}
|
|
3810
|
+
}
|
|
3811
|
+
function $fnVal(params, impl, opts) {
|
|
3812
|
+
return absFunction(params, {
|
|
3813
|
+
body: noBody,
|
|
3814
|
+
// bindThis(对象方法):receiver 走首参注入,无宿主 this;
|
|
3815
|
+
// 非方法 fn:宿主 this 传递(call/apply/bind 的 thisArg 经 $rawThis 进入函数体)
|
|
3816
|
+
apply: opts?.bindThis ? (args) => callAtFunctionBoundary(() => impl(...args)) : (args, thisVal) => callAtFunctionBoundary(() => impl.apply(thisVal, args)),
|
|
3817
|
+
...opts?.bindThis ? { bindThis: true } : {}
|
|
3818
|
+
});
|
|
3819
|
+
}
|
|
3820
|
+
function $rawThis(v2) {
|
|
3821
|
+
if (v2 === void 0 || v2 === globalThis) return $lit(void 0);
|
|
3822
|
+
if (v2 && typeof v2 === "object" && "shape" in v2) return v2;
|
|
3823
|
+
return $lit(v2);
|
|
3824
|
+
}
|
|
3825
|
+
function throwStrictWrite() {
|
|
3826
|
+
throw new NudoThrow(errorTypeAbs("TypeError"));
|
|
3827
|
+
}
|
|
3828
|
+
function $throwConstAssign() {
|
|
3829
|
+
throw new NudoThrow(errorTypeAbs("TypeError"));
|
|
3830
|
+
}
|
|
3831
|
+
function $litTruth(a) {
|
|
3832
|
+
return litTruth(a);
|
|
3833
|
+
}
|
|
3834
|
+
function $lit(v2) {
|
|
3835
|
+
if (v2 && typeof v2 === "object" && "shape" in v2 && "conf" in v2) {
|
|
3836
|
+
return v2;
|
|
3837
|
+
}
|
|
3838
|
+
return litAbsFromJs(v2);
|
|
3839
|
+
}
|
|
3840
|
+
function litAbsFromJs(v2, depth = 0) {
|
|
3841
|
+
if (v2 === null || v2 === void 0) {
|
|
3842
|
+
return abs({ k: "unknown" }, { op: "lit", value: v2 }, pTrue, "exact");
|
|
3843
|
+
}
|
|
3844
|
+
const t = typeof v2;
|
|
3845
|
+
if (t === "number" || t === "string" || t === "boolean" || t === "bigint") {
|
|
3846
|
+
return abs(
|
|
3847
|
+
{ k: "prim", type: t },
|
|
3848
|
+
{ op: "lit", value: v2 },
|
|
3849
|
+
pTrue,
|
|
3850
|
+
"exact"
|
|
3851
|
+
);
|
|
3852
|
+
}
|
|
3853
|
+
if (depth < 8) {
|
|
3854
|
+
if (Array.isArray(v2)) {
|
|
3855
|
+
const els = v2.map((x) => litAbsFromJs(x, depth + 1));
|
|
3856
|
+
if (shouldWidenArrayLiteral(els.length)) {
|
|
3857
|
+
return abs(
|
|
3858
|
+
{ k: "arr", element: els.reduce((x, y) => joinAbs(x, y)) },
|
|
3859
|
+
void 0,
|
|
3860
|
+
void 0,
|
|
3861
|
+
widenedArrayConf()
|
|
3862
|
+
);
|
|
3863
|
+
}
|
|
3864
|
+
return abs({ k: "tuple", elements: els }, void 0, void 0, "exact");
|
|
3865
|
+
}
|
|
3866
|
+
if (t === "object") {
|
|
3867
|
+
const proto = Object.getPrototypeOf(v2);
|
|
3868
|
+
if (proto === Object.prototype || proto === null) {
|
|
3869
|
+
const slots = {};
|
|
3870
|
+
for (const [k, val] of Object.entries(v2)) {
|
|
3871
|
+
Object.defineProperty(slots, k, {
|
|
3872
|
+
value: { value: litAbsFromJs(val, depth + 1) },
|
|
3873
|
+
enumerable: true,
|
|
3874
|
+
writable: true,
|
|
3875
|
+
configurable: true
|
|
3876
|
+
});
|
|
3877
|
+
}
|
|
3878
|
+
return objOf(slots);
|
|
3879
|
+
}
|
|
3880
|
+
}
|
|
3881
|
+
}
|
|
3882
|
+
return unknown;
|
|
3883
|
+
}
|
|
3884
|
+
function litTruth(a) {
|
|
3885
|
+
if (a.term?.op === "lit") {
|
|
3886
|
+
return Boolean(a.term.value);
|
|
3887
|
+
}
|
|
3888
|
+
switch (a.shape.k) {
|
|
3889
|
+
case "obj":
|
|
3890
|
+
case "arr":
|
|
3891
|
+
case "tuple":
|
|
3892
|
+
case "fn":
|
|
3893
|
+
case "brand":
|
|
3894
|
+
case "eff":
|
|
3895
|
+
return true;
|
|
3896
|
+
case "prim":
|
|
3897
|
+
return a.shape.type === "symbol" ? true : void 0;
|
|
3898
|
+
case "never":
|
|
3899
|
+
return false;
|
|
3900
|
+
default:
|
|
3901
|
+
return void 0;
|
|
3902
|
+
}
|
|
3903
|
+
}
|
|
3904
|
+
function isDefinitelyTrue(a) {
|
|
3905
|
+
return litTruth(a) === true;
|
|
3906
|
+
}
|
|
3907
|
+
function isDefinitelyFalse(a) {
|
|
3908
|
+
const t = litTruth(a);
|
|
3909
|
+
if (t === false) return true;
|
|
3910
|
+
if (a.shape.k === "never") return true;
|
|
3911
|
+
return false;
|
|
3912
|
+
}
|
|
3913
|
+
function undef() {
|
|
3914
|
+
return abs({ k: "unknown" }, { op: "lit", value: void 0 }, pTrue, "exact");
|
|
3915
|
+
}
|
|
3916
|
+
var loopExitsAls = new AsyncLocalStorage2();
|
|
3917
|
+
var throwExitsAls = new AsyncLocalStorage2();
|
|
3918
|
+
var tryMarksAls = new AsyncLocalStorage2();
|
|
3919
|
+
var softFrameActiveAls = new AsyncLocalStorage2();
|
|
3920
|
+
function runWithLoopExits(body) {
|
|
3921
|
+
return loopExitsAls.run(
|
|
3922
|
+
[],
|
|
3923
|
+
() => throwExitsAls.run(
|
|
3924
|
+
[],
|
|
3925
|
+
() => tryMarksAls.run([], () => softFrameActiveAls.run([], body))
|
|
3926
|
+
)
|
|
3927
|
+
);
|
|
3928
|
+
}
|
|
3929
|
+
function takeLoopExits() {
|
|
3930
|
+
return loopExitsAls.getStore() ?? [];
|
|
3931
|
+
}
|
|
3932
|
+
function takeThrowExits() {
|
|
3933
|
+
return throwExitsAls.getStore() ?? [];
|
|
3934
|
+
}
|
|
3935
|
+
function pushLoopExit(v2) {
|
|
3936
|
+
loopExitsAls.getStore()?.push(v2);
|
|
3937
|
+
}
|
|
3938
|
+
function pushThrowExit(v2) {
|
|
3939
|
+
throwExitsAls.getStore()?.push(v2);
|
|
3940
|
+
}
|
|
3941
|
+
function $pushLoopExit(v2) {
|
|
3942
|
+
pushLoopExit(v2);
|
|
3943
|
+
}
|
|
3944
|
+
function $tryMark() {
|
|
3945
|
+
$tryMarkSoft();
|
|
3946
|
+
softFrameActiveAls.getStore()?.push(true);
|
|
3947
|
+
const store = throwExitsAls.getStore();
|
|
3948
|
+
const m = store?.length ?? 0;
|
|
3949
|
+
tryMarksAls.getStore()?.push(m);
|
|
3950
|
+
return m;
|
|
3951
|
+
}
|
|
3952
|
+
function $tryCurrentMark() {
|
|
3953
|
+
const stack = tryMarksAls.getStore();
|
|
3954
|
+
return stack && stack.length > 0 ? stack[stack.length - 1] : 0;
|
|
3955
|
+
}
|
|
3956
|
+
function $tryPopMark() {
|
|
3957
|
+
tryMarksAls.getStore()?.pop();
|
|
3958
|
+
const soft = softFrameActiveAls.getStore();
|
|
3959
|
+
if (soft && soft.length > 0) {
|
|
3960
|
+
if (soft[soft.length - 1]) $tryReleaseSoftOut();
|
|
3961
|
+
soft.pop();
|
|
3962
|
+
}
|
|
3963
|
+
}
|
|
3964
|
+
function $tryTakeSince(mark) {
|
|
3965
|
+
const store = throwExitsAls.getStore();
|
|
3966
|
+
if (!store) return [];
|
|
3967
|
+
return store.splice(Math.min(mark, store.length));
|
|
3968
|
+
}
|
|
3969
|
+
function peekThrowExitsSince(mark) {
|
|
3970
|
+
const store = throwExitsAls.getStore();
|
|
3971
|
+
if (!store) return [];
|
|
3972
|
+
return store.slice(Math.min(mark, store.length));
|
|
3973
|
+
}
|
|
3974
|
+
function throwExitsMark() {
|
|
3975
|
+
return throwExitsAls.getStore()?.length ?? 0;
|
|
3976
|
+
}
|
|
3977
|
+
function $tryDigestSoftCatch() {
|
|
3978
|
+
const soft = softFrameActiveAls.getStore();
|
|
3979
|
+
if (!soft || soft.length === 0 || !soft[soft.length - 1]) return;
|
|
3980
|
+
$tryDigestSoft();
|
|
3981
|
+
soft[soft.length - 1] = false;
|
|
3982
|
+
}
|
|
3983
|
+
function $tryReleaseSoftCatch() {
|
|
3984
|
+
const soft = softFrameActiveAls.getStore();
|
|
3985
|
+
if (!soft || soft.length === 0 || !soft[soft.length - 1]) return;
|
|
3986
|
+
$tryReleaseSoft();
|
|
3987
|
+
soft[soft.length - 1] = false;
|
|
3988
|
+
}
|
|
3989
|
+
function $tryDetachSoftCatch() {
|
|
3990
|
+
const soft = softFrameActiveAls.getStore();
|
|
3991
|
+
if (!soft || soft.length === 0 || !soft[soft.length - 1]) return [];
|
|
3992
|
+
const effects = popMayThrowFrame(false);
|
|
3993
|
+
soft[soft.length - 1] = false;
|
|
3994
|
+
return effects;
|
|
3995
|
+
}
|
|
3996
|
+
function $tryDiscardSoft(_effects) {
|
|
3997
|
+
}
|
|
3998
|
+
function $tryOrphanSoft(effects) {
|
|
3999
|
+
orphanMayThrowEffects(effects);
|
|
4000
|
+
}
|
|
4001
|
+
function $tryReleaseSoftOut() {
|
|
4002
|
+
const soft = softFrameActiveAls.getStore();
|
|
4003
|
+
if (!soft || soft.length === 0 || !soft[soft.length - 1]) return;
|
|
4004
|
+
$tryReleaseSoft();
|
|
4005
|
+
soft[soft.length - 1] = false;
|
|
4006
|
+
}
|
|
4007
|
+
var NudoReturn = class extends Error {
|
|
4008
|
+
absValue;
|
|
4009
|
+
constructor(absValue) {
|
|
4010
|
+
super("nudo:return");
|
|
4011
|
+
this.name = "NudoReturn";
|
|
4012
|
+
this.absValue = absValue;
|
|
4013
|
+
}
|
|
4014
|
+
};
|
|
4015
|
+
function isNudoReturn(e) {
|
|
4016
|
+
return e instanceof NudoReturn;
|
|
4017
|
+
}
|
|
4018
|
+
function $loopReturn(v2) {
|
|
4019
|
+
throw new NudoReturn(v2);
|
|
4020
|
+
}
|
|
4021
|
+
var NudoLoopSignal = class extends Error {
|
|
4022
|
+
kind;
|
|
4023
|
+
label;
|
|
4024
|
+
constructor(kind, label) {
|
|
4025
|
+
super("nudo:loop");
|
|
4026
|
+
this.name = "NudoLoopSignal";
|
|
4027
|
+
this.kind = kind;
|
|
4028
|
+
this.label = label;
|
|
4029
|
+
}
|
|
4030
|
+
};
|
|
4031
|
+
function $loopBreak(label) {
|
|
4032
|
+
throw new NudoLoopSignal("break", label || void 0);
|
|
4033
|
+
}
|
|
4034
|
+
function $loopContinue(label) {
|
|
4035
|
+
throw new NudoLoopSignal("continue", label || void 0);
|
|
4036
|
+
}
|
|
4037
|
+
function loopSignalMatches(e, label) {
|
|
4038
|
+
return e.label === void 0 || e.label === label;
|
|
4039
|
+
}
|
|
4040
|
+
function isNudoBreak(e, label) {
|
|
4041
|
+
return e instanceof NudoLoopSignal && e.kind === "break" && loopSignalMatches(e, label);
|
|
4042
|
+
}
|
|
4043
|
+
function isNudoContinue(e, label) {
|
|
4044
|
+
return e instanceof NudoLoopSignal && e.kind === "continue" && loopSignalMatches(e, label);
|
|
4045
|
+
}
|
|
4046
|
+
function $isBreakTo(e, label) {
|
|
4047
|
+
return e instanceof NudoLoopSignal && e.kind === "break" && e.label === label;
|
|
4048
|
+
}
|
|
4049
|
+
function $rethrowIfNudoReturn(e) {
|
|
4050
|
+
if (isNudoReturn(e)) throw e;
|
|
4051
|
+
}
|
|
4052
|
+
|
|
4053
|
+
// src/algebra/builtins/shared.ts
|
|
4054
|
+
var noBody2 = { type: "BlockStatement", body: [], directives: [] };
|
|
3739
4055
|
function numPrim(conf = "path") {
|
|
3740
4056
|
return abs({ k: "prim", type: "number" }, void 0, void 0, conf);
|
|
3741
4057
|
}
|
|
@@ -3770,13 +4086,199 @@ function coerceMathArg(a) {
|
|
|
3770
4086
|
if (v2 === void 0) return void 0;
|
|
3771
4087
|
return "throw";
|
|
3772
4088
|
}
|
|
3773
|
-
function mathMethod(name) {
|
|
3774
|
-
if (!Object.hasOwn(Math, name)) return void 0;
|
|
3775
|
-
const impl = Math[name];
|
|
3776
|
-
return typeof impl === "function" ? impl : void 0;
|
|
4089
|
+
function mathMethod(name) {
|
|
4090
|
+
if (!Object.hasOwn(Math, name)) return void 0;
|
|
4091
|
+
const impl = Math[name];
|
|
4092
|
+
return typeof impl === "function" ? impl : void 0;
|
|
4093
|
+
}
|
|
4094
|
+
function isNonNaN(a, phi2) {
|
|
4095
|
+
if (a.term?.op === "lit") {
|
|
4096
|
+
return typeof a.term.value === "number" && !Number.isNaN(a.term.value);
|
|
4097
|
+
}
|
|
4098
|
+
const hasNonNaNFact = (p) => {
|
|
4099
|
+
if (!p) return false;
|
|
4100
|
+
if (p.op === "and") return p.args.some(hasNonNaNFact);
|
|
4101
|
+
if (p.op === "assumeFinite") {
|
|
4102
|
+
return !!a.term && termEquals(p.t, a.term);
|
|
4103
|
+
}
|
|
4104
|
+
if (p.op === "ne") {
|
|
4105
|
+
if (p.b.op === "lit" && typeof p.b.value === "number" && Number.isNaN(p.b.value) && a.term && termEquals(p.a, a.term)) {
|
|
4106
|
+
return true;
|
|
4107
|
+
}
|
|
4108
|
+
}
|
|
4109
|
+
if (p.op === "gt" || p.op === "ge" || p.op === "lt" || p.op === "le") {
|
|
4110
|
+
if (a.term && (termEquals(p.a, a.term) || termEquals(p.b, a.term))) return true;
|
|
4111
|
+
}
|
|
4112
|
+
return false;
|
|
4113
|
+
};
|
|
4114
|
+
if (hasNonNaNFact(a.pred)) return true;
|
|
4115
|
+
if (a.term?.op === "var") {
|
|
4116
|
+
const id = a.term.id;
|
|
4117
|
+
const conjs = phi2.op === "and" ? phi2.args : [phi2];
|
|
4118
|
+
for (const p of conjs) {
|
|
4119
|
+
if (p.op === "assumeFinite" && p.t.op === "var" && p.t.id === id) {
|
|
4120
|
+
return true;
|
|
4121
|
+
}
|
|
4122
|
+
if (p.op === "ne") {
|
|
4123
|
+
const b = p.b;
|
|
4124
|
+
if (b.op === "lit" && typeof b.value === "number" && Number.isNaN(b.value) && p.a.op === "var" && p.a.id === id) {
|
|
4125
|
+
return true;
|
|
4126
|
+
}
|
|
4127
|
+
}
|
|
4128
|
+
if (p.op === "gt" || p.op === "ge" || p.op === "lt" || p.op === "le") {
|
|
4129
|
+
const sides = [p.a, p.b];
|
|
4130
|
+
if (sides.some((t) => t.op === "var" && t.id === id) && sides.some((t) => t.op === "lit" && typeof t.value === "number")) {
|
|
4131
|
+
return true;
|
|
4132
|
+
}
|
|
4133
|
+
}
|
|
4134
|
+
}
|
|
4135
|
+
}
|
|
4136
|
+
return false;
|
|
4137
|
+
}
|
|
4138
|
+
function ieeeBoundNum(n) {
|
|
4139
|
+
return Number.isFinite(n) || n === Infinity || n === -Infinity ? n : void 0;
|
|
4140
|
+
}
|
|
4141
|
+
function loMin(a, b) {
|
|
4142
|
+
if (a.lo === void 0 || b.lo === void 0) return void 0;
|
|
4143
|
+
if (b.lo.value < a.lo.value) return b.lo;
|
|
4144
|
+
if (b.lo.value === a.lo.value && b.lo.strict && !a.lo.strict) return b.lo;
|
|
4145
|
+
return a.lo;
|
|
4146
|
+
}
|
|
4147
|
+
function loMax(a, b) {
|
|
4148
|
+
if (a.lo === void 0) return b.lo;
|
|
4149
|
+
if (b.lo === void 0) return a.lo;
|
|
4150
|
+
if (b.lo.value > a.lo.value) return b.lo;
|
|
4151
|
+
if (b.lo.value === a.lo.value && b.lo.strict && !a.lo.strict) return b.lo;
|
|
4152
|
+
return a.lo;
|
|
4153
|
+
}
|
|
4154
|
+
function hiMin(a, b) {
|
|
4155
|
+
if (a.hi === void 0) return b.hi;
|
|
4156
|
+
if (b.hi === void 0) return a.hi;
|
|
4157
|
+
if (b.hi.value < a.hi.value) return b.hi;
|
|
4158
|
+
if (b.hi.value === a.hi.value && b.hi.strict && !a.hi.strict) return b.hi;
|
|
4159
|
+
return a.hi;
|
|
4160
|
+
}
|
|
4161
|
+
function hiMax(a, b) {
|
|
4162
|
+
if (a.hi === void 0 || b.hi === void 0) return void 0;
|
|
4163
|
+
if (b.hi.value > a.hi.value) return b.hi;
|
|
4164
|
+
if (b.hi.value === a.hi.value && b.hi.strict && !a.hi.strict) return b.hi;
|
|
4165
|
+
return a.hi;
|
|
4166
|
+
}
|
|
4167
|
+
function boundsToPred(t, b) {
|
|
4168
|
+
const facts = [];
|
|
4169
|
+
if (b.lo !== void 0) {
|
|
4170
|
+
const v2 = ieeeBoundNum(b.lo.value);
|
|
4171
|
+
if (v2 !== void 0) {
|
|
4172
|
+
facts.push(b.lo.strict ? { op: "gt", a: t, b: lit(v2) } : { op: "ge", a: t, b: lit(v2) });
|
|
4173
|
+
}
|
|
4174
|
+
}
|
|
4175
|
+
if (b.hi !== void 0) {
|
|
4176
|
+
const v2 = ieeeBoundNum(b.hi.value);
|
|
4177
|
+
if (v2 !== void 0) {
|
|
4178
|
+
facts.push(b.hi.strict ? { op: "lt", a: t, b: lit(v2) } : { op: "le", a: t, b: lit(v2) });
|
|
4179
|
+
}
|
|
4180
|
+
}
|
|
4181
|
+
if (facts.length === 0) return void 0;
|
|
4182
|
+
return facts.length === 1 ? facts[0] : and(...facts);
|
|
4183
|
+
}
|
|
4184
|
+
function minMaxAbs(name, args) {
|
|
4185
|
+
const phi2 = currentExecPhi();
|
|
4186
|
+
const empty = {};
|
|
4187
|
+
let acc = empty;
|
|
4188
|
+
const termArgs = args.map(
|
|
4189
|
+
(a, i) => a.term ?? app(`arg${i}`, [])
|
|
4190
|
+
);
|
|
4191
|
+
const term = simplifyTerm(app(`Math.${name}`, termArgs));
|
|
4192
|
+
let first = true;
|
|
4193
|
+
let mayNaN = false;
|
|
4194
|
+
for (const a of args) {
|
|
4195
|
+
if (!isNonNaN(a, phi2)) mayNaN = true;
|
|
4196
|
+
const b = numericBounds(a, phi2) ?? {};
|
|
4197
|
+
if (first) {
|
|
4198
|
+
acc = { lo: b.lo, hi: b.hi };
|
|
4199
|
+
first = false;
|
|
4200
|
+
continue;
|
|
4201
|
+
}
|
|
4202
|
+
if (name === "min") {
|
|
4203
|
+
acc = { lo: loMin(acc, b), hi: hiMin(acc, b) };
|
|
4204
|
+
} else {
|
|
4205
|
+
acc = { lo: loMax(acc, b), hi: hiMax(acc, b) };
|
|
4206
|
+
}
|
|
4207
|
+
}
|
|
4208
|
+
const pred = boundsToPred(term, acc);
|
|
4209
|
+
const bounded = abs({ k: "prim", type: "number" }, term, pred, "path");
|
|
4210
|
+
if (!mayNaN) return bounded;
|
|
4211
|
+
const nanArm = numLit(NaN);
|
|
4212
|
+
return makeSum(nanArm, bounded);
|
|
4213
|
+
}
|
|
4214
|
+
function roundingAbs(name, arg) {
|
|
4215
|
+
const phi2 = currentExecPhi();
|
|
4216
|
+
const impl = name === "round" ? Math.round : name === "floor" ? Math.floor : name === "ceil" ? Math.ceil : Math.trunc;
|
|
4217
|
+
const b = numericBounds(arg, phi2);
|
|
4218
|
+
const mayNaN = !isNonNaN(arg, phi2);
|
|
4219
|
+
const term = arg.term ? simplifyTerm(app(`Math.${name}`, [arg.term])) : void 0;
|
|
4220
|
+
let out = {};
|
|
4221
|
+
if (b) {
|
|
4222
|
+
if (b.lo !== void 0) {
|
|
4223
|
+
const v2 = impl(b.lo.value);
|
|
4224
|
+
out.lo = Number.isNaN(v2) ? void 0 : { value: v2, strict: false };
|
|
4225
|
+
}
|
|
4226
|
+
if (b.hi !== void 0) {
|
|
4227
|
+
const v2 = impl(b.hi.value);
|
|
4228
|
+
out.hi = Number.isNaN(v2) ? void 0 : { value: v2, strict: false };
|
|
4229
|
+
}
|
|
4230
|
+
}
|
|
4231
|
+
const pred = term ? boundsToPred(term, out) : void 0;
|
|
4232
|
+
const bounded = abs({ k: "prim", type: "number" }, term, pred, "path");
|
|
4233
|
+
if (!mayNaN) return bounded;
|
|
4234
|
+
return makeSum(numLit(NaN), bounded);
|
|
3777
4235
|
}
|
|
3778
4236
|
function evalMathMethod(name, args) {
|
|
3779
4237
|
if (name === "random") return numPrim("path");
|
|
4238
|
+
if (name === "min" || name === "max") {
|
|
4239
|
+
const nums2 = [];
|
|
4240
|
+
let allLit = true;
|
|
4241
|
+
for (const a of args) {
|
|
4242
|
+
const n = coerceMathArg(a);
|
|
4243
|
+
if (n === void 0) {
|
|
4244
|
+
allLit = false;
|
|
4245
|
+
break;
|
|
4246
|
+
}
|
|
4247
|
+
if (n === "throw") throw new NudoThrow(errorTypeAbs("TypeError"));
|
|
4248
|
+
nums2.push(n);
|
|
4249
|
+
}
|
|
4250
|
+
if (allLit) {
|
|
4251
|
+
try {
|
|
4252
|
+
return numLit((name === "min" ? Math.min : Math.max)(...nums2));
|
|
4253
|
+
} catch {
|
|
4254
|
+
return numPrim();
|
|
4255
|
+
}
|
|
4256
|
+
}
|
|
4257
|
+
for (const a of args) {
|
|
4258
|
+
const n = coerceMathArg(a);
|
|
4259
|
+
if (n === "throw") throw new NudoThrow(errorTypeAbs("TypeError"));
|
|
4260
|
+
}
|
|
4261
|
+
return minMaxAbs(name, args);
|
|
4262
|
+
}
|
|
4263
|
+
if (name === "round" || name === "floor" || name === "ceil" || name === "trunc") {
|
|
4264
|
+
const n = coerceMathArg(args[0]);
|
|
4265
|
+
if (n === "throw") throw new NudoThrow(errorTypeAbs("TypeError"));
|
|
4266
|
+
if (typeof n === "number") {
|
|
4267
|
+
try {
|
|
4268
|
+
return numLit(
|
|
4269
|
+
name === "round" ? Math.round(n) : name === "floor" ? Math.floor(n) : name === "ceil" ? Math.ceil(n) : Math.trunc(n)
|
|
4270
|
+
);
|
|
4271
|
+
} catch {
|
|
4272
|
+
return numPrim();
|
|
4273
|
+
}
|
|
4274
|
+
}
|
|
4275
|
+
if (args[0]) {
|
|
4276
|
+
const c2 = coerceMathArg(args[0]);
|
|
4277
|
+
if (c2 === "throw") throw new NudoThrow(errorTypeAbs("TypeError"));
|
|
4278
|
+
return roundingAbs(name, args[0]);
|
|
4279
|
+
}
|
|
4280
|
+
return numPrim();
|
|
4281
|
+
}
|
|
3780
4282
|
const impl = mathMethod(name);
|
|
3781
4283
|
if (!impl) return void 0;
|
|
3782
4284
|
const nums = [];
|
|
@@ -3952,16 +4454,6 @@ function isObjectProtoBrand(a) {
|
|
|
3952
4454
|
return !!a && a.shape.k === "brand" && a.shape.name === "Object.prototype";
|
|
3953
4455
|
}
|
|
3954
4456
|
|
|
3955
|
-
// src/algebra/containers.ts
|
|
3956
|
-
var TUPLE_LITERAL_CAP = 8;
|
|
3957
|
-
function shouldWidenArrayLiteral(n) {
|
|
3958
|
-
return n > TUPLE_LITERAL_CAP;
|
|
3959
|
-
}
|
|
3960
|
-
var TUPLE_MATERIALIZE_CAP = 4096;
|
|
3961
|
-
function widenedArrayConf() {
|
|
3962
|
-
return "path";
|
|
3963
|
-
}
|
|
3964
|
-
|
|
3965
4457
|
// src/algebra/builtins/object.ts
|
|
3966
4458
|
function assignSourceSlots(src) {
|
|
3967
4459
|
const s = src.shape;
|
|
@@ -4546,8 +5038,19 @@ function evalNumberStatic(name, args) {
|
|
|
4546
5038
|
switch (name) {
|
|
4547
5039
|
case "isInteger":
|
|
4548
5040
|
return foldStrictNumberPred(Number.isInteger) ?? boolPrim();
|
|
4549
|
-
case "isNaN":
|
|
4550
|
-
|
|
5041
|
+
case "isNaN": {
|
|
5042
|
+
const folded = foldStrictNumberPred(Number.isNaN);
|
|
5043
|
+
if (folded) return folded;
|
|
5044
|
+
if (a0Arg?.term) {
|
|
5045
|
+
return abs(
|
|
5046
|
+
{ k: "prim", type: "boolean" },
|
|
5047
|
+
void 0,
|
|
5048
|
+
{ op: "eq", a: a0Arg.term, b: { op: "lit", value: NaN } },
|
|
5049
|
+
"path"
|
|
5050
|
+
);
|
|
5051
|
+
}
|
|
5052
|
+
return boolPrim();
|
|
5053
|
+
}
|
|
4551
5054
|
case "isFinite":
|
|
4552
5055
|
return foldStrictNumberPred(Number.isFinite) ?? boolPrim();
|
|
4553
5056
|
case "parseInt": {
|
|
@@ -5403,7 +5906,7 @@ function arrayJoinToString(recv) {
|
|
|
5403
5906
|
}
|
|
5404
5907
|
function arrayMethodAbs(name) {
|
|
5405
5908
|
return absFunction(["thisArg"], {
|
|
5406
|
-
body:
|
|
5909
|
+
body: noBody2,
|
|
5407
5910
|
bindThis: true,
|
|
5408
5911
|
apply: (a) => {
|
|
5409
5912
|
const recv = a[0] ?? undefAbs();
|
|
@@ -5766,11 +6269,11 @@ function evalPromiseCtor(args) {
|
|
|
5766
6269
|
return undefAbs();
|
|
5767
6270
|
};
|
|
5768
6271
|
const resolveAbs = absFunction(["value"], {
|
|
5769
|
-
body:
|
|
6272
|
+
body: noBody2,
|
|
5770
6273
|
apply: (args2) => onResolve(args2[0])
|
|
5771
6274
|
});
|
|
5772
6275
|
const rejectAbs = absFunction(["reason"], {
|
|
5773
|
-
body:
|
|
6276
|
+
body: noBody2,
|
|
5774
6277
|
apply: (args2) => onReject(args2[0])
|
|
5775
6278
|
});
|
|
5776
6279
|
enterPromiseExecutorScope();
|
|
@@ -6453,7 +6956,7 @@ function evalObjectProtoMethod(name, thisVal, args) {
|
|
|
6453
6956
|
}
|
|
6454
6957
|
function objectProtoMethodAbs(name) {
|
|
6455
6958
|
return absFunction(["thisArg", "arg0"], {
|
|
6456
|
-
body:
|
|
6959
|
+
body: noBody2,
|
|
6457
6960
|
bindThis: true,
|
|
6458
6961
|
apply: (a) => {
|
|
6459
6962
|
const recv = a[0] ?? undefLit();
|
|
@@ -11428,349 +11931,49 @@ ${inner}
|
|
|
11428
11931
|
if (fn.async) {
|
|
11429
11932
|
return `$fnVal(${nameList}, (${argsParamParts.join(", ")}) => $async(() => ${bodySrc}))`;
|
|
11430
11933
|
}
|
|
11431
|
-
return `$fnVal(${nameList}, (${argsParamParts.join(", ")}) => ${bodySrc})`;
|
|
11432
|
-
}
|
|
11433
|
-
case "MetaProperty":
|
|
11434
|
-
return "$importMeta()";
|
|
11435
|
-
case "ImportExpression": {
|
|
11436
|
-
const specSrc = transpileExpression(expr.source, opts);
|
|
11437
|
-
return `$dynamicImport(${specSrc})`;
|
|
11438
|
-
}
|
|
11439
|
-
case "JSXElement":
|
|
11440
|
-
case "JSXFragment":
|
|
11441
|
-
return "$unknown()";
|
|
11442
|
-
default:
|
|
11443
|
-
throw new NudoUnsupportedError(
|
|
11444
|
-
`expression:${expr.type}`,
|
|
11445
|
-
expr.loc ? { line: expr.loc.start.line, column: expr.loc.start.column } : void 0
|
|
11446
|
-
);
|
|
11447
|
-
}
|
|
11448
|
-
}
|
|
11449
|
-
bindTranspileExpression(transpileExpression);
|
|
11450
|
-
bindTranspileShortCircuit(transpileShortCircuitExpr);
|
|
11451
|
-
|
|
11452
|
-
// src/algebra/exec/transpile.ts
|
|
11453
|
-
function transpileSource(source, opts = {}) {
|
|
11454
|
-
const file = parseSource(source);
|
|
11455
|
-
return transpileFile(file, { ...opts, source: opts.source ?? source });
|
|
11456
|
-
}
|
|
11457
|
-
function runtimeImportOf(runtime) {
|
|
11458
|
-
return `import { $add, $sub, $mul, $div, $mod, $bitand, $bitor, $bitxor, $bitnot, $shl, $shr, $ushr, $pow, $toNumber, $toNumeric, $updateAdd, $updateSub, $in, $instanceof, $instanceofNonIdent, $classExpr, $del, $delRes, $objAccessor, $neg, $typeof, $not, $eq, $ne, $eqLoose, $neLoose, $lt, $le, $gt, $ge, $join, $lit, $fork, $for, $forIter, $obj, $get, $set, $setProto, $while, $whileSeq, $arr, $arrWithHoles, $arrMutContainer, $idx, $idxSet, $len, $call, $throw, $loopReturn, $loopBreak, $loopContinue, $class, $new, $invoke, $invokeSuper, $super, $async, $copy, $await, $asyncReturn, $orDefault, $callNamed, $optionalGet, $optionalInvoke, $spread, $concat, $forOf, $forInKeys, $catchVal, $switch, $staticInvoke, $setKey, $gen, $yield, $fnVal, $regex, $reStateCall, $rethrowIfNudoReturn, $nullishTest, $tryMark, $assignRecord, $recordBinding, $unknown, $importMeta, $dynamicImport, $tryTakeSince, $tryCurrentMark, $tryPopMark, $tryDigestSoftCatch, $tryReleaseSoftOut, $tryDetachSoftCatch, $tryDiscardSoft, $tryOrphanSoft, $pushLoopExit, $objRest, $arrRest, $elems, $arguments, $isForkExit, $rawThis, $isBreakTo } from ${JSON.stringify(runtime)};`;
|
|
11459
|
-
}
|
|
11460
|
-
function transpileFile(file, opts = {}) {
|
|
11461
|
-
const runtime = opts.runtimeImport ?? "@nudojs/core/exec";
|
|
11462
|
-
const lines = [
|
|
11463
|
-
`// nudo evaluator transpile \u2014 values are Abs; operators are overloaded calls`,
|
|
11464
|
-
`import { $add, $sub, $mul, $div, $mod, $bitand, $bitor, $bitxor, $bitnot, $shl, $shr, $ushr, $pow, $toNumber, $toNumeric, $updateAdd, $updateSub, $in, $instanceof, $instanceofNonIdent, $classExpr, $del, $delRes, $objAccessor, $neg, $typeof, $not, $eq, $ne, $eqLoose, $neLoose, $lt, $le, $gt, $ge, $join, $lit, $fork, $for, $forIter, $obj, $get, $set, $setProto, $while, $whileSeq, $arr, $arrWithHoles, $arrMutContainer, $idx, $idxSet, $len, $call, $throw, $loopReturn, $loopBreak, $loopContinue, $class, $new, $invoke, $invokeSuper, $super, $async, $copy, $await, $asyncReturn, $orDefault, $callNamed, $optionalGet, $optionalInvoke, $spread, $concat, $forOf, $forInKeys, $catchVal, $switch, $staticInvoke, $setKey, $gen, $yield, $fnVal, $regex, $reStateCall, $rethrowIfNudoReturn, $nullishTest, $tryMark, $assignRecord, $recordBinding, $unknown, $importMeta, $dynamicImport, $tryTakeSince, $tryCurrentMark, $tryPopMark, $tryDigestSoftCatch, $tryReleaseSoftOut, $tryDetachSoftCatch, $tryDiscardSoft, $tryOrphanSoft, $pushLoopExit, $objRest, $arrRest, $elems, $arguments, $isForkExit, $rawThis, $isBreakTo } from ${JSON.stringify(runtime)};`,
|
|
11465
|
-
``
|
|
11466
|
-
];
|
|
11467
|
-
for (const stmt of file.program.body) {
|
|
11468
|
-
lines.push(transpileStatement(stmt, 0, opts));
|
|
11469
|
-
}
|
|
11470
|
-
return lines.join("\n") + "\n";
|
|
11471
|
-
}
|
|
11472
|
-
function transpile(source, opts) {
|
|
11473
|
-
return transpileSource(source, opts);
|
|
11474
|
-
}
|
|
11475
|
-
|
|
11476
|
-
// src/algebra/exec/runtime/state.ts
|
|
11477
|
-
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
11478
|
-
function writeInPlace(target, next) {
|
|
11479
|
-
target.shape = next.shape;
|
|
11480
|
-
target.conf = next.conf;
|
|
11481
|
-
target.term = void 0;
|
|
11482
|
-
target.pred = void 0;
|
|
11483
|
-
return target;
|
|
11484
|
-
}
|
|
11485
|
-
function clearStaleTermPred(v2) {
|
|
11486
|
-
v2.term = void 0;
|
|
11487
|
-
v2.pred = void 0;
|
|
11488
|
-
}
|
|
11489
|
-
var phi = pTrue;
|
|
11490
|
-
function currentExecPhi() {
|
|
11491
|
-
return phi;
|
|
11492
|
-
}
|
|
11493
|
-
function withExecPhi(p, body) {
|
|
11494
|
-
const prev = phi;
|
|
11495
|
-
phi = p;
|
|
11496
|
-
try {
|
|
11497
|
-
return body();
|
|
11498
|
-
} finally {
|
|
11499
|
-
phi = prev;
|
|
11500
|
-
}
|
|
11501
|
-
}
|
|
11502
|
-
var noBody2 = { type: "BlockStatement", body: [], directives: [] };
|
|
11503
|
-
function asAbsVal(v2) {
|
|
11504
|
-
if (v2 && typeof v2 === "object" && "shape" in v2) return v2;
|
|
11505
|
-
if (typeof v2 === "function") {
|
|
11506
|
-
const n = Math.max(0, v2.length);
|
|
11507
|
-
const params = Array.from({ length: n }, (_, i) => `arg${i}`);
|
|
11508
|
-
return absFunction(params, {
|
|
11509
|
-
body: noBody2,
|
|
11510
|
-
// 与 $fnVal / $callNamed 同边界:callee 的 NudoReturn 不得冒泡成 caller
|
|
11511
|
-
apply: (args) => callAtFunctionBoundary(() => v2(...args))
|
|
11512
|
-
});
|
|
11513
|
-
}
|
|
11514
|
-
return $lit(v2);
|
|
11515
|
-
}
|
|
11516
|
-
function callAtFunctionBoundary(body) {
|
|
11517
|
-
let forwarded = [];
|
|
11518
|
-
try {
|
|
11519
|
-
return runWithLoopExits(() => {
|
|
11520
|
-
try {
|
|
11521
|
-
const r = body();
|
|
11522
|
-
forwarded = takeThrowExits();
|
|
11523
|
-
return r;
|
|
11524
|
-
} catch (e) {
|
|
11525
|
-
forwarded = takeThrowExits();
|
|
11526
|
-
if (isNudoReturn(e)) return e.absValue;
|
|
11527
|
-
throw e;
|
|
11528
|
-
}
|
|
11529
|
-
});
|
|
11530
|
-
} finally {
|
|
11531
|
-
for (const x of forwarded) pushThrowExit(x);
|
|
11532
|
-
}
|
|
11533
|
-
}
|
|
11534
|
-
function $fnVal(params, impl, opts) {
|
|
11535
|
-
return absFunction(params, {
|
|
11536
|
-
body: noBody2,
|
|
11537
|
-
// bindThis(对象方法):receiver 走首参注入,无宿主 this;
|
|
11538
|
-
// 非方法 fn:宿主 this 传递(call/apply/bind 的 thisArg 经 $rawThis 进入函数体)
|
|
11539
|
-
apply: opts?.bindThis ? (args) => callAtFunctionBoundary(() => impl(...args)) : (args, thisVal) => callAtFunctionBoundary(() => impl.apply(thisVal, args)),
|
|
11540
|
-
...opts?.bindThis ? { bindThis: true } : {}
|
|
11541
|
-
});
|
|
11542
|
-
}
|
|
11543
|
-
function $rawThis(v2) {
|
|
11544
|
-
if (v2 === void 0 || v2 === globalThis) return $lit(void 0);
|
|
11545
|
-
if (v2 && typeof v2 === "object" && "shape" in v2) return v2;
|
|
11546
|
-
return $lit(v2);
|
|
11547
|
-
}
|
|
11548
|
-
function throwStrictWrite() {
|
|
11549
|
-
throw new NudoThrow(errorTypeAbs("TypeError"));
|
|
11550
|
-
}
|
|
11551
|
-
function $throwConstAssign() {
|
|
11552
|
-
throw new NudoThrow(errorTypeAbs("TypeError"));
|
|
11553
|
-
}
|
|
11554
|
-
function $litTruth(a) {
|
|
11555
|
-
return litTruth(a);
|
|
11556
|
-
}
|
|
11557
|
-
function $lit(v2) {
|
|
11558
|
-
if (v2 && typeof v2 === "object" && "shape" in v2 && "conf" in v2) {
|
|
11559
|
-
return v2;
|
|
11560
|
-
}
|
|
11561
|
-
return litAbsFromJs(v2);
|
|
11562
|
-
}
|
|
11563
|
-
function litAbsFromJs(v2, depth = 0) {
|
|
11564
|
-
if (v2 === null || v2 === void 0) {
|
|
11565
|
-
return abs({ k: "unknown" }, { op: "lit", value: v2 }, pTrue, "exact");
|
|
11566
|
-
}
|
|
11567
|
-
const t = typeof v2;
|
|
11568
|
-
if (t === "number" || t === "string" || t === "boolean" || t === "bigint") {
|
|
11569
|
-
return abs(
|
|
11570
|
-
{ k: "prim", type: t },
|
|
11571
|
-
{ op: "lit", value: v2 },
|
|
11572
|
-
pTrue,
|
|
11573
|
-
"exact"
|
|
11574
|
-
);
|
|
11575
|
-
}
|
|
11576
|
-
if (depth < 8) {
|
|
11577
|
-
if (Array.isArray(v2)) {
|
|
11578
|
-
const els = v2.map((x) => litAbsFromJs(x, depth + 1));
|
|
11579
|
-
if (shouldWidenArrayLiteral(els.length)) {
|
|
11580
|
-
return abs(
|
|
11581
|
-
{ k: "arr", element: els.reduce((x, y) => joinAbs(x, y)) },
|
|
11582
|
-
void 0,
|
|
11583
|
-
void 0,
|
|
11584
|
-
widenedArrayConf()
|
|
11585
|
-
);
|
|
11586
|
-
}
|
|
11587
|
-
return abs({ k: "tuple", elements: els }, void 0, void 0, "exact");
|
|
11588
|
-
}
|
|
11589
|
-
if (t === "object") {
|
|
11590
|
-
const proto = Object.getPrototypeOf(v2);
|
|
11591
|
-
if (proto === Object.prototype || proto === null) {
|
|
11592
|
-
const slots = {};
|
|
11593
|
-
for (const [k, val] of Object.entries(v2)) {
|
|
11594
|
-
Object.defineProperty(slots, k, {
|
|
11595
|
-
value: { value: litAbsFromJs(val, depth + 1) },
|
|
11596
|
-
enumerable: true,
|
|
11597
|
-
writable: true,
|
|
11598
|
-
configurable: true
|
|
11599
|
-
});
|
|
11600
|
-
}
|
|
11601
|
-
return objOf(slots);
|
|
11602
|
-
}
|
|
11603
|
-
}
|
|
11604
|
-
}
|
|
11605
|
-
return unknown;
|
|
11606
|
-
}
|
|
11607
|
-
function litTruth(a) {
|
|
11608
|
-
if (a.term?.op === "lit") {
|
|
11609
|
-
return Boolean(a.term.value);
|
|
11610
|
-
}
|
|
11611
|
-
switch (a.shape.k) {
|
|
11612
|
-
case "obj":
|
|
11613
|
-
case "arr":
|
|
11614
|
-
case "tuple":
|
|
11615
|
-
case "fn":
|
|
11616
|
-
case "brand":
|
|
11617
|
-
case "eff":
|
|
11618
|
-
return true;
|
|
11619
|
-
case "prim":
|
|
11620
|
-
return a.shape.type === "symbol" ? true : void 0;
|
|
11621
|
-
case "never":
|
|
11622
|
-
return false;
|
|
11934
|
+
return `$fnVal(${nameList}, (${argsParamParts.join(", ")}) => ${bodySrc})`;
|
|
11935
|
+
}
|
|
11936
|
+
case "MetaProperty":
|
|
11937
|
+
return "$importMeta()";
|
|
11938
|
+
case "ImportExpression": {
|
|
11939
|
+
const specSrc = transpileExpression(expr.source, opts);
|
|
11940
|
+
return `$dynamicImport(${specSrc})`;
|
|
11941
|
+
}
|
|
11942
|
+
case "JSXElement":
|
|
11943
|
+
case "JSXFragment":
|
|
11944
|
+
return "$unknown()";
|
|
11623
11945
|
default:
|
|
11624
|
-
|
|
11625
|
-
|
|
11626
|
-
}
|
|
11627
|
-
|
|
11628
|
-
return litTruth(a) === true;
|
|
11629
|
-
}
|
|
11630
|
-
function isDefinitelyFalse(a) {
|
|
11631
|
-
const t = litTruth(a);
|
|
11632
|
-
if (t === false) return true;
|
|
11633
|
-
if (a.shape.k === "never") return true;
|
|
11634
|
-
return false;
|
|
11635
|
-
}
|
|
11636
|
-
function undef() {
|
|
11637
|
-
return abs({ k: "unknown" }, { op: "lit", value: void 0 }, pTrue, "exact");
|
|
11638
|
-
}
|
|
11639
|
-
var loopExitsAls = new AsyncLocalStorage2();
|
|
11640
|
-
var throwExitsAls = new AsyncLocalStorage2();
|
|
11641
|
-
var tryMarksAls = new AsyncLocalStorage2();
|
|
11642
|
-
var softFrameActiveAls = new AsyncLocalStorage2();
|
|
11643
|
-
function runWithLoopExits(body) {
|
|
11644
|
-
return loopExitsAls.run(
|
|
11645
|
-
[],
|
|
11646
|
-
() => throwExitsAls.run(
|
|
11647
|
-
[],
|
|
11648
|
-
() => tryMarksAls.run([], () => softFrameActiveAls.run([], body))
|
|
11649
|
-
)
|
|
11650
|
-
);
|
|
11651
|
-
}
|
|
11652
|
-
function takeLoopExits() {
|
|
11653
|
-
return loopExitsAls.getStore() ?? [];
|
|
11654
|
-
}
|
|
11655
|
-
function takeThrowExits() {
|
|
11656
|
-
return throwExitsAls.getStore() ?? [];
|
|
11657
|
-
}
|
|
11658
|
-
function pushLoopExit(v2) {
|
|
11659
|
-
loopExitsAls.getStore()?.push(v2);
|
|
11660
|
-
}
|
|
11661
|
-
function pushThrowExit(v2) {
|
|
11662
|
-
throwExitsAls.getStore()?.push(v2);
|
|
11663
|
-
}
|
|
11664
|
-
function $pushLoopExit(v2) {
|
|
11665
|
-
pushLoopExit(v2);
|
|
11666
|
-
}
|
|
11667
|
-
function $tryMark() {
|
|
11668
|
-
$tryMarkSoft();
|
|
11669
|
-
softFrameActiveAls.getStore()?.push(true);
|
|
11670
|
-
const store = throwExitsAls.getStore();
|
|
11671
|
-
const m = store?.length ?? 0;
|
|
11672
|
-
tryMarksAls.getStore()?.push(m);
|
|
11673
|
-
return m;
|
|
11674
|
-
}
|
|
11675
|
-
function $tryCurrentMark() {
|
|
11676
|
-
const stack = tryMarksAls.getStore();
|
|
11677
|
-
return stack && stack.length > 0 ? stack[stack.length - 1] : 0;
|
|
11678
|
-
}
|
|
11679
|
-
function $tryPopMark() {
|
|
11680
|
-
tryMarksAls.getStore()?.pop();
|
|
11681
|
-
const soft = softFrameActiveAls.getStore();
|
|
11682
|
-
if (soft && soft.length > 0) {
|
|
11683
|
-
if (soft[soft.length - 1]) $tryReleaseSoftOut();
|
|
11684
|
-
soft.pop();
|
|
11946
|
+
throw new NudoUnsupportedError(
|
|
11947
|
+
`expression:${expr.type}`,
|
|
11948
|
+
expr.loc ? { line: expr.loc.start.line, column: expr.loc.start.column } : void 0
|
|
11949
|
+
);
|
|
11685
11950
|
}
|
|
11686
11951
|
}
|
|
11687
|
-
|
|
11688
|
-
|
|
11689
|
-
|
|
11690
|
-
|
|
11691
|
-
}
|
|
11692
|
-
|
|
11693
|
-
|
|
11694
|
-
if (!store) return [];
|
|
11695
|
-
return store.slice(Math.min(mark, store.length));
|
|
11696
|
-
}
|
|
11697
|
-
function throwExitsMark() {
|
|
11698
|
-
return throwExitsAls.getStore()?.length ?? 0;
|
|
11699
|
-
}
|
|
11700
|
-
function $tryDigestSoftCatch() {
|
|
11701
|
-
const soft = softFrameActiveAls.getStore();
|
|
11702
|
-
if (!soft || soft.length === 0 || !soft[soft.length - 1]) return;
|
|
11703
|
-
$tryDigestSoft();
|
|
11704
|
-
soft[soft.length - 1] = false;
|
|
11705
|
-
}
|
|
11706
|
-
function $tryReleaseSoftCatch() {
|
|
11707
|
-
const soft = softFrameActiveAls.getStore();
|
|
11708
|
-
if (!soft || soft.length === 0 || !soft[soft.length - 1]) return;
|
|
11709
|
-
$tryReleaseSoft();
|
|
11710
|
-
soft[soft.length - 1] = false;
|
|
11711
|
-
}
|
|
11712
|
-
function $tryDetachSoftCatch() {
|
|
11713
|
-
const soft = softFrameActiveAls.getStore();
|
|
11714
|
-
if (!soft || soft.length === 0 || !soft[soft.length - 1]) return [];
|
|
11715
|
-
const effects = popMayThrowFrame(false);
|
|
11716
|
-
soft[soft.length - 1] = false;
|
|
11717
|
-
return effects;
|
|
11718
|
-
}
|
|
11719
|
-
function $tryDiscardSoft(_effects) {
|
|
11720
|
-
}
|
|
11721
|
-
function $tryOrphanSoft(effects) {
|
|
11722
|
-
orphanMayThrowEffects(effects);
|
|
11723
|
-
}
|
|
11724
|
-
function $tryReleaseSoftOut() {
|
|
11725
|
-
const soft = softFrameActiveAls.getStore();
|
|
11726
|
-
if (!soft || soft.length === 0 || !soft[soft.length - 1]) return;
|
|
11727
|
-
$tryReleaseSoft();
|
|
11728
|
-
soft[soft.length - 1] = false;
|
|
11729
|
-
}
|
|
11730
|
-
var NudoReturn = class extends Error {
|
|
11731
|
-
absValue;
|
|
11732
|
-
constructor(absValue) {
|
|
11733
|
-
super("nudo:return");
|
|
11734
|
-
this.name = "NudoReturn";
|
|
11735
|
-
this.absValue = absValue;
|
|
11736
|
-
}
|
|
11737
|
-
};
|
|
11738
|
-
function isNudoReturn(e) {
|
|
11739
|
-
return e instanceof NudoReturn;
|
|
11952
|
+
bindTranspileExpression(transpileExpression);
|
|
11953
|
+
bindTranspileShortCircuit(transpileShortCircuitExpr);
|
|
11954
|
+
|
|
11955
|
+
// src/algebra/exec/transpile.ts
|
|
11956
|
+
function transpileSource(source, opts = {}) {
|
|
11957
|
+
const file = parseSource(source);
|
|
11958
|
+
return transpileFile(file, { ...opts, source: opts.source ?? source });
|
|
11740
11959
|
}
|
|
11741
|
-
function
|
|
11742
|
-
throw new
|
|
11960
|
+
function runtimeImportOf(runtime) {
|
|
11961
|
+
return `import { $add, $sub, $mul, $div, $mod, $bitand, $bitor, $bitxor, $bitnot, $shl, $shr, $ushr, $pow, $toNumber, $toNumeric, $updateAdd, $updateSub, $in, $instanceof, $instanceofNonIdent, $classExpr, $del, $delRes, $objAccessor, $neg, $typeof, $not, $eq, $ne, $eqLoose, $neLoose, $lt, $le, $gt, $ge, $join, $lit, $fork, $for, $forIter, $obj, $get, $set, $setProto, $while, $whileSeq, $arr, $arrWithHoles, $arrMutContainer, $idx, $idxSet, $len, $call, $throw, $loopReturn, $loopBreak, $loopContinue, $class, $new, $invoke, $invokeSuper, $super, $async, $copy, $await, $asyncReturn, $orDefault, $callNamed, $optionalGet, $optionalInvoke, $spread, $concat, $forOf, $forInKeys, $catchVal, $switch, $staticInvoke, $setKey, $gen, $yield, $fnVal, $regex, $reStateCall, $rethrowIfNudoReturn, $nullishTest, $tryMark, $assignRecord, $recordBinding, $unknown, $importMeta, $dynamicImport, $tryTakeSince, $tryCurrentMark, $tryPopMark, $tryDigestSoftCatch, $tryReleaseSoftOut, $tryDetachSoftCatch, $tryDiscardSoft, $tryOrphanSoft, $pushLoopExit, $objRest, $arrRest, $elems, $arguments, $isForkExit, $rawThis, $isBreakTo } from ${JSON.stringify(runtime)};`;
|
|
11743
11962
|
}
|
|
11744
|
-
|
|
11745
|
-
|
|
11746
|
-
|
|
11747
|
-
|
|
11748
|
-
super(
|
|
11749
|
-
|
|
11750
|
-
|
|
11751
|
-
|
|
11963
|
+
function transpileFile(file, opts = {}) {
|
|
11964
|
+
const runtime = opts.runtimeImport ?? "@nudojs/core/exec";
|
|
11965
|
+
const lines = [
|
|
11966
|
+
`// nudo evaluator transpile \u2014 values are Abs; operators are overloaded calls`,
|
|
11967
|
+
`import { $add, $sub, $mul, $div, $mod, $bitand, $bitor, $bitxor, $bitnot, $shl, $shr, $ushr, $pow, $toNumber, $toNumeric, $updateAdd, $updateSub, $in, $instanceof, $instanceofNonIdent, $classExpr, $del, $delRes, $objAccessor, $neg, $typeof, $not, $eq, $ne, $eqLoose, $neLoose, $lt, $le, $gt, $ge, $join, $lit, $fork, $for, $forIter, $obj, $get, $set, $setProto, $while, $whileSeq, $arr, $arrWithHoles, $arrMutContainer, $idx, $idxSet, $len, $call, $throw, $loopReturn, $loopBreak, $loopContinue, $class, $new, $invoke, $invokeSuper, $super, $async, $copy, $await, $asyncReturn, $orDefault, $callNamed, $optionalGet, $optionalInvoke, $spread, $concat, $forOf, $forInKeys, $catchVal, $switch, $staticInvoke, $setKey, $gen, $yield, $fnVal, $regex, $reStateCall, $rethrowIfNudoReturn, $nullishTest, $tryMark, $assignRecord, $recordBinding, $unknown, $importMeta, $dynamicImport, $tryTakeSince, $tryCurrentMark, $tryPopMark, $tryDigestSoftCatch, $tryReleaseSoftOut, $tryDetachSoftCatch, $tryDiscardSoft, $tryOrphanSoft, $pushLoopExit, $objRest, $arrRest, $elems, $arguments, $isForkExit, $rawThis, $isBreakTo } from ${JSON.stringify(runtime)};`,
|
|
11968
|
+
``
|
|
11969
|
+
];
|
|
11970
|
+
for (const stmt of file.program.body) {
|
|
11971
|
+
lines.push(transpileStatement(stmt, 0, opts));
|
|
11752
11972
|
}
|
|
11753
|
-
|
|
11754
|
-
function $loopBreak(label) {
|
|
11755
|
-
throw new NudoLoopSignal("break", label || void 0);
|
|
11756
|
-
}
|
|
11757
|
-
function $loopContinue(label) {
|
|
11758
|
-
throw new NudoLoopSignal("continue", label || void 0);
|
|
11759
|
-
}
|
|
11760
|
-
function loopSignalMatches(e, label) {
|
|
11761
|
-
return e.label === void 0 || e.label === label;
|
|
11762
|
-
}
|
|
11763
|
-
function isNudoBreak(e, label) {
|
|
11764
|
-
return e instanceof NudoLoopSignal && e.kind === "break" && loopSignalMatches(e, label);
|
|
11765
|
-
}
|
|
11766
|
-
function isNudoContinue(e, label) {
|
|
11767
|
-
return e instanceof NudoLoopSignal && e.kind === "continue" && loopSignalMatches(e, label);
|
|
11768
|
-
}
|
|
11769
|
-
function $isBreakTo(e, label) {
|
|
11770
|
-
return e instanceof NudoLoopSignal && e.kind === "break" && e.label === label;
|
|
11973
|
+
return lines.join("\n") + "\n";
|
|
11771
11974
|
}
|
|
11772
|
-
function
|
|
11773
|
-
|
|
11975
|
+
function transpile(source, opts) {
|
|
11976
|
+
return transpileSource(source, opts);
|
|
11774
11977
|
}
|
|
11775
11978
|
|
|
11776
11979
|
// src/algebra/exec/runtime/ops.ts
|
|
@@ -13052,7 +13255,7 @@ function $get(o, key, opts) {
|
|
|
13052
13255
|
const raw = o[key];
|
|
13053
13256
|
if (typeof raw === "function") {
|
|
13054
13257
|
return absFunction([`${ns}.${key}`], {
|
|
13055
|
-
body:
|
|
13258
|
+
body: noBody,
|
|
13056
13259
|
apply: (args) => evalNamespaceCall(ns, key, args) ?? unknown
|
|
13057
13260
|
});
|
|
13058
13261
|
}
|
|
@@ -13071,7 +13274,7 @@ function $get(o, key, opts) {
|
|
|
13071
13274
|
}
|
|
13072
13275
|
if (o.shape.k === "eff" && o.shape.eff === "promise" && (key === "then" || key === "catch" || key === "finally")) {
|
|
13073
13276
|
return absFunction([key === "then" ? "onFulfilled" : key === "catch" ? "onRejected" : "onFinally"], {
|
|
13074
|
-
body:
|
|
13277
|
+
body: noBody
|
|
13075
13278
|
});
|
|
13076
13279
|
}
|
|
13077
13280
|
if (o.shape.k === "brand") {
|
|
@@ -13082,7 +13285,7 @@ function $get(o, key, opts) {
|
|
|
13082
13285
|
const isClassVal = classNameOfValue(o) === o.shape.name;
|
|
13083
13286
|
const builtinM = BUILTIN_BRAND_METHODS[o.shape.name];
|
|
13084
13287
|
if (builtinM && !isClassVal && (key === "@@iterator" || builtinM.has(key))) {
|
|
13085
|
-
return absFunction([], { body:
|
|
13288
|
+
return absFunction([], { body: noBody });
|
|
13086
13289
|
}
|
|
13087
13290
|
if (key === "size" && o.shape.name === "Map") return mapSizeAbs(o);
|
|
13088
13291
|
if (key === "size" && o.shape.name === "Set") return setSizeAbs(o);
|
|
@@ -13098,14 +13301,14 @@ function $get(o, key, opts) {
|
|
|
13098
13301
|
for (const n of evalClassChain(o.shape.name)) {
|
|
13099
13302
|
const spec = getEvalClass(n);
|
|
13100
13303
|
if (spec?.staticMethods?.[key]) {
|
|
13101
|
-
return absFunction(spec.staticMethodParams?.[key] ?? [], { body:
|
|
13304
|
+
return absFunction(spec.staticMethodParams?.[key] ?? [], { body: noBody });
|
|
13102
13305
|
}
|
|
13103
13306
|
}
|
|
13104
13307
|
if (key === "prototype") {
|
|
13105
13308
|
return abs({ k: "obj", slots: {} }, void 0, void 0, "path");
|
|
13106
13309
|
}
|
|
13107
13310
|
if (key === "call" || key === "apply" || key === "bind") {
|
|
13108
|
-
return absFunction([], { body:
|
|
13311
|
+
return absFunction([], { body: noBody });
|
|
13109
13312
|
}
|
|
13110
13313
|
} else {
|
|
13111
13314
|
const acc = findClassAccessor(o.shape.name, key);
|
|
@@ -13114,7 +13317,7 @@ function $get(o, key, opts) {
|
|
|
13114
13317
|
for (const n of evalClassChain(o.shape.name)) {
|
|
13115
13318
|
const spec = getEvalClass(n);
|
|
13116
13319
|
if (spec?.methods?.[key]) {
|
|
13117
|
-
return absFunction(spec.methodParams?.[key] ?? [], { body:
|
|
13320
|
+
return absFunction(spec.methodParams?.[key] ?? [], { body: noBody });
|
|
13118
13321
|
}
|
|
13119
13322
|
}
|
|
13120
13323
|
}
|
|
@@ -16535,7 +16738,7 @@ function $instanceofNonIdent(_left) {
|
|
|
16535
16738
|
}
|
|
16536
16739
|
function $classExpr() {
|
|
16537
16740
|
return absFunction(["_rest"], {
|
|
16538
|
-
body:
|
|
16741
|
+
body: noBody,
|
|
16539
16742
|
apply: () => unknown
|
|
16540
16743
|
});
|
|
16541
16744
|
}
|
|
@@ -16797,6 +17000,43 @@ export {
|
|
|
16797
17000
|
getPropFlags,
|
|
16798
17001
|
setPropFlags,
|
|
16799
17002
|
migrateInvariants,
|
|
17003
|
+
clearStaleTermPred,
|
|
17004
|
+
currentExecPhi,
|
|
17005
|
+
withExecPhi,
|
|
17006
|
+
asAbsVal,
|
|
17007
|
+
callAtFunctionBoundary,
|
|
17008
|
+
$fnVal,
|
|
17009
|
+
$rawThis,
|
|
17010
|
+
$lit,
|
|
17011
|
+
litTruth,
|
|
17012
|
+
isDefinitelyTrue,
|
|
17013
|
+
isDefinitelyFalse,
|
|
17014
|
+
runWithLoopExits,
|
|
17015
|
+
takeLoopExits,
|
|
17016
|
+
takeThrowExits,
|
|
17017
|
+
pushLoopExit,
|
|
17018
|
+
pushThrowExit,
|
|
17019
|
+
$pushLoopExit,
|
|
17020
|
+
$tryMark,
|
|
17021
|
+
$tryCurrentMark,
|
|
17022
|
+
$tryPopMark,
|
|
17023
|
+
$tryTakeSince,
|
|
17024
|
+
$tryDigestSoftCatch,
|
|
17025
|
+
$tryReleaseSoftCatch,
|
|
17026
|
+
$tryDetachSoftCatch,
|
|
17027
|
+
$tryDiscardSoft,
|
|
17028
|
+
$tryOrphanSoft,
|
|
17029
|
+
$tryReleaseSoftOut,
|
|
17030
|
+
NudoReturn,
|
|
17031
|
+
isNudoReturn,
|
|
17032
|
+
$loopReturn,
|
|
17033
|
+
NudoLoopSignal,
|
|
17034
|
+
$loopBreak,
|
|
17035
|
+
$loopContinue,
|
|
17036
|
+
isNudoBreak,
|
|
17037
|
+
isNudoContinue,
|
|
17038
|
+
$isBreakTo,
|
|
17039
|
+
$rethrowIfNudoReturn,
|
|
16800
17040
|
evalMathMethod,
|
|
16801
17041
|
builtinCtorAbs,
|
|
16802
17042
|
builtinCtorNameOf,
|
|
@@ -16965,43 +17205,6 @@ export {
|
|
|
16965
17205
|
runtimeImportOf,
|
|
16966
17206
|
transpileFile,
|
|
16967
17207
|
transpile,
|
|
16968
|
-
clearStaleTermPred,
|
|
16969
|
-
currentExecPhi,
|
|
16970
|
-
withExecPhi,
|
|
16971
|
-
asAbsVal,
|
|
16972
|
-
callAtFunctionBoundary,
|
|
16973
|
-
$fnVal,
|
|
16974
|
-
$rawThis,
|
|
16975
|
-
$lit,
|
|
16976
|
-
litTruth,
|
|
16977
|
-
isDefinitelyTrue,
|
|
16978
|
-
isDefinitelyFalse,
|
|
16979
|
-
runWithLoopExits,
|
|
16980
|
-
takeLoopExits,
|
|
16981
|
-
takeThrowExits,
|
|
16982
|
-
pushLoopExit,
|
|
16983
|
-
pushThrowExit,
|
|
16984
|
-
$pushLoopExit,
|
|
16985
|
-
$tryMark,
|
|
16986
|
-
$tryCurrentMark,
|
|
16987
|
-
$tryPopMark,
|
|
16988
|
-
$tryTakeSince,
|
|
16989
|
-
$tryDigestSoftCatch,
|
|
16990
|
-
$tryReleaseSoftCatch,
|
|
16991
|
-
$tryDetachSoftCatch,
|
|
16992
|
-
$tryDiscardSoft,
|
|
16993
|
-
$tryOrphanSoft,
|
|
16994
|
-
$tryReleaseSoftOut,
|
|
16995
|
-
NudoReturn,
|
|
16996
|
-
isNudoReturn,
|
|
16997
|
-
$loopReturn,
|
|
16998
|
-
NudoLoopSignal,
|
|
16999
|
-
$loopBreak,
|
|
17000
|
-
$loopContinue,
|
|
17001
|
-
isNudoBreak,
|
|
17002
|
-
isNudoContinue,
|
|
17003
|
-
$isBreakTo,
|
|
17004
|
-
$rethrowIfNudoReturn,
|
|
17005
17208
|
$unknown,
|
|
17006
17209
|
$importMeta,
|
|
17007
17210
|
$dynamicImport,
|
package/dist/exec.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -365,7 +365,12 @@ declare function setPropFlags(o: Abs, key: string, f: PropFlags): void;
|
|
|
365
365
|
declare function migrateInvariants(from: Abs, to: Abs): void;
|
|
366
366
|
|
|
367
367
|
/**
|
|
368
|
-
* Math.* — 字面量实参走 ToNumber/ToInt32
|
|
368
|
+
* Math.* — 字面量实参走 ToNumber/ToInt32 后调用原生折叠;非字面量对
|
|
369
|
+
* min/max/round/floor/ceil/trunc 透传数值区间(#68)。
|
|
370
|
+
*
|
|
371
|
+
* NaN 策略(DEC:显式 NaN 臂):操作数可能为 NaN 时结果为
|
|
372
|
+
* `NaN | number@bounds`。契约 `ge(0).le(100)` 对 NaN 臂诚实报违例;
|
|
373
|
+
* `if (Number.isNaN(n)) return …` 假臂的 `ne(n, NaN)` 事实可排除 NaN 臂。
|
|
369
374
|
*/
|
|
370
375
|
|
|
371
376
|
declare function evalMathMethod(name: string, args: Abs[]): Abs | undefined;
|
package/dist/index.js
CHANGED
|
@@ -91,7 +91,7 @@ import {
|
|
|
91
91
|
takeRefineDiagsSince,
|
|
92
92
|
throwConstraintToKinds,
|
|
93
93
|
union
|
|
94
|
-
} from "./chunk-
|
|
94
|
+
} from "./chunk-YO4GKCNE.js";
|
|
95
95
|
import {
|
|
96
96
|
$add,
|
|
97
97
|
$arguments,
|
|
@@ -507,7 +507,7 @@ import {
|
|
|
507
507
|
v,
|
|
508
508
|
withExecPhi,
|
|
509
509
|
withVar
|
|
510
|
-
} from "./chunk-
|
|
510
|
+
} from "./chunk-W2MP6REI.js";
|
|
511
511
|
|
|
512
512
|
// src/environment.ts
|
|
513
513
|
function createEnvironment(parent, bindings = /* @__PURE__ */ new Map()) {
|
|
@@ -768,60 +768,92 @@ function isBoundedEvidenceMissing(ret, constraint) {
|
|
|
768
768
|
if (ret.pred && ret.pred.op !== "true") return false;
|
|
769
769
|
return true;
|
|
770
770
|
}
|
|
771
|
+
function flattenSumArms(ret) {
|
|
772
|
+
if (ret.shape.k !== "sum") return [ret];
|
|
773
|
+
const out = [];
|
|
774
|
+
for (const m of ret.shape.members) {
|
|
775
|
+
if (m.shape.k === "sum") out.push(...flattenSumArms(m));
|
|
776
|
+
else out.push(m);
|
|
777
|
+
}
|
|
778
|
+
return out;
|
|
779
|
+
}
|
|
780
|
+
function isWidenedSumArm(m, parent) {
|
|
781
|
+
return parent.conf === "partial" && m.shape.k === "prim" && !m.term && (!m.pred || m.pred.op === "true");
|
|
782
|
+
}
|
|
771
783
|
function assertImplies(ret, constraint, opts) {
|
|
772
784
|
const phi = opts?.phi ?? pTrue;
|
|
773
785
|
if (ret.shape.k === "never") return proved();
|
|
774
786
|
if (isAnyConstraint(constraint)) return proved();
|
|
775
|
-
const nullishOk = constraintAdmitsNullish(constraint);
|
|
776
|
-
if (isNullishLitAbs(ret)) {
|
|
777
|
-
return nullishOk ? proved() : disproved(`nullish return \u22AD ${formatConstraint(constraint)}`);
|
|
778
|
-
}
|
|
779
|
-
let sumMembers;
|
|
780
|
-
if (ret.shape.k === "sum") {
|
|
781
|
-
const members = ret.shape.members;
|
|
782
|
-
const nullishMembers = members.filter((m) => isNullishLitAbs(m));
|
|
783
|
-
if (nullishMembers.length > 0 && !nullishOk) {
|
|
784
|
-
return disproved(
|
|
785
|
-
`nullish return arm \u22AD ${formatConstraint(constraint)} (contract does not admit nullish)`
|
|
786
|
-
);
|
|
787
|
-
}
|
|
788
|
-
sumMembers = members.filter((m) => !isNullishLitAbs(m));
|
|
789
|
-
}
|
|
790
787
|
if (isValueSetUnknown(ret)) {
|
|
791
788
|
return unprovable(
|
|
792
789
|
ret.shape.k === "any" ? "any does not establish the return contract" : "inference failure (unknown/opaque) \u2014 cannot prove the return contract"
|
|
793
790
|
);
|
|
794
791
|
}
|
|
792
|
+
const arms = flattenSumArms(ret);
|
|
793
|
+
if (arms.length > 1) {
|
|
794
|
+
return assertSumArms(arms, ret, constraint, opts, phi);
|
|
795
|
+
}
|
|
796
|
+
return assertImpliesSingle(arms[0], constraint, opts, phi);
|
|
797
|
+
}
|
|
798
|
+
function assertSumArms(arms, parent, constraint, opts, phi) {
|
|
799
|
+
const hasWidenedArm = arms.some(
|
|
800
|
+
(a) => isValueSetUnknown(a) || isWidenedSumArm(a, parent)
|
|
801
|
+
);
|
|
802
|
+
let sawUnprovable = false;
|
|
803
|
+
for (const arm of arms) {
|
|
804
|
+
if (isNullishLitAbs(arm)) {
|
|
805
|
+
if (!constraintAdmitsNullish(constraint)) {
|
|
806
|
+
return disproved(
|
|
807
|
+
`nullish return arm \u22AD ${formatConstraint(constraint)} (contract does not admit nullish)`
|
|
808
|
+
);
|
|
809
|
+
}
|
|
810
|
+
continue;
|
|
811
|
+
}
|
|
812
|
+
if (isValueSetUnknown(arm) || isWidenedSumArm(arm, parent)) {
|
|
813
|
+
sawUnprovable = true;
|
|
814
|
+
continue;
|
|
815
|
+
}
|
|
816
|
+
const r = assertImpliesSingle(arm, constraint, opts, phi);
|
|
817
|
+
if (r.status === "disproved") {
|
|
818
|
+
if (hasWidenedArm) {
|
|
819
|
+
sawUnprovable = true;
|
|
820
|
+
continue;
|
|
821
|
+
}
|
|
822
|
+
return r;
|
|
823
|
+
}
|
|
824
|
+
if (r.status === "unprovable") sawUnprovable = true;
|
|
825
|
+
}
|
|
826
|
+
return sawUnprovable ? unprovable("sum: some arms unprovable") : proved();
|
|
827
|
+
}
|
|
828
|
+
function assertImpliesSingle(arm, constraint, opts, phi) {
|
|
829
|
+
if (isNullishLitAbs(arm)) {
|
|
830
|
+
return constraintAdmitsNullish(constraint) ? proved() : disproved(`nullish return \u22AD ${formatConstraint(constraint)}`);
|
|
831
|
+
}
|
|
832
|
+
if (isValueSetUnknown(arm)) {
|
|
833
|
+
return unprovable(
|
|
834
|
+
arm.shape.k === "any" ? "any does not establish the return contract" : "inference failure (unknown/opaque) \u2014 cannot prove the return contract"
|
|
835
|
+
);
|
|
836
|
+
}
|
|
795
837
|
if (constraint.members && constraint.members.length > 0) {
|
|
796
838
|
let sawUnprovable = false;
|
|
797
839
|
for (const m of constraint.members) {
|
|
798
|
-
const r = assertImplies(
|
|
840
|
+
const r = assertImplies(arm, m, opts);
|
|
799
841
|
if (r.status === "proved") return proved();
|
|
800
842
|
if (r.status === "unprovable") sawUnprovable = true;
|
|
801
843
|
}
|
|
802
844
|
return sawUnprovable ? unprovable("union: no member proved the return contract") : disproved(`return \u22AD union(${constraint.members.map((m) => formatConstraint(m)).join(", ")})`);
|
|
803
845
|
}
|
|
804
|
-
if (sumMembers && (constraint.fields || constraint.element)) {
|
|
805
|
-
let sawUnprovable = false;
|
|
806
|
-
for (const m of sumMembers) {
|
|
807
|
-
if (isValueSetUnknown(m)) continue;
|
|
808
|
-
const r = assertImplies(m, constraint, opts);
|
|
809
|
-
if (r.status === "disproved") return r;
|
|
810
|
-
if (r.status === "unprovable") sawUnprovable = true;
|
|
811
|
-
}
|
|
812
|
-
return sawUnprovable ? unprovable("sum: some arms unprovable") : proved();
|
|
813
|
-
}
|
|
814
846
|
if (constraint.fields) {
|
|
815
|
-
return assertShapeFields(
|
|
847
|
+
return assertShapeFields(arm, constraint, opts);
|
|
816
848
|
}
|
|
817
849
|
if (constraint.element) {
|
|
818
|
-
if (
|
|
819
|
-
return disproved(`return shape ${
|
|
850
|
+
if (arm.shape.k !== "arr" && arm.shape.k !== "tuple") {
|
|
851
|
+
return disproved(`return shape ${arm.shape.k} \u22AD array(...)`);
|
|
820
852
|
}
|
|
821
853
|
return proved();
|
|
822
854
|
}
|
|
823
855
|
if (constraint.fn) return proved();
|
|
824
|
-
return assertScalar(
|
|
856
|
+
return assertScalar(arm, constraint, phi);
|
|
825
857
|
}
|
|
826
858
|
function isAnyConstraint(c) {
|
|
827
859
|
return !c.prim && c.preds.length === 0 && !c.fields && !c.element && !c.members && !c.fn && !isIntFlag(c);
|
|
@@ -2214,7 +2246,7 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
|
|
|
2214
2246
|
message: `${name} (export): may throw ${gateDisplay}`,
|
|
2215
2247
|
actual: `${name}(\u2026) throws ${gateDisplay}`,
|
|
2216
2248
|
expected: "entry total, or @nudo:throws / try-catch",
|
|
2217
|
-
suggestion: first.cause ? `${first.cause} \u2192 ${first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind}
|
|
2249
|
+
suggestion: first.cause ? `${first.cause} \u2192 ${first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind} | sidecar: fn({ \u2026 }): shape({ <body-read fields> }) | refine / guard / try-catch`}` : first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind} | sidecar: fn({ \u2026 }): shape({ <body-read fields> }) | refine / guard / try-catch`,
|
|
2218
2250
|
fn: name,
|
|
2219
2251
|
...loc.line !== void 0 ? { line: loc.line } : {},
|
|
2220
2252
|
...loc.column !== void 0 ? { column: loc.column } : {}
|
|
@@ -2259,7 +2291,7 @@ function checkSourceInner(filePath, source, file, phi, opts, issues, signatures,
|
|
|
2259
2291
|
message: `${name} (export): may throw ${gateDisplay}`,
|
|
2260
2292
|
actual: `${formatEntrySigLine(name, g, gateDisplay)}`,
|
|
2261
2293
|
expected: "entry total, or @nudo:throws / try-catch",
|
|
2262
|
-
suggestion: first.cause ? `${first.cause} \u2192 ${first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind}
|
|
2294
|
+
suggestion: first.cause ? `${first.cause} \u2192 ${first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind} | sidecar: fn({ \u2026 }): shape({ <body-read fields> }) | refine / guard / try-catch`}` : first.kind === "ReferenceError" ? "re-export `export { x } from` \u4E0D\u662F\u5C40\u90E8\u7ED1\u5B9A\u2014\u2014\u6539 `import { x }` / @nudo:throws ReferenceError" : `@nudo:throws ${first.kind} | sidecar: fn({ \u2026 }): shape({ <body-read fields> }) | refine / guard / try-catch`,
|
|
2263
2295
|
fn: name,
|
|
2264
2296
|
...loc.line !== void 0 ? { line: loc.line } : {},
|
|
2265
2297
|
...loc.column !== void 0 ? { column: loc.column } : {}
|
|
@@ -2627,6 +2659,19 @@ function actionsForIssue(i) {
|
|
|
2627
2659
|
label: "migration switch: ignore this throw class on L2"
|
|
2628
2660
|
}
|
|
2629
2661
|
];
|
|
2662
|
+
case "nudo:unproven-return":
|
|
2663
|
+
return [
|
|
2664
|
+
{
|
|
2665
|
+
kind: "relax",
|
|
2666
|
+
label: `relax the return contract${i.fn ? ` of ${i.fn}` : ""} to the inferred surface (review the diff \u2014 not a silent green)`,
|
|
2667
|
+
...i.expected ? { hint: i.expected } : {}
|
|
2668
|
+
},
|
|
2669
|
+
draft,
|
|
2670
|
+
{
|
|
2671
|
+
kind: "info",
|
|
2672
|
+
label: "or narrow the return expression / add a precondition so the bound is implied"
|
|
2673
|
+
}
|
|
2674
|
+
];
|
|
2630
2675
|
case "nudo:unknown-inference":
|
|
2631
2676
|
case "nudo:opaque-result":
|
|
2632
2677
|
return [
|
package/dist/internal.js
CHANGED
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
stableAnalyzeKeySource,
|
|
19
19
|
stablePathKey,
|
|
20
20
|
stablePathKeyGraph
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-YO4GKCNE.js";
|
|
22
22
|
import {
|
|
23
23
|
$tryDigestSoft,
|
|
24
24
|
$tryMarkSoft,
|
|
@@ -157,7 +157,7 @@ import {
|
|
|
157
157
|
withEvalBudgetOverride,
|
|
158
158
|
withFnBudgetOverride,
|
|
159
159
|
wrapPromise
|
|
160
|
-
} from "./chunk-
|
|
160
|
+
} from "./chunk-W2MP6REI.js";
|
|
161
161
|
|
|
162
162
|
// src/algebra/inlay.ts
|
|
163
163
|
function listFunctions(source) {
|