@nudojs/core 0.1.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.
Files changed (117) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/LICENSE +21 -0
  3. package/README.md +26 -0
  4. package/dist/index.d.ts +1633 -11
  5. package/dist/index.js +9965 -107
  6. package/package.json +28 -2
  7. package/src/__tests__/fn-sig-impl.test.ts +57 -0
  8. package/src/__tests__/ops-refined.test.ts +196 -0
  9. package/src/__tests__/ops.test.ts +8 -33
  10. package/src/__tests__/type-value-refined.test.ts +210 -0
  11. package/src/__tests__/type-value.test.ts +106 -0
  12. package/src/algebra/__tests__/abs-native.test.ts +176 -0
  13. package/src/algebra/__tests__/arithmetic.test.ts +170 -0
  14. package/src/algebra/__tests__/ast-eval.test.ts +154 -0
  15. package/src/algebra/__tests__/bridge.test.ts +160 -0
  16. package/src/algebra/__tests__/call-budget.test.ts +117 -0
  17. package/src/algebra/__tests__/check-case-consistency.test.ts +69 -0
  18. package/src/algebra/__tests__/check-gold.test.ts +290 -0
  19. package/src/algebra/__tests__/check-json.test.ts +57 -0
  20. package/src/algebra/__tests__/check-mini-repo.test.ts +49 -0
  21. package/src/algebra/__tests__/check-real-commander.test.ts +43 -0
  22. package/src/algebra/__tests__/check-real-packages.test.ts +165 -0
  23. package/src/algebra/__tests__/check-recall-gold.test.ts +1024 -0
  24. package/src/algebra/__tests__/check-require-dep-memo.test.ts +45 -0
  25. package/src/algebra/__tests__/check-return-contract.test.ts +90 -0
  26. package/src/algebra/__tests__/check-shape-gold.test.ts +303 -0
  27. package/src/algebra/__tests__/check-source-memo.test.ts +204 -0
  28. package/src/algebra/__tests__/check.test.ts +69 -0
  29. package/src/algebra/__tests__/denote.test.ts +77 -0
  30. package/src/algebra/__tests__/diagnostics.test.ts +64 -0
  31. package/src/algebra/__tests__/differential.test.ts +124 -0
  32. package/src/algebra/__tests__/div-mod.test.ts +38 -0
  33. package/src/algebra/__tests__/example0.test.ts +103 -0
  34. package/src/algebra/__tests__/exec-analyze-throws.test.ts +60 -0
  35. package/src/algebra/__tests__/exec-async.test.ts +46 -0
  36. package/src/algebra/__tests__/exec-bpath.test.ts +193 -0
  37. package/src/algebra/__tests__/exec-class.test.ts +56 -0
  38. package/src/algebra/__tests__/exec-e2e.test.ts +97 -0
  39. package/src/algebra/__tests__/exec-generator.test.ts +53 -0
  40. package/src/algebra/__tests__/exec-inherit-default.test.ts +111 -0
  41. package/src/algebra/__tests__/exec-optional-nested.test.ts +87 -0
  42. package/src/algebra/__tests__/exec-rest.test.ts +55 -0
  43. package/src/algebra/__tests__/exec-spread-forof.test.ts +85 -0
  44. package/src/algebra/__tests__/exec-static-computed.test.ts +61 -0
  45. package/src/algebra/__tests__/exec-switch.test.ts +74 -0
  46. package/src/algebra/__tests__/exec-trycatch.test.ts +71 -0
  47. package/src/algebra/__tests__/fn-fp-memo.test.ts +166 -0
  48. package/src/algebra/__tests__/fn-fp-multidecl.test.ts +49 -0
  49. package/src/algebra/__tests__/format.test.ts +34 -0
  50. package/src/algebra/__tests__/generalize-memo.test.ts +285 -0
  51. package/src/algebra/__tests__/generalize.test.ts +113 -0
  52. package/src/algebra/__tests__/hash-source.test.ts +19 -0
  53. package/src/algebra/__tests__/hof.test.ts +80 -0
  54. package/src/algebra/__tests__/inlay.test.ts +30 -0
  55. package/src/algebra/__tests__/language.test.ts +77 -0
  56. package/src/algebra/__tests__/leq.test.ts +109 -0
  57. package/src/algebra/__tests__/load-deps-fp-memo.test.ts +132 -0
  58. package/src/algebra/__tests__/methods.test.ts +37 -0
  59. package/src/algebra/__tests__/node-types.test.ts +26 -0
  60. package/src/algebra/__tests__/nudo-constraints.ts +46 -0
  61. package/src/algebra/__tests__/objects.test.ts +117 -0
  62. package/src/algebra/__tests__/parse-source-cache.test.ts +42 -0
  63. package/src/algebra/__tests__/refine-import.test.ts +109 -0
  64. package/src/algebra/__tests__/stable-source-key-block.test.ts +23 -0
  65. package/src/algebra/__tests__/stable-source-key.test.ts +31 -0
  66. package/src/algebra/__tests__/surface.test.ts +41 -0
  67. package/src/algebra/__tests__/this-inherit.test.ts +130 -0
  68. package/src/algebra/abs-fn.ts +49 -0
  69. package/src/algebra/abs-modules.ts +139 -0
  70. package/src/algebra/abs.ts +206 -0
  71. package/src/algebra/arithmetic.ts +691 -0
  72. package/src/algebra/ast-eval.ts +1763 -0
  73. package/src/algebra/bridge.ts +350 -0
  74. package/src/algebra/builtins.ts +373 -0
  75. package/src/algebra/check-report.ts +150 -0
  76. package/src/algebra/check.ts +1867 -0
  77. package/src/algebra/constraint.ts +304 -0
  78. package/src/algebra/denote.ts +166 -0
  79. package/src/algebra/diagnostics.ts +210 -0
  80. package/src/algebra/exec/call.ts +29 -0
  81. package/src/algebra/exec/calls.ts +96 -0
  82. package/src/algebra/exec/class-registry.ts +29 -0
  83. package/src/algebra/exec/class.ts +329 -0
  84. package/src/algebra/exec/index.ts +6 -0
  85. package/src/algebra/exec/member-diag.ts +141 -0
  86. package/src/algebra/exec/run.ts +341 -0
  87. package/src/algebra/exec/runtime.ts +583 -0
  88. package/src/algebra/exec/transpile.ts +993 -0
  89. package/src/algebra/fn-fp.ts +294 -0
  90. package/src/algebra/format.ts +91 -0
  91. package/src/algebra/generalize.ts +776 -0
  92. package/src/algebra/hash-source.ts +27 -0
  93. package/src/algebra/index.ts +34 -0
  94. package/src/algebra/inlay.ts +198 -0
  95. package/src/algebra/language.ts +289 -0
  96. package/src/algebra/leak.ts +68 -0
  97. package/src/algebra/leq.ts +301 -0
  98. package/src/algebra/load-deps-fp.ts +97 -0
  99. package/src/algebra/methods.ts +128 -0
  100. package/src/algebra/objects.ts +251 -0
  101. package/src/algebra/parse-source.ts +64 -0
  102. package/src/algebra/phi.ts +42 -0
  103. package/src/algebra/pred.ts +395 -0
  104. package/src/algebra/refine.ts +227 -0
  105. package/src/algebra/stable-source-key.ts +81 -0
  106. package/src/algebra/surface.ts +206 -0
  107. package/src/algebra/template.ts +143 -0
  108. package/src/algebra/term.ts +119 -0
  109. package/src/environment.ts +5 -0
  110. package/src/index.ts +52 -1
  111. package/src/mock-helpers.ts +166 -0
  112. package/src/ops.ts +106 -62
  113. package/src/refinements/range.ts +86 -0
  114. package/src/refinements/template-predicates.ts +11 -0
  115. package/src/refinements/template.ts +176 -0
  116. package/src/strip-types.ts +236 -0
  117. package/src/type-value.ts +193 -12
@@ -0,0 +1,206 @@
1
+ /**
2
+ * 语言表面运算(仍在 Abs 上):typeof / 一元- / ! / nullish 相等。
3
+ * 类型即计算——一元与控制流判定与二元算术同一运算域。
4
+ */
5
+
6
+ import type { Abs, Shape, Confidence } from "./abs.ts";
7
+ import { abs, litValue, confJoin, num, bool, boolLit, strLit } from "./abs.ts";
8
+ import type { Term } from "./term.ts";
9
+ import { lit, simplifyTerm, app } from "./term.ts";
10
+ import type { Pred } from "./pred.ts";
11
+ import {
12
+ pTrue,
13
+ gt,
14
+ ge,
15
+ lt,
16
+ le,
17
+ and,
18
+ type Phi,
19
+ } from "./pred.ts";
20
+ import { implies } from "./pred.ts";
21
+
22
+ /** JS typeof:结果域永远是 string */
23
+ export function typeofAbs(a: Abs): Abs {
24
+ const v = litValue(a);
25
+ if (v === null) return strLit("object");
26
+ // lit(undefined) 与「无 lit」在 litValue 上都是 undefined,须看 term
27
+ if (a.term?.op === "lit" && a.term.value === undefined) {
28
+ return strLit("undefined");
29
+ }
30
+ if (a.shape.k === "any" || a.shape.k === "unknown") {
31
+ // any/unknown:typeof 只能确定是 string,具体名未知
32
+ return abs({ k: "prim", type: "string" }, undefined, undefined, "partial");
33
+ }
34
+ if (a.shape.k === "sum") {
35
+ const names = [...new Set(a.shape.members.map((m) => typeofName(m.shape)))];
36
+ if (names.length === 1 && names[0] !== "unknown") return strLit(names[0]!);
37
+ return abs({ k: "prim", type: "string" }, undefined, undefined, "partial");
38
+ }
39
+ return strLit(typeofName(a.shape));
40
+ }
41
+
42
+ function typeofName(s: Shape): string {
43
+ switch (s.k) {
44
+ case "never":
45
+ return "undefined";
46
+ case "any":
47
+ return "unknown";
48
+ case "unknown":
49
+ return "unknown";
50
+ case "prim":
51
+ return s.type;
52
+ case "obj":
53
+ case "arr":
54
+ case "tuple":
55
+ case "brand":
56
+ return "object";
57
+ case "fn":
58
+ return "function";
59
+ case "eff":
60
+ return "object";
61
+ case "sum": {
62
+ const names = [...new Set(s.members.map((m) => typeofName(m.shape)))];
63
+ if (names.length === 1) return names[0]!;
64
+ return "unknown";
65
+ }
66
+ default:
67
+ return "unknown";
68
+ }
69
+ }
70
+
71
+ /** 一元负号:字面量折叠;符号数翻转不等式 */
72
+ export function negAbs(a: Abs, _phi: Phi = pTrue): Abs {
73
+ const v = litValue(a);
74
+ if (typeof v === "number") return numLitAbs(-v);
75
+ if (a.shape.k === "prim" && a.shape.type === "number") {
76
+ if (!a.term) {
77
+ return abs(num().shape, undefined, undefined, confJoin(a.conf, "widened"));
78
+ }
79
+ const term = simplifyTerm(app("-", [a.term]));
80
+ // -x:lo/hi 互换并取负
81
+ const facts: Pred[] = [];
82
+ // 从自身 pred 推:若 x > c ⇒ -x < -c
83
+ if (a.pred && a.pred.op !== "true" && a.term) {
84
+ flipBounds(a.pred, a.term, term, facts);
85
+ }
86
+ return abs(
87
+ num().shape,
88
+ term,
89
+ facts.length ? and(...facts) : undefined,
90
+ confJoin(a.conf, "path"),
91
+ );
92
+ }
93
+ return abs({ k: "unknown" }, undefined, undefined, "partial");
94
+ }
95
+
96
+ function numLitAbs(n: number): Abs {
97
+ return abs(num().shape, lit(n), pTrue, "exact");
98
+ }
99
+
100
+ function flipBounds(pred: Pred, src: Term, dst: Term, out: Pred[]): void {
101
+ const apply = (p: Pred): void => {
102
+ if (p.op === "and") {
103
+ p.args.forEach(apply);
104
+ return;
105
+ }
106
+ if (
107
+ p.op !== "gt" && p.op !== "ge" && p.op !== "lt" && p.op !== "le"
108
+ ) {
109
+ return;
110
+ }
111
+ if (termKey(p.a) !== termKey(src)) return;
112
+ if (p.b.op !== "lit" || typeof p.b.value !== "number") return;
113
+ const n = p.b.value;
114
+ // x > n ⇒ -x < -n;x ≥ n ⇒ -x ≤ -n;对称
115
+ if (p.op === "gt") out.push(lt(dst, lit(-n)));
116
+ else if (p.op === "ge") out.push(le(dst, lit(-n)));
117
+ else if (p.op === "lt") out.push(gt(dst, lit(-n)));
118
+ else if (p.op === "le") out.push(ge(dst, lit(-n)));
119
+ };
120
+ apply(pred);
121
+ }
122
+
123
+ function termKey(t: Term): string {
124
+ if (t.op === "lit") return `lit:${JSON.stringify(t.value)}`;
125
+ if (t.op === "var") return `var:${t.id}`;
126
+ return `app:${t.fn}`;
127
+ }
128
+
129
+ /** 逻辑非 */
130
+ export function notAbs(a: Abs): Abs {
131
+ // 字面量(含 null/undefined/0/""):直接折叠
132
+ if (a.term?.op === "lit") {
133
+ return boolLit(!a.term.value);
134
+ }
135
+ if (a.shape.k === "prim" && a.shape.type === "boolean") {
136
+ return abs(bool().shape, undefined, undefined, confJoin(a.conf, "widened"));
137
+ }
138
+ // 对象恒真
139
+ if (isDefinitelyTruthyShape(a.shape)) return boolLit(false);
140
+ if (isDefinitelyFalsyShape(a.shape)) return boolLit(true);
141
+ return abs(bool().shape, undefined, undefined, "partial");
142
+ }
143
+
144
+ function isDefinitelyTruthyShape(s: Shape): boolean {
145
+ switch (s.k) {
146
+ case "obj":
147
+ case "arr":
148
+ case "tuple":
149
+ case "fn":
150
+ case "brand":
151
+ case "eff":
152
+ return true;
153
+ case "prim":
154
+ return s.type === "symbol" || s.type === "bigint";
155
+ default:
156
+ return false;
157
+ }
158
+ }
159
+
160
+ function isDefinitelyFalsyShape(s: Shape): boolean {
161
+ return s.k === "never";
162
+ }
163
+
164
+ /** 该 shape 在 JS 上一定不是 null/undefined */
165
+ export function definitelyNotNullishShape(s: Shape): boolean {
166
+ switch (s.k) {
167
+ case "prim":
168
+ case "obj":
169
+ case "arr":
170
+ case "tuple":
171
+ case "fn":
172
+ case "brand":
173
+ case "eff":
174
+ return true;
175
+ case "sum":
176
+ return s.members.every((m) => definitelyNotNullishShape(m.shape));
177
+ default:
178
+ return false;
179
+ }
180
+ }
181
+
182
+ export function isNullishLitAbs(a: Abs): boolean {
183
+ const v = litValue(a);
184
+ if (v === null || v === undefined) return true;
185
+ // shape 层:无 lit 的 unknown 不判 nullish
186
+ return false;
187
+ }
188
+
189
+ /**
190
+ * 严格相等(Abs):双字面量折叠;nullish 与 definitely-not-nullish → false。
191
+ * 返回 undefined = 无法判定(交给 boolean + 调用方)。
192
+ */
193
+ export function strictEqAbs(a: Abs, b: Abs): boolean | undefined {
194
+ const va = litValue(a);
195
+ const vb = litValue(b);
196
+ if (va !== undefined && vb !== undefined) return va === vb;
197
+ const aNullish = va === null || (a.term?.op === "lit" && a.term.value === undefined);
198
+ const bNullish = vb === null || (b.term?.op === "lit" && b.term.value === undefined);
199
+ if (bNullish && definitelyNotNullishShape(a.shape)) return false;
200
+ if (aNullish && definitelyNotNullishShape(b.shape)) return false;
201
+ // 同 var 恒等
202
+ if (a.term && b.term && a.term.op === "var" && b.term.op === "var" && a.term.id === b.term.id) {
203
+ return true;
204
+ }
205
+ return undefined;
206
+ }
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Template string 拼接(代数侧)。
3
+ * 表示:prim(string) + refinement.meta.templateParts = Abs[]
4
+ * 与 core 的 createTemplate 对齐,使 `"x" + string + "!"` 得到 template refined。
5
+ */
6
+
7
+ import type { Abs } from "./abs.ts";
8
+ import { abs, litValue } from "./abs.ts";
9
+ import { lit, termToString, type Term } from "./term.ts";
10
+ import { pTrue, type Pred } from "./pred.ts";
11
+
12
+ export type TemplateMeta = {
13
+ templateParts: Abs[];
14
+ };
15
+
16
+ function isStrLit(a: Abs): a is Abs & { term: { op: "lit"; value: string } } {
17
+ return (
18
+ a.shape.k === "prim" &&
19
+ a.shape.type === "string" &&
20
+ a.term?.op === "lit" &&
21
+ typeof a.term.value === "string"
22
+ );
23
+ }
24
+
25
+ function isStrPrim(a: Abs): boolean {
26
+ return a.shape.k === "prim" && a.shape.type === "string";
27
+ }
28
+
29
+ function isTemplateAbs(a: Abs): boolean {
30
+ return (
31
+ a.shape.k === "prim" &&
32
+ a.shape.type === "string" &&
33
+ !!a.pred &&
34
+ (a.pred as { name?: string }).name?.startsWith("`") === true &&
35
+ Array.isArray(((a.pred as { meta?: TemplateMeta }).meta)?.templateParts)
36
+ );
37
+ }
38
+
39
+ /** 从 Abs 提取 template parts(已是 template 则展开,否则 [self]) */
40
+ export function templatePartsOf(a: Abs): Abs[] {
41
+ if (isTemplateAbs(a)) {
42
+ const meta = (a.pred as unknown as { meta: TemplateMeta }).meta;
43
+ return meta.templateParts;
44
+ }
45
+ return [a];
46
+ }
47
+
48
+ /**
49
+ * 合并相邻字面量;纯字面量折叠为 lit;单 string prim → prim。
50
+ */
51
+ function normalizeParts(parts: Abs[]): Abs[] {
52
+ const out: Abs[] = [];
53
+ for (const p of parts) {
54
+ const last = out[out.length - 1];
55
+ if (last && isStrLit(last) && isStrLit(p)) {
56
+ out[out.length - 1] = abs(
57
+ { k: "prim", type: "string" },
58
+ lit(String(litValue(last)) + String(litValue(p))),
59
+ undefined,
60
+ "exact",
61
+ );
62
+ } else {
63
+ out.push(p);
64
+ }
65
+ }
66
+ return out;
67
+ }
68
+
69
+ function formatTemplateName(parts: Abs[]): string {
70
+ const inner = parts
71
+ .map((p) => {
72
+ if (isStrLit(p)) return String(litValue(p));
73
+ return `\${${p.term ? termToString(p.term) : "string"}}`;
74
+ })
75
+ .join("");
76
+ return `\`${inner}\``;
77
+ }
78
+
79
+ /**
80
+ * 构造 template Abs。
81
+ * - 全字面量 → exact lit
82
+ * - 单 string prim → prim
83
+ * - 否则 prim(string) + pred(name=template, meta.templateParts)
84
+ */
85
+ export function createTemplateAbs(parts: Abs[]): Abs {
86
+ const normalized = normalizeParts(parts);
87
+ if (normalized.length === 1) {
88
+ const only = normalized[0]!;
89
+ if (isStrLit(only)) return only;
90
+ if (isStrPrim(only) && !isTemplateAbs(only)) return only;
91
+ }
92
+ const name = formatTemplateName(normalized);
93
+ // abs() 会丢弃 op==="true" 的 pred;直接构造以保留 template meta
94
+ const predObj = {
95
+ op: "true",
96
+ name,
97
+ meta: { templateParts: normalized } satisfies TemplateMeta,
98
+ } as unknown as Pred;
99
+
100
+ return {
101
+ shape: { k: "prim", type: "string" },
102
+ term: undefined,
103
+ pred: predObj,
104
+ conf: "path",
105
+ };
106
+ }
107
+
108
+ export function isTemplateLike(a: Abs): boolean {
109
+ return isTemplateAbs(a);
110
+ }
111
+
112
+ /** 字符串拼接:字面量折叠 + template parts 合并 */
113
+ export function concatString(a: Abs, b: Abs): Abs {
114
+ // 双字面量
115
+ if (isStrLit(a) && isStrLit(b)) {
116
+ return abs(
117
+ { k: "prim", type: "string" },
118
+ lit(String(litValue(a)) + String(litValue(b))),
119
+ undefined,
120
+ "exact",
121
+ );
122
+ }
123
+ // 至少一侧是 string(含 template / prim / 可 stringify 字面量)
124
+ const aParts = coerceToStringParts(a);
125
+ const bParts = coerceToStringParts(b);
126
+ if (!aParts || !bParts) return abs({ k: "unknown" }, undefined, undefined, "partial");
127
+ return createTemplateAbs([...aParts, ...bParts]);
128
+ }
129
+
130
+ function coerceToStringParts(a: Abs): Abs[] | undefined {
131
+ if (isTemplateAbs(a) || isStrPrim(a)) return templatePartsOf(a);
132
+ if (isStrLit(a)) return [a];
133
+ // 数值/布尔字面量:JS ToPrimitive 拼接
134
+ const lv = litValue(a);
135
+ if (typeof lv === "number" || typeof lv === "boolean") {
136
+ return [abs({ k: "prim", type: "string" }, lit(String(lv)), undefined, "exact")];
137
+ }
138
+ if (a.shape.k === "prim" && a.shape.type === "number") {
139
+ // abstract number → `${number}` part
140
+ return [a];
141
+ }
142
+ return undefined;
143
+ }
@@ -0,0 +1,119 @@
1
+ /** 项(Term):抽象值的身份。字面量是项的特例。 */
2
+
3
+ export type LiteralValue = string | number | boolean | null | undefined;
4
+
5
+ export type Term =
6
+ | { op: "lit"; value: LiteralValue }
7
+ | { op: "var"; id: string }
8
+ | { op: "app"; fn: string; args: Term[] };
9
+
10
+ export const lit = (value: LiteralValue): Term => ({
11
+ op: "lit",
12
+ // -0 与 0 在约束语义上等价,统一为 +0
13
+ value: typeof value === "number" && value === 0 ? 0 : value,
14
+ });
15
+ export const v = (id: string): Term => ({ op: "var", id });
16
+ export const app = (fn: string, args: Term[]): Term => ({ op: "app", fn, args });
17
+
18
+ export function termEquals(a: Term, b: Term): boolean {
19
+ if (a.op !== b.op) return false;
20
+ if (a.op === "lit" && b.op === "lit") return a.value === b.value;
21
+ if (a.op === "var" && b.op === "var") return a.id === b.id;
22
+ if (a.op === "app" && b.op === "app") {
23
+ return (
24
+ a.fn === b.fn &&
25
+ a.args.length === b.args.length &&
26
+ a.args.every((x, i) => termEquals(x, b.args[i]!))
27
+ );
28
+ }
29
+ return false;
30
+ }
31
+
32
+ export function termToString(t: Term): string {
33
+ if (t.op === "lit") {
34
+ return typeof t.value === "string" ? JSON.stringify(t.value) : String(t.value);
35
+ }
36
+ if (t.op === "var") return t.id;
37
+ // 字段访问:get(u, "id") → u.id
38
+ if (t.op === "app" && t.fn === "get" && t.args.length === 2) {
39
+ const obj = termToString(t.args[0]!);
40
+ const key = t.args[1]!;
41
+ if (key.op === "lit" && typeof key.value === "string") {
42
+ return `${obj}.${key.value}`;
43
+ }
44
+ }
45
+ if (t.fn === "+" && t.args.length === 2) {
46
+ return `(${termToString(t.args[0]!)} + ${termToString(t.args[1]!)})`;
47
+ }
48
+ if (t.fn === "-" && t.args.length === 2) {
49
+ return `(${termToString(t.args[0]!)} - ${termToString(t.args[1]!)})`;
50
+ }
51
+ if (t.fn === "*" && t.args.length === 2) {
52
+ return `(${termToString(t.args[0]!)} * ${termToString(t.args[1]!)})`;
53
+ }
54
+ return `${t.fn}(${t.args.map(termToString).join(", ")})`;
55
+ }
56
+
57
+ /** 常量折叠 + 简单代数化简 */
58
+ export function simplifyTerm(t: Term): Term {
59
+ if (t.op !== "app") return t;
60
+ const args = t.args.map(simplifyTerm);
61
+ const fn = t.fn;
62
+
63
+ if (args.every((a) => a.op === "lit")) {
64
+ const xs = args.map((a) => (a as { value: LiteralValue }).value);
65
+ const folded = foldLiterals(fn, xs);
66
+ if (folded !== undefined) return lit(folded);
67
+ }
68
+
69
+ // x + 0 = x, 0 + x = x
70
+ if (fn === "+" && args.length === 2) {
71
+ const [a, b] = args as [Term, Term];
72
+ if (a.op === "lit" && a.value === 0) return b;
73
+ if (b.op === "lit" && b.value === 0) return a;
74
+ }
75
+ // x * 1 = x, 1 * x = x; x * 0 = 0
76
+ if (fn === "*" && args.length === 2) {
77
+ const [a, b] = args as [Term, Term];
78
+ if (a.op === "lit" && a.value === 1) return b;
79
+ if (b.op === "lit" && b.value === 1) return a;
80
+ if (
81
+ (a.op === "lit" && a.value === 0) ||
82
+ (b.op === "lit" && b.value === 0)
83
+ ) {
84
+ return lit(0);
85
+ }
86
+ }
87
+ // x - 0 = x
88
+ if (fn === "-" && args.length === 2) {
89
+ const [a, b] = args as [Term, Term];
90
+ if (b.op === "lit" && b.value === 0) return a;
91
+ }
92
+
93
+ return app(fn, args);
94
+ }
95
+
96
+ function foldLiterals(fn: string, xs: LiteralValue[]): LiteralValue | undefined {
97
+ if (fn === "+" && xs.length === 2) {
98
+ const [a, b] = xs as [number | string, number | string];
99
+ if (typeof a === "number" && typeof b === "number") return a + b;
100
+ if (typeof a === "string" || typeof b === "string") return String(a) + String(b);
101
+ return undefined;
102
+ }
103
+ if (fn === "-" && xs.length === 2) {
104
+ const [a, b] = xs as [number, number];
105
+ if (typeof a === "number" && typeof b === "number") return a - b;
106
+ return undefined;
107
+ }
108
+ if (fn === "*" && xs.length === 2) {
109
+ const [a, b] = xs as [number, number];
110
+ if (typeof a === "number" && typeof b === "number") return a * b;
111
+ return undefined;
112
+ }
113
+ if (fn === "neg" && xs.length === 1) {
114
+ const a = xs[0];
115
+ if (typeof a === "number") return -a;
116
+ return undefined;
117
+ }
118
+ return undefined;
119
+ }
@@ -5,6 +5,7 @@ export type Environment = {
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>;
@@ -46,6 +47,10 @@ export function createEnvironment(
46
47
  return createEnvironment(env, childMap);
47
48
  },
48
49
 
50
+ fork() {
51
+ return createEnvironment(env);
52
+ },
53
+
49
54
  has(name) {
50
55
  return store.has(name) || (parent?.has(name) ?? false);
51
56
  },
package/src/index.ts CHANGED
@@ -1,22 +1,73 @@
1
+ /**
2
+ * @nudojs/core — 唯一类型系统。
3
+ *
4
+ * 内涵(algebra):Abs = shape × term × pred × conf,类型即计算。
5
+ * 外延(TypeValue):评估 IR——环境绑定、dts/lsp/序列化消费的投影格式,
6
+ * 不是平行类型系统。Abs ⇄ TypeValue 经 bridge 有损投影。
7
+ */
8
+
9
+ // --- 评估 IR(TypeValue)---
1
10
  export {
2
11
  type TypeValue,
3
12
  type LiteralValue,
13
+ type Refinement,
14
+ type FunctionSignature,
15
+ type SigImpl,
4
16
  T,
5
17
  typeValueEquals,
6
18
  simplifyUnion,
7
19
  widenLiteral,
20
+ collapseLiteralUnion,
8
21
  isSubtypeOf,
9
22
  typeValueToString,
10
23
  narrowType,
11
24
  subtractType,
12
25
  getPrimitiveTypeOf,
26
+ getRefinedBase,
13
27
  deepCloneTypeValue,
14
28
  mergeObjectProperties,
29
+ isFnSig,
30
+ getFnSig,
15
31
  } from "./type-value.ts";
16
32
 
17
- export { Ops, applyBinaryOp } from "./ops.ts";
33
+ /** 外延二元/一元运算:代数未覆盖的语言表面(/ % === typeof 等) */
34
+ export { Ops, applyBinaryOp, dispatchBinaryOp, dispatchMethod, dispatchProperty } from "./ops.ts";
18
35
 
19
36
  export {
20
37
  type Environment,
21
38
  createEnvironment,
22
39
  } from "./environment.ts";
40
+
41
+ export {
42
+ createTemplate,
43
+ isTemplate,
44
+ getTemplateParts,
45
+ concatTemplates,
46
+ getKnownPrefix,
47
+ getKnownSuffix,
48
+ } from "./refinements/template.ts";
49
+
50
+ export {
51
+ createRange,
52
+ isRange,
53
+ getRangeMeta,
54
+ type RangeMeta,
55
+ } from "./refinements/range.ts";
56
+
57
+ export {
58
+ type MockHelper,
59
+ stub,
60
+ spy,
61
+ mock,
62
+ mockHelperToTypeValue,
63
+ } from "./mock-helpers.ts";
64
+
65
+ export { stripTypes } from "./strip-types.ts";
66
+ export {
67
+ parseSource,
68
+ resetParseSourceCache,
69
+ getParseSourceCacheSize,
70
+ } from "./algebra/parse-source.ts";
71
+
72
+ // --- 内涵:类型即计算 ---
73
+ export * from "./algebra/index.ts";