@nudojs/core 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/dist/chunk-BU4A6XJ3.js +6856 -0
  2. package/dist/exec.d.ts +2 -0
  3. package/dist/exec.js +168 -0
  4. package/dist/index-CVYjXnwU.d.ts +902 -0
  5. package/dist/index.d.ts +64 -710
  6. package/dist/index.js +3258 -8426
  7. package/package.json +18 -5
  8. package/CHANGELOG.md +0 -34
  9. package/src/__tests__/environment.test.ts +0 -48
  10. package/src/__tests__/fn-sig-impl.test.ts +0 -57
  11. package/src/__tests__/ops-refined.test.ts +0 -196
  12. package/src/__tests__/ops.test.ts +0 -84
  13. package/src/__tests__/type-value-phase2.test.ts +0 -117
  14. package/src/__tests__/type-value-phase3.test.ts +0 -94
  15. package/src/__tests__/type-value-refined.test.ts +0 -210
  16. package/src/__tests__/type-value.test.ts +0 -319
  17. package/src/algebra/__tests__/abs-native.test.ts +0 -176
  18. package/src/algebra/__tests__/arithmetic.test.ts +0 -170
  19. package/src/algebra/__tests__/ast-eval.test.ts +0 -154
  20. package/src/algebra/__tests__/bridge.test.ts +0 -160
  21. package/src/algebra/__tests__/call-budget.test.ts +0 -117
  22. package/src/algebra/__tests__/check-case-consistency.test.ts +0 -69
  23. package/src/algebra/__tests__/check-gold.test.ts +0 -290
  24. package/src/algebra/__tests__/check-json.test.ts +0 -57
  25. package/src/algebra/__tests__/check-mini-repo.test.ts +0 -49
  26. package/src/algebra/__tests__/check-real-commander.test.ts +0 -43
  27. package/src/algebra/__tests__/check-real-packages.test.ts +0 -165
  28. package/src/algebra/__tests__/check-recall-gold.test.ts +0 -1024
  29. package/src/algebra/__tests__/check-require-dep-memo.test.ts +0 -45
  30. package/src/algebra/__tests__/check-return-contract.test.ts +0 -90
  31. package/src/algebra/__tests__/check-shape-gold.test.ts +0 -303
  32. package/src/algebra/__tests__/check-source-memo.test.ts +0 -204
  33. package/src/algebra/__tests__/check.test.ts +0 -69
  34. package/src/algebra/__tests__/denote.test.ts +0 -77
  35. package/src/algebra/__tests__/diagnostics.test.ts +0 -64
  36. package/src/algebra/__tests__/differential.test.ts +0 -124
  37. package/src/algebra/__tests__/div-mod.test.ts +0 -38
  38. package/src/algebra/__tests__/example0.test.ts +0 -103
  39. package/src/algebra/__tests__/exec-analyze-throws.test.ts +0 -60
  40. package/src/algebra/__tests__/exec-async.test.ts +0 -46
  41. package/src/algebra/__tests__/exec-bpath.test.ts +0 -193
  42. package/src/algebra/__tests__/exec-class.test.ts +0 -56
  43. package/src/algebra/__tests__/exec-e2e.test.ts +0 -97
  44. package/src/algebra/__tests__/exec-generator.test.ts +0 -53
  45. package/src/algebra/__tests__/exec-inherit-default.test.ts +0 -111
  46. package/src/algebra/__tests__/exec-optional-nested.test.ts +0 -87
  47. package/src/algebra/__tests__/exec-rest.test.ts +0 -55
  48. package/src/algebra/__tests__/exec-spread-forof.test.ts +0 -85
  49. package/src/algebra/__tests__/exec-static-computed.test.ts +0 -61
  50. package/src/algebra/__tests__/exec-switch.test.ts +0 -74
  51. package/src/algebra/__tests__/exec-trycatch.test.ts +0 -71
  52. package/src/algebra/__tests__/fn-fp-memo.test.ts +0 -166
  53. package/src/algebra/__tests__/fn-fp-multidecl.test.ts +0 -49
  54. package/src/algebra/__tests__/format.test.ts +0 -34
  55. package/src/algebra/__tests__/generalize-memo.test.ts +0 -285
  56. package/src/algebra/__tests__/generalize.test.ts +0 -113
  57. package/src/algebra/__tests__/hash-source.test.ts +0 -19
  58. package/src/algebra/__tests__/hof.test.ts +0 -80
  59. package/src/algebra/__tests__/inlay.test.ts +0 -30
  60. package/src/algebra/__tests__/language.test.ts +0 -77
  61. package/src/algebra/__tests__/leq.test.ts +0 -109
  62. package/src/algebra/__tests__/load-deps-fp-memo.test.ts +0 -132
  63. package/src/algebra/__tests__/methods.test.ts +0 -37
  64. package/src/algebra/__tests__/node-types.test.ts +0 -26
  65. package/src/algebra/__tests__/nudo-constraints.ts +0 -46
  66. package/src/algebra/__tests__/objects.test.ts +0 -117
  67. package/src/algebra/__tests__/parse-source-cache.test.ts +0 -42
  68. package/src/algebra/__tests__/refine-import.test.ts +0 -109
  69. package/src/algebra/__tests__/stable-source-key-block.test.ts +0 -23
  70. package/src/algebra/__tests__/stable-source-key.test.ts +0 -31
  71. package/src/algebra/__tests__/surface.test.ts +0 -41
  72. package/src/algebra/__tests__/this-inherit.test.ts +0 -130
  73. package/src/algebra/abs-fn.ts +0 -49
  74. package/src/algebra/abs-modules.ts +0 -139
  75. package/src/algebra/abs.ts +0 -206
  76. package/src/algebra/arithmetic.ts +0 -691
  77. package/src/algebra/ast-eval.ts +0 -1763
  78. package/src/algebra/bridge.ts +0 -350
  79. package/src/algebra/builtins.ts +0 -373
  80. package/src/algebra/check-report.ts +0 -150
  81. package/src/algebra/check.ts +0 -1867
  82. package/src/algebra/constraint.ts +0 -304
  83. package/src/algebra/denote.ts +0 -166
  84. package/src/algebra/diagnostics.ts +0 -210
  85. package/src/algebra/exec/call.ts +0 -29
  86. package/src/algebra/exec/calls.ts +0 -96
  87. package/src/algebra/exec/class-registry.ts +0 -29
  88. package/src/algebra/exec/class.ts +0 -329
  89. package/src/algebra/exec/index.ts +0 -6
  90. package/src/algebra/exec/member-diag.ts +0 -141
  91. package/src/algebra/exec/run.ts +0 -341
  92. package/src/algebra/exec/runtime.ts +0 -583
  93. package/src/algebra/exec/transpile.ts +0 -993
  94. package/src/algebra/fn-fp.ts +0 -294
  95. package/src/algebra/format.ts +0 -91
  96. package/src/algebra/generalize.ts +0 -776
  97. package/src/algebra/hash-source.ts +0 -27
  98. package/src/algebra/index.ts +0 -34
  99. package/src/algebra/inlay.ts +0 -198
  100. package/src/algebra/language.ts +0 -289
  101. package/src/algebra/leak.ts +0 -68
  102. package/src/algebra/leq.ts +0 -301
  103. package/src/algebra/load-deps-fp.ts +0 -97
  104. package/src/algebra/methods.ts +0 -128
  105. package/src/algebra/objects.ts +0 -251
  106. package/src/algebra/parse-source.ts +0 -64
  107. package/src/algebra/phi.ts +0 -42
  108. package/src/algebra/pred.ts +0 -395
  109. package/src/algebra/refine.ts +0 -227
  110. package/src/algebra/stable-source-key.ts +0 -81
  111. package/src/algebra/surface.ts +0 -206
  112. package/src/algebra/template.ts +0 -143
  113. package/src/algebra/term.ts +0 -119
  114. package/src/environment.ts +0 -74
  115. package/src/index.ts +0 -73
  116. package/src/mock-helpers.ts +0 -166
  117. package/src/ops.ts +0 -191
  118. package/src/refinements/range.ts +0 -86
  119. package/src/refinements/template-predicates.ts +0 -11
  120. package/src/refinements/template.ts +0 -176
  121. package/src/strip-types.ts +0 -236
  122. package/src/type-value.ts +0 -513
  123. package/tsconfig.json +0 -8
@@ -1,294 +0,0 @@
1
- /**
2
- * per-function fingerprint: after-edit only dirty fn + callers miss L0.
3
- *
4
- * - own: function declaration slice (incl. leading comments / refine)
5
- * - deps: transitively referenced sibling own hashes + non-fn top-level context
6
- * - context change (import/class/const...) -> all miss (conservative)
7
- *
8
- * Multi-declarator `const a = fn, b = fn` yields one fingerprint per function;
9
- * each own-slice is its own declarator (first also carries statement leading comments).
10
- */
11
- import type { Node, File } from "@babel/types";
12
- import { hashSource } from "./hash-source.ts";
13
-
14
- export type FnFp = { own: string; deps: string; nRefs: number };
15
-
16
- /** source → per-fn fingerprints. Key is full source (collision-safe); cap keeps
17
- * retained text bounded: 24 × 1MB ≈ 24MB worst-case key strings. */
18
- const fnFpCache = new Map<string, Map<string, FnFp>>();
19
- const MAX_FN_FP_CACHE = 24;
20
- /** Cap on cached whole-source keys so large monorepo sessions stay bounded. */
21
- const MAX_FN_FP_SOURCE_CHARS = 1_000_000;
22
-
23
- export function resetFnFpCache(): void {
24
- fnFpCache.clear();
25
- }
26
-
27
- type FnDeclInfo = {
28
- name: string;
29
- body: Node;
30
- /** Function/arrow node (own-slice end; also scanned for sibling refs incl. defaults). */
31
- fnNode: Node;
32
- /** Declarator start when from a VariableDeclaration; else undefined. */
33
- declaratorStart?: number;
34
- /** First leading-comment start on this declarator (multi-decl refine/@nudo). */
35
- declaratorLeadStart?: number;
36
- };
37
-
38
- /** Every top-level function binding in a declaration node (not just the first). */
39
- export function getFnNameAndBodies(decl: Node): FnDeclInfo[] {
40
- const out: FnDeclInfo[] = [];
41
- if (decl.type === "FunctionDeclaration" && decl.id) {
42
- out.push({ name: decl.id.name, body: decl.body, fnNode: decl });
43
- return out;
44
- }
45
- if (decl.type === "VariableDeclaration") {
46
- for (const d of decl.declarations) {
47
- if (
48
- d.id.type === "Identifier" &&
49
- d.init &&
50
- (d.init.type === "ArrowFunctionExpression" || d.init.type === "FunctionExpression")
51
- ) {
52
- const comments = (d as { leadingComments?: Array<{ start?: number }> }).leadingComments;
53
- const first = comments?.[0];
54
- out.push({
55
- name: d.id.name,
56
- body: d.init.body,
57
- fnNode: d.init,
58
- declaratorStart: d.start ?? undefined,
59
- declaratorLeadStart: typeof first?.start === "number" ? first.start : undefined,
60
- });
61
- }
62
- }
63
- }
64
- return out;
65
- }
66
-
67
- function leadingSliceStart(stmt: Node, decl: Node): number {
68
- const comments =
69
- (stmt as { leadingComments?: Array<{ start?: number }> }).leadingComments ??
70
- (decl as { leadingComments?: Array<{ start?: number }> }).leadingComments;
71
- const first = comments?.[0];
72
- if (first && typeof first.start === "number") return first.start;
73
- return stmt.start ?? decl.start ?? 0;
74
- }
75
-
76
- /** Conservative: any top-level sibling name appearing in the body is a dep. */
77
- function collectSiblingRefs(node: unknown, known: Set<string>, out: Set<string>): void {
78
- if (!node || typeof node !== "object") return;
79
- const obj = node as Record<string, unknown> & { type?: string };
80
- if (obj.type === "Identifier" && typeof obj.name === "string" && known.has(obj.name)) {
81
- out.add(obj.name);
82
- }
83
- for (const key of Object.keys(obj)) {
84
- if (
85
- key === "loc" ||
86
- key === "start" ||
87
- key === "end" ||
88
- key === "leadingComments" ||
89
- key === "trailingComments" ||
90
- key === "innerComments"
91
- ) {
92
- continue;
93
- }
94
- if (
95
- (key === "key" || key === "property") &&
96
- (obj.type === "MemberExpression" ||
97
- obj.type === "ObjectProperty" ||
98
- obj.type === "ObjectMethod" ||
99
- obj.type === "ClassMethod" ||
100
- obj.type === "ClassProperty") &&
101
- obj.computed !== true
102
- ) {
103
- continue;
104
- }
105
- // Binding name, not a use: `function id() {}` / `class id {}` must not
106
- // count as a sibling ref (would make nRefs≥1 for every named decl and
107
- // permanently disable canSkipLiteralCallScan).
108
- if (
109
- key === "id" &&
110
- (obj.type === "FunctionDeclaration" ||
111
- obj.type === "FunctionExpression" ||
112
- obj.type === "ClassDeclaration" ||
113
- obj.type === "ClassExpression")
114
- ) {
115
- continue;
116
- }
117
- const v = obj[key];
118
- if (Array.isArray(v)) {
119
- for (const x of v) collectSiblingRefs(x, known, out);
120
- } else if (v && typeof v === "object") {
121
- collectSiblingRefs(v, known, out);
122
- }
123
- }
124
- }
125
-
126
- function computeFnFingerprints(source: string, file: File): Map<string, FnFp> {
127
- const top: Array<{ name: string; slice: string; fnNode: Node }> = [];
128
- const contextParts: string[] = [];
129
-
130
- for (const stmt of file.program.body) {
131
- let decl: Node = stmt;
132
- if (stmt.type === "ExportNamedDeclaration" && stmt.declaration) {
133
- decl = stmt.declaration;
134
- } else if (stmt.type === "ExportDefaultDeclaration" && stmt.declaration) {
135
- decl = stmt.declaration;
136
- }
137
- const fnInfos = getFnNameAndBodies(decl);
138
- if (fnInfos.length > 0) {
139
- const lead = leadingSliceStart(stmt, decl);
140
- for (let i = 0; i < fnInfos.length; i++) {
141
- const info = fnInfos[i]!;
142
- // First declarator carries statement leading comments; later ones start
143
- // at their own leading comments so sibling edits do not dirty this own-hash.
144
- const sliceStart =
145
- i === 0
146
- ? lead
147
- : (info.declaratorLeadStart ??
148
- info.declaratorStart ??
149
- info.fnNode.start ??
150
- lead);
151
- const end = info.fnNode.end ?? info.declaratorStart ?? decl.end ?? stmt.end ?? sliceStart;
152
- top.push({
153
- name: info.name,
154
- slice: source.slice(sliceStart, Math.max(end, sliceStart)),
155
- fnNode: info.fnNode,
156
- });
157
- }
158
- } else if (typeof stmt.start === "number" && typeof stmt.end === "number") {
159
- contextParts.push(source.slice(stmt.start, stmt.end));
160
- } else {
161
- contextParts.push(stmt.type);
162
- }
163
- }
164
-
165
- const context = hashSource(contextParts.join("\n "));
166
- const names = new Set(top.map((t) => t.name));
167
- const own = new Map<string, string>();
168
- for (const t of top) own.set(t.name, hashSource(t.slice));
169
-
170
- const edges = new Map<string, Set<string>>();
171
- for (const t of top) {
172
- const refs = new Set<string>();
173
- // Whole fn node (params defaults + body), not body alone
174
- collectSiblingRefs(t.fnNode, names, refs);
175
- edges.set(t.name, refs);
176
- }
177
-
178
- const result = new Map<string, FnFp>();
179
- for (const t of top) {
180
- const seen = new Set<string>();
181
- const stack = [...(edges.get(t.name) ?? [])];
182
- const depParts: string[] = [];
183
- while (stack.length > 0) {
184
- const cur = stack.pop()!;
185
- if (seen.has(cur)) continue;
186
- seen.add(cur);
187
- depParts.push(`${cur}=${own.get(cur) ?? "?"}`);
188
- for (const next of edges.get(cur) ?? []) {
189
- if (!seen.has(next)) stack.push(next);
190
- }
191
- }
192
- depParts.sort();
193
- result.set(t.name, {
194
- own: own.get(t.name)!,
195
- deps: hashSource(`${depParts.join(",")} ${context}`),
196
- nRefs: seen.size,
197
- });
198
- }
199
- return result;
200
- }
201
-
202
- /** source -> (fnName -> own/deps); LRU */
203
- export function fnFingerprints(source: string, file: File): Map<string, FnFp> {
204
- if (source.length > MAX_FN_FP_SOURCE_CHARS) {
205
- return computeFnFingerprints(source, file);
206
- }
207
- const hit = fnFpCache.get(source);
208
- if (hit !== undefined) {
209
- fnFpCache.delete(source);
210
- fnFpCache.set(source, hit);
211
- return hit;
212
- }
213
- const fp = computeFnFingerprints(source, file);
214
- if (fnFpCache.size >= MAX_FN_FP_CACHE) {
215
- const oldest = fnFpCache.keys().next().value;
216
- if (oldest !== undefined) fnFpCache.delete(oldest);
217
- }
218
- fnFpCache.set(source, fp);
219
- return fp;
220
- }
221
-
222
- /** L0 source part: per-fn fingerprint when AST available; else full-file hash */
223
- export function generalizeSourceKeyPart(
224
- source: string,
225
- fnName: string,
226
- file?: File,
227
- ): string {
228
- if (!file) return `w:${hashSource(source)}`;
229
- const fp = fnFingerprints(source, file).get(fnName);
230
- if (fp) return `f:${fp.own}:${fp.deps}`;
231
- return `u:${hashSource(source)}`;
232
- }
233
-
234
- /** Any CallExpression / NewExpression / dynamic import in the AST. */
235
- function hasAnyCallLike(node: unknown, depth = 0): boolean {
236
- if (!node || typeof node !== "object") return false;
237
- // Depth cap: unexplored subtree must be treated as "may contain a call"
238
- // (return true). Returning false would let canSkipLiteralCallScan skip
239
- // scanLiteralCalls and miss constraint violations in deep expressions.
240
- if (depth > 80) return true;
241
- const obj = node as Record<string, unknown> & { type?: string };
242
- if (
243
- obj.type === "CallExpression" ||
244
- obj.type === "NewExpression" ||
245
- obj.type === "OptionalCallExpression" ||
246
- obj.type === "ImportExpression"
247
- ) {
248
- return true;
249
- }
250
- for (const key of Object.keys(obj)) {
251
- if (
252
- key === "loc" ||
253
- key === "start" ||
254
- key === "end" ||
255
- key === "leadingComments" ||
256
- key === "trailingComments" ||
257
- key === "innerComments"
258
- ) {
259
- continue;
260
- }
261
- const v = obj[key];
262
- if (Array.isArray(v)) {
263
- for (const x of v) if (hasAnyCallLike(x, depth + 1)) return true;
264
- } else if (v && typeof v === "object") {
265
- if (hasAnyCallLike(v, depth + 1)) return true;
266
- }
267
- }
268
- return false;
269
- }
270
-
271
- function hasModuleSyntax(file: File): boolean {
272
- for (const stmt of file.program.body) {
273
- if (stmt.type === "ImportDeclaration") return true;
274
- if (stmt.type === "ExportAllDeclaration") return true;
275
- if (stmt.type === "ExportNamedDeclaration" && stmt.source) return true;
276
- }
277
- return false;
278
- }
279
-
280
- /**
281
- * 无 refine、无模块语法、无兄弟调用、无任何调用表达式 → scanLiteralCalls 可整段跳过。
282
- * 必须保守:`const x = f(-1)` / `if (f(-1))` / `require("x")` 都含 CallExpression,
283
- * 只认顶层 ExpressionStatement 会漏报约束违规。
284
- */
285
- export function canSkipLiteralCallScan(source: string, file: File): boolean {
286
- if (source.includes("@nudo:refine")) return false;
287
- if (hasModuleSyntax(file)) return false;
288
- if (hasAnyCallLike(file)) return false;
289
- const fps = fnFingerprints(source, file);
290
- for (const fp of fps.values()) {
291
- if (fp.nRefs > 0) return false;
292
- }
293
- return true;
294
- }
@@ -1,91 +0,0 @@
1
- /**
2
- * 格式化:把 Abs 渲染成人类可读 / CLI 友好的字符串。
3
- */
4
-
5
- import type { Abs } from "./abs.ts";
6
- import { litValue } from "./abs.ts";
7
- import type { Term } from "./term.ts";
8
- import { termToString } from "./term.ts";
9
- import type { Pred } from "./pred.ts";
10
- import { predToString } from "./pred.ts";
11
-
12
- export type FormatOptions = {
13
- /** 是否显示 term= */
14
- showTerm?: boolean;
15
- /** 是否显示 pred */
16
- showPred?: boolean;
17
- indent?: string;
18
- };
19
-
20
- export function formatAbs(a: Abs, opts: FormatOptions = {}): string {
21
- const showTerm = opts.showTerm !== false;
22
- const showPred = opts.showPred !== false;
23
- const parts: string[] = [];
24
-
25
- parts.push(formatShape(a));
26
-
27
- if (showTerm && a.term && a.term.op !== "lit") {
28
- parts.push(`= ${termToString(a.term)}`);
29
- }
30
- if (showPred && a.pred && a.pred.op !== "true") {
31
- parts.push(`where ${predToString(a.pred)}`);
32
- }
33
- parts.push(`#${a.conf}`);
34
- return parts.join(" ");
35
- }
36
-
37
- export function formatShape(a: Abs): string {
38
- const s = a.shape;
39
- switch (s.k) {
40
- case "never":
41
- return "never";
42
- case "any":
43
- return "any";
44
- case "unknown":
45
- return "unknown";
46
- case "prim": {
47
- const lv = litValue(a);
48
- if (lv !== undefined) return JSON.stringify(lv);
49
- return s.type;
50
- }
51
- case "obj": {
52
- const entries = Object.entries(s.slots).map(([k, slot]) => {
53
- const opt = slot.optional ? "?" : "";
54
- return `${k}${opt}: ${formatShape(slot.value)}`;
55
- });
56
- return `{ ${entries.join(", ")} }`;
57
- }
58
- case "arr":
59
- return `${formatShape(s.element)}[]`;
60
- case "tuple":
61
- return `[${s.elements.map(formatShape).join(", ")}]`;
62
- case "fn": {
63
- const ret =
64
- s.returnType !== undefined ? formatShape(s.returnType) : "?";
65
- return `(${s.params.join(", ")}) => ${ret}`;
66
- }
67
- case "brand":
68
- return `${s.name}`;
69
- case "eff":
70
- return `${s.eff}<${formatShape(s.inner)}>`;
71
- case "sum":
72
- return s.members.map(formatShape).join(" | ");
73
- default:
74
- return "·";
75
- }
76
- }
77
-
78
- /** 多行展示,CLI 用 */
79
- export function formatAbsMultiline(a: Abs, label?: string): string {
80
- const lines: string[] = [];
81
- if (label) lines.push(label);
82
- lines.push(` ${formatShape(a)}`);
83
- if (a.term && a.term.op !== "lit") {
84
- lines.push(` term: ${termToString(a.term)}`);
85
- }
86
- if (a.pred && a.pred.op !== "true") {
87
- lines.push(` pred: ${predToString(a.pred)}`);
88
- }
89
- lines.push(` conf: ${a.conf}`);
90
- return lines.join("\n");
91
- }