@nudojs/core 0.2.0 → 0.3.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/CHANGELOG.md +19 -0
- package/README.md +26 -0
- package/dist/index.d.ts +1601 -12
- package/dist/index.js +9657 -110
- package/package.json +18 -2
- package/src/__tests__/fn-sig-impl.test.ts +57 -0
- package/src/__tests__/ops-refined.test.ts +3 -1
- package/src/__tests__/ops.test.ts +8 -33
- package/src/__tests__/type-value.test.ts +106 -0
- package/src/algebra/__tests__/abs-native.test.ts +176 -0
- package/src/algebra/__tests__/arithmetic.test.ts +170 -0
- package/src/algebra/__tests__/ast-eval.test.ts +154 -0
- package/src/algebra/__tests__/bridge.test.ts +160 -0
- package/src/algebra/__tests__/call-budget.test.ts +117 -0
- package/src/algebra/__tests__/check-case-consistency.test.ts +69 -0
- package/src/algebra/__tests__/check-gold.test.ts +290 -0
- package/src/algebra/__tests__/check-json.test.ts +57 -0
- package/src/algebra/__tests__/check-mini-repo.test.ts +49 -0
- package/src/algebra/__tests__/check-real-commander.test.ts +43 -0
- package/src/algebra/__tests__/check-real-packages.test.ts +165 -0
- package/src/algebra/__tests__/check-recall-gold.test.ts +1024 -0
- package/src/algebra/__tests__/check-require-dep-memo.test.ts +45 -0
- package/src/algebra/__tests__/check-return-contract.test.ts +90 -0
- package/src/algebra/__tests__/check-shape-gold.test.ts +303 -0
- package/src/algebra/__tests__/check-source-memo.test.ts +204 -0
- package/src/algebra/__tests__/check.test.ts +69 -0
- package/src/algebra/__tests__/denote.test.ts +77 -0
- package/src/algebra/__tests__/diagnostics.test.ts +64 -0
- package/src/algebra/__tests__/differential.test.ts +124 -0
- package/src/algebra/__tests__/div-mod.test.ts +38 -0
- package/src/algebra/__tests__/example0.test.ts +103 -0
- package/src/algebra/__tests__/exec-analyze-throws.test.ts +60 -0
- package/src/algebra/__tests__/exec-async.test.ts +46 -0
- package/src/algebra/__tests__/exec-bpath.test.ts +193 -0
- package/src/algebra/__tests__/exec-class.test.ts +56 -0
- package/src/algebra/__tests__/exec-e2e.test.ts +97 -0
- package/src/algebra/__tests__/exec-generator.test.ts +53 -0
- package/src/algebra/__tests__/exec-inherit-default.test.ts +111 -0
- package/src/algebra/__tests__/exec-optional-nested.test.ts +87 -0
- package/src/algebra/__tests__/exec-rest.test.ts +55 -0
- package/src/algebra/__tests__/exec-spread-forof.test.ts +85 -0
- package/src/algebra/__tests__/exec-static-computed.test.ts +61 -0
- package/src/algebra/__tests__/exec-switch.test.ts +74 -0
- package/src/algebra/__tests__/exec-trycatch.test.ts +71 -0
- package/src/algebra/__tests__/fn-fp-memo.test.ts +166 -0
- package/src/algebra/__tests__/fn-fp-multidecl.test.ts +49 -0
- package/src/algebra/__tests__/format.test.ts +34 -0
- package/src/algebra/__tests__/generalize-memo.test.ts +285 -0
- package/src/algebra/__tests__/generalize.test.ts +113 -0
- package/src/algebra/__tests__/hash-source.test.ts +19 -0
- package/src/algebra/__tests__/hof.test.ts +80 -0
- package/src/algebra/__tests__/inlay.test.ts +30 -0
- package/src/algebra/__tests__/language.test.ts +77 -0
- package/src/algebra/__tests__/leq.test.ts +109 -0
- package/src/algebra/__tests__/load-deps-fp-memo.test.ts +132 -0
- package/src/algebra/__tests__/methods.test.ts +37 -0
- package/src/algebra/__tests__/node-types.test.ts +26 -0
- package/src/algebra/__tests__/nudo-constraints.ts +46 -0
- package/src/algebra/__tests__/objects.test.ts +117 -0
- package/src/algebra/__tests__/parse-source-cache.test.ts +42 -0
- package/src/algebra/__tests__/refine-import.test.ts +109 -0
- package/src/algebra/__tests__/stable-source-key-block.test.ts +23 -0
- package/src/algebra/__tests__/stable-source-key.test.ts +31 -0
- package/src/algebra/__tests__/surface.test.ts +41 -0
- package/src/algebra/__tests__/this-inherit.test.ts +130 -0
- package/src/algebra/abs-fn.ts +49 -0
- package/src/algebra/abs-modules.ts +139 -0
- package/src/algebra/abs.ts +206 -0
- package/src/algebra/arithmetic.ts +691 -0
- package/src/algebra/ast-eval.ts +1763 -0
- package/src/algebra/bridge.ts +350 -0
- package/src/algebra/builtins.ts +373 -0
- package/src/algebra/check-report.ts +150 -0
- package/src/algebra/check.ts +1867 -0
- package/src/algebra/constraint.ts +304 -0
- package/src/algebra/denote.ts +166 -0
- package/src/algebra/diagnostics.ts +210 -0
- package/src/algebra/exec/call.ts +29 -0
- package/src/algebra/exec/calls.ts +96 -0
- package/src/algebra/exec/class-registry.ts +29 -0
- package/src/algebra/exec/class.ts +329 -0
- package/src/algebra/exec/index.ts +6 -0
- package/src/algebra/exec/member-diag.ts +141 -0
- package/src/algebra/exec/run.ts +341 -0
- package/src/algebra/exec/runtime.ts +583 -0
- package/src/algebra/exec/transpile.ts +993 -0
- package/src/algebra/fn-fp.ts +294 -0
- package/src/algebra/format.ts +91 -0
- package/src/algebra/generalize.ts +776 -0
- package/src/algebra/hash-source.ts +27 -0
- package/src/algebra/index.ts +34 -0
- package/src/algebra/inlay.ts +198 -0
- package/src/algebra/language.ts +289 -0
- package/src/algebra/leak.ts +68 -0
- package/src/algebra/leq.ts +301 -0
- package/src/algebra/load-deps-fp.ts +97 -0
- package/src/algebra/methods.ts +128 -0
- package/src/algebra/objects.ts +251 -0
- package/src/algebra/parse-source.ts +64 -0
- package/src/algebra/phi.ts +42 -0
- package/src/algebra/pred.ts +395 -0
- package/src/algebra/refine.ts +227 -0
- package/src/algebra/stable-source-key.ts +81 -0
- package/src/algebra/surface.ts +206 -0
- package/src/algebra/template.ts +143 -0
- package/src/algebra/term.ts +119 -0
- package/src/environment.ts +5 -0
- package/src/index.ts +33 -0
- package/src/mock-helpers.ts +166 -0
- package/src/ops.ts +44 -63
- package/src/refinements/template-predicates.ts +11 -0
- package/src/refinements/template.ts +1 -3
- package/src/strip-types.ts +236 -0
- package/src/type-value.ts +153 -12
- package/src/refinements/index.ts +0 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
|
-
import { Node } from '@babel/types';
|
|
1
|
+
import { Node, File, ImportDeclaration, Expression } from '@babel/types';
|
|
2
2
|
|
|
3
3
|
type Environment = {
|
|
4
4
|
lookup(name: string): TypeValue;
|
|
5
5
|
bind(name: string, value: TypeValue): Environment;
|
|
6
6
|
update(name: string, value: TypeValue): boolean;
|
|
7
7
|
extend(bindings: Record<string, TypeValue>): Environment;
|
|
8
|
+
fork(): Environment;
|
|
8
9
|
has(name: string): boolean;
|
|
9
10
|
snapshot(): Environment;
|
|
10
11
|
getOwnBindings(): Record<string, TypeValue>;
|
|
11
12
|
};
|
|
12
13
|
declare function createEnvironment(parent?: Environment, bindings?: Map<string, TypeValue>): Environment;
|
|
13
14
|
|
|
14
|
-
type LiteralValue = string | number | boolean | null | undefined;
|
|
15
|
+
type LiteralValue$1 = string | number | boolean | bigint | null | undefined;
|
|
16
|
+
type SigImpl = (args: TypeValue[], thisVal?: TypeValue) => TypeValue | undefined;
|
|
17
|
+
type FunctionSignature = {
|
|
18
|
+
paramTypes: TypeValue[];
|
|
19
|
+
returnType: TypeValue;
|
|
20
|
+
throwsType: TypeValue;
|
|
21
|
+
impl?: SigImpl;
|
|
22
|
+
};
|
|
15
23
|
type Refinement = {
|
|
16
24
|
name: string;
|
|
17
25
|
meta: Record<string, unknown>;
|
|
@@ -22,7 +30,7 @@ type Refinement = {
|
|
|
22
30
|
};
|
|
23
31
|
type TypeValue = {
|
|
24
32
|
kind: "literal";
|
|
25
|
-
value: LiteralValue;
|
|
33
|
+
value: LiteralValue$1;
|
|
26
34
|
} | {
|
|
27
35
|
kind: "primitive";
|
|
28
36
|
type: "number" | "string" | "boolean" | "bigint" | "symbol";
|
|
@@ -62,7 +70,7 @@ type TypeValue = {
|
|
|
62
70
|
};
|
|
63
71
|
declare function createUnion(...members: TypeValue[]): TypeValue;
|
|
64
72
|
declare const T: {
|
|
65
|
-
readonly literal: (value: LiteralValue) => TypeValue;
|
|
73
|
+
readonly literal: (value: LiteralValue$1) => TypeValue;
|
|
66
74
|
readonly number: TypeValue;
|
|
67
75
|
readonly string: TypeValue;
|
|
68
76
|
readonly boolean: TypeValue;
|
|
@@ -80,10 +88,21 @@ declare const T: {
|
|
|
80
88
|
readonly union: typeof createUnion;
|
|
81
89
|
readonly fn: (params: string[], body: Node, closure: Environment) => TypeValue;
|
|
82
90
|
readonly refine: (base: TypeValue, refinement: Refinement) => TypeValue;
|
|
91
|
+
readonly fnSig: (paramTypes: TypeValue[], returnType: TypeValue, throwsType?: TypeValue, impl?: SigImpl) => TypeValue;
|
|
83
92
|
};
|
|
84
93
|
declare function typeValueEquals(a: TypeValue, b: TypeValue): boolean;
|
|
85
94
|
declare function simplifyUnion(members: TypeValue[]): TypeValue;
|
|
86
95
|
declare function widenLiteral(tv: TypeValue): TypeValue;
|
|
96
|
+
/**
|
|
97
|
+
* union 成员全部为同原语基底的字面量且数量 > maxLiterals 时塌缩为该基类型;
|
|
98
|
+
* 非 union、混合类型、或数量不超限的原样返回。
|
|
99
|
+
*
|
|
100
|
+
* 复用 simplifyUnion(内含吸收律与去重):先让「基类型已在场」的字面量被吸收
|
|
101
|
+
* (3 | number → number),再对剩余的纯字面量联合做阈值坍缩(1|2|…|20 → number)。
|
|
102
|
+
* 两步不冲突也不重复:吸收只删基类型已在场的字面量,阈值坍缩只处理无基类型
|
|
103
|
+
* 在场的纯字面量联合。
|
|
104
|
+
*/
|
|
105
|
+
declare function collapseLiteralUnion(tv: TypeValue, maxLiterals: number): TypeValue;
|
|
87
106
|
declare function isSubtypeOf(a: TypeValue, b: TypeValue): boolean;
|
|
88
107
|
declare function deepCloneTypeValue(tv: TypeValue, idMap?: Map<symbol, symbol>): TypeValue;
|
|
89
108
|
declare function mergeObjectProperties(a: TypeValue & {
|
|
@@ -96,32 +115,46 @@ declare function narrowType(tv: TypeValue, predicate: (member: TypeValue) => boo
|
|
|
96
115
|
declare function subtractType(tv: TypeValue, predicate: (member: TypeValue) => boolean): TypeValue;
|
|
97
116
|
declare function getPrimitiveTypeOf(tv: TypeValue): string | undefined;
|
|
98
117
|
declare function getRefinedBase(tv: TypeValue): TypeValue;
|
|
118
|
+
declare function isFnSig(tv: TypeValue): boolean;
|
|
119
|
+
declare function getFnSig(tv: TypeValue): FunctionSignature | undefined;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* 残差 IR 兜底(不是类型运算真理源)。
|
|
123
|
+
*
|
|
124
|
+
* 真理在 algebra:算术/比较/相等/typeof/!/−/字符串词法序/nullish 均走 Abs。
|
|
125
|
+
* 这里只保留:
|
|
126
|
+
* - add:代数拒绝时的混合 `+`
|
|
127
|
+
* - 比较/相等:代数无法判定时的保守 boolean / 字面量折叠
|
|
128
|
+
* - dispatchMethod/Property:宿主 refined 扩展(startsWith、length…)
|
|
129
|
+
*/
|
|
99
130
|
|
|
100
131
|
declare const Ops: {
|
|
101
132
|
readonly add: (left: TypeValue, right: TypeValue) => TypeValue;
|
|
102
|
-
readonly sub: (left: TypeValue, right: TypeValue) => TypeValue;
|
|
103
|
-
readonly mul: (left: TypeValue, right: TypeValue) => TypeValue;
|
|
104
|
-
readonly div: (left: TypeValue, right: TypeValue) => TypeValue;
|
|
105
|
-
readonly mod: (left: TypeValue, right: TypeValue) => TypeValue;
|
|
106
133
|
readonly strictEq: (left: TypeValue, right: TypeValue) => TypeValue;
|
|
107
134
|
readonly strictNeq: (left: TypeValue, right: TypeValue) => TypeValue;
|
|
108
135
|
readonly gt: (left: TypeValue, right: TypeValue) => TypeValue;
|
|
109
136
|
readonly lt: (left: TypeValue, right: TypeValue) => TypeValue;
|
|
110
137
|
readonly gte: (left: TypeValue, right: TypeValue) => TypeValue;
|
|
111
138
|
readonly lte: (left: TypeValue, right: TypeValue) => TypeValue;
|
|
112
|
-
readonly typeof_: (operand: TypeValue) => TypeValue;
|
|
113
139
|
readonly not: (operand: TypeValue) => TypeValue;
|
|
114
|
-
readonly neg: (operand: TypeValue) => TypeValue;
|
|
115
140
|
};
|
|
116
141
|
declare function applyBinaryOp(op: string, left: TypeValue, right: TypeValue): TypeValue;
|
|
117
142
|
declare function dispatchBinaryOp(op: string, left: TypeValue, right: TypeValue): TypeValue;
|
|
118
143
|
declare function dispatchMethod(receiver: TypeValue, name: string, args: TypeValue[]): TypeValue | undefined;
|
|
119
144
|
declare function dispatchProperty(receiver: TypeValue, name: string): TypeValue | undefined;
|
|
120
145
|
|
|
146
|
+
/**
|
|
147
|
+
* 模板字面量谓词,独立于 template.ts 以断开运行时循环引用:
|
|
148
|
+
* type-value.ts(联合吸收律)与 template.ts 都依赖本模块,而本模块对
|
|
149
|
+
* type-value.ts 只有 `import type` 边(编译后消失),运行时依赖保持单向
|
|
150
|
+
* type-value.ts / template.ts -> template-predicates.ts。
|
|
151
|
+
*/
|
|
152
|
+
declare function isTemplate(tv: TypeValue): boolean;
|
|
153
|
+
|
|
121
154
|
declare function getKnownPrefix(parts: TypeValue[]): string;
|
|
122
155
|
declare function getKnownSuffix(parts: TypeValue[]): string;
|
|
123
156
|
declare function createTemplate(parts: TypeValue[]): TypeValue;
|
|
124
|
-
|
|
157
|
+
|
|
125
158
|
declare function getTemplateParts(tv: TypeValue): TypeValue[] | undefined;
|
|
126
159
|
declare function concatTemplates(left: TypeValue, right: TypeValue): TypeValue;
|
|
127
160
|
|
|
@@ -134,4 +167,1560 @@ declare function createRange(meta: RangeMeta): TypeValue;
|
|
|
134
167
|
declare function isRange(tv: TypeValue): boolean;
|
|
135
168
|
declare function getRangeMeta(tv: TypeValue): RangeMeta | undefined;
|
|
136
169
|
|
|
137
|
-
|
|
170
|
+
/**
|
|
171
|
+
* Nudo Mock 帮助函数
|
|
172
|
+
*
|
|
173
|
+
* 提供类型安全的 mock 创建,替代 sinon 表达式
|
|
174
|
+
*/
|
|
175
|
+
|
|
176
|
+
type MockHelper = {
|
|
177
|
+
kind: "mock-helper";
|
|
178
|
+
returnValue?: TypeValue;
|
|
179
|
+
resolvedValue?: TypeValue;
|
|
180
|
+
rejectedValue?: TypeValue;
|
|
181
|
+
implementation?: (...args: TypeValue[]) => TypeValue;
|
|
182
|
+
onFirstCallValue?: TypeValue;
|
|
183
|
+
onSecondCallValue?: TypeValue;
|
|
184
|
+
withArgsCases?: {
|
|
185
|
+
args: TypeValue[];
|
|
186
|
+
returnValue: TypeValue;
|
|
187
|
+
}[];
|
|
188
|
+
callsFakeImpl?: TypeValue;
|
|
189
|
+
};
|
|
190
|
+
/**
|
|
191
|
+
* 创建一个 stub mock
|
|
192
|
+
* 用法: @nudo:mock fetch = stub()
|
|
193
|
+
*/
|
|
194
|
+
declare function stub(): MockHelper;
|
|
195
|
+
declare namespace stub {
|
|
196
|
+
var returns: (value: TypeValue) => MockHelper;
|
|
197
|
+
var resolves: (value: TypeValue) => MockHelper;
|
|
198
|
+
var rejects: (value: TypeValue) => MockHelper;
|
|
199
|
+
var onFirstCall: (value: TypeValue) => MockHelper;
|
|
200
|
+
var onSecondCall: (value: TypeValue) => MockHelper;
|
|
201
|
+
var withArgs: (...args: TypeValue[]) => MockHelper;
|
|
202
|
+
var callsFake: (fn: TypeValue) => MockHelper;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* 创建一个 spy mock
|
|
206
|
+
* 用法: @nudo:mock handler = spy()
|
|
207
|
+
*/
|
|
208
|
+
declare function spy(): MockHelper;
|
|
209
|
+
declare namespace spy {
|
|
210
|
+
var returns: (value: TypeValue) => MockHelper;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* 创建一个 mock
|
|
214
|
+
* 用法: @nudo:mock service = mock()
|
|
215
|
+
*/
|
|
216
|
+
declare function mock(): MockHelper;
|
|
217
|
+
/**
|
|
218
|
+
* 将 MockHelper 转换为 TypeValue
|
|
219
|
+
*/
|
|
220
|
+
declare function mockHelperToTypeValue(helper: MockHelper, env: Environment): TypeValue;
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* 原地剥除 AST 中的 TS-only 语法节点/字段,返回同一棵 AST(便于链式使用)。
|
|
224
|
+
* 不改写任何 loc/start/end;语句删除只影响所在数组,不重排兄弟节点。
|
|
225
|
+
*/
|
|
226
|
+
declare function stripTypes<T extends Node>(ast: T): T;
|
|
227
|
+
|
|
228
|
+
declare function resetParseSourceCache(): void;
|
|
229
|
+
declare function getParseSourceCacheSize(): number;
|
|
230
|
+
declare function parseSource(source: string, opts?: {
|
|
231
|
+
errorRecovery?: boolean;
|
|
232
|
+
}): File;
|
|
233
|
+
|
|
234
|
+
/** 项(Term):抽象值的身份。字面量是项的特例。 */
|
|
235
|
+
type LiteralValue = string | number | boolean | null | undefined;
|
|
236
|
+
type Term = {
|
|
237
|
+
op: "lit";
|
|
238
|
+
value: LiteralValue;
|
|
239
|
+
} | {
|
|
240
|
+
op: "var";
|
|
241
|
+
id: string;
|
|
242
|
+
} | {
|
|
243
|
+
op: "app";
|
|
244
|
+
fn: string;
|
|
245
|
+
args: Term[];
|
|
246
|
+
};
|
|
247
|
+
declare const lit: (value: LiteralValue) => Term;
|
|
248
|
+
declare const v: (id: string) => Term;
|
|
249
|
+
declare const app: (fn: string, args: Term[]) => Term;
|
|
250
|
+
declare function termEquals(a: Term, b: Term): boolean;
|
|
251
|
+
declare function termToString(t: Term): string;
|
|
252
|
+
/** 常量折叠 + 简单代数化简 */
|
|
253
|
+
declare function simplifyTerm(t: Term): Term;
|
|
254
|
+
|
|
255
|
+
/** 约束(Pred):附着在项上的事实,可传播。 */
|
|
256
|
+
|
|
257
|
+
type PrimName = "number" | "string" | "boolean" | "bigint" | "symbol";
|
|
258
|
+
type Pred = {
|
|
259
|
+
op: "true";
|
|
260
|
+
} | {
|
|
261
|
+
op: "false";
|
|
262
|
+
} | {
|
|
263
|
+
op: "eq";
|
|
264
|
+
a: Term;
|
|
265
|
+
b: Term;
|
|
266
|
+
} | {
|
|
267
|
+
op: "ne";
|
|
268
|
+
a: Term;
|
|
269
|
+
b: Term;
|
|
270
|
+
} | {
|
|
271
|
+
op: "lt";
|
|
272
|
+
a: Term;
|
|
273
|
+
b: Term;
|
|
274
|
+
} | {
|
|
275
|
+
op: "le";
|
|
276
|
+
a: Term;
|
|
277
|
+
b: Term;
|
|
278
|
+
} | {
|
|
279
|
+
op: "gt";
|
|
280
|
+
a: Term;
|
|
281
|
+
b: Term;
|
|
282
|
+
} | {
|
|
283
|
+
op: "ge";
|
|
284
|
+
a: Term;
|
|
285
|
+
b: Term;
|
|
286
|
+
} | {
|
|
287
|
+
op: "and";
|
|
288
|
+
args: Pred[];
|
|
289
|
+
} | {
|
|
290
|
+
op: "or";
|
|
291
|
+
args: Pred[];
|
|
292
|
+
} | {
|
|
293
|
+
op: "not";
|
|
294
|
+
arg: Pred;
|
|
295
|
+
} | {
|
|
296
|
+
op: "typeof";
|
|
297
|
+
t: Term;
|
|
298
|
+
type: PrimName;
|
|
299
|
+
};
|
|
300
|
+
declare const pTrue: Pred;
|
|
301
|
+
declare const pFalse: Pred;
|
|
302
|
+
declare const eq: (a: Term, b: Term) => Pred;
|
|
303
|
+
declare const ne: (a: Term, b: Term) => Pred;
|
|
304
|
+
declare const lt: (a: Term, b: Term) => Pred;
|
|
305
|
+
declare const le: (a: Term, b: Term) => Pred;
|
|
306
|
+
declare const gt: (a: Term, b: Term) => Pred;
|
|
307
|
+
declare const ge: (a: Term, b: Term) => Pred;
|
|
308
|
+
declare const ptypeof: (t: Term, type: PrimName) => Pred;
|
|
309
|
+
declare function and(...preds: Pred[]): Pred;
|
|
310
|
+
declare function or(...preds: Pred[]): Pred;
|
|
311
|
+
declare function not(p: Pred): Pred;
|
|
312
|
+
declare function predEquals(a: Pred, b: Pred): boolean;
|
|
313
|
+
declare function predToString(p: Pred): string;
|
|
314
|
+
/** 把 pred 里的 Term 用 subst 替换(用于 bound 变量重命名等) */
|
|
315
|
+
declare function substPred(p: Pred, subst: (t: Term) => Term): Pred;
|
|
316
|
+
/** 收集 pred 中出现的自由变量 */
|
|
317
|
+
declare function predVars(p: Pred): Set<string>;
|
|
318
|
+
/** 约束环境 Φ:Pred 的合取 */
|
|
319
|
+
type Phi = Pred;
|
|
320
|
+
declare const emptyPhi: Phi;
|
|
321
|
+
declare const phiAnd: typeof and;
|
|
322
|
+
/** 简单蕴含:在区间/字面量可判定范围内判断 Φ ⊢ pred */
|
|
323
|
+
declare function implies(phi: Phi, pred: Pred): boolean;
|
|
324
|
+
/** 便捷:数字下界 */
|
|
325
|
+
declare function gtNum(term: Term, n: number): Pred;
|
|
326
|
+
declare function geNum(term: Term, n: number): Pred;
|
|
327
|
+
declare function ltNum(term: Term, n: number): Pred;
|
|
328
|
+
declare function leNum(term: Term, n: number): Pred;
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* 路径约束栈(Φ)。
|
|
332
|
+
*
|
|
333
|
+
* Φ 是当前控制流路径上的合取前提。代数运算(add/cmp/…)读取它做单调传播;
|
|
334
|
+
* evaluator 在 if 守卫处 push/pop。栈属于类型系统,不属于 host CLI。
|
|
335
|
+
*/
|
|
336
|
+
|
|
337
|
+
declare function currentPhi(): Phi;
|
|
338
|
+
declare function pushPhi(p: Phi): void;
|
|
339
|
+
declare function popPhi(): void;
|
|
340
|
+
declare function resetPhi(): void;
|
|
341
|
+
/** 在当前 Φ 上合取额外约束,body 结束后恢复 */
|
|
342
|
+
declare function withPhiConstraint(extra: Phi, body: () => void): void;
|
|
343
|
+
declare function describePhi(): string;
|
|
344
|
+
|
|
345
|
+
/** 抽象值 Abs = 形状 × 项 × 约束 × 置信度 */
|
|
346
|
+
|
|
347
|
+
type Confidence = "exact" | "path" | "widened" | "mock" | "partial" | "opaque";
|
|
348
|
+
type Shape = {
|
|
349
|
+
k: "never";
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* any:JS 里可以是任意值(无约束参数)。
|
|
353
|
+
* 运算按真实 JS 语义取并集,不是「分析失败」。
|
|
354
|
+
*/
|
|
355
|
+
| {
|
|
356
|
+
k: "any";
|
|
357
|
+
}
|
|
358
|
+
/** unknown:分析拿不到信息(求值失败/泄漏),不是「任意值」 */
|
|
359
|
+
| {
|
|
360
|
+
k: "unknown";
|
|
361
|
+
} | {
|
|
362
|
+
k: "prim";
|
|
363
|
+
type: PrimName;
|
|
364
|
+
} | {
|
|
365
|
+
k: "obj";
|
|
366
|
+
slots: Record<string, {
|
|
367
|
+
value: Abs;
|
|
368
|
+
optional?: boolean;
|
|
369
|
+
readonly?: boolean;
|
|
370
|
+
}>;
|
|
371
|
+
index?: {
|
|
372
|
+
key: Abs;
|
|
373
|
+
value: Abs;
|
|
374
|
+
};
|
|
375
|
+
open?: boolean;
|
|
376
|
+
} | {
|
|
377
|
+
k: "arr";
|
|
378
|
+
element: Abs;
|
|
379
|
+
} | {
|
|
380
|
+
k: "tuple";
|
|
381
|
+
elements: Abs[];
|
|
382
|
+
rest?: Abs;
|
|
383
|
+
} | {
|
|
384
|
+
k: "fn";
|
|
385
|
+
params: string[];
|
|
386
|
+
name?: string;
|
|
387
|
+
paramTypes?: Abs[];
|
|
388
|
+
returnType?: Abs;
|
|
389
|
+
} | {
|
|
390
|
+
k: "brand";
|
|
391
|
+
name: string;
|
|
392
|
+
shape: Abs;
|
|
393
|
+
} | {
|
|
394
|
+
k: "eff";
|
|
395
|
+
eff: "promise" | "generator";
|
|
396
|
+
inner: Abs;
|
|
397
|
+
} | {
|
|
398
|
+
k: "sum";
|
|
399
|
+
members: Abs[];
|
|
400
|
+
};
|
|
401
|
+
type Abs = {
|
|
402
|
+
shape: Shape;
|
|
403
|
+
term?: Term;
|
|
404
|
+
pred?: Pred;
|
|
405
|
+
conf: Confidence;
|
|
406
|
+
};
|
|
407
|
+
declare const never: Abs;
|
|
408
|
+
/** 分析无信息 */
|
|
409
|
+
declare const unknown: Abs;
|
|
410
|
+
/** 带 term 的 any(generalize type-var) */
|
|
411
|
+
declare function anyVar(id: string, conf?: Confidence): Abs;
|
|
412
|
+
declare function num(): Abs;
|
|
413
|
+
declare function str(): Abs;
|
|
414
|
+
declare function bool(): Abs;
|
|
415
|
+
declare function numLit(value: number): Abs;
|
|
416
|
+
declare function strLit(value: string): Abs;
|
|
417
|
+
declare function boolLit(value: boolean): Abs;
|
|
418
|
+
/** 带项的符号数,例如参数 x */
|
|
419
|
+
declare function numVar(id: string, pred?: Pred, conf?: Confidence): Abs;
|
|
420
|
+
declare function obj(slots: Record<string, {
|
|
421
|
+
value: Abs;
|
|
422
|
+
optional?: boolean;
|
|
423
|
+
}>): Abs;
|
|
424
|
+
declare function confJoin(a: Confidence, b: Confidence): Confidence;
|
|
425
|
+
declare function absToString(a: Abs): string;
|
|
426
|
+
declare function shapeToString(s: Shape): string;
|
|
427
|
+
/** 从 term 反推 prim shape */
|
|
428
|
+
declare function shapeOfTerm(t: Term): Shape;
|
|
429
|
+
/** 构造带项的结果 Abs;pred 相对 term */
|
|
430
|
+
declare function abs(shape: Shape, term: Term | undefined, pred: Pred | undefined, conf: Confidence): Abs;
|
|
431
|
+
declare function isNumPrim(a: Abs): boolean;
|
|
432
|
+
declare function isStrPrim(a: Abs): boolean;
|
|
433
|
+
/** 置信度:字面量全确定 */
|
|
434
|
+
declare function isExactLit(a: Abs): boolean;
|
|
435
|
+
declare function litValue(a: Abs): LiteralValue | undefined;
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* 项(Term)防爆炸:深度/宽度阈值 → leak 为新鲜 var + 等式约束。
|
|
439
|
+
*/
|
|
440
|
+
|
|
441
|
+
type LeakBudget = {
|
|
442
|
+
maxDepth: number;
|
|
443
|
+
maxNodes: number;
|
|
444
|
+
};
|
|
445
|
+
declare const defaultLeakBudget: LeakBudget;
|
|
446
|
+
declare function termDepth(t: Term): number;
|
|
447
|
+
declare function termNodes(t: Term): number;
|
|
448
|
+
declare function exceedsBudget(t: Term, budget?: LeakBudget): boolean;
|
|
449
|
+
declare function resetLeakCounter(): void;
|
|
450
|
+
/**
|
|
451
|
+
* 若项超预算,替换为新鲜变量,并返回附加等式 pred:fresh = originalTerm。
|
|
452
|
+
* 未超预算则原样返回。
|
|
453
|
+
*/
|
|
454
|
+
declare function maybeLeak(a: Abs, budget?: LeakBudget, label?: string): Abs;
|
|
455
|
+
/**
|
|
456
|
+
* 批量:在算术结果上应用 leak。
|
|
457
|
+
*/
|
|
458
|
+
declare function leakIfNeeded(a: Abs, budget?: LeakBudget, label?: string): Abs;
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Abs 模块面(无 fs):import 绑定 + export 收集。
|
|
462
|
+
* 解析路径/读文件在 host;core 只吃「specifier → 导出表」。
|
|
463
|
+
*/
|
|
464
|
+
|
|
465
|
+
type AbsModuleExports = {
|
|
466
|
+
named: Record<string, Abs>;
|
|
467
|
+
default?: Abs;
|
|
468
|
+
};
|
|
469
|
+
/** 把 import 说明符绑定进 env(宿主已求值依赖) */
|
|
470
|
+
declare function bindImports(node: ImportDeclaration, env: AstEnv, modules: Record<string, AbsModuleExports>): void;
|
|
471
|
+
/**
|
|
472
|
+
* 从已求值 env + AST 收集 ESM 导出。
|
|
473
|
+
* 支持:export function/const、export { a, b as c }、export default(具名)、
|
|
474
|
+
* 以及带 source 的 re-export(`export { a } from "mod"` / `export * from "mod"`——
|
|
475
|
+
* 需 host 传入已求值 modules)。
|
|
476
|
+
*/
|
|
477
|
+
declare function collectAbsExports(file: File, env: AstEnv, modules?: Record<string, AbsModuleExports>): AbsModuleExports;
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Babel AST 抽象求值:把「类型即计算」接到真实 JS 源码。
|
|
481
|
+
* 支持表达式、函数声明/箭头、return、if、const/let、块作用域、类、循环。
|
|
482
|
+
*/
|
|
483
|
+
|
|
484
|
+
type AstEnv = {
|
|
485
|
+
vars: Map<string, Abs>;
|
|
486
|
+
/** 用户函数:name → { params, body } */
|
|
487
|
+
fns: Map<string, {
|
|
488
|
+
params: string[];
|
|
489
|
+
body: Node;
|
|
490
|
+
async?: boolean;
|
|
491
|
+
kind?: string;
|
|
492
|
+
}>;
|
|
493
|
+
/** class 表(旁路,withVar 必须保留) */
|
|
494
|
+
classes?: Map<string, unknown>;
|
|
495
|
+
/** 当前正在求值的方法所属类名(super.x() 从它的父类派发) */
|
|
496
|
+
currentOwner?: string;
|
|
497
|
+
};
|
|
498
|
+
declare function emptyEnv(): AstEnv;
|
|
499
|
+
declare function withVar(env: AstEnv, name: string, value: Abs): AstEnv;
|
|
500
|
+
type EvalOptions = {
|
|
501
|
+
phi?: Phi;
|
|
502
|
+
budget?: LeakBudget;
|
|
503
|
+
/** 预解析 AST(check 等批量场景避免重复 parse) */
|
|
504
|
+
file?: File;
|
|
505
|
+
/** host 已求值的相对依赖导出表 */
|
|
506
|
+
modules?: Record<string, AbsModuleExports>;
|
|
507
|
+
};
|
|
508
|
+
declare const MAX_CALL_DEPTH = 64;
|
|
509
|
+
declare const MAX_TOTAL_CALLS = 200000;
|
|
510
|
+
/** 宿主入口(evalProgramAbs / analyzeFn / check)前重置 */
|
|
511
|
+
declare function resetAbsCallBudget(): void;
|
|
512
|
+
/** 记录被截断的递归(service 可映射为 nudo:recursion-truncated) */
|
|
513
|
+
declare function setAbsTruncationCollector(collector: ((fnLabel: string) => void) | null): void;
|
|
514
|
+
/** Abs 域调用记录(自包含程序可不经 TypeValue evaluator) */
|
|
515
|
+
type AbsCallRecord = {
|
|
516
|
+
fnName: string;
|
|
517
|
+
args: Abs[];
|
|
518
|
+
result: Abs;
|
|
519
|
+
callLoc?: {
|
|
520
|
+
line: number;
|
|
521
|
+
column: number;
|
|
522
|
+
};
|
|
523
|
+
threw?: boolean;
|
|
524
|
+
};
|
|
525
|
+
declare function setAbsCallCollector(collector: ((r: AbsCallRecord) => void) | null): void;
|
|
526
|
+
declare function setAbsNodeCollector(collector: ((node: Node, value: Abs) => void) | null): void;
|
|
527
|
+
/** 赋值记录:结构可赋值检查用 */
|
|
528
|
+
type AbsAssignRecord = {
|
|
529
|
+
name: string;
|
|
530
|
+
prev?: Abs;
|
|
531
|
+
next: Abs;
|
|
532
|
+
line?: number;
|
|
533
|
+
column?: number;
|
|
534
|
+
};
|
|
535
|
+
declare function setAbsAssignCollector(collector: ((r: AbsAssignRecord) => void) | null): void;
|
|
536
|
+
type EvalResult = {
|
|
537
|
+
value: Abs;
|
|
538
|
+
phi: Phi;
|
|
539
|
+
env: AstEnv;
|
|
540
|
+
/** 函数已通过 return 跳出,块内后续语句不可达 */
|
|
541
|
+
returned?: boolean;
|
|
542
|
+
/** break 跳出最近循环 */
|
|
543
|
+
brk?: boolean;
|
|
544
|
+
/** continue 进入下一轮 */
|
|
545
|
+
cont?: boolean;
|
|
546
|
+
/** throw 了 value(未捕获时向上传播) */
|
|
547
|
+
threw?: boolean;
|
|
548
|
+
};
|
|
549
|
+
/**
|
|
550
|
+
* 分析一段 JS 源码。
|
|
551
|
+
* 若含多个顶层函数声明,先注册全部,再对 `main` 或最后一个有调用的函数求值。
|
|
552
|
+
* 更简单:提供 `analyzeFunction(source, fnName, args)`。
|
|
553
|
+
*/
|
|
554
|
+
declare function evalSource(source: string, entry: {
|
|
555
|
+
fn: string;
|
|
556
|
+
args: Abs[];
|
|
557
|
+
}, opts?: EvalOptions): EvalResult;
|
|
558
|
+
declare function callFunction(env: AstEnv, name: string, args: Abs[], phi?: Phi, budget?: LeakBudget): Abs;
|
|
559
|
+
/**
|
|
560
|
+
* 在 this=receiver 下求值方法体。
|
|
561
|
+
* constructor 无显式 return 时返回更新后的 this(字段写入已并入 env)。
|
|
562
|
+
*/
|
|
563
|
+
declare function evalMethodBody(method: {
|
|
564
|
+
params: string[];
|
|
565
|
+
body: Node;
|
|
566
|
+
async?: boolean;
|
|
567
|
+
kind?: string;
|
|
568
|
+
}, args: Abs[], thisVal: Abs, env: AstEnv, phi?: Phi, budget?: LeakBudget,
|
|
569
|
+
/** 方法定义所在类名(用于 super 派发) */
|
|
570
|
+
ownerClass?: string): Abs;
|
|
571
|
+
/** 对外入口:求值并记入节点表(Map<Node, Abs> 由 collector 消费) */
|
|
572
|
+
declare function evalNode(node: Node, env: AstEnv, phi: Phi, budget: LeakBudget): EvalResult;
|
|
573
|
+
/**
|
|
574
|
+
* 从源码分析指定函数在给定实参下的抽象结果。
|
|
575
|
+
*
|
|
576
|
+
* @example
|
|
577
|
+
* analyzeFn(`
|
|
578
|
+
* const add = (a, b) => a + b;
|
|
579
|
+
* function scale(x) { return add(x, 1); }
|
|
580
|
+
* `, "scale", [numVar("x", gtNum(v("x"), 0))], gtNum(v("x"), 0))
|
|
581
|
+
*/
|
|
582
|
+
declare function analyzeFn(source: string, fnName: string, args: Abs[], phi?: Phi, budget?: LeakBudget, file?: File, modules?: Record<string, AbsModuleExports>): Abs;
|
|
583
|
+
/**
|
|
584
|
+
* 程序级 Abs 求值:注册全部顶层函数/class,再顺序执行语句。
|
|
585
|
+
* 返回最终 env(vars 含导出绑定)。TypeValue 仅在调用方 bridge 时出现。
|
|
586
|
+
*
|
|
587
|
+
* seedVars / seedFns:host 注入(@nudo:mock 等)在求值前绑定。
|
|
588
|
+
* modules:host 已求值的依赖导出表(specifier → AbsModuleExports)。
|
|
589
|
+
*/
|
|
590
|
+
declare function evalProgramAbs(source: string, opts?: EvalOptions & {
|
|
591
|
+
seedVars?: Record<string, Abs>;
|
|
592
|
+
seedFns?: Record<string, {
|
|
593
|
+
params: string[];
|
|
594
|
+
body: Node;
|
|
595
|
+
async?: boolean;
|
|
596
|
+
}>;
|
|
597
|
+
modules?: Record<string, AbsModuleExports>;
|
|
598
|
+
}): {
|
|
599
|
+
env: AstEnv;
|
|
600
|
+
last: Abs;
|
|
601
|
+
phi: Phi;
|
|
602
|
+
};
|
|
603
|
+
/**
|
|
604
|
+
* 收集整文件的节点 → Abs 表(LSP 无损信息源)。
|
|
605
|
+
* 自包含源码上一次 evalProgramAbs 即可;失败返回空表。
|
|
606
|
+
*/
|
|
607
|
+
declare function collectAbsNodeTypes(source: string, opts?: EvalOptions & {
|
|
608
|
+
seedVars?: Record<string, Abs>;
|
|
609
|
+
seedFns?: Record<string, {
|
|
610
|
+
params: string[];
|
|
611
|
+
body: Node;
|
|
612
|
+
async?: boolean;
|
|
613
|
+
}>;
|
|
614
|
+
}): Map<Node, Abs>;
|
|
615
|
+
/** 按 loc 找最紧的节点 Abs(hover 用) */
|
|
616
|
+
declare function findAbsAtPosition(nodeTypes: Map<Node, Abs>, line: number, column: number): Abs | undefined;
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* Abs 上的一等函数:shape 是 fn,实现在旁路(不污染 Shape)。
|
|
620
|
+
* 与 term-registry 同一纪律:不给共享单例挂 impl。
|
|
621
|
+
*/
|
|
622
|
+
|
|
623
|
+
type AbsFnImpl = {
|
|
624
|
+
params: string[];
|
|
625
|
+
body: Node;
|
|
626
|
+
async?: boolean;
|
|
627
|
+
/** 声明时捕获的环境(闭包) */
|
|
628
|
+
env?: AstEnv;
|
|
629
|
+
kind?: string;
|
|
630
|
+
/** 调用时直接派发(mock withArgs 等),优先于 body */
|
|
631
|
+
apply?: (args: Abs[]) => Abs;
|
|
632
|
+
/**
|
|
633
|
+
* Optional content key for cache fingerprints. formatAbs cannot see
|
|
634
|
+
* WeakMap-side mock semantics (returns/withArgs/callsFake), so hosts that
|
|
635
|
+
* build mocks should stamp a stable fingerprint here.
|
|
636
|
+
*/
|
|
637
|
+
fingerprint?: string;
|
|
638
|
+
};
|
|
639
|
+
declare function attachFnImpl(a: Abs, impl: AbsFnImpl): void;
|
|
640
|
+
declare function getFnImpl(a: Abs): AbsFnImpl | undefined;
|
|
641
|
+
/** 造一个带实现的 Abs 函数值 */
|
|
642
|
+
declare function absFunction(params: string[], impl: Omit<AbsFnImpl, "params">): Abs;
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* 算术核:单调性 + 常量折叠 + 约束传播。
|
|
646
|
+
* 这是「类型即计算」的主武器——x>0 时 x+1 必须得到 >1。
|
|
647
|
+
*/
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* 抽象加法:eval(a + b) —— 跟真实 JS,不无根据地假定 number。
|
|
651
|
+
* 1. 双方字面量 → 直接求值
|
|
652
|
+
* 2. 双方 number prim → term + 单调性 pred,shape=number
|
|
653
|
+
* 3. 含 string/template → 拼接
|
|
654
|
+
* 4. any / type-var 参与 → 按 JS + 的可能结果取并集:number | string
|
|
655
|
+
* (bool/null 走 ToNumber→number;object 默认 ToPrimitive→string;
|
|
656
|
+
* bigint/symbol 边角不在默认并集里,由调用点实例化再收窄)
|
|
657
|
+
* 无契约的 score(x){return x+1}:score("x") 合法,不得钉成 number。
|
|
658
|
+
*/
|
|
659
|
+
declare function add(a: Abs, b: Abs, phi?: Phi): Abs;
|
|
660
|
+
type NumBounds = {
|
|
661
|
+
lo?: {
|
|
662
|
+
value: number;
|
|
663
|
+
strict: boolean;
|
|
664
|
+
};
|
|
665
|
+
hi?: {
|
|
666
|
+
value: number;
|
|
667
|
+
strict: boolean;
|
|
668
|
+
};
|
|
669
|
+
};
|
|
670
|
+
/**
|
|
671
|
+
* 提取 Abs 上相对 term 的数值界。
|
|
672
|
+
* 优先用自身 pred;否则查 Φ(针对 var id)。
|
|
673
|
+
*/
|
|
674
|
+
declare function numericBounds(a: Abs, phi?: Phi): NumBounds | undefined;
|
|
675
|
+
/** 减法:a - b = a + (-b),数值上做单调性 */
|
|
676
|
+
declare function sub(a: Abs, b: Abs, phi?: Phi): Abs;
|
|
677
|
+
/** 乘法:字面量直接求值;×正数同向缩放;×负数翻转不等式;×0 归零 */
|
|
678
|
+
declare function mul(a: Abs, b: Abs, phi?: Phi): Abs;
|
|
679
|
+
/**
|
|
680
|
+
* 除法:字面量折叠;除以正/负常数时按单调性推界。
|
|
681
|
+
* 除以 0:JS 语义为 ±Infinity / NaN,shape 仍 number(不报违例)。
|
|
682
|
+
*/
|
|
683
|
+
declare function div(a: Abs, b: Abs, phi?: Phi): Abs;
|
|
684
|
+
/**
|
|
685
|
+
* 取模:字面量折叠;`x % k`(k>0 字面量)结果界在 (−|k|, |k|)。
|
|
686
|
+
* 整数模可收紧到 [0, k),此处先做保守实数界。
|
|
687
|
+
*/
|
|
688
|
+
declare function mod(a: Abs, b: Abs, phi?: Phi): Abs;
|
|
689
|
+
/** 比较:返回 boolean Abs;若双字面量则 exact */
|
|
690
|
+
declare function cmp(op: "lt" | "le" | "gt" | "ge" | "eq" | "ne", a: Abs, b: Abs, phi?: Phi): Abs;
|
|
691
|
+
/** 从比较结果 Abs 提取「若为真」的额外约束(供 if 使用) */
|
|
692
|
+
declare function trueConstraint(c: Abs): Pred | undefined;
|
|
693
|
+
declare function falseConstraint(c: Abs): Pred | undefined;
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* 语言表面运算(仍在 Abs 上):typeof / 一元- / ! / nullish 相等。
|
|
697
|
+
* 类型即计算——一元与控制流判定与二元算术同一运算域。
|
|
698
|
+
*/
|
|
699
|
+
|
|
700
|
+
/** JS typeof:结果域永远是 string */
|
|
701
|
+
declare function typeofAbs(a: Abs): Abs;
|
|
702
|
+
/** 一元负号:字面量折叠;符号数翻转不等式 */
|
|
703
|
+
declare function negAbs(a: Abs, _phi?: Phi): Abs;
|
|
704
|
+
/** 逻辑非 */
|
|
705
|
+
declare function notAbs(a: Abs): Abs;
|
|
706
|
+
/** 该 shape 在 JS 上一定不是 null/undefined */
|
|
707
|
+
declare function definitelyNotNullishShape(s: Shape): boolean;
|
|
708
|
+
declare function isNullishLitAbs(a: Abs): boolean;
|
|
709
|
+
/**
|
|
710
|
+
* 严格相等(Abs):双字面量折叠;nullish 与 definitely-not-nullish → false。
|
|
711
|
+
* 返回 undefined = 无法判定(交给 boolean + 调用方)。
|
|
712
|
+
*/
|
|
713
|
+
declare function strictEqAbs(a: Abs, b: Abs): boolean | undefined;
|
|
714
|
+
|
|
715
|
+
/**
|
|
716
|
+
* Abs 侧常用 builtin:shape 级运算,不依赖 TypeValue host 库。
|
|
717
|
+
* 覆盖 Math / Object / JSON / Number / 全局转换函数的常见面。
|
|
718
|
+
*/
|
|
719
|
+
|
|
720
|
+
/** Math.* — 字面量可折叠的返回精确值,否则 number */
|
|
721
|
+
declare function evalMathMethod(name: string, args: Abs[]): Abs | undefined;
|
|
722
|
+
/** Object.keys/values/entries/assign */
|
|
723
|
+
declare function evalObjectMethod(name: string, args: Abs[]): Abs | undefined;
|
|
724
|
+
/** JSON.parse / stringify */
|
|
725
|
+
declare function evalJsonMethod(name: string, args: Abs[]): Abs | undefined;
|
|
726
|
+
/** Number.isInteger / isNaN / parseFloat 等 */
|
|
727
|
+
declare function evalNumberStatic(name: string, args: Abs[]): Abs | undefined;
|
|
728
|
+
/** 全局 parseInt / parseFloat / isNaN / Number / String / Boolean */
|
|
729
|
+
declare function evalGlobalFn(name: string, args: Abs[]): Abs | undefined;
|
|
730
|
+
/** Array.isArray / Array.from / Array.of */
|
|
731
|
+
declare function evalArrayStatic(name: string, args: Abs[]): Abs | undefined;
|
|
732
|
+
/** new Date() / Date.now / date.getTime */
|
|
733
|
+
declare function evalDateCtor(args: Abs[]): Abs;
|
|
734
|
+
declare function evalDateStatic(name: string, _args: Abs[]): Abs | undefined;
|
|
735
|
+
declare function evalDateMethod(name: string, _recv: Abs, _args: Abs[]): Abs | undefined;
|
|
736
|
+
/** new RegExp / regexp.test / exec */
|
|
737
|
+
declare function evalRegExpCtor(_args: Abs[]): Abs;
|
|
738
|
+
declare function evalRegExpMethod(name: string, _recv: Abs, _args: Abs[]): Abs | undefined;
|
|
739
|
+
/** Promise:new Promise / Promise.resolve / reject / all */
|
|
740
|
+
declare function evalPromiseCtor(_args: Abs[]): Abs;
|
|
741
|
+
declare function evalPromiseStatic(name: string, args: Abs[]): Abs | undefined;
|
|
742
|
+
/** 命名空间分派入口 */
|
|
743
|
+
declare function evalNamespaceCall(ns: string, method: string, args: Abs[]): Abs | undefined;
|
|
744
|
+
/** new X(...) */
|
|
745
|
+
declare function evalBuiltinNew(className: string, args: Abs[]): Abs | undefined;
|
|
746
|
+
/** brand 实例方法(Date/RegExp/Map/Set) */
|
|
747
|
+
declare function evalBuiltinInstanceMethod(brandName: string, method: string, recv: Abs, args: Abs[]): Abs | undefined;
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* Abs 方法表:模板字符串 / 结构值上的方法与属性。
|
|
751
|
+
* 类型即计算——方法结果仍是 Abs,可继续参与约束推理。
|
|
752
|
+
* 宿主 TypeValue 的 dispatchMethod 只服务 IR 兜底,不是真理源。
|
|
753
|
+
*/
|
|
754
|
+
|
|
755
|
+
/**
|
|
756
|
+
* 调用 Abs 方法。返回 undefined = 未接管(调用方走其它路径)。
|
|
757
|
+
*/
|
|
758
|
+
declare function callAbsMethod(recv: Abs, name: string, args: Abs[]): Abs | undefined;
|
|
759
|
+
/** 属性读取:template.length 等 */
|
|
760
|
+
declare function getAbsProperty(recv: Abs, name: string): Abs | undefined;
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* 结构层:对象槽位、spread、函数重载并。
|
|
764
|
+
* 纪律:积之和默认;optional 塌缩是显式损失;函数并保输入→输出相关性。
|
|
765
|
+
*/
|
|
766
|
+
|
|
767
|
+
type Slot = {
|
|
768
|
+
value: Abs;
|
|
769
|
+
optional?: boolean;
|
|
770
|
+
readonly?: boolean;
|
|
771
|
+
};
|
|
772
|
+
type ObjShape = {
|
|
773
|
+
k: "obj";
|
|
774
|
+
slots: Record<string, Slot>;
|
|
775
|
+
index?: {
|
|
776
|
+
key: Abs;
|
|
777
|
+
value: Abs;
|
|
778
|
+
};
|
|
779
|
+
open?: boolean;
|
|
780
|
+
};
|
|
781
|
+
declare function objOf(slots: Record<string, Slot>, opts?: {
|
|
782
|
+
index?: {
|
|
783
|
+
key: Abs;
|
|
784
|
+
value: Abs;
|
|
785
|
+
};
|
|
786
|
+
open?: boolean;
|
|
787
|
+
}): Abs;
|
|
788
|
+
declare function isObj(a: Abs): a is Abs & {
|
|
789
|
+
shape: ObjShape;
|
|
790
|
+
};
|
|
791
|
+
/**
|
|
792
|
+
* spread:base ⊕ over(右侧覆盖,不是 join)
|
|
793
|
+
* 未出现在 over 的 key 保留 base;over 的 key 覆盖。
|
|
794
|
+
*/
|
|
795
|
+
declare function spread(base: Abs, over: Abs): Abs;
|
|
796
|
+
/**
|
|
797
|
+
* 对象 join:默认积之和(sum),不自动折 optional。
|
|
798
|
+
* 同 key 集:槽位级 join(字面量并);异 key 集:保持 sum。
|
|
799
|
+
*/
|
|
800
|
+
declare function joinObjects(a: Abs, b: Abs): Abs;
|
|
801
|
+
/** 值级 join:字面量保留为… Phase A 对 prim 做 term 保留策略 */
|
|
802
|
+
declare function joinValues(a: Abs, b: Abs): Abs;
|
|
803
|
+
declare function makeSum(a: Abs, b: Abs): Abs;
|
|
804
|
+
/**
|
|
805
|
+
* 显式损失:sum-of-products → optional 槽(仅 emit/阈值)。
|
|
806
|
+
* 强制 #widened。
|
|
807
|
+
*/
|
|
808
|
+
declare function collapseToOptional(sum: Abs): Abs;
|
|
809
|
+
type FnAbs = Abs & {
|
|
810
|
+
shape: {
|
|
811
|
+
k: "fn";
|
|
812
|
+
params: string[];
|
|
813
|
+
name?: string;
|
|
814
|
+
/** 外延参数类型(若已知) */
|
|
815
|
+
paramTypes?: Abs[];
|
|
816
|
+
/** 外延返回类型 */
|
|
817
|
+
returnType?: Abs;
|
|
818
|
+
};
|
|
819
|
+
};
|
|
820
|
+
declare function fnOf(params: string[], name?: string): Abs;
|
|
821
|
+
/**
|
|
822
|
+
* 函数 join:签名并(重载),禁止 (A|C)→(B|D)。
|
|
823
|
+
*/
|
|
824
|
+
declare function joinFunctions(a: Abs, b: Abs): Abs;
|
|
825
|
+
/** 通用 join:分派到对象/函数/值 */
|
|
826
|
+
declare function joinAbs(a: Abs, b: Abs): Abs;
|
|
827
|
+
|
|
828
|
+
/**
|
|
829
|
+
* 结构可赋值:src ≤ tgt(Abs 上的 leq)。
|
|
830
|
+
*
|
|
831
|
+
* 规则与 TS 结构子类型同构,但作用在推断出的 Abs 上:
|
|
832
|
+
* - 对象宽度 + 深度;optional 可缺
|
|
833
|
+
* - brand 名义;fn 参数逆变、返回协变
|
|
834
|
+
* - pred:src 蕴含 tgt(更严的值可赋给更宽的目标)
|
|
835
|
+
*
|
|
836
|
+
* 不是完备 checker 的替代——是 Abs 之间的兼容判定。
|
|
837
|
+
*/
|
|
838
|
+
|
|
839
|
+
type LeqResult = {
|
|
840
|
+
ok: boolean;
|
|
841
|
+
/** Nudo 式原因(actual ⊭ target),不是 TS 文案 */
|
|
842
|
+
reason?: string;
|
|
843
|
+
};
|
|
844
|
+
/**
|
|
845
|
+
* src 可赋给 tgt。
|
|
846
|
+
* phi:路径前提(可选);env:用于 brand 继承链。
|
|
847
|
+
*/
|
|
848
|
+
declare function leqAbs(src: Abs, tgt: Abs, opts?: {
|
|
849
|
+
phi?: Phi;
|
|
850
|
+
env?: AstEnv;
|
|
851
|
+
}): LeqResult;
|
|
852
|
+
|
|
853
|
+
/**
|
|
854
|
+
* 格式化:把 Abs 渲染成人类可读 / CLI 友好的字符串。
|
|
855
|
+
*/
|
|
856
|
+
|
|
857
|
+
type FormatOptions = {
|
|
858
|
+
/** 是否显示 term= */
|
|
859
|
+
showTerm?: boolean;
|
|
860
|
+
/** 是否显示 pred */
|
|
861
|
+
showPred?: boolean;
|
|
862
|
+
indent?: string;
|
|
863
|
+
};
|
|
864
|
+
declare function formatAbs(a: Abs, opts?: FormatOptions): string;
|
|
865
|
+
declare function formatShape(a: Abs): string;
|
|
866
|
+
/** 多行展示,CLI 用 */
|
|
867
|
+
declare function formatAbsMultiline(a: Abs, label?: string): string;
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* 约束模板构建器(参数无关)。
|
|
871
|
+
*
|
|
872
|
+
* number().gt(0) → 占位项 self 上的 Pred
|
|
873
|
+
* number().int().ge(0) → 整数 + 下界
|
|
874
|
+
* string().min(1) → 非空串(长度)
|
|
875
|
+
* array(number().gt(0)) → 元素约束
|
|
876
|
+
* shape({ id: number().gt(0) }) → object 形状约束
|
|
877
|
+
* instantiate("ms") → Pred ms > 0 / u.id > 0 ∧ …
|
|
878
|
+
*
|
|
879
|
+
* 在 *.nudo.js 里执行;不是 zod 绑定,是我们自己的运行时 API。
|
|
880
|
+
* 不需要 interface/type 语法——契约用 JS 表达式声明。
|
|
881
|
+
*/
|
|
882
|
+
|
|
883
|
+
/** 模板占位项;instantiate 时换成真实参数名 */
|
|
884
|
+
declare const SELF = "__nudo_self__";
|
|
885
|
+
/** 字段访问项:u.id */
|
|
886
|
+
declare function getTerm(obj: Term, key: string): Term;
|
|
887
|
+
/** 长度项:length(u) */
|
|
888
|
+
declare function lenTerm(t: Term): Term;
|
|
889
|
+
type NudoField = {
|
|
890
|
+
constraint: NudoConstraint;
|
|
891
|
+
optional?: boolean;
|
|
892
|
+
};
|
|
893
|
+
type NudoConstraint = {
|
|
894
|
+
readonly __nudoConstraint: true;
|
|
895
|
+
readonly prim?: PrimName;
|
|
896
|
+
readonly preds: Pred[];
|
|
897
|
+
/** object 形状:字段名 → 嵌套约束 */
|
|
898
|
+
readonly fields?: Record<string, NudoField>;
|
|
899
|
+
/** array 元素约束 */
|
|
900
|
+
readonly element?: NudoConstraint;
|
|
901
|
+
/** 整数(number 链式 .int()) */
|
|
902
|
+
readonly int?: boolean;
|
|
903
|
+
/** 该约束整体可选(shape 字段用;不用 optional 以免与链式方法撞名) */
|
|
904
|
+
readonly isOptional?: boolean;
|
|
905
|
+
};
|
|
906
|
+
declare function isNudoConstraint(x: unknown): x is NudoConstraint;
|
|
907
|
+
/** 链式约束:不可变,每次 .gt() 返回新对象 */
|
|
908
|
+
type ConstraintBuilder = NudoConstraint & {
|
|
909
|
+
gt(n: number): ConstraintBuilder;
|
|
910
|
+
ge(n: number): ConstraintBuilder;
|
|
911
|
+
lt(n: number): ConstraintBuilder;
|
|
912
|
+
le(n: number): ConstraintBuilder;
|
|
913
|
+
/** number:要求整数 */
|
|
914
|
+
int(): ConstraintBuilder;
|
|
915
|
+
/** string:长度下界 */
|
|
916
|
+
min(n: number): ConstraintBuilder;
|
|
917
|
+
/** string:长度上界 */
|
|
918
|
+
max(n: number): ConstraintBuilder;
|
|
919
|
+
/** string:精确长度 */
|
|
920
|
+
length(n: number): ConstraintBuilder;
|
|
921
|
+
/** 字段可选(仅在 shape 内有意义) */
|
|
922
|
+
optional(): ConstraintBuilder;
|
|
923
|
+
};
|
|
924
|
+
/** number() —— 约束 number 原语 + 后续链式界 */
|
|
925
|
+
declare function number(): ConstraintBuilder;
|
|
926
|
+
declare function string(): ConstraintBuilder;
|
|
927
|
+
declare function boolean(): ConstraintBuilder;
|
|
928
|
+
/** array(item) —— 数组,元素满足 item */
|
|
929
|
+
declare function array(item: NudoConstraint | ConstraintBuilder): ConstraintBuilder;
|
|
930
|
+
/**
|
|
931
|
+
* object 形状约束(契约规范形状,无需 interface):
|
|
932
|
+
*
|
|
933
|
+
* shape({ id: number().gt(0), name: string() })
|
|
934
|
+
*/
|
|
935
|
+
declare function shape(fields: Record<string, NudoConstraint | ConstraintBuilder>): ConstraintBuilder;
|
|
936
|
+
/** 把模板绑定到参数名:self → paramName;shape 展开为字段访问 Pred */
|
|
937
|
+
declare function instantiateConstraint(c: NudoConstraint, paramName: string): Pred;
|
|
938
|
+
/**
|
|
939
|
+
* 契约 → 函数入口 param Abs(infer/hover 用)。
|
|
940
|
+
* 标量:prim + pred;shape:obj slots 递归。
|
|
941
|
+
*/
|
|
942
|
+
declare function constraintToEntryAbs(c: NudoConstraint, paramName: string): Abs;
|
|
943
|
+
|
|
944
|
+
/**
|
|
945
|
+
* 精化契约解析:唯一形态
|
|
946
|
+
*
|
|
947
|
+
* @nudo:refine <param> <constraint> 参数精化(挂入口 Abs,参与运算)
|
|
948
|
+
* @nudo:refine return <constraint> 返回精化(推断返回值 ⊭ 时红)
|
|
949
|
+
*
|
|
950
|
+
* 不叫 requires:那只是「校验挡板」。
|
|
951
|
+
* refine 表示约束是类型的一部分——Abs = shape × term × **pred** × conf,
|
|
952
|
+
* pred 会流入代数(x>0 ⇒ x+1>1),不只是调用点挡一下。
|
|
953
|
+
*
|
|
954
|
+
* constraint 来自 *.nudo.js 导出的模板(number().gt(0) 等),
|
|
955
|
+
* 由 /// @nudo:import { delay } from "./delay.nudo.js" 引入。
|
|
956
|
+
* 不支持写 `x > 0`(绑死参数名)。
|
|
957
|
+
* 不用 JSDoc @param/@return:那是类型注解语法。
|
|
958
|
+
*/
|
|
959
|
+
|
|
960
|
+
/** `/// @nudo:import { delay, percent } from "./delay.nudo.js"` */
|
|
961
|
+
type NamedImport = {
|
|
962
|
+
names: string[];
|
|
963
|
+
spec: string;
|
|
964
|
+
};
|
|
965
|
+
declare function extractNudoImports(source: string): NamedImport[];
|
|
966
|
+
/**
|
|
967
|
+
* 执行 *.nudo.js(真实 JS + 我们的构建器)。
|
|
968
|
+
* 把 export const 改写成 const,末尾 return { names }。
|
|
969
|
+
*/
|
|
970
|
+
declare function execNudoModule(src: string): Record<string, unknown>;
|
|
971
|
+
type RefineResolveOpts = {
|
|
972
|
+
loadModule?: (spec: string, fromFile: string) => string | undefined;
|
|
973
|
+
fromFile?: string;
|
|
974
|
+
};
|
|
975
|
+
declare function resetNudoModuleExecCache(): void;
|
|
976
|
+
/**
|
|
977
|
+
* 解析 `ms delay` / `n percent` → [param, Pred]
|
|
978
|
+
* 多条用 && 或换行连接。
|
|
979
|
+
* 同时保留原始 NudoConstraint(shape 字段检查用)。
|
|
980
|
+
*/
|
|
981
|
+
type RefineEntry = {
|
|
982
|
+
param: string;
|
|
983
|
+
pred: Pred;
|
|
984
|
+
constraint: NudoConstraint;
|
|
985
|
+
};
|
|
986
|
+
declare function extractRefinesFromSource(source: string, fnName: string, opts?: RefineResolveOpts): RefineEntry[];
|
|
987
|
+
/** refine 参数 → 带约束模板的下标表(shape 检查用) */
|
|
988
|
+
declare function refineToIndexedFull(source: string, fnName: string, paramNames: string[], opts?: RefineResolveOpts): Array<[number, RefineEntry]>;
|
|
989
|
+
/**
|
|
990
|
+
* 解析 `@nudo:refine return positive` → 返回精化。
|
|
991
|
+
* 返回 undefined = 无声明(不猜后置)。
|
|
992
|
+
*/
|
|
993
|
+
declare function extractRefineReturnFromSource(source: string, fnName: string, opts?: RefineResolveOpts): {
|
|
994
|
+
name: string;
|
|
995
|
+
constraint: NudoConstraint;
|
|
996
|
+
} | undefined;
|
|
997
|
+
|
|
998
|
+
type LoadDepsFingerprint = {
|
|
999
|
+
fp: string;
|
|
1000
|
+
paths: string[];
|
|
1001
|
+
/** BFS 撞到节点上限:剩余 dep 未进指纹,键不可信 */
|
|
1002
|
+
truncated: boolean;
|
|
1003
|
+
};
|
|
1004
|
+
declare function normPath(p: string): string;
|
|
1005
|
+
/** core 不引 path:相对 spec 纯字符串拼接(与 LSP resolve 对齐时双方 norm) */
|
|
1006
|
+
declare function resolveDepPath(fromFile: string, spec: string): string;
|
|
1007
|
+
/**
|
|
1008
|
+
* All string module specs that analysis may resolve through loadModule.
|
|
1009
|
+
* Regex over-approximates (may hit comments) — extra dep fingerprint is safe
|
|
1010
|
+
* (more misses, never a stale hit).
|
|
1011
|
+
*/
|
|
1012
|
+
declare function extractAllLoadSpecs(source: string): string[];
|
|
1013
|
+
/**
|
|
1014
|
+
* Fingerprint every loadModule-reachable dep (not only `*.nudo.js`), including
|
|
1015
|
+
* one hop of transitive specs from each dep source.
|
|
1016
|
+
*/
|
|
1017
|
+
declare function loadModuleDepsFingerprint(source: string, loadModule: (spec: string, fromFile: string) => string | undefined, fromFile: string): LoadDepsFingerprint;
|
|
1018
|
+
|
|
1019
|
+
declare function resetGeneralizeMemo(): void;
|
|
1020
|
+
declare function getGeneralizeMemoSize(): number;
|
|
1021
|
+
/**
|
|
1022
|
+
* LSP/宿主:`*.nudo.js` 变更后按路径定向逐出依赖它的 L0 条目。
|
|
1023
|
+
* 返回删除的条目数。路径需与 generalize 时 resolveDepPath 形态一致(建议先 norm)。
|
|
1024
|
+
*/
|
|
1025
|
+
declare function evictGeneralizeMemoForPaths(paths: string[]): number;
|
|
1026
|
+
type TypeParam = {
|
|
1027
|
+
id: string;
|
|
1028
|
+
value: Abs;
|
|
1029
|
+
};
|
|
1030
|
+
type PolyFn = {
|
|
1031
|
+
name: string;
|
|
1032
|
+
params: string[];
|
|
1033
|
+
typeParams: TypeParam[];
|
|
1034
|
+
instantiate: (args: Abs[], phi?: Phi) => Abs;
|
|
1035
|
+
symbolic: Abs;
|
|
1036
|
+
display: string;
|
|
1037
|
+
/** 入口契约(@nudo:refine),供签名/inlay 展示 */
|
|
1038
|
+
entryReqs?: Array<{
|
|
1039
|
+
param: string;
|
|
1040
|
+
pred: Pred;
|
|
1041
|
+
}>;
|
|
1042
|
+
};
|
|
1043
|
+
declare function generalizeFromAst(fnName: string, source: string, opts?: {
|
|
1044
|
+
budget?: LeakBudget;
|
|
1045
|
+
label?: string;
|
|
1046
|
+
/** 传入则把 @nudo:refine 挂到入口 param Abs */
|
|
1047
|
+
refine?: RefineResolveOpts;
|
|
1048
|
+
/** 预解析 AST,避免 check 批量场景重复 parse */
|
|
1049
|
+
file?: ReturnType<typeof parseSource>;
|
|
1050
|
+
/** 预计算 load-deps 指纹(checkSource 整文件一次,避免 per-fn 重读) */
|
|
1051
|
+
depsFp?: LoadDepsFingerprint;
|
|
1052
|
+
}): PolyFn | undefined;
|
|
1053
|
+
declare function generalizeAll(source: string, opts?: {
|
|
1054
|
+
budget?: LeakBudget;
|
|
1055
|
+
}): PolyFn[];
|
|
1056
|
+
/** 列出源码中的顶层函数名 */
|
|
1057
|
+
declare function listFunctionNames(source: string): string[];
|
|
1058
|
+
/**
|
|
1059
|
+
* 按 assume 集合构造实参:被 assume 的参数给带约束的符号,其余 unknown。
|
|
1060
|
+
*/
|
|
1061
|
+
declare function buildArgsFromAssume(source: string, fnName: string, assumeIds: Set<string>): Abs[];
|
|
1062
|
+
|
|
1063
|
+
/**
|
|
1064
|
+
* 约束诊断:检查调用点实参是否满足函数的前置约束 / 参数 shape。
|
|
1065
|
+
* 输出可行动的建议,而不是 TS 式「类型不匹配」。
|
|
1066
|
+
*/
|
|
1067
|
+
|
|
1068
|
+
type Diagnostic = {
|
|
1069
|
+
severity: "error" | "warning" | "info";
|
|
1070
|
+
code: string;
|
|
1071
|
+
message: string;
|
|
1072
|
+
suggestion?: string;
|
|
1073
|
+
fn?: string;
|
|
1074
|
+
argIndex?: number;
|
|
1075
|
+
};
|
|
1076
|
+
/**
|
|
1077
|
+
* 检查实参是否满足「期望约束」。
|
|
1078
|
+
* expect: 相对参数 term 的 pred,例如 term > 0
|
|
1079
|
+
* arg: 实际实参 Abs
|
|
1080
|
+
*/
|
|
1081
|
+
declare function checkArg(arg: Abs, expect: Pred | undefined, phi?: Phi): Diagnostic | undefined;
|
|
1082
|
+
/**
|
|
1083
|
+
* 对一次函数调用做诊断:实参 shape + 约束。
|
|
1084
|
+
*/
|
|
1085
|
+
declare function checkCall(source: string, fnName: string, args: Abs[], phi?: Phi): Diagnostic[];
|
|
1086
|
+
declare function formatDiagnostics(diags: Diagnostic[]): string;
|
|
1087
|
+
|
|
1088
|
+
/**
|
|
1089
|
+
* Template string 拼接(代数侧)。
|
|
1090
|
+
* 表示:prim(string) + refinement.meta.templateParts = Abs[]
|
|
1091
|
+
* 与 core 的 createTemplate 对齐,使 `"x" + string + "!"` 得到 template refined。
|
|
1092
|
+
*/
|
|
1093
|
+
|
|
1094
|
+
type TemplateMeta = {
|
|
1095
|
+
templateParts: Abs[];
|
|
1096
|
+
};
|
|
1097
|
+
/** 从 Abs 提取 template parts(已是 template 则展开,否则 [self]) */
|
|
1098
|
+
declare function templatePartsOf(a: Abs): Abs[];
|
|
1099
|
+
/**
|
|
1100
|
+
* 构造 template Abs。
|
|
1101
|
+
* - 全字面量 → exact lit
|
|
1102
|
+
* - 单 string prim → prim
|
|
1103
|
+
* - 否则 prim(string) + pred(name=template, meta.templateParts)
|
|
1104
|
+
*/
|
|
1105
|
+
declare function createTemplateAbs(parts: Abs[]): Abs;
|
|
1106
|
+
declare function isTemplateLike(a: Abs): boolean;
|
|
1107
|
+
/** 字符串拼接:字面量折叠 + template parts 合并 */
|
|
1108
|
+
declare function concatString(a: Abs, b: Abs): Abs;
|
|
1109
|
+
|
|
1110
|
+
/**
|
|
1111
|
+
* 语言覆盖:class / new / instanceof / this / async await。
|
|
1112
|
+
* brand 表示名义类;eff("promise") 表示异步效应。
|
|
1113
|
+
*
|
|
1114
|
+
* 方法体:ClassDef.methods 存 AST body,调用时在 this=receiver 下求值。
|
|
1115
|
+
*/
|
|
1116
|
+
|
|
1117
|
+
type MethodDef = {
|
|
1118
|
+
name: string;
|
|
1119
|
+
params: string[];
|
|
1120
|
+
body: Node;
|
|
1121
|
+
kind?: string;
|
|
1122
|
+
async?: boolean;
|
|
1123
|
+
};
|
|
1124
|
+
type ClassDef = {
|
|
1125
|
+
name: string;
|
|
1126
|
+
instanceShape: Abs;
|
|
1127
|
+
ctorParams: string[];
|
|
1128
|
+
methods: Map<string, MethodDef>;
|
|
1129
|
+
superClass?: string;
|
|
1130
|
+
};
|
|
1131
|
+
declare function defineClass(env: AstEnv, def: ClassDef): void;
|
|
1132
|
+
declare function getClass(env: AstEnv, name: string): ClassDef | undefined;
|
|
1133
|
+
/** 沿继承链找类 */
|
|
1134
|
+
declare function getClassChain(env: AstEnv, name: string): ClassDef[];
|
|
1135
|
+
/** new C(...) → brand 实例;并跑 constructor 以写入字段 */
|
|
1136
|
+
declare function instantiateClass(env: AstEnv, className: string, args: Abs[], evalBody?: (fn: {
|
|
1137
|
+
params: string[];
|
|
1138
|
+
body: Node;
|
|
1139
|
+
}, args: Abs[], thisVal: Abs, env: AstEnv) => Abs): Abs;
|
|
1140
|
+
/** 读取当前 this 所属类的父类名 */
|
|
1141
|
+
declare function superNameOf(env: AstEnv, className: string): string | undefined;
|
|
1142
|
+
/**
|
|
1143
|
+
* instanceof:沿继承链匹配 brand 名。
|
|
1144
|
+
*/
|
|
1145
|
+
declare function instanceOf(left: Abs, rightClassName: string, env?: AstEnv): Abs;
|
|
1146
|
+
declare function projectBrand(self: Abs, key: string): Abs;
|
|
1147
|
+
/** 在 brand 上查找方法定义(含继承) */
|
|
1148
|
+
declare function lookupMethod(env: AstEnv, receiver: Abs, methodName: string): MethodDef | undefined;
|
|
1149
|
+
/** 沿继承链查找方法,返回定义与所在类名 */
|
|
1150
|
+
declare function lookupMethodWithOwner(env: AstEnv, receiver: Abs, methodName: string): {
|
|
1151
|
+
def: MethodDef;
|
|
1152
|
+
owner: string;
|
|
1153
|
+
} | undefined;
|
|
1154
|
+
/** super.method():从父类开始找(跳过当前类) */
|
|
1155
|
+
declare function lookupSuperMethod(env: AstEnv, receiver: Abs, fromClass: string, methodName: string): {
|
|
1156
|
+
def: MethodDef;
|
|
1157
|
+
owner: string;
|
|
1158
|
+
} | undefined;
|
|
1159
|
+
declare function wrapPromise(inner: Abs): Abs;
|
|
1160
|
+
declare function awaitAbs(v: Abs): Abs;
|
|
1161
|
+
declare function coerceAsyncReturn(value: Abs): Abs;
|
|
1162
|
+
/** 从 ClassMethod 列表构造 methods map + instance shape */
|
|
1163
|
+
declare function classFromMethods(name: string, methods: MethodDef[], superClass?: string, superShape?: Abs): ClassDef;
|
|
1164
|
+
|
|
1165
|
+
declare function hashSource(s: string): string;
|
|
1166
|
+
declare function resetHashSourceCache(): void;
|
|
1167
|
+
|
|
1168
|
+
/**
|
|
1169
|
+
* Analysis-stable source key: strip trailing noise that cannot affect types.
|
|
1170
|
+
* Keeps every line that may carry @nudo directives.
|
|
1171
|
+
*
|
|
1172
|
+
* Fast path: already-stable sources return the same string identity (O(1)
|
|
1173
|
+
* compare in B-path / analysis caches when the caller reuses the buffer).
|
|
1174
|
+
*/
|
|
1175
|
+
declare function stableAnalyzeKeySource(source: string): string;
|
|
1176
|
+
|
|
1177
|
+
/**
|
|
1178
|
+
* per-function fingerprint: after-edit only dirty fn + callers miss L0.
|
|
1179
|
+
*
|
|
1180
|
+
* - own: function declaration slice (incl. leading comments / refine)
|
|
1181
|
+
* - deps: transitively referenced sibling own hashes + non-fn top-level context
|
|
1182
|
+
* - context change (import/class/const...) -> all miss (conservative)
|
|
1183
|
+
*
|
|
1184
|
+
* Multi-declarator `const a = fn, b = fn` yields one fingerprint per function;
|
|
1185
|
+
* each own-slice is its own declarator (first also carries statement leading comments).
|
|
1186
|
+
*/
|
|
1187
|
+
|
|
1188
|
+
type FnFp = {
|
|
1189
|
+
own: string;
|
|
1190
|
+
deps: string;
|
|
1191
|
+
nRefs: number;
|
|
1192
|
+
};
|
|
1193
|
+
declare function resetFnFpCache(): void;
|
|
1194
|
+
type FnDeclInfo = {
|
|
1195
|
+
name: string;
|
|
1196
|
+
body: Node;
|
|
1197
|
+
/** Function/arrow node (own-slice end; also scanned for sibling refs incl. defaults). */
|
|
1198
|
+
fnNode: Node;
|
|
1199
|
+
/** Declarator start when from a VariableDeclaration; else undefined. */
|
|
1200
|
+
declaratorStart?: number;
|
|
1201
|
+
/** First leading-comment start on this declarator (multi-decl refine/@nudo). */
|
|
1202
|
+
declaratorLeadStart?: number;
|
|
1203
|
+
};
|
|
1204
|
+
/** Every top-level function binding in a declaration node (not just the first). */
|
|
1205
|
+
declare function getFnNameAndBodies(decl: Node): FnDeclInfo[];
|
|
1206
|
+
/** source -> (fnName -> own/deps); LRU */
|
|
1207
|
+
declare function fnFingerprints(source: string, file: File): Map<string, FnFp>;
|
|
1208
|
+
/** L0 source part: per-fn fingerprint when AST available; else full-file hash */
|
|
1209
|
+
declare function generalizeSourceKeyPart(source: string, fnName: string, file?: File): string;
|
|
1210
|
+
/**
|
|
1211
|
+
* 无 refine、无模块语法、无兄弟调用、无任何调用表达式 → scanLiteralCalls 可整段跳过。
|
|
1212
|
+
* 必须保守:`const x = f(-1)` / `if (f(-1))` / `require("x")` 都含 CallExpression,
|
|
1213
|
+
* 只认顶层 ExpressionStatement 会漏报约束违规。
|
|
1214
|
+
*/
|
|
1215
|
+
declare function canSkipLiteralCallScan(source: string, file: File): boolean;
|
|
1216
|
+
|
|
1217
|
+
/**
|
|
1218
|
+
* check 报告面:数据模型 + 渲染/序列化。
|
|
1219
|
+
*
|
|
1220
|
+
* 分析在 check.ts(Abs 优先的 Nudo 原生诊断),这里只投影:
|
|
1221
|
+
* - formatCheckReport → 人类可读文本
|
|
1222
|
+
* - serializeCheckJson → `nudo check --json` 稳定契约(CI / Agent,v1)
|
|
1223
|
+
*/
|
|
1224
|
+
|
|
1225
|
+
/** 无损函数签名(类型即计算) */
|
|
1226
|
+
type NudoSig = {
|
|
1227
|
+
name: string;
|
|
1228
|
+
params: string[];
|
|
1229
|
+
/** 符号 Abs 本体 */
|
|
1230
|
+
abs: Abs;
|
|
1231
|
+
/** formatAbs 单行 */
|
|
1232
|
+
display: string;
|
|
1233
|
+
/** formatAbsMultiline */
|
|
1234
|
+
detail: string;
|
|
1235
|
+
conf: Confidence;
|
|
1236
|
+
};
|
|
1237
|
+
type CheckIssue = Diagnostic & {
|
|
1238
|
+
fn?: string;
|
|
1239
|
+
line?: number;
|
|
1240
|
+
column?: number;
|
|
1241
|
+
/** 实参 / 实际值的 Abs 展示 */
|
|
1242
|
+
actual?: string;
|
|
1243
|
+
/** 期望约束(Pred 或 Abs 展示) */
|
|
1244
|
+
expected?: string;
|
|
1245
|
+
};
|
|
1246
|
+
type CheckReport = {
|
|
1247
|
+
file: string;
|
|
1248
|
+
issues: CheckIssue[];
|
|
1249
|
+
/** 有 error 则 CI 应失败 */
|
|
1250
|
+
ok: boolean;
|
|
1251
|
+
/** Abs 优先的签名表(替代 TS 式 display-only) */
|
|
1252
|
+
signatures: NudoSig[];
|
|
1253
|
+
summary: {
|
|
1254
|
+
errors: number;
|
|
1255
|
+
warnings: number;
|
|
1256
|
+
infos: number;
|
|
1257
|
+
functions: number;
|
|
1258
|
+
};
|
|
1259
|
+
};
|
|
1260
|
+
/**
|
|
1261
|
+
* `nudo check --json` 稳定契约(供 CI / Agent)。
|
|
1262
|
+
* 字段只增不改语义;Abs 以 formatAbs 字符串给出,不序列化内部 shape 图。
|
|
1263
|
+
*/
|
|
1264
|
+
type CheckJson = {
|
|
1265
|
+
version: 1;
|
|
1266
|
+
file: string;
|
|
1267
|
+
ok: boolean;
|
|
1268
|
+
summary: CheckReport["summary"];
|
|
1269
|
+
signatures: Array<{
|
|
1270
|
+
name: string;
|
|
1271
|
+
params: string[];
|
|
1272
|
+
display: string;
|
|
1273
|
+
detail: string;
|
|
1274
|
+
conf: string;
|
|
1275
|
+
abs: string;
|
|
1276
|
+
}>;
|
|
1277
|
+
issues: Array<{
|
|
1278
|
+
severity: string;
|
|
1279
|
+
code: string;
|
|
1280
|
+
message: string;
|
|
1281
|
+
fn?: string;
|
|
1282
|
+
line?: number;
|
|
1283
|
+
column?: number;
|
|
1284
|
+
actual?: string;
|
|
1285
|
+
expected?: string;
|
|
1286
|
+
suggestion?: string;
|
|
1287
|
+
}>;
|
|
1288
|
+
};
|
|
1289
|
+
declare function serializeCheckJson(r: CheckReport): CheckJson;
|
|
1290
|
+
/**
|
|
1291
|
+
* Nudo 原生报告:Abs 签名表 + actual ⊭ expected。
|
|
1292
|
+
* 不是 tsc 输出的换皮。
|
|
1293
|
+
*/
|
|
1294
|
+
declare function formatCheckReport(r: CheckReport, opts?: {
|
|
1295
|
+
verbose?: boolean;
|
|
1296
|
+
}): string;
|
|
1297
|
+
|
|
1298
|
+
/**
|
|
1299
|
+
* nudo check 门禁:对源码跑代数分析,产出 error/warning。
|
|
1300
|
+
*
|
|
1301
|
+
* 报告是 **Nudo 原生格式**(Abs 优先),不是 TS 诊断的换皮:
|
|
1302
|
+
* - 签名表给出无损 Abs(shape/term/pred/conf)
|
|
1303
|
+
* - 违例写清 actual ⊭ expected(实参 Abs vs 前置 Pred)
|
|
1304
|
+
* - dts/TS 兼容不是本报告的职责
|
|
1305
|
+
*/
|
|
1306
|
+
|
|
1307
|
+
declare function resetCheckSourceMemo(): void;
|
|
1308
|
+
declare function getCheckSourceMemoSize(): number;
|
|
1309
|
+
/** `*.nudo.js` 变更后定向逐出依赖它的整文件 check 缓存 */
|
|
1310
|
+
declare function evictCheckSourceMemoForPaths(paths: string[]): number;
|
|
1311
|
+
/**
|
|
1312
|
+
* check 选项:core 不碰 fs;host 用 loadModule 喂 require 目标源码。
|
|
1313
|
+
*/
|
|
1314
|
+
type CheckOptions = {
|
|
1315
|
+
/** 相对/绝对 require 说明符 → 模块源码;undefined = 解析失败 */
|
|
1316
|
+
loadModule?: (spec: string, fromFile: string) => string | undefined;
|
|
1317
|
+
/** 当前文件路径(供 loadModule 解析相对 spec) */
|
|
1318
|
+
fromFile?: string;
|
|
1319
|
+
};
|
|
1320
|
+
/**
|
|
1321
|
+
* 检查一个文件:
|
|
1322
|
+
* - 每个顶层函数 generalize;无法得到任何签名 → warning
|
|
1323
|
+
* - 若 source 中有字面量调用 `f(负数)` 且 f 有 `>0` 约束 → error
|
|
1324
|
+
* - entry 结果 partial/opaque → info
|
|
1325
|
+
*
|
|
1326
|
+
* 默认 Φ(pTrue)走整文件 memo:同 source + deps + loadModule 身份 → O(1)。
|
|
1327
|
+
*/
|
|
1328
|
+
declare function checkSource(filePath: string, source: string, phi?: Phi, opts?: CheckOptions): CheckReport;
|
|
1329
|
+
|
|
1330
|
+
/**
|
|
1331
|
+
* Abs inlay hint:把无损约束内联到源码位置。
|
|
1332
|
+
* 不是 TS 风格 type annotation 复读,而是 term/pred/conf 的计算结果。
|
|
1333
|
+
*/
|
|
1334
|
+
type AbsInlay = {
|
|
1335
|
+
/** 1-based 行号 */
|
|
1336
|
+
line: number;
|
|
1337
|
+
/** 0-based 列(label 插入点) */
|
|
1338
|
+
character: number;
|
|
1339
|
+
label: string;
|
|
1340
|
+
kind: "type" | "parameter";
|
|
1341
|
+
};
|
|
1342
|
+
/**
|
|
1343
|
+
* 收集源码中函数签名的 Abs inlay:
|
|
1344
|
+
* - 参数后:前置约束(声明 refine 优先;否则从 if 推)
|
|
1345
|
+
* - `)` 后:返回 shape + term(类型即计算)
|
|
1346
|
+
*/
|
|
1347
|
+
declare function collectAbsInlays(source: string, refineOpts?: {
|
|
1348
|
+
loadModule?: (spec: string, fromFile: string) => string | undefined;
|
|
1349
|
+
fromFile?: string;
|
|
1350
|
+
}): AbsInlay[];
|
|
1351
|
+
|
|
1352
|
+
/**
|
|
1353
|
+
* 指称:Abs → 运行时谓词(设计 §2.7)。
|
|
1354
|
+
* - 无 pred:按 shape 检查(typeof / 结构)
|
|
1355
|
+
* - 有 pred:在 `term ↦ v` 下检查可判定的数值比较
|
|
1356
|
+
* - sum:任一成员
|
|
1357
|
+
*/
|
|
1358
|
+
|
|
1359
|
+
/** Abs 上的运行时守卫表达式(JS boolean 布尔串) */
|
|
1360
|
+
declare function denoteGuard(a: Abs, v: string): string;
|
|
1361
|
+
|
|
1362
|
+
/**
|
|
1363
|
+
* B 路径运行时:transpile 后的程序在 Node 上执行时,值就是 Abs。
|
|
1364
|
+
* 与 AST 解释器语义同构;TypeValue 不再是求值载体。
|
|
1365
|
+
*/
|
|
1366
|
+
|
|
1367
|
+
declare function currentExecPhi(): Phi;
|
|
1368
|
+
declare function withExecPhi<T>(p: Phi, body: () => T): T;
|
|
1369
|
+
declare function $add(a: Abs, b: Abs): Abs;
|
|
1370
|
+
declare function $sub(a: Abs, b: Abs): Abs;
|
|
1371
|
+
declare function $mul(a: Abs, b: Abs): Abs;
|
|
1372
|
+
declare function $div(a: Abs, b: Abs): Abs;
|
|
1373
|
+
declare function $mod(a: Abs, b: Abs): Abs;
|
|
1374
|
+
declare function $neg(a: Abs): Abs;
|
|
1375
|
+
declare function $typeof(a: Abs): Abs;
|
|
1376
|
+
declare function $not(a: Abs): Abs;
|
|
1377
|
+
declare function $eq(a: Abs, b: Abs): Abs;
|
|
1378
|
+
declare function $ne(a: Abs, b: Abs): Abs;
|
|
1379
|
+
declare function $lt(a: Abs, b: Abs): Abs;
|
|
1380
|
+
declare function $le(a: Abs, b: Abs): Abs;
|
|
1381
|
+
declare function $gt(a: Abs, b: Abs): Abs;
|
|
1382
|
+
declare function $ge(a: Abs, b: Abs): Abs;
|
|
1383
|
+
declare function $join(a: Abs, b: Abs): Abs;
|
|
1384
|
+
/**
|
|
1385
|
+
* transpile 泄漏的 JS 函数值 → 一等 fn Abs。
|
|
1386
|
+
* B 路径把函数声明/表达式编译成真实 JS 函数;它们流进对象槽、
|
|
1387
|
+
* 元组、join 等 Abs 结构时不能裸存——下游(bridge/leq/join)读 `.shape`。
|
|
1388
|
+
* 参数名无法从运行时函数恢复(用 fn.length → argN,与 analyzer 的
|
|
1389
|
+
* extractParamNames 回退口径一致);带真实参数名走 $fnVal(transpile 侧)。
|
|
1390
|
+
*/
|
|
1391
|
+
declare function asAbsVal(v: unknown): Abs;
|
|
1392
|
+
/** 函数表达式 → 一等 fn Abs(transpile 侧带真实参数名;异步 body 包 $async) */
|
|
1393
|
+
declare function $fnVal(params: string[], impl: (...args: Abs[]) => Abs): Abs;
|
|
1394
|
+
/** 字面量 → Abs(transpile 侧数字/字符串/布尔/null/undefined) */
|
|
1395
|
+
declare function $lit(v: unknown): Abs;
|
|
1396
|
+
declare function isDefinitelyTrue(a: Abs): boolean;
|
|
1397
|
+
declare function isDefinitelyFalse(a: Abs): boolean;
|
|
1398
|
+
/**
|
|
1399
|
+
* if:两侧都探索(抽象条件),具体条件短路。
|
|
1400
|
+
*/
|
|
1401
|
+
declare function $fork(test: Abs, consequent: () => Abs, alternate?: () => Abs): Abs;
|
|
1402
|
+
declare const DEFAULT_MAX_LOOP_ITERS = 8;
|
|
1403
|
+
/**
|
|
1404
|
+
* for 的惰性展开:生成器只负责「按上限吐状态」。
|
|
1405
|
+
* 抽象条件无法诚实终止——消费者必须自带 maxIters。
|
|
1406
|
+
*/
|
|
1407
|
+
declare function $forIter(init: Abs, test: (s: Abs) => Abs, step: (s: Abs) => Abs, body: (s: Abs) => Abs, maxIters?: number): Generator<{
|
|
1408
|
+
state: Abs;
|
|
1409
|
+
test: Abs;
|
|
1410
|
+
afterBody: Abs;
|
|
1411
|
+
}, void, void>;
|
|
1412
|
+
/**
|
|
1413
|
+
* 有界 for:unroll ≤ maxIters,每步「可能退出」的态 join;
|
|
1414
|
+
* 相邻态 leq 视为不动点提前停。
|
|
1415
|
+
*/
|
|
1416
|
+
declare function $for(init: Abs, test: (s: Abs) => Abs, step: (s: Abs) => Abs, body: (s: Abs) => Abs, maxIters?: number): Abs;
|
|
1417
|
+
/** 数组字面量 → Abs tuple(长度已知) */
|
|
1418
|
+
declare function $arr(items: Abs[]): Abs;
|
|
1419
|
+
/** 下标读 a[i];字面量 i 走 tuple 精确投影,否则并所有元素 */
|
|
1420
|
+
declare function $idx(a: Abs, i: Abs): Abs;
|
|
1421
|
+
/** 下标写 a[i]=v → 新 tuple */
|
|
1422
|
+
declare function $idxSet(a: Abs, i: Abs, value: Abs): Abs;
|
|
1423
|
+
/** 数组长度 */
|
|
1424
|
+
declare function $len(a: Abs): Abs;
|
|
1425
|
+
/** 对象字面量 → Abs obj */
|
|
1426
|
+
declare function $obj(slots: Record<string, Abs>): Abs;
|
|
1427
|
+
/** 对象展开 { ...a, b } */
|
|
1428
|
+
declare function $spread(a: Abs, b: Abs): Abs;
|
|
1429
|
+
/** 数组连接 [...a, ...b] / [...a, x] */
|
|
1430
|
+
declare function $concat(a: Abs, b: Abs): Abs;
|
|
1431
|
+
/** 元素列表(tuple 展开;arr 抽象) */
|
|
1432
|
+
declare function $elems(a: Abs): Abs[];
|
|
1433
|
+
/**
|
|
1434
|
+
* for-of:对 iterable 每个元素跑 body;有界展开。
|
|
1435
|
+
* body(item, i) 可返回 void;状态由外部 JS 变量承接。
|
|
1436
|
+
*/
|
|
1437
|
+
declare function $forOf(iterable: Abs, body: (item: Abs, index: Abs) => void, maxIters?: number): void;
|
|
1438
|
+
/** 成员读:obj.slots[key];缺失 → undefined 字面量;brand 解包内层 */
|
|
1439
|
+
declare function $get(o: Abs, key: string, opts?: {
|
|
1440
|
+
silent?: boolean;
|
|
1441
|
+
}): Abs;
|
|
1442
|
+
/** 成员写:返回新 obj/brand(不可变更新) */
|
|
1443
|
+
declare function $set(o: Abs, key: string, value: Abs): Abs;
|
|
1444
|
+
/**
|
|
1445
|
+
* 有界 while:state 线程穿 test/step(与 $for 同折叠语义)。
|
|
1446
|
+
* 抽象条件无法诚实终止——必须 maxIters。
|
|
1447
|
+
*/
|
|
1448
|
+
declare function $while(init: Abs, test: (s: Abs) => Abs, step: (s: Abs) => Abs, maxIters?: number): Abs;
|
|
1449
|
+
/**
|
|
1450
|
+
* 顺序 while(具体/可变闭包):body 内对 JS 变量赋值。
|
|
1451
|
+
* 适合 transpile `let i; while (…) { i = … }`;抽象条件仍靠预算截断,
|
|
1452
|
+
* 不保证 exit-join 健全——健全路径用 $while/$for + 状态对象。
|
|
1453
|
+
*/
|
|
1454
|
+
declare function $whileSeq(test: () => Abs, body: () => void, maxIters?: number): void;
|
|
1455
|
+
/** B 路径 throw 载荷:携带 Abs 抛出值 */
|
|
1456
|
+
declare class NudoThrow extends Error {
|
|
1457
|
+
readonly absValue: Abs;
|
|
1458
|
+
constructor(absValue: Abs);
|
|
1459
|
+
}
|
|
1460
|
+
/** transpile `throw x` → `$throw(x)` */
|
|
1461
|
+
declare function $throw(v: Abs): never;
|
|
1462
|
+
declare function isNudoThrow(e: unknown): e is NudoThrow;
|
|
1463
|
+
/** catch 参数:从 NudoThrow 取出 Abs,否则 unknown */
|
|
1464
|
+
declare function $catchVal(e: unknown): Abs;
|
|
1465
|
+
/**
|
|
1466
|
+
* async 函数体包进 thunk,返回值经 wrapPromise。
|
|
1467
|
+
*/
|
|
1468
|
+
declare function $async(thunk: () => Abs): Abs;
|
|
1469
|
+
/** await → 解包 eff("promise") */
|
|
1470
|
+
declare function $await(v: Abs): Abs;
|
|
1471
|
+
/** async 直接 return 的 coerce */
|
|
1472
|
+
declare function $asyncReturn(v: Abs): Abs;
|
|
1473
|
+
/** function* 体:收集所有 yield 值为 tuple Abs */
|
|
1474
|
+
declare function $gen(body: () => void): Abs;
|
|
1475
|
+
/** yield v:压入当前生成器收集器;表达式值用 unknown */
|
|
1476
|
+
declare function $yield(v: Abs): Abs;
|
|
1477
|
+
/**
|
|
1478
|
+
* switch:具体 disc 选中匹配 case;抽象 disc 并所有分支。
|
|
1479
|
+
*/
|
|
1480
|
+
declare function $switch(disc: Abs, cases: Array<{
|
|
1481
|
+
test: Abs;
|
|
1482
|
+
run: () => Abs;
|
|
1483
|
+
}>, dflt?: () => Abs): Abs;
|
|
1484
|
+
|
|
1485
|
+
/**
|
|
1486
|
+
* B 路径 transpile:JS AST → 可在 Node 上执行的抽象值程序(源码字符串)。
|
|
1487
|
+
* 运算符改为 $add/$sub/…;if 改为 $fork;for 改为 $for。
|
|
1488
|
+
* 值类型是 Abs;副作用与模块仍由 host mock/注入。
|
|
1489
|
+
*/
|
|
1490
|
+
|
|
1491
|
+
type TranspileOptions = {
|
|
1492
|
+
/** 运行时 import 说明符 */
|
|
1493
|
+
runtimeImport?: string;
|
|
1494
|
+
maxLoopIters?: number;
|
|
1495
|
+
/** 方法体内 this 的绑定名(transpile class 时注入) */
|
|
1496
|
+
thisParam?: string;
|
|
1497
|
+
/** 当前类名(super 派发用) */
|
|
1498
|
+
className?: string;
|
|
1499
|
+
/** 原始源码(@nudo:replace 按节点文本匹配) */
|
|
1500
|
+
source?: string;
|
|
1501
|
+
/** 替换表:归一化目标文本 → 注入变量名;可选语句范围 */
|
|
1502
|
+
replacements?: Array<{
|
|
1503
|
+
target: string;
|
|
1504
|
+
varName: string;
|
|
1505
|
+
/** 仅该语句范围内生效(1-based 行) */
|
|
1506
|
+
stmtStart?: number;
|
|
1507
|
+
stmtEnd?: number;
|
|
1508
|
+
}>;
|
|
1509
|
+
/** @nudo:as:覆盖紧随语句的 init / return */
|
|
1510
|
+
asOverrides?: Array<{
|
|
1511
|
+
varName: string;
|
|
1512
|
+
stmtStart: number;
|
|
1513
|
+
stmtEnd: number;
|
|
1514
|
+
}>;
|
|
1515
|
+
};
|
|
1516
|
+
declare function transpileSource(source: string, opts?: TranspileOptions): string;
|
|
1517
|
+
declare function transpileFile(file: File, opts?: TranspileOptions): string;
|
|
1518
|
+
declare function transpileExpression(expr: Expression, opts?: TranspileOptions): string;
|
|
1519
|
+
/** 解析 + transpile */
|
|
1520
|
+
declare function transpile(source: string, opts?: TranspileOptions): string;
|
|
1521
|
+
|
|
1522
|
+
/**
|
|
1523
|
+
* 调用 Abs 一等函数(absFunction impl)或 mock apply。
|
|
1524
|
+
* 供 B 路径 import 绑定包装:`(...args) => $call(absFn, args)`。
|
|
1525
|
+
*/
|
|
1526
|
+
|
|
1527
|
+
declare function $call(fn: Abs, args: Abs[]): Abs;
|
|
1528
|
+
|
|
1529
|
+
/**
|
|
1530
|
+
* B class 规格表(无 call/ast-eval 依赖,避免循环)。
|
|
1531
|
+
* Abs-eval registerClassDecl 与 transpile $class 共用。
|
|
1532
|
+
*/
|
|
1533
|
+
|
|
1534
|
+
type BClassSpec = {
|
|
1535
|
+
name: string;
|
|
1536
|
+
superName?: string;
|
|
1537
|
+
ctor?: (thisVal: Abs, ...args: Abs[]) => Abs;
|
|
1538
|
+
methods?: Record<string, (thisVal: Abs, ...args: Abs[]) => Abs>;
|
|
1539
|
+
staticMethods?: Record<string, (...args: Abs[]) => Abs>;
|
|
1540
|
+
statics?: Record<string, Abs>;
|
|
1541
|
+
};
|
|
1542
|
+
declare function registerBClass(spec: BClassSpec): void;
|
|
1543
|
+
declare function getBClass(name: string): BClassSpec | undefined;
|
|
1544
|
+
declare function clearBClasses(): void;
|
|
1545
|
+
|
|
1546
|
+
/**
|
|
1547
|
+
* B 路径 class:brand 实例 + ctor/method 闭包 + 继承链。
|
|
1548
|
+
* 方法内 this 由 transpile 改写为 thisVal 参数。
|
|
1549
|
+
*/
|
|
1550
|
+
|
|
1551
|
+
/** 定义类 → 可 new 的 Abs(brand 标记;静态字段挂在 slots) */
|
|
1552
|
+
declare function $class(name: string, spec: Omit<BClassSpec, "name"> & {
|
|
1553
|
+
extends?: string;
|
|
1554
|
+
}): Abs;
|
|
1555
|
+
/** new C(...) → 空 brand 实例 + ctor 写字段;非类构造走 impl/$call */
|
|
1556
|
+
declare function $new(cls: Abs | ((...a: unknown[]) => unknown), args: Abs[]): Abs;
|
|
1557
|
+
/**
|
|
1558
|
+
* super(...):父类构造写入字段(this 保持子类 brand)。
|
|
1559
|
+
* transpile: super(a,b) → __this = $super(__this, "Child", [a,b])
|
|
1560
|
+
*/
|
|
1561
|
+
declare function $super(thisVal: Abs, childName: string, args: Abs[]): Abs;
|
|
1562
|
+
/** 实例方法调用:沿继承链;类 Abs 上回落 staticMethods;obj 上回落属性函数 */
|
|
1563
|
+
declare function $invoke(thisVal: Abs, method: string, args: Abs[], loc?: [number, number]): Abs;
|
|
1564
|
+
/** super.method():从父类起找(跳过自身覆盖) */
|
|
1565
|
+
declare function $invokeSuper(thisVal: Abs, childName: string, method: string, args: Abs[]): Abs;
|
|
1566
|
+
declare function $thisGet(thisVal: Abs, key: string): Abs;
|
|
1567
|
+
declare function $thisSet(thisVal: Abs, key: string, value: Abs): Abs;
|
|
1568
|
+
/** 解构默认值:undefined 时用 default */
|
|
1569
|
+
declare function $orDefault(v: Abs, dflt: () => Abs): Abs;
|
|
1570
|
+
/** 可选链 a?.b:nullish 短路为 undefined 字面量 */
|
|
1571
|
+
declare function $optionalGet(o: Abs, key: string): Abs;
|
|
1572
|
+
/** 可选链 a?.m():nullish 短路为 undefined */
|
|
1573
|
+
declare function $optionalInvoke(thisVal: Abs, method: string, args: Abs[]): Abs;
|
|
1574
|
+
/** 静态方法:cls.staticMethod(args) */
|
|
1575
|
+
declare function $staticInvoke(cls: Abs, method: string, args: Abs[]): Abs;
|
|
1576
|
+
/** 计算属性写:o[kAbs] = v */
|
|
1577
|
+
declare function $setKey(o: Abs, key: Abs, value: Abs): Abs;
|
|
1578
|
+
|
|
1579
|
+
/**
|
|
1580
|
+
* 成员缺失诊断(B 路径 + Abs ast-eval 共用)。
|
|
1581
|
+
* 无 $call / transpile 依赖,避免 ast-eval ↔ calls 循环。
|
|
1582
|
+
*/
|
|
1583
|
+
|
|
1584
|
+
type BMemberDiag = {
|
|
1585
|
+
kind: "method" | "property";
|
|
1586
|
+
name: string;
|
|
1587
|
+
/** 接收者 prim 类型名,或 "unknown" */
|
|
1588
|
+
receiver: string;
|
|
1589
|
+
line?: number;
|
|
1590
|
+
column?: number;
|
|
1591
|
+
/** 调用点来源(provenance):实参字面量 loc 优先,否则最近 $callNamed loc */
|
|
1592
|
+
origin?: {
|
|
1593
|
+
line: number;
|
|
1594
|
+
column: number;
|
|
1595
|
+
};
|
|
1596
|
+
};
|
|
1597
|
+
/** 给实参 Abs 打 provenance(调用点参数字面量) */
|
|
1598
|
+
declare function tagAbsOrigin(a: Abs, loc: {
|
|
1599
|
+
line: number;
|
|
1600
|
+
column: number;
|
|
1601
|
+
}): void;
|
|
1602
|
+
declare function getAbsOrigin(a: Abs | undefined): {
|
|
1603
|
+
line: number;
|
|
1604
|
+
column: number;
|
|
1605
|
+
} | undefined;
|
|
1606
|
+
declare function setMemberDiagCollector(c: ((d: BMemberDiag) => void) | null): void;
|
|
1607
|
+
declare function recordMemberDiag(d: BMemberDiag): void;
|
|
1608
|
+
/**
|
|
1609
|
+
* prim 接收者上的未知成员 → 诊断。
|
|
1610
|
+
* 返回 true 表示确定缺失(number 上任意方法;string 上表外方法)。
|
|
1611
|
+
*/
|
|
1612
|
+
declare function notePrimMemberMissing(recv: Abs | undefined, name: string, kind: "method" | "property", loc?: [number, number]): boolean;
|
|
1613
|
+
/**
|
|
1614
|
+
* unknown 接收者上的成员访问 → unknown-recv(与 TypeValue 口径对齐:
|
|
1615
|
+
* object/instance/refined/promise 静默;其余记一条)。
|
|
1616
|
+
*/
|
|
1617
|
+
declare function noteUnknownMemberMissing(recv: Abs | undefined, name: string, kind: "method" | "property", loc?: [number, number]): boolean;
|
|
1618
|
+
/** 方法分派失败时的统一记账(prim / unknown;obj/brand/promise 静默) */
|
|
1619
|
+
declare function noteMemberDispatchMiss(recv: Abs | undefined, name: string, kind: "method" | "property", loc?: [number, number]): void;
|
|
1620
|
+
|
|
1621
|
+
/**
|
|
1622
|
+
* B 路径调用点记录:transpile 把 `f(args)` 改成 $callNamed,
|
|
1623
|
+
* 分析时可收集 call@ 所需的 AbsCallRecord。
|
|
1624
|
+
* 成员缺失诊断见 member-diag.ts(与 ast-eval 共用,避免循环依赖)。
|
|
1625
|
+
*/
|
|
1626
|
+
|
|
1627
|
+
type BCallRecord = {
|
|
1628
|
+
fnName: string;
|
|
1629
|
+
args: Abs[];
|
|
1630
|
+
result: Abs;
|
|
1631
|
+
callLoc?: {
|
|
1632
|
+
line: number;
|
|
1633
|
+
column: number;
|
|
1634
|
+
};
|
|
1635
|
+
threw?: boolean;
|
|
1636
|
+
};
|
|
1637
|
+
declare function setBCallCollector(collector: ((r: BCallRecord) => void) | null): void;
|
|
1638
|
+
declare function getBCallCollector(): ((r: BCallRecord) => void) | null;
|
|
1639
|
+
/**
|
|
1640
|
+
* 按名调用并记录。
|
|
1641
|
+
* loc: [line, column](1-based line,0-based column,与 Babel 一致)
|
|
1642
|
+
* argLocs: 与 args 对齐的实参字面量源位置(provenance;无 loc 用 null)
|
|
1643
|
+
*/
|
|
1644
|
+
declare function $callNamed(name: string, fn: unknown, args: Abs[], loc?: [number, number], argLocs?: Array<[number, number] | null | undefined>): Abs;
|
|
1645
|
+
|
|
1646
|
+
/**
|
|
1647
|
+
* 进程内 B 路径执行:transpile 源码 → new Function 跑在 runtime 上。
|
|
1648
|
+
* 不写临时文件;相对 import 用注入的 AbsModuleExports / JS 导出绑定。
|
|
1649
|
+
*
|
|
1650
|
+
* mode:
|
|
1651
|
+
* - "exec"(默认):执行全部顶层(含副作用)
|
|
1652
|
+
* - "analyze":只保留函数声明与纯字面量 const;跳过顶层表达式/循环/if
|
|
1653
|
+
* ——分析入口安全,不触发 fetch 等顶层副作用
|
|
1654
|
+
*/
|
|
1655
|
+
|
|
1656
|
+
type RunTranspiledOptions = {
|
|
1657
|
+
/** 说明符 → 依赖导出(host 模块图或 runTranspiled 产物) */
|
|
1658
|
+
modules?: Record<string, AbsModuleExports | Record<string, unknown>>;
|
|
1659
|
+
maxLoopIters?: number;
|
|
1660
|
+
/** analyze = 跳过效应性顶层语句 */
|
|
1661
|
+
mode?: "exec" | "analyze";
|
|
1662
|
+
/** @nudo:replace 注入值:varName → Abs */
|
|
1663
|
+
replacements?: Record<string, Abs>;
|
|
1664
|
+
/** @nudo:replace 匹配表:传给 transpile */
|
|
1665
|
+
replacementTargets?: Array<{
|
|
1666
|
+
target: string;
|
|
1667
|
+
varName: string;
|
|
1668
|
+
stmtStart?: number;
|
|
1669
|
+
stmtEnd?: number;
|
|
1670
|
+
}>;
|
|
1671
|
+
/** @nudo:as 注入值:varName → Abs */
|
|
1672
|
+
asOverrides?: Record<string, Abs>;
|
|
1673
|
+
/** @nudo:as 语句范围表 */
|
|
1674
|
+
asOverrideTargets?: Array<{
|
|
1675
|
+
varName: string;
|
|
1676
|
+
stmtStart: number;
|
|
1677
|
+
stmtEnd: number;
|
|
1678
|
+
}>;
|
|
1679
|
+
/** @nudo:env 全局 Abs(JSON/Math/console…)→ 作用域绑定 */
|
|
1680
|
+
envGlobals?: Record<string, Abs>;
|
|
1681
|
+
};
|
|
1682
|
+
/**
|
|
1683
|
+
* 执行一段 B 路径程序,返回顶层 `export function` / `export const`。
|
|
1684
|
+
*/
|
|
1685
|
+
declare function runTranspiled(source: string, opts?: RunTranspiledOptions): Record<string, unknown>;
|
|
1686
|
+
type TranspiledCallResult = {
|
|
1687
|
+
result: Abs;
|
|
1688
|
+
/** 非 never 表示函数可能 throw 该类型 */
|
|
1689
|
+
throws: Abs;
|
|
1690
|
+
};
|
|
1691
|
+
/** 调用 runTranspiled 导出(捕获 $throw) */
|
|
1692
|
+
declare function callTranspiledExportFull(exports: Record<string, unknown>, name: string, args: Abs[]): TranspiledCallResult;
|
|
1693
|
+
/** 调用 runTranspiled 导出(仅结果) */
|
|
1694
|
+
declare function callTranspiledExport(exports: Record<string, unknown>, name: string, args: Abs[]): Abs;
|
|
1695
|
+
|
|
1696
|
+
/**
|
|
1697
|
+
* Abs ⇄ TypeValue 桥。
|
|
1698
|
+
*
|
|
1699
|
+
* 纪律:
|
|
1700
|
+
* - absToTypeValue 有损:丢 term/pred 时 conf 降为 widened,禁止假装 exact
|
|
1701
|
+
* - typeValueToAbs 尽量恢复 term=lit
|
|
1702
|
+
* - 下游(dts/lsp/service)吃 TypeValue;代数运算吃 Abs
|
|
1703
|
+
*/
|
|
1704
|
+
|
|
1705
|
+
declare function setTvConfidence(tv: TypeValue, conf: Confidence): void;
|
|
1706
|
+
declare function getTvConfidence(tv: TypeValue): Confidence | undefined;
|
|
1707
|
+
/**
|
|
1708
|
+
* Abs → TypeValue(给下游)。
|
|
1709
|
+
* 有损:非 lit term 丢弃;pred 尽量 encode 成 refined,否则丢。
|
|
1710
|
+
*/
|
|
1711
|
+
declare function absToTypeValue(a: Abs): TypeValue;
|
|
1712
|
+
/**
|
|
1713
|
+
* TypeValue → Abs(给代数运算)。
|
|
1714
|
+
* 置信度:优先读 abs→tv 时挂上的 conf 旁路,避免 #widened 回升 #exact。
|
|
1715
|
+
*/
|
|
1716
|
+
declare function typeValueToAbs(tv: TypeValue): Abs;
|
|
1717
|
+
/**
|
|
1718
|
+
* 有损检查:Abs 转 TypeValue 后是否丢了 term/pred。
|
|
1719
|
+
* 用于金标与调试。
|
|
1720
|
+
*/
|
|
1721
|
+
declare function bridgeIsLossy(a: Abs): {
|
|
1722
|
+
lossy: boolean;
|
|
1723
|
+
reasons: string[];
|
|
1724
|
+
};
|
|
1725
|
+
|
|
1726
|
+
export { $add, $arr, $async, $asyncReturn, $await, $call, $callNamed, $catchVal, $class, $concat, $div, $elems, $eq, $fnVal, $for, $forIter, $forOf, $fork, $ge, $gen, $get, $gt, $idx, $idxSet, $invoke, $invokeSuper, $join, $le, $len, $lit, $lt, $mod, $mul, $ne, $neg, $new, $not, $obj, $optionalGet, $optionalInvoke, $orDefault, $set, $setKey, $spread, $staticInvoke, $sub, $super, $switch, $thisGet, $thisSet, $throw, $typeof, $while, $whileSeq, $yield, type Abs, type AbsAssignRecord, type AbsCallRecord, type AbsFnImpl, type AbsInlay, type AbsModuleExports, type AstEnv, type BCallRecord, type BClassSpec, type BMemberDiag, type CheckIssue, type CheckJson, type CheckOptions, type CheckReport, type ClassDef, type Confidence, type ConstraintBuilder, DEFAULT_MAX_LOOP_ITERS, type Diagnostic, type Environment, type EvalOptions, type EvalResult, type FnAbs, type FnFp, type FormatOptions, type FunctionSignature, type LeakBudget, type LeqResult, type LiteralValue$1 as LiteralValue, type LoadDepsFingerprint, MAX_CALL_DEPTH, MAX_TOTAL_CALLS, type MethodDef, type MockHelper, type NamedImport, type NudoConstraint, type NudoField, type NudoSig, NudoThrow, type ObjShape, Ops, type Phi, type PolyFn, type Pred, type PrimName, type RangeMeta, type RefineEntry, type RefineResolveOpts, type Refinement, type RunTranspiledOptions, SELF, type Shape, type SigImpl, type Slot, T, type TemplateMeta, type Term, type TranspileOptions, type TranspiledCallResult, type TypeParam, type TypeValue, abs, absFunction, absToString, absToTypeValue, add, analyzeFn, and, anyVar, app, applyBinaryOp, array, asAbsVal, attachFnImpl, awaitAbs, bindImports, bool, boolLit, boolean, bridgeIsLossy, buildArgsFromAssume, callAbsMethod, callFunction, callTranspiledExport, callTranspiledExportFull, canSkipLiteralCallScan, checkArg, checkCall, checkSource, classFromMethods, clearBClasses, cmp, coerceAsyncReturn, collapseLiteralUnion, collapseToOptional, collectAbsExports, collectAbsInlays, collectAbsNodeTypes, concatString, concatTemplates, confJoin, constraintToEntryAbs, createEnvironment, createRange, createTemplate, createTemplateAbs, currentExecPhi, currentPhi, deepCloneTypeValue, defaultLeakBudget, defineClass, definitelyNotNullishShape, denoteGuard, describePhi, dispatchBinaryOp, dispatchMethod, dispatchProperty, div, emptyEnv, emptyPhi, eq, evalArrayStatic, evalBuiltinInstanceMethod, evalBuiltinNew, evalDateCtor, evalDateMethod, evalDateStatic, evalGlobalFn, evalJsonMethod, evalMathMethod, evalMethodBody, evalNamespaceCall, evalNode, evalNumberStatic, evalObjectMethod, evalProgramAbs, evalPromiseCtor, evalPromiseStatic, evalRegExpCtor, evalRegExpMethod, evalSource, evictCheckSourceMemoForPaths, evictGeneralizeMemoForPaths, exceedsBudget, execNudoModule, extractAllLoadSpecs, extractNudoImports, extractRefineReturnFromSource, extractRefinesFromSource, falseConstraint, findAbsAtPosition, fnFingerprints, fnOf, formatAbs, formatAbsMultiline, formatCheckReport, formatDiagnostics, formatShape, ge, geNum, generalizeAll, generalizeFromAst, generalizeSourceKeyPart, getAbsOrigin, getAbsProperty, getBCallCollector, getBClass, getCheckSourceMemoSize, getClass, getClassChain, getFnImpl, getFnNameAndBodies, getFnSig, getGeneralizeMemoSize, getKnownPrefix, getKnownSuffix, getParseSourceCacheSize, getPrimitiveTypeOf, getRangeMeta, getRefinedBase, getTemplateParts, getTerm, getTvConfidence, gt, gtNum, hashSource, implies, instanceOf, instantiateClass, instantiateConstraint, isDefinitelyFalse, isDefinitelyTrue, isExactLit, isFnSig, isNudoConstraint, isNudoThrow, isNullishLitAbs, isNumPrim, isObj, isRange, isStrPrim, isSubtypeOf, isTemplate, isTemplateLike, joinAbs, joinFunctions, joinObjects, joinValues, le, leNum, leakIfNeeded, lenTerm, leqAbs, listFunctionNames, lit, litValue, loadModuleDepsFingerprint, lookupMethod, lookupMethodWithOwner, lookupSuperMethod, lt, ltNum, makeSum, maybeLeak, mergeObjectProperties, mock, mockHelperToTypeValue, mod, mul, narrowType, ne, negAbs, never, normPath, not, notAbs, noteMemberDispatchMiss, notePrimMemberMissing, noteUnknownMemberMissing, num, numLit, numVar, number, numericBounds, obj, objOf, or, pFalse, pTrue, parseSource, phiAnd, popPhi, predEquals, predToString, predVars, projectBrand, ptypeof, pushPhi, recordMemberDiag, refineToIndexedFull, registerBClass, resetAbsCallBudget, resetCheckSourceMemo, resetFnFpCache, resetGeneralizeMemo, resetHashSourceCache, resetLeakCounter, resetNudoModuleExecCache, resetParseSourceCache, resetPhi, resolveDepPath, runTranspiled, serializeCheckJson, setAbsAssignCollector, setAbsCallCollector, setAbsNodeCollector, setAbsTruncationCollector, setBCallCollector, setMemberDiagCollector, setTvConfidence, shape, shapeOfTerm, shapeToString, simplifyTerm, simplifyUnion, spread, spy, stableAnalyzeKeySource, str, strLit, strictEqAbs, string, stripTypes, stub, sub, substPred, subtractType, superNameOf, tagAbsOrigin, templatePartsOf, termDepth, termEquals, termNodes, termToString, transpile, transpileExpression, transpileFile, transpileSource, trueConstraint, typeValueEquals, typeValueToAbs, typeValueToString, typeofAbs, unknown, v, widenLiteral, withExecPhi, withPhiConstraint, withVar, wrapPromise };
|