@nudojs/core 0.3.0 → 0.4.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-N7E2A7IK.js +7216 -0
- package/dist/exec.d.ts +2 -0
- package/dist/exec.js +174 -0
- package/dist/index-DgyudAkw.d.ts +911 -0
- package/dist/index.d.ts +64 -710
- package/dist/index.js +3269 -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
package/src/algebra/builtins.ts
DELETED
|
@@ -1,373 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Abs 侧常用 builtin:shape 级运算,不依赖 TypeValue host 库。
|
|
3
|
-
* 覆盖 Math / Object / JSON / Number / 全局转换函数的常见面。
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Abs } from "./abs.ts";
|
|
7
|
-
import { abs, litValue, numLit, strLit, boolLit, unknown, confJoin } from "./abs.ts";
|
|
8
|
-
|
|
9
|
-
function numPrim(conf: Abs["conf"] = "path"): Abs {
|
|
10
|
-
return abs({ k: "prim", type: "number" }, undefined, undefined, conf);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function strPrim(conf: Abs["conf"] = "path"): Abs {
|
|
14
|
-
return abs({ k: "prim", type: "string" }, undefined, undefined, conf);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function boolPrim(conf: Abs["conf"] = "partial"): Abs {
|
|
18
|
-
return abs({ k: "prim", type: "boolean" }, undefined, undefined, conf);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/** Math.* — 字面量可折叠的返回精确值,否则 number */
|
|
22
|
-
export function evalMathMethod(name: string, args: Abs[]): Abs | undefined {
|
|
23
|
-
const a0 = args[0] ? litValue(args[0]) : undefined;
|
|
24
|
-
const a1 = args[1] ? litValue(args[1]) : undefined;
|
|
25
|
-
switch (name) {
|
|
26
|
-
case "abs":
|
|
27
|
-
if (typeof a0 === "number") return numLit(Math.abs(a0));
|
|
28
|
-
return numPrim();
|
|
29
|
-
case "floor":
|
|
30
|
-
if (typeof a0 === "number") return numLit(Math.floor(a0));
|
|
31
|
-
return numPrim();
|
|
32
|
-
case "ceil":
|
|
33
|
-
if (typeof a0 === "number") return numLit(Math.ceil(a0));
|
|
34
|
-
return numPrim();
|
|
35
|
-
case "round":
|
|
36
|
-
if (typeof a0 === "number") return numLit(Math.round(a0));
|
|
37
|
-
return numPrim();
|
|
38
|
-
case "sqrt":
|
|
39
|
-
if (typeof a0 === "number") return numLit(Math.sqrt(a0));
|
|
40
|
-
return numPrim();
|
|
41
|
-
case "min": {
|
|
42
|
-
const lits = args.map(litValue);
|
|
43
|
-
if (lits.length > 0 && lits.every((x) => typeof x === "number")) {
|
|
44
|
-
return numLit(Math.min(...(lits as number[])));
|
|
45
|
-
}
|
|
46
|
-
return numPrim();
|
|
47
|
-
}
|
|
48
|
-
case "max": {
|
|
49
|
-
const lits = args.map(litValue);
|
|
50
|
-
if (lits.length > 0 && lits.every((x) => typeof x === "number")) {
|
|
51
|
-
return numLit(Math.max(...(lits as number[])));
|
|
52
|
-
}
|
|
53
|
-
return numPrim();
|
|
54
|
-
}
|
|
55
|
-
case "pow":
|
|
56
|
-
if (typeof a0 === "number" && typeof a1 === "number") return numLit(Math.pow(a0, a1));
|
|
57
|
-
return numPrim();
|
|
58
|
-
case "sign":
|
|
59
|
-
if (typeof a0 === "number") return numLit(Math.sign(a0));
|
|
60
|
-
return numPrim();
|
|
61
|
-
default:
|
|
62
|
-
return undefined;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/** Object.keys/values/entries/assign */
|
|
67
|
-
export function evalObjectMethod(name: string, args: Abs[]): Abs | undefined {
|
|
68
|
-
const a0 = args[0];
|
|
69
|
-
switch (name) {
|
|
70
|
-
case "keys": {
|
|
71
|
-
if (a0?.shape.k === "obj") {
|
|
72
|
-
const keys = Object.keys((a0.shape as { slots: Record<string, unknown> }).slots).map((k) =>
|
|
73
|
-
strLit(k),
|
|
74
|
-
);
|
|
75
|
-
return abs({ k: "tuple", elements: keys }, undefined, undefined, "exact");
|
|
76
|
-
}
|
|
77
|
-
return abs({ k: "arr", element: strPrim("path") }, undefined, undefined, "partial");
|
|
78
|
-
}
|
|
79
|
-
case "values": {
|
|
80
|
-
if (a0?.shape.k === "obj") {
|
|
81
|
-
const slots = (a0.shape as { slots: Record<string, { value: Abs }> }).slots;
|
|
82
|
-
const vals = Object.values(slots).map((s) => s.value);
|
|
83
|
-
return abs({ k: "tuple", elements: vals }, undefined, undefined, "exact");
|
|
84
|
-
}
|
|
85
|
-
return abs({ k: "arr", element: unknown }, undefined, undefined, "partial");
|
|
86
|
-
}
|
|
87
|
-
case "entries": {
|
|
88
|
-
if (a0?.shape.k === "obj") {
|
|
89
|
-
const slots = (a0.shape as { slots: Record<string, { value: Abs }> }).slots;
|
|
90
|
-
const entries = Object.entries(slots).map(([, s]) =>
|
|
91
|
-
abs({ k: "tuple", elements: [strPrim("exact"), s.value] }, undefined, undefined, "exact"),
|
|
92
|
-
);
|
|
93
|
-
return abs({ k: "tuple", elements: entries }, undefined, undefined, "exact");
|
|
94
|
-
}
|
|
95
|
-
return abs({ k: "arr", element: unknown }, undefined, undefined, "partial");
|
|
96
|
-
}
|
|
97
|
-
case "assign": {
|
|
98
|
-
// Object.assign(a, b) ≈ spread
|
|
99
|
-
if (!args.length) return unknown;
|
|
100
|
-
let acc = args[0]!;
|
|
101
|
-
for (let i = 1; i < args.length; i++) {
|
|
102
|
-
acc = { ...acc }; // 保持结构;细粒度 spread 在 evalCall 侧
|
|
103
|
-
if (acc.shape.k === "obj" && args[i]!.shape.k === "obj") {
|
|
104
|
-
const base = (acc.shape as { slots: Record<string, { value: Abs }> }).slots;
|
|
105
|
-
const over = (args[i]!.shape as { slots: Record<string, { value: Abs }> }).slots;
|
|
106
|
-
acc = abs({ k: "obj", slots: { ...base, ...over } }, undefined, undefined, confJoin(acc.conf, args[i]!.conf));
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return acc;
|
|
110
|
-
}
|
|
111
|
-
default:
|
|
112
|
-
return undefined;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/** JSON.parse / stringify */
|
|
117
|
-
export function evalJsonMethod(name: string, args: Abs[]): Abs | undefined {
|
|
118
|
-
if (name === "stringify") return strPrim("partial");
|
|
119
|
-
if (name === "parse") return unknown;
|
|
120
|
-
return undefined;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/** Number.isInteger / isNaN / parseFloat 等 */
|
|
124
|
-
export function evalNumberStatic(name: string, args: Abs[]): Abs | undefined {
|
|
125
|
-
const a0 = args[0] ? litValue(args[0]) : undefined;
|
|
126
|
-
switch (name) {
|
|
127
|
-
case "isInteger":
|
|
128
|
-
if (typeof a0 === "number") return boolLit(Number.isInteger(a0));
|
|
129
|
-
return boolPrim();
|
|
130
|
-
case "isNaN":
|
|
131
|
-
if (typeof a0 === "number") return boolLit(Number.isNaN(a0));
|
|
132
|
-
return boolPrim();
|
|
133
|
-
case "isFinite":
|
|
134
|
-
if (typeof a0 === "number") return boolLit(Number.isFinite(a0));
|
|
135
|
-
return boolPrim();
|
|
136
|
-
case "parseInt":
|
|
137
|
-
case "parseFloat":
|
|
138
|
-
if (typeof a0 === "string" || typeof a0 === "number") {
|
|
139
|
-
const n = name === "parseInt" ? parseInt(String(a0), 10) : parseFloat(String(a0));
|
|
140
|
-
return numLit(n);
|
|
141
|
-
}
|
|
142
|
-
return numPrim();
|
|
143
|
-
case "MAX_SAFE_INTEGER":
|
|
144
|
-
return numLit(Number.MAX_SAFE_INTEGER);
|
|
145
|
-
default:
|
|
146
|
-
return undefined;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/** 全局 parseInt / parseFloat / isNaN / Number / String / Boolean */
|
|
151
|
-
export function evalGlobalFn(name: string, args: Abs[]): Abs | undefined {
|
|
152
|
-
const a0 = args[0] ? litValue(args[0]) : undefined;
|
|
153
|
-
switch (name) {
|
|
154
|
-
case "parseInt":
|
|
155
|
-
if (typeof a0 === "string" || typeof a0 === "number") return numLit(parseInt(String(a0), 10));
|
|
156
|
-
return numPrim();
|
|
157
|
-
case "parseFloat":
|
|
158
|
-
if (typeof a0 === "string" || typeof a0 === "number") return numLit(parseFloat(String(a0)));
|
|
159
|
-
return numPrim();
|
|
160
|
-
case "isNaN":
|
|
161
|
-
if (typeof a0 === "number") return boolLit(Number.isNaN(a0));
|
|
162
|
-
return boolPrim();
|
|
163
|
-
case "Number":
|
|
164
|
-
if (typeof a0 === "number") return numLit(a0);
|
|
165
|
-
if (typeof a0 === "string") return numLit(Number(a0));
|
|
166
|
-
if (typeof a0 === "boolean") return numLit(a0 ? 1 : 0);
|
|
167
|
-
return numPrim();
|
|
168
|
-
case "String":
|
|
169
|
-
if (a0 !== undefined) return strLit(String(a0));
|
|
170
|
-
return strPrim();
|
|
171
|
-
case "Boolean":
|
|
172
|
-
if (a0 !== undefined) return boolLit(Boolean(a0));
|
|
173
|
-
return boolPrim();
|
|
174
|
-
default:
|
|
175
|
-
return undefined;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/** Array.isArray / Array.from / Array.of */
|
|
180
|
-
export function evalArrayStatic(name: string, args: Abs[]): Abs | undefined {
|
|
181
|
-
const a0 = args[0];
|
|
182
|
-
switch (name) {
|
|
183
|
-
case "isArray": {
|
|
184
|
-
if (!a0) return boolLit(false);
|
|
185
|
-
const k = a0.shape.k;
|
|
186
|
-
return boolLit(k === "arr" || k === "tuple");
|
|
187
|
-
}
|
|
188
|
-
case "from":
|
|
189
|
-
case "of":
|
|
190
|
-
return abs({ k: "arr", element: a0 ?? unknown }, undefined, undefined, "path");
|
|
191
|
-
default:
|
|
192
|
-
return undefined;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/** new Date() / Date.now / date.getTime */
|
|
197
|
-
export function evalDateCtor(args: Abs[]): Abs {
|
|
198
|
-
return abs(
|
|
199
|
-
{ k: "brand", name: "Date", shape: abs({ k: "obj", slots: {} }, undefined, undefined, "exact") },
|
|
200
|
-
undefined,
|
|
201
|
-
undefined,
|
|
202
|
-
"path",
|
|
203
|
-
);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
export function evalDateStatic(name: string, _args: Abs[]): Abs | undefined {
|
|
207
|
-
if (name === "now") return numLit(Date.now());
|
|
208
|
-
return undefined;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
export function evalDateMethod(name: string, _recv: Abs, _args: Abs[]): Abs | undefined {
|
|
212
|
-
switch (name) {
|
|
213
|
-
case "getTime":
|
|
214
|
-
case "valueOf":
|
|
215
|
-
return numPrim("path");
|
|
216
|
-
case "toISOString":
|
|
217
|
-
case "toString":
|
|
218
|
-
return strPrim("path");
|
|
219
|
-
default:
|
|
220
|
-
return undefined;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/** new RegExp / regexp.test / exec */
|
|
225
|
-
export function evalRegExpCtor(_args: Abs[]): Abs {
|
|
226
|
-
return abs(
|
|
227
|
-
{ k: "brand", name: "RegExp", shape: abs({ k: "obj", slots: {} }, undefined, undefined, "exact") },
|
|
228
|
-
undefined,
|
|
229
|
-
undefined,
|
|
230
|
-
"path",
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
export function evalRegExpMethod(name: string, _recv: Abs, _args: Abs[]): Abs | undefined {
|
|
235
|
-
switch (name) {
|
|
236
|
-
case "test":
|
|
237
|
-
return boolPrim();
|
|
238
|
-
case "exec":
|
|
239
|
-
return unknown;
|
|
240
|
-
default:
|
|
241
|
-
return undefined;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/** Promise:new Promise / Promise.resolve / reject / all */
|
|
246
|
-
export function evalPromiseCtor(_args: Abs[]): Abs {
|
|
247
|
-
return abs(
|
|
248
|
-
{ k: "eff", eff: "promise", inner: unknown },
|
|
249
|
-
undefined,
|
|
250
|
-
undefined,
|
|
251
|
-
"partial",
|
|
252
|
-
);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
export function evalPromiseStatic(name: string, args: Abs[]): Abs | undefined {
|
|
256
|
-
switch (name) {
|
|
257
|
-
case "resolve": {
|
|
258
|
-
const inner = args[0] ?? unknown;
|
|
259
|
-
// Promise.resolve(thenable) 展开
|
|
260
|
-
if (inner.shape.k === "eff" && inner.shape.eff === "promise") return inner;
|
|
261
|
-
return abs({ k: "eff", eff: "promise", inner }, undefined, undefined, "path");
|
|
262
|
-
}
|
|
263
|
-
case "reject":
|
|
264
|
-
return abs({ k: "eff", eff: "promise", inner: unknown }, undefined, undefined, "partial");
|
|
265
|
-
case "all": {
|
|
266
|
-
const a0 = args[0];
|
|
267
|
-
if (a0?.shape.k === "arr" && a0.shape.element.shape.k === "eff") {
|
|
268
|
-
return abs(
|
|
269
|
-
{ k: "eff", eff: "promise", inner: abs({ k: "arr", element: a0.shape.element.shape.inner }, undefined, undefined, "path") },
|
|
270
|
-
undefined,
|
|
271
|
-
undefined,
|
|
272
|
-
"path",
|
|
273
|
-
);
|
|
274
|
-
}
|
|
275
|
-
return abs({ k: "eff", eff: "promise", inner: abs({ k: "arr", element: unknown }, undefined, undefined, "partial") }, undefined, undefined, "partial");
|
|
276
|
-
}
|
|
277
|
-
default:
|
|
278
|
-
return undefined;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/** 命名空间分派入口 */
|
|
283
|
-
export function evalNamespaceCall(
|
|
284
|
-
ns: string,
|
|
285
|
-
method: string,
|
|
286
|
-
args: Abs[],
|
|
287
|
-
): Abs | undefined {
|
|
288
|
-
switch (ns) {
|
|
289
|
-
case "Math":
|
|
290
|
-
return evalMathMethod(method, args);
|
|
291
|
-
case "Object":
|
|
292
|
-
return evalObjectMethod(method, args);
|
|
293
|
-
case "JSON":
|
|
294
|
-
return evalJsonMethod(method, args);
|
|
295
|
-
case "Number":
|
|
296
|
-
return evalNumberStatic(method, args);
|
|
297
|
-
case "Array":
|
|
298
|
-
return evalArrayStatic(method, args);
|
|
299
|
-
case "Date":
|
|
300
|
-
return evalDateStatic(method, args);
|
|
301
|
-
case "Promise":
|
|
302
|
-
return evalPromiseStatic(method, args);
|
|
303
|
-
default:
|
|
304
|
-
return undefined;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
/** new X(...) */
|
|
309
|
-
export function evalBuiltinNew(className: string, args: Abs[]): Abs | undefined {
|
|
310
|
-
switch (className) {
|
|
311
|
-
case "Date":
|
|
312
|
-
return evalDateCtor(args);
|
|
313
|
-
case "RegExp":
|
|
314
|
-
return evalRegExpCtor(args);
|
|
315
|
-
case "Promise":
|
|
316
|
-
return evalPromiseCtor(args);
|
|
317
|
-
case "Map":
|
|
318
|
-
return abs(
|
|
319
|
-
{ k: "brand", name: "Map", shape: abs({ k: "obj", slots: {} }, undefined, undefined, "exact") },
|
|
320
|
-
undefined,
|
|
321
|
-
undefined,
|
|
322
|
-
"path",
|
|
323
|
-
);
|
|
324
|
-
case "Set":
|
|
325
|
-
return abs(
|
|
326
|
-
{ k: "brand", name: "Set", shape: abs({ k: "obj", slots: {} }, undefined, undefined, "exact") },
|
|
327
|
-
undefined,
|
|
328
|
-
undefined,
|
|
329
|
-
"path",
|
|
330
|
-
);
|
|
331
|
-
default:
|
|
332
|
-
return undefined;
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
/** brand 实例方法(Date/RegExp/Map/Set) */
|
|
337
|
-
export function evalBuiltinInstanceMethod(
|
|
338
|
-
brandName: string,
|
|
339
|
-
method: string,
|
|
340
|
-
recv: Abs,
|
|
341
|
-
args: Abs[],
|
|
342
|
-
): Abs | undefined {
|
|
343
|
-
if (brandName === "Date") return evalDateMethod(method, recv, args);
|
|
344
|
-
if (brandName === "RegExp") return evalRegExpMethod(method, recv, args);
|
|
345
|
-
if (brandName === "Map") {
|
|
346
|
-
switch (method) {
|
|
347
|
-
case "get":
|
|
348
|
-
return unknown;
|
|
349
|
-
case "has":
|
|
350
|
-
return boolPrim();
|
|
351
|
-
case "set":
|
|
352
|
-
return recv;
|
|
353
|
-
case "size":
|
|
354
|
-
return numPrim("path");
|
|
355
|
-
default:
|
|
356
|
-
return undefined;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
if (brandName === "Set") {
|
|
360
|
-
switch (method) {
|
|
361
|
-
case "has":
|
|
362
|
-
return boolPrim();
|
|
363
|
-
case "add":
|
|
364
|
-
return recv;
|
|
365
|
-
case "size":
|
|
366
|
-
return numPrim("path");
|
|
367
|
-
default:
|
|
368
|
-
return undefined;
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
return undefined;
|
|
372
|
-
}
|
|
373
|
-
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* check 报告面:数据模型 + 渲染/序列化。
|
|
3
|
-
*
|
|
4
|
-
* 分析在 check.ts(Abs 优先的 Nudo 原生诊断),这里只投影:
|
|
5
|
-
* - formatCheckReport → 人类可读文本
|
|
6
|
-
* - serializeCheckJson → `nudo check --json` 稳定契约(CI / Agent,v1)
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { Diagnostic } from "./diagnostics.ts";
|
|
10
|
-
import type { Abs, Confidence } from "./abs.ts";
|
|
11
|
-
import { formatAbs } from "./format.ts";
|
|
12
|
-
|
|
13
|
-
/** 无损函数签名(类型即计算) */
|
|
14
|
-
export type NudoSig = {
|
|
15
|
-
name: string;
|
|
16
|
-
params: string[];
|
|
17
|
-
/** 符号 Abs 本体 */
|
|
18
|
-
abs: Abs;
|
|
19
|
-
/** formatAbs 单行 */
|
|
20
|
-
display: string;
|
|
21
|
-
/** formatAbsMultiline */
|
|
22
|
-
detail: string;
|
|
23
|
-
conf: Confidence;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export type CheckIssue = Diagnostic & {
|
|
27
|
-
fn?: string;
|
|
28
|
-
line?: number;
|
|
29
|
-
column?: number;
|
|
30
|
-
/** 实参 / 实际值的 Abs 展示 */
|
|
31
|
-
actual?: string;
|
|
32
|
-
/** 期望约束(Pred 或 Abs 展示) */
|
|
33
|
-
expected?: string;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
export type CheckReport = {
|
|
37
|
-
file: string;
|
|
38
|
-
issues: CheckIssue[];
|
|
39
|
-
/** 有 error 则 CI 应失败 */
|
|
40
|
-
ok: boolean;
|
|
41
|
-
/** Abs 优先的签名表(替代 TS 式 display-only) */
|
|
42
|
-
signatures: NudoSig[];
|
|
43
|
-
summary: {
|
|
44
|
-
errors: number;
|
|
45
|
-
warnings: number;
|
|
46
|
-
infos: number;
|
|
47
|
-
functions: number;
|
|
48
|
-
};
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* `nudo check --json` 稳定契约(供 CI / Agent)。
|
|
53
|
-
* 字段只增不改语义;Abs 以 formatAbs 字符串给出,不序列化内部 shape 图。
|
|
54
|
-
*/
|
|
55
|
-
export type CheckJson = {
|
|
56
|
-
version: 1;
|
|
57
|
-
file: string;
|
|
58
|
-
ok: boolean;
|
|
59
|
-
summary: CheckReport["summary"];
|
|
60
|
-
signatures: Array<{
|
|
61
|
-
name: string;
|
|
62
|
-
params: string[];
|
|
63
|
-
display: string;
|
|
64
|
-
detail: string;
|
|
65
|
-
conf: string;
|
|
66
|
-
abs: string;
|
|
67
|
-
}>;
|
|
68
|
-
issues: Array<{
|
|
69
|
-
severity: string;
|
|
70
|
-
code: string;
|
|
71
|
-
message: string;
|
|
72
|
-
fn?: string;
|
|
73
|
-
line?: number;
|
|
74
|
-
column?: number;
|
|
75
|
-
actual?: string;
|
|
76
|
-
expected?: string;
|
|
77
|
-
suggestion?: string;
|
|
78
|
-
}>;
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
export function serializeCheckJson(r: CheckReport): CheckJson {
|
|
82
|
-
return {
|
|
83
|
-
version: 1,
|
|
84
|
-
file: r.file,
|
|
85
|
-
ok: r.ok,
|
|
86
|
-
summary: { ...r.summary },
|
|
87
|
-
signatures: r.signatures.map((s) => ({
|
|
88
|
-
name: s.name,
|
|
89
|
-
params: [...s.params],
|
|
90
|
-
display: s.display,
|
|
91
|
-
detail: s.detail,
|
|
92
|
-
conf: s.conf,
|
|
93
|
-
abs: formatAbs(s.abs),
|
|
94
|
-
})),
|
|
95
|
-
issues: r.issues.map((i) => ({
|
|
96
|
-
severity: i.severity,
|
|
97
|
-
code: i.code,
|
|
98
|
-
message: i.message,
|
|
99
|
-
...(i.fn !== undefined ? { fn: i.fn } : {}),
|
|
100
|
-
...(i.line !== undefined ? { line: i.line } : {}),
|
|
101
|
-
...(i.column !== undefined ? { column: i.column } : {}),
|
|
102
|
-
...(i.actual !== undefined ? { actual: i.actual } : {}),
|
|
103
|
-
...(i.expected !== undefined ? { expected: i.expected } : {}),
|
|
104
|
-
...(i.suggestion !== undefined ? { suggestion: i.suggestion } : {}),
|
|
105
|
-
})),
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Nudo 原生报告:Abs 签名表 + actual ⊭ expected。
|
|
111
|
-
* 不是 tsc 输出的换皮。
|
|
112
|
-
*/
|
|
113
|
-
export function formatCheckReport(r: CheckReport, opts: { verbose?: boolean } = {}): string {
|
|
114
|
-
const lines: string[] = [];
|
|
115
|
-
lines.push(`nudo check ${r.file}`);
|
|
116
|
-
lines.push(r.ok ? "OK" : "FAILED");
|
|
117
|
-
lines.push(
|
|
118
|
-
` ${r.summary.errors} error · ${r.summary.warnings} warning · ${r.summary.infos} info · ${r.summary.functions} fn`,
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
if (r.signatures.length > 0) {
|
|
122
|
-
lines.push("");
|
|
123
|
-
lines.push("signatures");
|
|
124
|
-
for (const s of r.signatures) {
|
|
125
|
-
lines.push(` ${s.name}(${s.params.join(", ")}) ${s.display}`);
|
|
126
|
-
if (opts.verbose) {
|
|
127
|
-
for (const ln of s.detail.split("\n").slice(1)) {
|
|
128
|
-
lines.push(` ${ln}`);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (r.issues.length === 0) {
|
|
135
|
-
lines.push("");
|
|
136
|
-
lines.push("(no issues)");
|
|
137
|
-
} else {
|
|
138
|
-
lines.push("");
|
|
139
|
-
lines.push("issues");
|
|
140
|
-
for (const i of r.issues) {
|
|
141
|
-
const loc = i.line != null ? `L${i.line}` : "";
|
|
142
|
-
const head = [i.severity.toUpperCase(), loc, i.fn].filter(Boolean).join(" ");
|
|
143
|
-
lines.push(` [${head}] ${i.message} (${i.code})`);
|
|
144
|
-
if (i.actual) lines.push(` actual: ${i.actual}`);
|
|
145
|
-
if (i.expected) lines.push(` expected: ${i.expected}`);
|
|
146
|
-
if (i.suggestion) lines.push(` → ${i.suggestion}`);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
return lines.join("\n");
|
|
150
|
-
}
|