@nudojs/core 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-N7E2A7IK.js +7216 -0
- package/dist/exec.d.ts +2 -0
- package/dist/exec.js +174 -0
- package/dist/index-DgyudAkw.d.ts +911 -0
- package/dist/index.d.ts +64 -710
- package/dist/index.js +3269 -8426
- package/package.json +18 -5
- package/CHANGELOG.md +0 -34
- package/src/__tests__/environment.test.ts +0 -48
- package/src/__tests__/fn-sig-impl.test.ts +0 -57
- package/src/__tests__/ops-refined.test.ts +0 -196
- package/src/__tests__/ops.test.ts +0 -84
- package/src/__tests__/type-value-phase2.test.ts +0 -117
- package/src/__tests__/type-value-phase3.test.ts +0 -94
- package/src/__tests__/type-value-refined.test.ts +0 -210
- package/src/__tests__/type-value.test.ts +0 -319
- package/src/algebra/__tests__/abs-native.test.ts +0 -176
- package/src/algebra/__tests__/arithmetic.test.ts +0 -170
- package/src/algebra/__tests__/ast-eval.test.ts +0 -154
- package/src/algebra/__tests__/bridge.test.ts +0 -160
- package/src/algebra/__tests__/call-budget.test.ts +0 -117
- package/src/algebra/__tests__/check-case-consistency.test.ts +0 -69
- package/src/algebra/__tests__/check-gold.test.ts +0 -290
- package/src/algebra/__tests__/check-json.test.ts +0 -57
- package/src/algebra/__tests__/check-mini-repo.test.ts +0 -49
- package/src/algebra/__tests__/check-real-commander.test.ts +0 -43
- package/src/algebra/__tests__/check-real-packages.test.ts +0 -165
- package/src/algebra/__tests__/check-recall-gold.test.ts +0 -1024
- package/src/algebra/__tests__/check-require-dep-memo.test.ts +0 -45
- package/src/algebra/__tests__/check-return-contract.test.ts +0 -90
- package/src/algebra/__tests__/check-shape-gold.test.ts +0 -303
- package/src/algebra/__tests__/check-source-memo.test.ts +0 -204
- package/src/algebra/__tests__/check.test.ts +0 -69
- package/src/algebra/__tests__/denote.test.ts +0 -77
- package/src/algebra/__tests__/diagnostics.test.ts +0 -64
- package/src/algebra/__tests__/differential.test.ts +0 -124
- package/src/algebra/__tests__/div-mod.test.ts +0 -38
- package/src/algebra/__tests__/example0.test.ts +0 -103
- package/src/algebra/__tests__/exec-analyze-throws.test.ts +0 -60
- package/src/algebra/__tests__/exec-async.test.ts +0 -46
- package/src/algebra/__tests__/exec-bpath.test.ts +0 -193
- package/src/algebra/__tests__/exec-class.test.ts +0 -56
- package/src/algebra/__tests__/exec-e2e.test.ts +0 -97
- package/src/algebra/__tests__/exec-generator.test.ts +0 -53
- package/src/algebra/__tests__/exec-inherit-default.test.ts +0 -111
- package/src/algebra/__tests__/exec-optional-nested.test.ts +0 -87
- package/src/algebra/__tests__/exec-rest.test.ts +0 -55
- package/src/algebra/__tests__/exec-spread-forof.test.ts +0 -85
- package/src/algebra/__tests__/exec-static-computed.test.ts +0 -61
- package/src/algebra/__tests__/exec-switch.test.ts +0 -74
- package/src/algebra/__tests__/exec-trycatch.test.ts +0 -71
- package/src/algebra/__tests__/fn-fp-memo.test.ts +0 -166
- package/src/algebra/__tests__/fn-fp-multidecl.test.ts +0 -49
- package/src/algebra/__tests__/format.test.ts +0 -34
- package/src/algebra/__tests__/generalize-memo.test.ts +0 -285
- package/src/algebra/__tests__/generalize.test.ts +0 -113
- package/src/algebra/__tests__/hash-source.test.ts +0 -19
- package/src/algebra/__tests__/hof.test.ts +0 -80
- package/src/algebra/__tests__/inlay.test.ts +0 -30
- package/src/algebra/__tests__/language.test.ts +0 -77
- package/src/algebra/__tests__/leq.test.ts +0 -109
- package/src/algebra/__tests__/load-deps-fp-memo.test.ts +0 -132
- package/src/algebra/__tests__/methods.test.ts +0 -37
- package/src/algebra/__tests__/node-types.test.ts +0 -26
- package/src/algebra/__tests__/nudo-constraints.ts +0 -46
- package/src/algebra/__tests__/objects.test.ts +0 -117
- package/src/algebra/__tests__/parse-source-cache.test.ts +0 -42
- package/src/algebra/__tests__/refine-import.test.ts +0 -109
- package/src/algebra/__tests__/stable-source-key-block.test.ts +0 -23
- package/src/algebra/__tests__/stable-source-key.test.ts +0 -31
- package/src/algebra/__tests__/surface.test.ts +0 -41
- package/src/algebra/__tests__/this-inherit.test.ts +0 -130
- package/src/algebra/abs-fn.ts +0 -49
- package/src/algebra/abs-modules.ts +0 -139
- package/src/algebra/abs.ts +0 -206
- package/src/algebra/arithmetic.ts +0 -691
- package/src/algebra/ast-eval.ts +0 -1763
- package/src/algebra/bridge.ts +0 -350
- package/src/algebra/builtins.ts +0 -373
- package/src/algebra/check-report.ts +0 -150
- package/src/algebra/check.ts +0 -1867
- package/src/algebra/constraint.ts +0 -304
- package/src/algebra/denote.ts +0 -166
- package/src/algebra/diagnostics.ts +0 -210
- package/src/algebra/exec/call.ts +0 -29
- package/src/algebra/exec/calls.ts +0 -96
- package/src/algebra/exec/class-registry.ts +0 -29
- package/src/algebra/exec/class.ts +0 -329
- package/src/algebra/exec/index.ts +0 -6
- package/src/algebra/exec/member-diag.ts +0 -141
- package/src/algebra/exec/run.ts +0 -341
- package/src/algebra/exec/runtime.ts +0 -583
- package/src/algebra/exec/transpile.ts +0 -993
- package/src/algebra/fn-fp.ts +0 -294
- package/src/algebra/format.ts +0 -91
- package/src/algebra/generalize.ts +0 -776
- package/src/algebra/hash-source.ts +0 -27
- package/src/algebra/index.ts +0 -34
- package/src/algebra/inlay.ts +0 -198
- package/src/algebra/language.ts +0 -289
- package/src/algebra/leak.ts +0 -68
- package/src/algebra/leq.ts +0 -301
- package/src/algebra/load-deps-fp.ts +0 -97
- package/src/algebra/methods.ts +0 -128
- package/src/algebra/objects.ts +0 -251
- package/src/algebra/parse-source.ts +0 -64
- package/src/algebra/phi.ts +0 -42
- package/src/algebra/pred.ts +0 -395
- package/src/algebra/refine.ts +0 -227
- package/src/algebra/stable-source-key.ts +0 -81
- package/src/algebra/surface.ts +0 -206
- package/src/algebra/template.ts +0 -143
- package/src/algebra/term.ts +0 -119
- package/src/environment.ts +0 -74
- package/src/index.ts +0 -73
- package/src/mock-helpers.ts +0 -166
- package/src/ops.ts +0 -191
- package/src/refinements/range.ts +0 -86
- package/src/refinements/template-predicates.ts +0 -11
- package/src/refinements/template.ts +0 -176
- package/src/strip-types.ts +0 -236
- package/src/type-value.ts +0 -513
- package/tsconfig.json +0 -8
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
runTranspiled,
|
|
4
|
-
callTranspiledExportFull,
|
|
5
|
-
$lit,
|
|
6
|
-
$obj,
|
|
7
|
-
$arr,
|
|
8
|
-
litValue,
|
|
9
|
-
absToString,
|
|
10
|
-
transpile,
|
|
11
|
-
} from "@nudojs/core";
|
|
12
|
-
|
|
13
|
-
describe("B-path spread", () => {
|
|
14
|
-
it("object spread overwrites keys", () => {
|
|
15
|
-
const src = `
|
|
16
|
-
export function go() {
|
|
17
|
-
const a = { x: 1, y: 2 };
|
|
18
|
-
const b = { y: 9, z: 3 };
|
|
19
|
-
const o = { ...a, ...b };
|
|
20
|
-
return o.x + o.y + o.z;
|
|
21
|
-
}
|
|
22
|
-
`;
|
|
23
|
-
const exports = runTranspiled(src, { mode: "analyze" });
|
|
24
|
-
const r = callTranspiledExportFull(exports, "go", []);
|
|
25
|
-
expect(litValue(r.result)).toBe(13); // 1+9+3
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it("array spread concatenates", () => {
|
|
29
|
-
const src = `
|
|
30
|
-
export function go() {
|
|
31
|
-
const a = [1, 2];
|
|
32
|
-
const b = [3];
|
|
33
|
-
const c = [...a, ...b];
|
|
34
|
-
return c[0] + c[1] + c[2];
|
|
35
|
-
}
|
|
36
|
-
`;
|
|
37
|
-
const exports = runTranspiled(src, { mode: "analyze" });
|
|
38
|
-
const r = callTranspiledExportFull(exports, "go", []);
|
|
39
|
-
expect(litValue(r.result)).toBe(6);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("transpiles spread", () => {
|
|
43
|
-
const out = transpile(`export function f(a, b) { return { ...a, z: 1 }; }`);
|
|
44
|
-
expect(out).toContain("$spread(");
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
describe("B-path for-of", () => {
|
|
49
|
-
it("iterates tuple elements", () => {
|
|
50
|
-
const src = `
|
|
51
|
-
export function go() {
|
|
52
|
-
const xs = [1, 2, 3];
|
|
53
|
-
let sum = 0;
|
|
54
|
-
for (const x of xs) {
|
|
55
|
-
sum = sum + x;
|
|
56
|
-
}
|
|
57
|
-
return sum;
|
|
58
|
-
}
|
|
59
|
-
`;
|
|
60
|
-
const exports = runTranspiled(src, { mode: "analyze" });
|
|
61
|
-
const r = callTranspiledExportFull(exports, "go", []);
|
|
62
|
-
expect(litValue(r.result)).toBe(6);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it("for-of with object destructure", () => {
|
|
66
|
-
const src = `
|
|
67
|
-
export function go() {
|
|
68
|
-
const xs = [{ v: 1 }, { v: 2 }];
|
|
69
|
-
let sum = 0;
|
|
70
|
-
for (const { v } of xs) {
|
|
71
|
-
sum = sum + v;
|
|
72
|
-
}
|
|
73
|
-
return sum;
|
|
74
|
-
}
|
|
75
|
-
`;
|
|
76
|
-
const exports = runTranspiled(src, { mode: "analyze" });
|
|
77
|
-
const r = callTranspiledExportFull(exports, "go", []);
|
|
78
|
-
expect(litValue(r.result)).toBe(3);
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it("transpiles for-of", () => {
|
|
82
|
-
const out = transpile(`export function f(xs) { let t = 0; for (const x of xs) { t = t + x; } return t; }`);
|
|
83
|
-
expect(out).toContain("$forOf(");
|
|
84
|
-
});
|
|
85
|
-
});
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
runTranspiled,
|
|
4
|
-
callTranspiledExportFull,
|
|
5
|
-
$lit,
|
|
6
|
-
litValue,
|
|
7
|
-
absToString,
|
|
8
|
-
transpile,
|
|
9
|
-
} from "@nudojs/core";
|
|
10
|
-
|
|
11
|
-
describe("B-path class static members", () => {
|
|
12
|
-
it("reads static fields and calls static methods", () => {
|
|
13
|
-
const src = `
|
|
14
|
-
class Point {
|
|
15
|
-
static origin = 0;
|
|
16
|
-
static make(n) { return n * 2; }
|
|
17
|
-
constructor(x) { this.x = x; }
|
|
18
|
-
get() { return this.x; }
|
|
19
|
-
}
|
|
20
|
-
export function go() {
|
|
21
|
-
const p = new Point(Point.make(3));
|
|
22
|
-
return p.get() + Point.origin;
|
|
23
|
-
}
|
|
24
|
-
`;
|
|
25
|
-
const exports = runTranspiled(src, { mode: "analyze" });
|
|
26
|
-
const r = callTranspiledExportFull(exports, "go", []);
|
|
27
|
-
expect(litValue(r.result)).toBe(6); // make(3)=6 + origin=0
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("transpiles static to $class statics/staticMethods", () => {
|
|
31
|
-
const out = transpile(`
|
|
32
|
-
class C {
|
|
33
|
-
static n = 1;
|
|
34
|
-
static f() { return 2; }
|
|
35
|
-
m() { return 3; }
|
|
36
|
-
}
|
|
37
|
-
`);
|
|
38
|
-
expect(out).toContain("statics:");
|
|
39
|
-
expect(out).toContain("staticMethods:");
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
describe("B-path computed object properties", () => {
|
|
44
|
-
it("{ [k]: v } uses $setKey", () => {
|
|
45
|
-
const src = `
|
|
46
|
-
export function go() {
|
|
47
|
-
const k = "id";
|
|
48
|
-
const o = { [k]: 7 };
|
|
49
|
-
return o.id;
|
|
50
|
-
}
|
|
51
|
-
`;
|
|
52
|
-
const exports = runTranspiled(src, { mode: "analyze" });
|
|
53
|
-
const r = callTranspiledExportFull(exports, "go", []);
|
|
54
|
-
expect(litValue(r.result)).toBe(7);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it("transpiles computed property", () => {
|
|
58
|
-
const out = transpile(`export function f(k, v) { return { [k]: v }; }`);
|
|
59
|
-
expect(out).toContain("$setKey(");
|
|
60
|
-
});
|
|
61
|
-
});
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
runTranspiled,
|
|
4
|
-
callTranspiledExportFull,
|
|
5
|
-
$lit,
|
|
6
|
-
litValue,
|
|
7
|
-
absToString,
|
|
8
|
-
transpile,
|
|
9
|
-
} from "@nudojs/core";
|
|
10
|
-
|
|
11
|
-
describe("B-path switch", () => {
|
|
12
|
-
it("selects matching case by concrete disc", () => {
|
|
13
|
-
const src = `
|
|
14
|
-
export function go(n) {
|
|
15
|
-
switch (n) {
|
|
16
|
-
case 1:
|
|
17
|
-
return "one";
|
|
18
|
-
case 2:
|
|
19
|
-
return "two";
|
|
20
|
-
default:
|
|
21
|
-
return "other";
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
`;
|
|
25
|
-
const exports = runTranspiled(src, { mode: "analyze" });
|
|
26
|
-
expect(litValue(callTranspiledExportFull(exports, "go", [$lit(1)]).result)).toBe("one");
|
|
27
|
-
expect(litValue(callTranspiledExportFull(exports, "go", [$lit(2)]).result)).toBe("two");
|
|
28
|
-
expect(litValue(callTranspiledExportFull(exports, "go", [$lit(9)]).result)).toBe("other");
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it("handles fall-through", () => {
|
|
32
|
-
const src = `
|
|
33
|
-
export function go(n) {
|
|
34
|
-
switch (n) {
|
|
35
|
-
case 1:
|
|
36
|
-
case 2:
|
|
37
|
-
return "small";
|
|
38
|
-
case 3:
|
|
39
|
-
return "three";
|
|
40
|
-
default:
|
|
41
|
-
return "big";
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
`;
|
|
45
|
-
const exports = runTranspiled(src, { mode: "analyze" });
|
|
46
|
-
expect(litValue(callTranspiledExportFull(exports, "go", [$lit(1)]).result)).toBe("small");
|
|
47
|
-
expect(litValue(callTranspiledExportFull(exports, "go", [$lit(2)]).result)).toBe("small");
|
|
48
|
-
expect(litValue(callTranspiledExportFull(exports, "go", [$lit(3)]).result)).toBe("three");
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it("abstract disc joins branches", () => {
|
|
52
|
-
const src = `
|
|
53
|
-
export function go(n) {
|
|
54
|
-
switch (n) {
|
|
55
|
-
case 1:
|
|
56
|
-
return 10;
|
|
57
|
-
default:
|
|
58
|
-
return 20;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
`;
|
|
62
|
-
const exports = runTranspiled(src, { mode: "analyze" });
|
|
63
|
-
const r = callTranspiledExportFull(exports, "go", [
|
|
64
|
-
{ shape: { k: "prim", type: "number" }, conf: "exact" },
|
|
65
|
-
]);
|
|
66
|
-
// 抽象 number → join(10, 20) → number #path
|
|
67
|
-
expect(absToString(r.result)).toContain("number");
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it("transpiles switch to $switch", () => {
|
|
71
|
-
const out = transpile(`export function f(n) { switch (n) { case 1: return 1; default: return 0; } }`);
|
|
72
|
-
expect(out).toContain("$switch(");
|
|
73
|
-
});
|
|
74
|
-
});
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
runTranspiled,
|
|
4
|
-
callTranspiledExportFull,
|
|
5
|
-
$lit,
|
|
6
|
-
litValue,
|
|
7
|
-
absToString,
|
|
8
|
-
transpile,
|
|
9
|
-
} from "@nudojs/core";
|
|
10
|
-
|
|
11
|
-
describe("B-path try/catch", () => {
|
|
12
|
-
it("catches $throw and binds Abs value", () => {
|
|
13
|
-
const src = `
|
|
14
|
-
export function go(n) {
|
|
15
|
-
try {
|
|
16
|
-
if (n > 0) {
|
|
17
|
-
return n;
|
|
18
|
-
} else {
|
|
19
|
-
throw "neg";
|
|
20
|
-
}
|
|
21
|
-
} catch (e) {
|
|
22
|
-
return e;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
`;
|
|
26
|
-
const exports = runTranspiled(src, { mode: "analyze" });
|
|
27
|
-
const ok = callTranspiledExportFull(exports, "go", [$lit(3)]);
|
|
28
|
-
expect(litValue(ok.result)).toBe(3);
|
|
29
|
-
expect(ok.throws.shape.k).toBe("never");
|
|
30
|
-
|
|
31
|
-
const bad = callTranspiledExportFull(exports, "go", [$lit(-1)]);
|
|
32
|
-
expect(litValue(bad.result)).toBe("neg");
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it("finally runs after catch", () => {
|
|
36
|
-
const src = `
|
|
37
|
-
export function go() {
|
|
38
|
-
let t = 0;
|
|
39
|
-
try {
|
|
40
|
-
throw "x";
|
|
41
|
-
} catch (e) {
|
|
42
|
-
t = 1;
|
|
43
|
-
} finally {
|
|
44
|
-
t = t + 10;
|
|
45
|
-
}
|
|
46
|
-
return t;
|
|
47
|
-
}
|
|
48
|
-
`;
|
|
49
|
-
const exports = runTranspiled(src, { mode: "analyze" });
|
|
50
|
-
const r = callTranspiledExportFull(exports, "go", []);
|
|
51
|
-
expect(litValue(r.result)).toBe(11);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it("uncaught throw still reports throws", () => {
|
|
55
|
-
const src = `
|
|
56
|
-
export function go() {
|
|
57
|
-
throw "boom";
|
|
58
|
-
}
|
|
59
|
-
`;
|
|
60
|
-
const exports = runTranspiled(src, { mode: "analyze" });
|
|
61
|
-
const r = callTranspiledExportFull(exports, "go", []);
|
|
62
|
-
expect(r.result.shape.k).toBe("never");
|
|
63
|
-
expect(absToString(r.throws)).toContain("boom");
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it("transpiles try/catch", () => {
|
|
67
|
-
const out = transpile(`export function f() { try { return 1; } catch (e) { return 0; } }`);
|
|
68
|
-
expect(out).toContain("try {");
|
|
69
|
-
expect(out).toContain("$catchVal(");
|
|
70
|
-
});
|
|
71
|
-
});
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
canSkipLiteralCallScan,
|
|
4
|
-
generalizeFromAst,
|
|
5
|
-
resetGeneralizeMemo,
|
|
6
|
-
getGeneralizeMemoSize,
|
|
7
|
-
parseSource,
|
|
8
|
-
} from "../index.ts";
|
|
9
|
-
|
|
10
|
-
const BASE = `
|
|
11
|
-
function alpha(x) {
|
|
12
|
-
return x + 1;
|
|
13
|
-
}
|
|
14
|
-
function beta(y) {
|
|
15
|
-
return y * 2;
|
|
16
|
-
}
|
|
17
|
-
function gamma(z) {
|
|
18
|
-
return alpha(z) + beta(z);
|
|
19
|
-
}
|
|
20
|
-
`;
|
|
21
|
-
|
|
22
|
-
beforeEach(() => {
|
|
23
|
-
resetGeneralizeMemo();
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
describe("per-function L0 fingerprints", () => {
|
|
27
|
-
it("editing one independent function does not miss another", () => {
|
|
28
|
-
const file0 = parseSource(BASE);
|
|
29
|
-
const a0 = generalizeFromAst("alpha", BASE, { file: file0 });
|
|
30
|
-
const b0 = generalizeFromAst("beta", BASE, { file: file0 });
|
|
31
|
-
expect(a0).toBeDefined();
|
|
32
|
-
expect(b0).toBeDefined();
|
|
33
|
-
|
|
34
|
-
const edited = BASE.replace("return y * 2;", "return y * 3;");
|
|
35
|
-
const file1 = parseSource(edited);
|
|
36
|
-
// beta changed -> new PolyFn
|
|
37
|
-
const b1 = generalizeFromAst("beta", edited, { file: file1 });
|
|
38
|
-
expect(b1).toBeDefined();
|
|
39
|
-
expect(b1).not.toBe(b0);
|
|
40
|
-
// alpha unchanged and does not reference beta -> same instance
|
|
41
|
-
const a1 = generalizeFromAst("alpha", edited, { file: file1 });
|
|
42
|
-
expect(a1).toBe(a0);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it("caller misses when callee body changes", () => {
|
|
46
|
-
const file0 = parseSource(BASE);
|
|
47
|
-
const g0 = generalizeFromAst("gamma", BASE, { file: file0 });
|
|
48
|
-
const a0 = generalizeFromAst("alpha", BASE, { file: file0 });
|
|
49
|
-
|
|
50
|
-
const edited = BASE.replace("return x + 1;", "return x + 10;");
|
|
51
|
-
const file1 = parseSource(edited);
|
|
52
|
-
const a1 = generalizeFromAst("alpha", edited, { file: file1 });
|
|
53
|
-
const g1 = generalizeFromAst("gamma", edited, { file: file1 });
|
|
54
|
-
expect(a1).not.toBe(a0);
|
|
55
|
-
expect(g1).not.toBe(g0);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it("top-level non-function context change misses all", () => {
|
|
59
|
-
const src = `const K = 1;\nfunction alpha(x) { return x + K; }\nfunction beta(y) { return y; }\n`;
|
|
60
|
-
const file0 = parseSource(src);
|
|
61
|
-
const a0 = generalizeFromAst("alpha", src, { file: file0 });
|
|
62
|
-
const b0 = generalizeFromAst("beta", src, { file: file0 });
|
|
63
|
-
|
|
64
|
-
const edited = `const K = 2;\nfunction alpha(x) { return x + K; }\nfunction beta(y) { return y; }\n`;
|
|
65
|
-
const file1 = parseSource(edited);
|
|
66
|
-
const a1 = generalizeFromAst("alpha", edited, { file: file1 });
|
|
67
|
-
const b1 = generalizeFromAst("beta", edited, { file: file1 });
|
|
68
|
-
expect(a1).not.toBe(a0);
|
|
69
|
-
expect(b1).not.toBe(b0);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it("without file AST falls back to whole-source key", () => {
|
|
73
|
-
const a0 = generalizeFromAst("alpha", BASE);
|
|
74
|
-
const edited = BASE.replace("return y * 2;", "return y * 3;");
|
|
75
|
-
const a1 = generalizeFromAst("alpha", edited);
|
|
76
|
-
// no file -> whole source hash, alpha misses too
|
|
77
|
-
expect(a1).not.toBe(a0);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it("refine leading comments are part of own slice", () => {
|
|
81
|
-
const src1 = `
|
|
82
|
-
/**
|
|
83
|
-
* @nudo:case "c" (1)
|
|
84
|
-
*/
|
|
85
|
-
function f(x) { return x + 1; }
|
|
86
|
-
`;
|
|
87
|
-
const src2 = `
|
|
88
|
-
/**
|
|
89
|
-
* @nudo:case "c" (2)
|
|
90
|
-
*/
|
|
91
|
-
function f(x) { return x + 1; }
|
|
92
|
-
`;
|
|
93
|
-
const g1 = generalizeFromAst("f", src1, { file: parseSource(src1) });
|
|
94
|
-
const g2 = generalizeFromAst("f", src2, { file: parseSource(src2) });
|
|
95
|
-
expect(g1).toBeDefined();
|
|
96
|
-
expect(g2).toBeDefined();
|
|
97
|
-
expect(g2).not.toBe(g1);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it("memo size grows with distinct fingerprints only", () => {
|
|
101
|
-
const file = parseSource(BASE);
|
|
102
|
-
generalizeFromAst("alpha", BASE, { file });
|
|
103
|
-
generalizeFromAst("beta", BASE, { file });
|
|
104
|
-
const n = getGeneralizeMemoSize();
|
|
105
|
-
generalizeFromAst("alpha", BASE, { file });
|
|
106
|
-
expect(getGeneralizeMemoSize()).toBe(n);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it("default-param sibling reference dirties caller L0", () => {
|
|
110
|
-
const src1 = `
|
|
111
|
-
function helper() { return 1; }
|
|
112
|
-
function f(a = helper()) { return a; }
|
|
113
|
-
`;
|
|
114
|
-
const src2 = `
|
|
115
|
-
function helper() { return 2; }
|
|
116
|
-
function f(a = helper()) { return a; }
|
|
117
|
-
`;
|
|
118
|
-
const g1 = generalizeFromAst("f", src1, { file: parseSource(src1) });
|
|
119
|
-
const g2 = generalizeFromAst("f", src2, { file: parseSource(src2) });
|
|
120
|
-
expect(g1).toBeDefined();
|
|
121
|
-
expect(g2).toBeDefined();
|
|
122
|
-
expect(g2).not.toBe(g1);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it("multi-declarator leading refine comment is part of own slice", () => {
|
|
126
|
-
const src1 = `
|
|
127
|
-
const f = (x) => x,
|
|
128
|
-
/**
|
|
129
|
-
* @nudo:case "c" (1)
|
|
130
|
-
*/
|
|
131
|
-
g = (y) => y + 1;
|
|
132
|
-
`;
|
|
133
|
-
const src2 = `
|
|
134
|
-
const f = (x) => x,
|
|
135
|
-
/**
|
|
136
|
-
* @nudo:case "c" (2)
|
|
137
|
-
*/
|
|
138
|
-
g = (y) => y + 1;
|
|
139
|
-
`;
|
|
140
|
-
const g1 = generalizeFromAst("g", src1, { file: parseSource(src1) });
|
|
141
|
-
const g2 = generalizeFromAst("g", src2, { file: parseSource(src2) });
|
|
142
|
-
expect(g1).toBeDefined();
|
|
143
|
-
expect(g2).toBeDefined();
|
|
144
|
-
expect(g2).not.toBe(g1);
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
describe("canSkipLiteralCallScan depth cap", () => {
|
|
149
|
-
it("does not skip when a call sits below the walk depth cap", () => {
|
|
150
|
-
// 90 nested arrays push the CallExpression past hasAnyCallLike's depth>80
|
|
151
|
-
// cut-off. Unexplored subtrees must be treated as "may contain a call".
|
|
152
|
-
let nest = "f(-1)";
|
|
153
|
-
for (let i = 0; i < 90; i++) nest = `[${nest}]`;
|
|
154
|
-
const src = `const x = ${nest};\n`;
|
|
155
|
-
const file = parseSource(src);
|
|
156
|
-
expect(canSkipLiteralCallScan(src, file)).toBe(false);
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it("still skips shallow call-free sources", () => {
|
|
160
|
-
const src = `function id(x) { return x + 1; }\nconst y = id(2);\n`;
|
|
161
|
-
// id(2) is a CallExpression — must NOT skip
|
|
162
|
-
expect(canSkipLiteralCallScan(src, parseSource(src))).toBe(false);
|
|
163
|
-
const pure = `const y = 1 + 2;\nfunction id(x) { return x + 1; }\n`;
|
|
164
|
-
expect(canSkipLiteralCallScan(pure, parseSource(pure))).toBe(true);
|
|
165
|
-
});
|
|
166
|
-
});
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
generalizeFromAst,
|
|
4
|
-
resetGeneralizeMemo,
|
|
5
|
-
parseSource,
|
|
6
|
-
fnFingerprints,
|
|
7
|
-
} from "../index.ts";
|
|
8
|
-
|
|
9
|
-
const SRC = `const a = (x) => x, b = (x) => x + 1;
|
|
10
|
-
function gamma(x) { return b(x); }
|
|
11
|
-
`;
|
|
12
|
-
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
resetGeneralizeMemo();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
describe("multi-declarator fingerprints", () => {
|
|
18
|
-
it("indexes every function declarator", () => {
|
|
19
|
-
const fps = fnFingerprints(SRC, parseSource(SRC));
|
|
20
|
-
expect([...fps.keys()].sort()).toEqual(["a", "b", "gamma"]);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it("caller misses L0 when callee in same declarator statement changes", () => {
|
|
24
|
-
const f0 = parseSource(SRC);
|
|
25
|
-
const g0 = generalizeFromAst("gamma", SRC, { file: f0 });
|
|
26
|
-
expect(g0).toBeDefined();
|
|
27
|
-
|
|
28
|
-
const edited = SRC.replace("b = (x) => x + 1", "b = (x) => x + 10");
|
|
29
|
-
const f1 = parseSource(edited);
|
|
30
|
-
const g1 = generalizeFromAst("gamma", edited, { file: f1 });
|
|
31
|
-
expect(g1).not.toBe(g0);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it("independent sibling in same statement does not dirty the other's callers", () => {
|
|
35
|
-
const f0 = parseSource(SRC);
|
|
36
|
-
const a0 = generalizeFromAst("a", SRC, { file: f0 });
|
|
37
|
-
const g0 = generalizeFromAst("gamma", SRC, { file: f0 });
|
|
38
|
-
expect(a0).toBeDefined();
|
|
39
|
-
expect(g0).toBeDefined();
|
|
40
|
-
|
|
41
|
-
// Only a changes; gamma calls b — a's own-slice must not drag gamma.
|
|
42
|
-
const edited = SRC.replace("a = (x) => x", "a = (x) => x + 100");
|
|
43
|
-
const f1 = parseSource(edited);
|
|
44
|
-
const a1 = generalizeFromAst("a", edited, { file: f1 });
|
|
45
|
-
const g1 = generalizeFromAst("gamma", edited, { file: f1 });
|
|
46
|
-
expect(a1).not.toBe(a0);
|
|
47
|
-
expect(g1).toBe(g0);
|
|
48
|
-
});
|
|
49
|
-
});
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { formatShape, formatAbs } from "../format.ts";
|
|
3
|
-
import { abs, num } from "../abs.ts";
|
|
4
|
-
import { v, lit } from "../term.ts";
|
|
5
|
-
import { ge } from "../pred.ts";
|
|
6
|
-
|
|
7
|
-
describe("formatShape brand/eff/fn", () => {
|
|
8
|
-
it("brand shows class name", () => {
|
|
9
|
-
const inner = abs(num().shape, undefined, undefined, "exact");
|
|
10
|
-
const a = abs({ k: "brand", name: "Counter", shape: inner }, undefined, undefined, "exact");
|
|
11
|
-
expect(formatShape(a)).toBe("Counter");
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it("eff shows promise inner", () => {
|
|
15
|
-
const inner = abs(num().shape, undefined, undefined, "exact");
|
|
16
|
-
const a = abs({ k: "eff", eff: "promise", inner }, undefined, undefined, "exact");
|
|
17
|
-
expect(formatShape(a)).toBe("promise<number>");
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it("fn shows return shape when present", () => {
|
|
21
|
-
const a = abs(
|
|
22
|
-
{ k: "fn", params: ["x"], returnType: abs(num().shape, undefined, undefined, "exact") },
|
|
23
|
-
undefined,
|
|
24
|
-
undefined,
|
|
25
|
-
"exact",
|
|
26
|
-
);
|
|
27
|
-
expect(formatShape(a)).toBe("(x) => number");
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("formatAbs still includes pred", () => {
|
|
31
|
-
const a = abs(num().shape, v("x"), ge(v("x"), lit(0)), "path");
|
|
32
|
-
expect(formatAbs(a)).toContain("0");
|
|
33
|
-
});
|
|
34
|
-
});
|