@nudojs/core 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-BU4A6XJ3.js +6856 -0
- package/dist/exec.d.ts +2 -0
- package/dist/exec.js +168 -0
- package/dist/index-CVYjXnwU.d.ts +902 -0
- package/dist/index.d.ts +64 -710
- package/dist/index.js +3258 -8426
- package/package.json +18 -5
- package/CHANGELOG.md +0 -34
- package/src/__tests__/environment.test.ts +0 -48
- package/src/__tests__/fn-sig-impl.test.ts +0 -57
- package/src/__tests__/ops-refined.test.ts +0 -196
- package/src/__tests__/ops.test.ts +0 -84
- package/src/__tests__/type-value-phase2.test.ts +0 -117
- package/src/__tests__/type-value-phase3.test.ts +0 -94
- package/src/__tests__/type-value-refined.test.ts +0 -210
- package/src/__tests__/type-value.test.ts +0 -319
- package/src/algebra/__tests__/abs-native.test.ts +0 -176
- package/src/algebra/__tests__/arithmetic.test.ts +0 -170
- package/src/algebra/__tests__/ast-eval.test.ts +0 -154
- package/src/algebra/__tests__/bridge.test.ts +0 -160
- package/src/algebra/__tests__/call-budget.test.ts +0 -117
- package/src/algebra/__tests__/check-case-consistency.test.ts +0 -69
- package/src/algebra/__tests__/check-gold.test.ts +0 -290
- package/src/algebra/__tests__/check-json.test.ts +0 -57
- package/src/algebra/__tests__/check-mini-repo.test.ts +0 -49
- package/src/algebra/__tests__/check-real-commander.test.ts +0 -43
- package/src/algebra/__tests__/check-real-packages.test.ts +0 -165
- package/src/algebra/__tests__/check-recall-gold.test.ts +0 -1024
- package/src/algebra/__tests__/check-require-dep-memo.test.ts +0 -45
- package/src/algebra/__tests__/check-return-contract.test.ts +0 -90
- package/src/algebra/__tests__/check-shape-gold.test.ts +0 -303
- package/src/algebra/__tests__/check-source-memo.test.ts +0 -204
- package/src/algebra/__tests__/check.test.ts +0 -69
- package/src/algebra/__tests__/denote.test.ts +0 -77
- package/src/algebra/__tests__/diagnostics.test.ts +0 -64
- package/src/algebra/__tests__/differential.test.ts +0 -124
- package/src/algebra/__tests__/div-mod.test.ts +0 -38
- package/src/algebra/__tests__/example0.test.ts +0 -103
- package/src/algebra/__tests__/exec-analyze-throws.test.ts +0 -60
- package/src/algebra/__tests__/exec-async.test.ts +0 -46
- package/src/algebra/__tests__/exec-bpath.test.ts +0 -193
- package/src/algebra/__tests__/exec-class.test.ts +0 -56
- package/src/algebra/__tests__/exec-e2e.test.ts +0 -97
- package/src/algebra/__tests__/exec-generator.test.ts +0 -53
- package/src/algebra/__tests__/exec-inherit-default.test.ts +0 -111
- package/src/algebra/__tests__/exec-optional-nested.test.ts +0 -87
- package/src/algebra/__tests__/exec-rest.test.ts +0 -55
- package/src/algebra/__tests__/exec-spread-forof.test.ts +0 -85
- package/src/algebra/__tests__/exec-static-computed.test.ts +0 -61
- package/src/algebra/__tests__/exec-switch.test.ts +0 -74
- package/src/algebra/__tests__/exec-trycatch.test.ts +0 -71
- package/src/algebra/__tests__/fn-fp-memo.test.ts +0 -166
- package/src/algebra/__tests__/fn-fp-multidecl.test.ts +0 -49
- package/src/algebra/__tests__/format.test.ts +0 -34
- package/src/algebra/__tests__/generalize-memo.test.ts +0 -285
- package/src/algebra/__tests__/generalize.test.ts +0 -113
- package/src/algebra/__tests__/hash-source.test.ts +0 -19
- package/src/algebra/__tests__/hof.test.ts +0 -80
- package/src/algebra/__tests__/inlay.test.ts +0 -30
- package/src/algebra/__tests__/language.test.ts +0 -77
- package/src/algebra/__tests__/leq.test.ts +0 -109
- package/src/algebra/__tests__/load-deps-fp-memo.test.ts +0 -132
- package/src/algebra/__tests__/methods.test.ts +0 -37
- package/src/algebra/__tests__/node-types.test.ts +0 -26
- package/src/algebra/__tests__/nudo-constraints.ts +0 -46
- package/src/algebra/__tests__/objects.test.ts +0 -117
- package/src/algebra/__tests__/parse-source-cache.test.ts +0 -42
- package/src/algebra/__tests__/refine-import.test.ts +0 -109
- package/src/algebra/__tests__/stable-source-key-block.test.ts +0 -23
- package/src/algebra/__tests__/stable-source-key.test.ts +0 -31
- package/src/algebra/__tests__/surface.test.ts +0 -41
- package/src/algebra/__tests__/this-inherit.test.ts +0 -130
- package/src/algebra/abs-fn.ts +0 -49
- package/src/algebra/abs-modules.ts +0 -139
- package/src/algebra/abs.ts +0 -206
- package/src/algebra/arithmetic.ts +0 -691
- package/src/algebra/ast-eval.ts +0 -1763
- package/src/algebra/bridge.ts +0 -350
- package/src/algebra/builtins.ts +0 -373
- package/src/algebra/check-report.ts +0 -150
- package/src/algebra/check.ts +0 -1867
- package/src/algebra/constraint.ts +0 -304
- package/src/algebra/denote.ts +0 -166
- package/src/algebra/diagnostics.ts +0 -210
- package/src/algebra/exec/call.ts +0 -29
- package/src/algebra/exec/calls.ts +0 -96
- package/src/algebra/exec/class-registry.ts +0 -29
- package/src/algebra/exec/class.ts +0 -329
- package/src/algebra/exec/index.ts +0 -6
- package/src/algebra/exec/member-diag.ts +0 -141
- package/src/algebra/exec/run.ts +0 -341
- package/src/algebra/exec/runtime.ts +0 -583
- package/src/algebra/exec/transpile.ts +0 -993
- package/src/algebra/fn-fp.ts +0 -294
- package/src/algebra/format.ts +0 -91
- package/src/algebra/generalize.ts +0 -776
- package/src/algebra/hash-source.ts +0 -27
- package/src/algebra/index.ts +0 -34
- package/src/algebra/inlay.ts +0 -198
- package/src/algebra/language.ts +0 -289
- package/src/algebra/leak.ts +0 -68
- package/src/algebra/leq.ts +0 -301
- package/src/algebra/load-deps-fp.ts +0 -97
- package/src/algebra/methods.ts +0 -128
- package/src/algebra/objects.ts +0 -251
- package/src/algebra/parse-source.ts +0 -64
- package/src/algebra/phi.ts +0 -42
- package/src/algebra/pred.ts +0 -395
- package/src/algebra/refine.ts +0 -227
- package/src/algebra/stable-source-key.ts +0 -81
- package/src/algebra/surface.ts +0 -206
- package/src/algebra/template.ts +0 -143
- package/src/algebra/term.ts +0 -119
- package/src/environment.ts +0 -74
- package/src/index.ts +0 -73
- package/src/mock-helpers.ts +0 -166
- package/src/ops.ts +0 -191
- package/src/refinements/range.ts +0 -86
- package/src/refinements/template-predicates.ts +0 -11
- package/src/refinements/template.ts +0 -176
- package/src/strip-types.ts +0 -236
- package/src/type-value.ts +0 -513
- package/tsconfig.json +0 -8
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* B 路径调用点记录:transpile 把 `f(args)` 改成 $callNamed,
|
|
3
|
-
* 分析时可收集 call@ 所需的 AbsCallRecord。
|
|
4
|
-
* 成员缺失诊断见 member-diag.ts(与 ast-eval 共用,避免循环依赖)。
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { Abs } from "../abs.ts";
|
|
8
|
-
import { unknown } from "../abs.ts";
|
|
9
|
-
import { $call } from "./call.ts";
|
|
10
|
-
import {
|
|
11
|
-
tagAbsOrigin,
|
|
12
|
-
pushCallLoc,
|
|
13
|
-
popCallLoc,
|
|
14
|
-
} from "./member-diag.ts";
|
|
15
|
-
|
|
16
|
-
export type {
|
|
17
|
-
BMemberDiag,
|
|
18
|
-
} from "./member-diag.ts";
|
|
19
|
-
export {
|
|
20
|
-
setMemberDiagCollector,
|
|
21
|
-
recordMemberDiag,
|
|
22
|
-
notePrimMemberMissing,
|
|
23
|
-
noteUnknownMemberMissing,
|
|
24
|
-
noteMemberDispatchMiss,
|
|
25
|
-
tagAbsOrigin,
|
|
26
|
-
getAbsOrigin,
|
|
27
|
-
} from "./member-diag.ts";
|
|
28
|
-
|
|
29
|
-
export type BCallRecord = {
|
|
30
|
-
fnName: string;
|
|
31
|
-
args: Abs[];
|
|
32
|
-
result: Abs;
|
|
33
|
-
callLoc?: { line: number; column: number };
|
|
34
|
-
threw?: boolean;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
let bCallCollector: ((r: BCallRecord) => void) | null = null;
|
|
38
|
-
|
|
39
|
-
export function setBCallCollector(
|
|
40
|
-
collector: ((r: BCallRecord) => void) | null,
|
|
41
|
-
): void {
|
|
42
|
-
bCallCollector = collector;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function getBCallCollector(): ((r: BCallRecord) => void) | null {
|
|
46
|
-
return bCallCollector;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* 按名调用并记录。
|
|
51
|
-
* loc: [line, column](1-based line,0-based column,与 Babel 一致)
|
|
52
|
-
* argLocs: 与 args 对齐的实参字面量源位置(provenance;无 loc 用 null)
|
|
53
|
-
*/
|
|
54
|
-
export function $callNamed(
|
|
55
|
-
name: string,
|
|
56
|
-
fn: unknown,
|
|
57
|
-
args: Abs[],
|
|
58
|
-
loc?: [number, number],
|
|
59
|
-
argLocs?: Array<[number, number] | null | undefined>,
|
|
60
|
-
): Abs {
|
|
61
|
-
let result: Abs = unknown;
|
|
62
|
-
let threw = false;
|
|
63
|
-
if (argLocs) {
|
|
64
|
-
for (let i = 0; i < args.length; i++) {
|
|
65
|
-
const al = argLocs[i];
|
|
66
|
-
if (al) tagAbsOrigin(args[i]!, { line: al[0], column: al[1] });
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
if (loc) pushCallLoc({ line: loc[0], column: loc[1] });
|
|
70
|
-
try {
|
|
71
|
-
if (typeof fn === "function") {
|
|
72
|
-
result = (fn as (...a: Abs[]) => Abs)(...args);
|
|
73
|
-
} else if (fn && typeof fn === "object" && "shape" in (fn as object)) {
|
|
74
|
-
result = $call(fn as Abs, args);
|
|
75
|
-
}
|
|
76
|
-
} catch (e) {
|
|
77
|
-
threw = true;
|
|
78
|
-
throw e;
|
|
79
|
-
} finally {
|
|
80
|
-
if (loc) popCallLoc();
|
|
81
|
-
if (bCallCollector) {
|
|
82
|
-
try {
|
|
83
|
-
bCallCollector({
|
|
84
|
-
fnName: name,
|
|
85
|
-
args,
|
|
86
|
-
result: threw ? unknown : result,
|
|
87
|
-
callLoc: loc ? { line: loc[0], column: loc[1] } : undefined,
|
|
88
|
-
threw,
|
|
89
|
-
});
|
|
90
|
-
} catch {
|
|
91
|
-
/* collector 不得打断 */
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return result;
|
|
96
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* B class 规格表(无 call/ast-eval 依赖,避免循环)。
|
|
3
|
-
* Abs-eval registerClassDecl 与 transpile $class 共用。
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Abs } from "../abs.ts";
|
|
7
|
-
|
|
8
|
-
export type BClassSpec = {
|
|
9
|
-
name: string;
|
|
10
|
-
superName?: string;
|
|
11
|
-
ctor?: (thisVal: Abs, ...args: Abs[]) => Abs;
|
|
12
|
-
methods?: Record<string, (thisVal: Abs, ...args: Abs[]) => Abs>;
|
|
13
|
-
staticMethods?: Record<string, (...args: Abs[]) => Abs>;
|
|
14
|
-
statics?: Record<string, Abs>;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
const classRegistry = new Map<string, BClassSpec>();
|
|
18
|
-
|
|
19
|
-
export function registerBClass(spec: BClassSpec): void {
|
|
20
|
-
classRegistry.set(spec.name, spec);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function getBClass(name: string): BClassSpec | undefined {
|
|
24
|
-
return classRegistry.get(name);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function clearBClasses(): void {
|
|
28
|
-
classRegistry.clear();
|
|
29
|
-
}
|
|
@@ -1,329 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* B 路径 class:brand 实例 + ctor/method 闭包 + 继承链。
|
|
3
|
-
* 方法内 this 由 transpile 改写为 thisVal 参数。
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Abs } from "../abs.ts";
|
|
7
|
-
import { abs, unknown, confJoin, litValue } from "../abs.ts";
|
|
8
|
-
import { objOf } from "../objects.ts";
|
|
9
|
-
import { $get, $set, asAbsVal } from "./runtime.ts";
|
|
10
|
-
import { $call } from "./call.ts";
|
|
11
|
-
import { getFnImpl } from "../abs-fn.ts";
|
|
12
|
-
import { notePrimMemberMissing, noteUnknownMemberMissing } from "./calls.ts";
|
|
13
|
-
import {
|
|
14
|
-
registerBClass,
|
|
15
|
-
getBClass,
|
|
16
|
-
type BClassSpec,
|
|
17
|
-
} from "./class-registry.ts";
|
|
18
|
-
|
|
19
|
-
export type { BClassSpec } from "./class-registry.ts";
|
|
20
|
-
export { registerBClass, getBClass, clearBClasses } from "./class-registry.ts";
|
|
21
|
-
|
|
22
|
-
const classImpl = new WeakMap<object, BClassSpec>();
|
|
23
|
-
|
|
24
|
-
/** 定义类 → 可 new 的 Abs(brand 标记;静态字段挂在 slots) */
|
|
25
|
-
export function $class(
|
|
26
|
-
name: string,
|
|
27
|
-
spec: Omit<BClassSpec, "name"> & { extends?: string },
|
|
28
|
-
): Abs {
|
|
29
|
-
const full: BClassSpec = {
|
|
30
|
-
name,
|
|
31
|
-
superName: spec.extends,
|
|
32
|
-
ctor: spec.ctor,
|
|
33
|
-
methods: spec.methods,
|
|
34
|
-
staticMethods: spec.staticMethods,
|
|
35
|
-
statics: spec.statics,
|
|
36
|
-
};
|
|
37
|
-
registerBClass(full);
|
|
38
|
-
const slots: Record<string, { value: Abs }> = {};
|
|
39
|
-
if (spec.statics) {
|
|
40
|
-
for (const [k, v] of Object.entries(spec.statics)) slots[k] = { value: asAbsVal(v) };
|
|
41
|
-
}
|
|
42
|
-
const val = abs(
|
|
43
|
-
{ k: "brand", name, shape: objOf(slots) },
|
|
44
|
-
undefined,
|
|
45
|
-
undefined,
|
|
46
|
-
"exact",
|
|
47
|
-
);
|
|
48
|
-
classImpl.set(val as object, full);
|
|
49
|
-
return val;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function specOf(cls: Abs): BClassSpec | undefined {
|
|
53
|
-
if (classImpl.has(cls as object)) return classImpl.get(cls as object);
|
|
54
|
-
if (cls.shape.k === "brand") return getBClass(cls.shape.name);
|
|
55
|
-
return undefined;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/** 沿继承链找方法 */
|
|
59
|
-
function findMethod(
|
|
60
|
-
startName: string,
|
|
61
|
-
method: string,
|
|
62
|
-
): ((thisVal: Abs, ...args: Abs[]) => Abs) | undefined {
|
|
63
|
-
let cur: string | undefined = startName;
|
|
64
|
-
const seen = new Set<string>();
|
|
65
|
-
while (cur && !seen.has(cur)) {
|
|
66
|
-
seen.add(cur);
|
|
67
|
-
const spec = getBClass(cur);
|
|
68
|
-
if (spec?.methods?.[method]) return spec.methods[method];
|
|
69
|
-
cur = spec?.superName;
|
|
70
|
-
}
|
|
71
|
-
return undefined;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function findCtor(
|
|
75
|
-
startName: string,
|
|
76
|
-
): { ctor: (thisVal: Abs, ...args: Abs[]) => Abs; className: string } | undefined {
|
|
77
|
-
let cur: string | undefined = startName;
|
|
78
|
-
const seen = new Set<string>();
|
|
79
|
-
while (cur && !seen.has(cur)) {
|
|
80
|
-
seen.add(cur);
|
|
81
|
-
const spec = getBClass(cur);
|
|
82
|
-
if (spec?.ctor) return { ctor: spec.ctor, className: cur };
|
|
83
|
-
cur = spec?.superName;
|
|
84
|
-
}
|
|
85
|
-
return undefined;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/** new C(...) → 空 brand 实例 + ctor 写字段;非类构造走 impl/$call */
|
|
89
|
-
export function $new(cls: Abs | ((...a: unknown[]) => unknown), args: Abs[]): Abs {
|
|
90
|
-
// JS 内建构造器(Error/Date/URL…):直接 brand,避免 $call 对非 Abs 炸掉
|
|
91
|
-
if (typeof cls === "function") {
|
|
92
|
-
const name = cls.name || "Object";
|
|
93
|
-
const shape = objOf({});
|
|
94
|
-
return abs({ k: "brand", name, shape }, undefined, undefined, "path");
|
|
95
|
-
}
|
|
96
|
-
const spec = specOf(cls);
|
|
97
|
-
if (!spec) {
|
|
98
|
-
// env 构造器(URL 等):fn impl / absFunction
|
|
99
|
-
return $call(cls, args);
|
|
100
|
-
}
|
|
101
|
-
const className = spec?.name ?? (cls.shape.k === "brand" ? cls.shape.name : "Anonymous");
|
|
102
|
-
let thisVal = abs(
|
|
103
|
-
{ k: "brand", name: className, shape: objOf({}) },
|
|
104
|
-
undefined,
|
|
105
|
-
undefined,
|
|
106
|
-
"path",
|
|
107
|
-
);
|
|
108
|
-
const found = findCtor(className);
|
|
109
|
-
if (found) {
|
|
110
|
-
const after = found.ctor(thisVal, ...args);
|
|
111
|
-
if (after && after.shape.k === "brand") thisVal = after;
|
|
112
|
-
else thisVal = after ?? thisVal;
|
|
113
|
-
}
|
|
114
|
-
return thisVal;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* super(...):父类构造写入字段(this 保持子类 brand)。
|
|
119
|
-
* transpile: super(a,b) → __this = $super(__this, "Child", [a,b])
|
|
120
|
-
*/
|
|
121
|
-
export function $super(thisVal: Abs, childName: string, args: Abs[]): Abs {
|
|
122
|
-
const child = getBClass(childName);
|
|
123
|
-
const parentName = child?.superName;
|
|
124
|
-
if (!parentName) return thisVal;
|
|
125
|
-
const found = findCtor(parentName);
|
|
126
|
-
if (!found) return thisVal;
|
|
127
|
-
const after = found.ctor(thisVal, ...args);
|
|
128
|
-
if (after && after.shape.k === "brand") {
|
|
129
|
-
// 保持子类 brand 名
|
|
130
|
-
return abs(
|
|
131
|
-
{ k: "brand", name: childName, shape: after.shape.shape },
|
|
132
|
-
after.term,
|
|
133
|
-
after.pred,
|
|
134
|
-
after.conf,
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
return after ?? thisVal;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/** 实例方法调用:沿继承链;类 Abs 上回落 staticMethods;obj 上回落属性函数 */
|
|
141
|
-
export function $invoke(
|
|
142
|
-
thisVal: Abs,
|
|
143
|
-
method: string,
|
|
144
|
-
args: Abs[],
|
|
145
|
-
loc?: [number, number],
|
|
146
|
-
): Abs {
|
|
147
|
-
const brandName = thisVal.shape.k === "brand" ? thisVal.shape.name : undefined;
|
|
148
|
-
if (brandName) {
|
|
149
|
-
const m = findMethod(brandName, method);
|
|
150
|
-
if (m) return m(thisVal, ...args);
|
|
151
|
-
const spec = getBClass(brandName);
|
|
152
|
-
const sm = spec?.staticMethods?.[method];
|
|
153
|
-
if (sm) return sm(...args);
|
|
154
|
-
}
|
|
155
|
-
// 数组/元组方法(与 ast-eval 口径对齐)
|
|
156
|
-
if (thisVal.shape.k === "arr" || thisVal.shape.k === "tuple") {
|
|
157
|
-
const arrR = invokeArrMethod(thisVal, method, args);
|
|
158
|
-
if (arrR !== undefined) return arrR;
|
|
159
|
-
}
|
|
160
|
-
// 属性上的可调用值(require namespace / 对象方法);method 诊断由下方统一报
|
|
161
|
-
const prop = $get(thisVal, method, { silent: true });
|
|
162
|
-
const impl = prop && typeof prop === "object" && "shape" in (prop as object)
|
|
163
|
-
? getFnImpl(prop as Abs)
|
|
164
|
-
: undefined;
|
|
165
|
-
if (impl) {
|
|
166
|
-
return $call(prop as Abs, args);
|
|
167
|
-
}
|
|
168
|
-
// prim 接收者上的未知方法 → no-method;unknown → unknown-recv
|
|
169
|
-
if (notePrimMemberMissing(thisVal, method, "method", loc)) return unknown;
|
|
170
|
-
noteUnknownMemberMissing(thisVal, method, "method", loc);
|
|
171
|
-
return unknown;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/** arr/tuple 上的 map/reduce/filter/join/includes */
|
|
175
|
-
function invokeArrMethod(arr: Abs, method: string, args: Abs[]): Abs | undefined {
|
|
176
|
-
const shape = arr.shape as
|
|
177
|
-
| { k: "arr"; element: Abs }
|
|
178
|
-
| { k: "tuple"; elements: Abs[] };
|
|
179
|
-
const callFn = (fn: unknown, ...fnArgs: Abs[]): Abs => {
|
|
180
|
-
if (typeof fn === "function") {
|
|
181
|
-
const r = (fn as (...a: Abs[]) => unknown)(...fnArgs);
|
|
182
|
-
if (r && typeof r === "object" && "shape" in (r as object)) return r as Abs;
|
|
183
|
-
return unknown;
|
|
184
|
-
}
|
|
185
|
-
if (fn && typeof fn === "object" && "shape" in (fn as object)) {
|
|
186
|
-
return $call(fn as Abs, fnArgs);
|
|
187
|
-
}
|
|
188
|
-
return unknown;
|
|
189
|
-
};
|
|
190
|
-
if (method === "map" && args[0]) {
|
|
191
|
-
if (shape.k === "tuple") {
|
|
192
|
-
const mapped = shape.elements.map((el) => callFn(args[0], el));
|
|
193
|
-
return abs({ k: "tuple", elements: mapped }, undefined, undefined, "path");
|
|
194
|
-
}
|
|
195
|
-
const out = callFn(args[0], shape.element);
|
|
196
|
-
return abs({ k: "arr", element: out }, undefined, undefined, "path");
|
|
197
|
-
}
|
|
198
|
-
if (method === "reduce" && args.length >= 1) {
|
|
199
|
-
const fn = args[0]!;
|
|
200
|
-
let acc = args[1] ?? unknown;
|
|
201
|
-
const list = shape.k === "tuple" ? shape.elements : [shape.element];
|
|
202
|
-
for (const el of list) {
|
|
203
|
-
acc = callFn(fn, acc, el);
|
|
204
|
-
}
|
|
205
|
-
return acc;
|
|
206
|
-
}
|
|
207
|
-
if (method === "filter" && args[0]) {
|
|
208
|
-
return arr;
|
|
209
|
-
}
|
|
210
|
-
if (method === "join") {
|
|
211
|
-
return abs({ k: "prim", type: "string" }, undefined, undefined, "path");
|
|
212
|
-
}
|
|
213
|
-
if (method === "includes") {
|
|
214
|
-
return abs({ k: "prim", type: "boolean" }, undefined, undefined, "partial");
|
|
215
|
-
}
|
|
216
|
-
if (method === "at" || method === "pop" || method === "shift") {
|
|
217
|
-
if (shape.k === "tuple" && shape.elements.length > 0) {
|
|
218
|
-
return shape.elements[0] ?? unknown;
|
|
219
|
-
}
|
|
220
|
-
if (shape.k === "arr") return shape.element;
|
|
221
|
-
}
|
|
222
|
-
return undefined;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/** super.method():从父类起找(跳过自身覆盖) */
|
|
226
|
-
export function $invokeSuper(
|
|
227
|
-
thisVal: Abs,
|
|
228
|
-
childName: string,
|
|
229
|
-
method: string,
|
|
230
|
-
args: Abs[],
|
|
231
|
-
): Abs {
|
|
232
|
-
const child = getBClass(childName);
|
|
233
|
-
const parentName = child?.superName;
|
|
234
|
-
if (!parentName) return unknown;
|
|
235
|
-
const m = findMethod(parentName, method);
|
|
236
|
-
if (!m) return unknown;
|
|
237
|
-
return m(thisVal, ...args);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
export function $thisGet(thisVal: Abs, key: string): Abs {
|
|
241
|
-
if (thisVal.shape.k === "brand") {
|
|
242
|
-
const inner = thisVal.shape.shape;
|
|
243
|
-
if (inner.shape.k === "obj") {
|
|
244
|
-
const slot = inner.shape.slots[key];
|
|
245
|
-
if (slot) return slot.value;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
return unknown;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
export function $thisSet(thisVal: Abs, key: string, value: Abs): Abs {
|
|
252
|
-
if (thisVal.shape.k === "brand") {
|
|
253
|
-
const inner = thisVal.shape.shape;
|
|
254
|
-
const slots = inner.shape.k === "obj" ? { ...inner.shape.slots } : {};
|
|
255
|
-
slots[key] = { value: asAbsVal(value) };
|
|
256
|
-
return abs(
|
|
257
|
-
{
|
|
258
|
-
k: "brand",
|
|
259
|
-
name: thisVal.shape.name,
|
|
260
|
-
shape: objOf(slots),
|
|
261
|
-
},
|
|
262
|
-
thisVal.term,
|
|
263
|
-
thisVal.pred,
|
|
264
|
-
confJoin(thisVal.conf, value.conf),
|
|
265
|
-
);
|
|
266
|
-
}
|
|
267
|
-
return unknown;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
/** 解构默认值:undefined 时用 default */
|
|
271
|
-
export function $orDefault(v: Abs, dflt: () => Abs): Abs {
|
|
272
|
-
if (litValue(v) === undefined && v.shape.k !== "never") {
|
|
273
|
-
// 明确 undefined 字面量 → 默认值;unknown 保守保留
|
|
274
|
-
if (v.term?.op === "lit" && v.term.value === undefined) return asAbsVal(dflt());
|
|
275
|
-
if (v.shape.k === "unknown" && v.term?.op === "lit") return asAbsVal(dflt());
|
|
276
|
-
}
|
|
277
|
-
if (v.term?.op === "lit" && v.term.value === undefined) return asAbsVal(dflt());
|
|
278
|
-
return v;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
function isNullishAbs(v: Abs): boolean {
|
|
282
|
-
// 仅明确 null/undefined 字面量;对象等无 term 不算 nullish
|
|
283
|
-
if (!v || v.term?.op !== "lit") return false;
|
|
284
|
-
const lv = v.term.value;
|
|
285
|
-
return lv === null || lv === undefined;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/** 可选链 a?.b:nullish 短路为 undefined 字面量 */
|
|
289
|
-
export function $optionalGet(o: Abs, key: string): Abs {
|
|
290
|
-
if (isNullishAbs(o)) {
|
|
291
|
-
return abs(
|
|
292
|
-
{ k: "unknown" },
|
|
293
|
-
{ op: "lit", value: undefined as never },
|
|
294
|
-
undefined,
|
|
295
|
-
"exact",
|
|
296
|
-
);
|
|
297
|
-
}
|
|
298
|
-
return $get(o, key);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/** 可选链 a?.m():nullish 短路为 undefined */
|
|
302
|
-
export function $optionalInvoke(thisVal: Abs, method: string, args: Abs[]): Abs {
|
|
303
|
-
if (isNullishAbs(thisVal)) {
|
|
304
|
-
return abs(
|
|
305
|
-
{ k: "unknown" },
|
|
306
|
-
{ op: "lit", value: undefined as never },
|
|
307
|
-
undefined,
|
|
308
|
-
"exact",
|
|
309
|
-
);
|
|
310
|
-
}
|
|
311
|
-
return $invoke(thisVal, method, args);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
/** 静态方法:cls.staticMethod(args) */
|
|
315
|
-
export function $staticInvoke(cls: Abs, method: string, args: Abs[]): Abs {
|
|
316
|
-
const spec = specOf(cls);
|
|
317
|
-
const m = spec?.staticMethods?.[method];
|
|
318
|
-
if (!m) return unknown;
|
|
319
|
-
return m(...args);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
/** 计算属性写:o[kAbs] = v */
|
|
323
|
-
export function $setKey(o: Abs, key: Abs, value: Abs): Abs {
|
|
324
|
-
const k = litValue(key);
|
|
325
|
-
if (typeof k === "string" || typeof k === "number") {
|
|
326
|
-
return $set(o, String(k), value);
|
|
327
|
-
}
|
|
328
|
-
return $set(o, "?", value);
|
|
329
|
-
}
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 成员缺失诊断(B 路径 + Abs ast-eval 共用)。
|
|
3
|
-
* 无 $call / transpile 依赖,避免 ast-eval ↔ calls 循环。
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Abs } from "../abs.ts";
|
|
7
|
-
|
|
8
|
-
export type BMemberDiag = {
|
|
9
|
-
kind: "method" | "property";
|
|
10
|
-
name: string;
|
|
11
|
-
/** 接收者 prim 类型名,或 "unknown" */
|
|
12
|
-
receiver: string;
|
|
13
|
-
line?: number;
|
|
14
|
-
column?: number;
|
|
15
|
-
/** 调用点来源(provenance):实参字面量 loc 优先,否则最近 $callNamed loc */
|
|
16
|
-
origin?: { line: number; column: number };
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
let memberDiagCollector: ((d: BMemberDiag) => void) | null = null;
|
|
20
|
-
const callLocStack: Array<{ line: number; column: number }> = [];
|
|
21
|
-
/** 实参 Abs → 字面量源位置($callNamed 按 argLocs 打标) */
|
|
22
|
-
const absOrigins = new WeakMap<object, { line: number; column: number }>();
|
|
23
|
-
|
|
24
|
-
/** 给实参 Abs 打 provenance(调用点参数字面量) */
|
|
25
|
-
export function tagAbsOrigin(a: Abs, loc: { line: number; column: number }): void {
|
|
26
|
-
if (a && typeof a === "object") absOrigins.set(a, loc);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function getAbsOrigin(a: Abs | undefined): { line: number; column: number } | undefined {
|
|
30
|
-
if (!a || typeof a !== "object") return undefined;
|
|
31
|
-
return absOrigins.get(a);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function setMemberDiagCollector(
|
|
35
|
-
c: ((d: BMemberDiag) => void) | null,
|
|
36
|
-
): void {
|
|
37
|
-
memberDiagCollector = c;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function pushCallLoc(loc: { line: number; column: number }): void {
|
|
41
|
-
callLocStack.push(loc);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function popCallLoc(): void {
|
|
45
|
-
callLocStack.pop();
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function recordMemberDiag(d: BMemberDiag): void {
|
|
49
|
-
if (!memberDiagCollector) return;
|
|
50
|
-
const origin = d.origin ?? callLocStack[callLocStack.length - 1];
|
|
51
|
-
try {
|
|
52
|
-
memberDiagCollector(origin ? { ...d, origin } : d);
|
|
53
|
-
} catch {
|
|
54
|
-
/* ignore */
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/** string 上仍可能存在的方法(与 TypeValue completions 对齐) */
|
|
59
|
-
const STRING_METHODS = new Set([
|
|
60
|
-
"toUpperCase", "toLowerCase", "trim", "split", "slice", "substring",
|
|
61
|
-
"includes", "indexOf", "lastIndexOf", "startsWith", "endsWith", "charAt",
|
|
62
|
-
"charCodeAt", "replace", "toString", "valueOf", "repeat", "padStart",
|
|
63
|
-
"padEnd", "replaceAll", "concat", "match", "search", "at",
|
|
64
|
-
]);
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* prim 接收者上的未知成员 → 诊断。
|
|
68
|
-
* 返回 true 表示确定缺失(number 上任意方法;string 上表外方法)。
|
|
69
|
-
*/
|
|
70
|
-
export function notePrimMemberMissing(
|
|
71
|
-
recv: Abs | undefined,
|
|
72
|
-
name: string,
|
|
73
|
-
kind: "method" | "property",
|
|
74
|
-
loc?: [number, number],
|
|
75
|
-
): boolean {
|
|
76
|
-
const shape = recv?.shape;
|
|
77
|
-
if (!shape || shape.k !== "prim") return false;
|
|
78
|
-
const t = shape.type;
|
|
79
|
-
const argOrigin = getAbsOrigin(recv);
|
|
80
|
-
const origin = argOrigin
|
|
81
|
-
? { line: argOrigin.line, column: argOrigin.column }
|
|
82
|
-
: undefined;
|
|
83
|
-
if (t === "number" || t === "boolean" || t === "bigint" || t === "symbol") {
|
|
84
|
-
recordMemberDiag({
|
|
85
|
-
kind,
|
|
86
|
-
name,
|
|
87
|
-
receiver: t,
|
|
88
|
-
line: loc?.[0],
|
|
89
|
-
column: loc?.[1],
|
|
90
|
-
...(origin ? { origin } : {}),
|
|
91
|
-
});
|
|
92
|
-
return true;
|
|
93
|
-
}
|
|
94
|
-
if (t === "string" && kind === "method" && !STRING_METHODS.has(name)) {
|
|
95
|
-
recordMemberDiag({
|
|
96
|
-
kind,
|
|
97
|
-
name,
|
|
98
|
-
receiver: t,
|
|
99
|
-
line: loc?.[0],
|
|
100
|
-
column: loc?.[1],
|
|
101
|
-
...(origin ? { origin } : {}),
|
|
102
|
-
});
|
|
103
|
-
return true;
|
|
104
|
-
}
|
|
105
|
-
return false;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* unknown 接收者上的成员访问 → unknown-recv(与 TypeValue 口径对齐:
|
|
110
|
-
* object/instance/refined/promise 静默;其余记一条)。
|
|
111
|
-
*/
|
|
112
|
-
export function noteUnknownMemberMissing(
|
|
113
|
-
recv: Abs | undefined,
|
|
114
|
-
name: string,
|
|
115
|
-
kind: "method" | "property",
|
|
116
|
-
loc?: [number, number],
|
|
117
|
-
): boolean {
|
|
118
|
-
const k = recv?.shape?.k;
|
|
119
|
-
if (k !== "unknown") return false;
|
|
120
|
-
const origin = getAbsOrigin(recv);
|
|
121
|
-
recordMemberDiag({
|
|
122
|
-
kind,
|
|
123
|
-
name,
|
|
124
|
-
receiver: "unknown",
|
|
125
|
-
line: loc?.[0],
|
|
126
|
-
column: loc?.[1],
|
|
127
|
-
...(origin ? { origin: { line: origin.line, column: origin.column } } : {}),
|
|
128
|
-
});
|
|
129
|
-
return true;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/** 方法分派失败时的统一记账(prim / unknown;obj/brand/promise 静默) */
|
|
133
|
-
export function noteMemberDispatchMiss(
|
|
134
|
-
recv: Abs | undefined,
|
|
135
|
-
name: string,
|
|
136
|
-
kind: "method" | "property",
|
|
137
|
-
loc?: [number, number],
|
|
138
|
-
): void {
|
|
139
|
-
if (notePrimMemberMissing(recv, name, kind, loc)) return;
|
|
140
|
-
noteUnknownMemberMissing(recv, name, kind, loc);
|
|
141
|
-
}
|