@nudojs/core 0.2.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.
package/src/type-value.ts DELETED
@@ -1,372 +0,0 @@
1
- import type { Node } from "@babel/types";
2
- import type { Environment } from "./environment.ts";
3
-
4
- // --- TypeValue discriminated union ---
5
-
6
- export type LiteralValue = string | number | boolean | null | undefined;
7
-
8
- export type Refinement = {
9
- name: string;
10
- meta: Record<string, unknown>;
11
- check?: (value: unknown) => boolean;
12
- ops?: Record<string, (self: TypeValue, other: TypeValue) => TypeValue | undefined>;
13
- methods?: Record<string, (self: TypeValue, args: TypeValue[]) => TypeValue | undefined>;
14
- properties?: Record<string, (self: TypeValue) => TypeValue | undefined>;
15
- };
16
-
17
- export type TypeValue =
18
- | { kind: "literal"; value: LiteralValue }
19
- | {
20
- kind: "primitive";
21
- type: "number" | "string" | "boolean" | "bigint" | "symbol";
22
- }
23
- | { kind: "refined"; base: TypeValue; refinement: Refinement }
24
- | { kind: "object"; properties: Record<string, TypeValue>; id: symbol }
25
- | { kind: "array"; element: TypeValue }
26
- | { kind: "tuple"; elements: TypeValue[] }
27
- | {
28
- kind: "function";
29
- params: string[];
30
- body: Node;
31
- closure: Environment;
32
- }
33
- | { kind: "promise"; value: TypeValue }
34
- | { kind: "instance"; className: string; properties: Record<string, TypeValue> }
35
- | { kind: "union"; members: TypeValue[] }
36
- | { kind: "never" }
37
- | { kind: "unknown" };
38
-
39
- // --- T: static factory ---
40
-
41
- function createUnion(...members: TypeValue[]): TypeValue {
42
- return simplifyUnion(members);
43
- }
44
-
45
- export const T = {
46
- literal: (value: LiteralValue): TypeValue => ({ kind: "literal", value }),
47
- number: { kind: "primitive", type: "number" } as TypeValue,
48
- string: { kind: "primitive", type: "string" } as TypeValue,
49
- boolean: { kind: "primitive", type: "boolean" } as TypeValue,
50
- bigint: { kind: "primitive", type: "bigint" } as TypeValue,
51
- symbol: { kind: "primitive", type: "symbol" } as TypeValue,
52
- null: { kind: "literal", value: null } as TypeValue,
53
- undefined: { kind: "literal", value: undefined } as TypeValue,
54
- unknown: { kind: "unknown" } as TypeValue,
55
- never: { kind: "never" } as TypeValue,
56
-
57
- object: (properties: Record<string, TypeValue>): TypeValue => ({
58
- kind: "object",
59
- properties,
60
- id: Symbol("object"),
61
- }),
62
- array: (element: TypeValue): TypeValue => ({ kind: "array", element }),
63
- tuple: (elements: TypeValue[]): TypeValue => ({ kind: "tuple", elements }),
64
- promise: (value: TypeValue): TypeValue => ({ kind: "promise", value }),
65
- instanceOf: (className: string, properties: Record<string, TypeValue> = {}): TypeValue => ({
66
- kind: "instance",
67
- className,
68
- properties,
69
- }),
70
- union: createUnion,
71
- fn: (
72
- params: string[],
73
- body: Node,
74
- closure: Environment,
75
- ): TypeValue => ({
76
- kind: "function",
77
- params,
78
- body,
79
- closure,
80
- }),
81
- refine: (base: TypeValue, refinement: Refinement): TypeValue => ({
82
- kind: "refined",
83
- base,
84
- refinement,
85
- }),
86
- } as const;
87
-
88
- // --- Helpers ---
89
-
90
- export function typeValueEquals(a: TypeValue, b: TypeValue): boolean {
91
- if (a.kind !== b.kind) return false;
92
- if (a.kind === "literal" && b.kind === "literal") return a.value === b.value;
93
- if (a.kind === "primitive" && b.kind === "primitive") return a.type === b.type;
94
- if (a.kind === "never" && b.kind === "never") return true;
95
- if (a.kind === "unknown" && b.kind === "unknown") return true;
96
- if (a.kind === "refined" && b.kind === "refined") {
97
- return a.refinement.name === b.refinement.name && typeValueEquals(a.base, b.base);
98
- }
99
- if (a.kind === "promise" && b.kind === "promise") {
100
- return typeValueEquals(a.value, b.value);
101
- }
102
- if (a.kind === "instance" && b.kind === "instance") {
103
- return a.className === b.className;
104
- }
105
- if (a.kind === "union" && b.kind === "union") {
106
- return (
107
- a.members.length === b.members.length &&
108
- a.members.every((m, i) => typeValueEquals(m, b.members[i]))
109
- );
110
- }
111
- return a === b;
112
- }
113
-
114
- export function simplifyUnion(members: TypeValue[]): TypeValue {
115
- const flat: TypeValue[] = [];
116
- for (const m of members) {
117
- if (m.kind === "never") continue;
118
- if (m.kind === "union") {
119
- flat.push(...m.members);
120
- } else {
121
- flat.push(m);
122
- }
123
- }
124
-
125
- const deduped: TypeValue[] = [];
126
- for (const m of flat) {
127
- if (!deduped.some((d) => typeValueEquals(d, m))) {
128
- deduped.push(m);
129
- }
130
- }
131
-
132
- if (deduped.length === 0) return T.never;
133
- if (deduped.length === 1) return deduped[0];
134
- if (deduped.some((m) => m.kind === "unknown")) return T.unknown;
135
- return { kind: "union", members: deduped };
136
- }
137
-
138
- export function widenLiteral(tv: TypeValue): TypeValue {
139
- if (tv.kind !== "literal") return tv;
140
- const v = tv.value;
141
- if (typeof v === "number") return T.number;
142
- if (typeof v === "string") return T.string;
143
- if (typeof v === "boolean") return T.boolean;
144
- if (v === null) return T.null;
145
- if (v === undefined) return T.undefined;
146
- return T.unknown;
147
- }
148
-
149
- export function isSubtypeOf(a: TypeValue, b: TypeValue): boolean {
150
- if (b.kind === "unknown") return true;
151
- if (a.kind === "never") return true;
152
- if (typeValueEquals(a, b)) return true;
153
-
154
- if (a.kind === "literal" && b.kind === "primitive") {
155
- const v = a.value;
156
- if (b.type === "number" && typeof v === "number") return true;
157
- if (b.type === "string" && typeof v === "string") return true;
158
- if (b.type === "boolean" && typeof v === "boolean") return true;
159
- return false;
160
- }
161
-
162
- if (a.kind === "literal" && b.kind === "refined") {
163
- if (!isSubtypeOf(a, b.base)) return false;
164
- return b.refinement.check ? b.refinement.check(a.value) : false;
165
- }
166
-
167
- if (a.kind === "refined") {
168
- if (b.kind === "refined" && a.refinement.name === b.refinement.name) {
169
- return isSubtypeOf(a.base, b.base);
170
- }
171
- return isSubtypeOf(a.base, b);
172
- }
173
-
174
- if (a.kind === "object" && b.kind === "object") {
175
- return Object.entries(b.properties).every(
176
- ([k, bv]) => k in a.properties && isSubtypeOf(a.properties[k], bv),
177
- );
178
- }
179
-
180
- if (a.kind === "array" && b.kind === "array") {
181
- return isSubtypeOf(a.element, b.element);
182
- }
183
-
184
- if (a.kind === "tuple" && b.kind === "tuple") {
185
- return (
186
- a.elements.length === b.elements.length &&
187
- a.elements.every((el, i) => isSubtypeOf(el, b.elements[i]))
188
- );
189
- }
190
-
191
- if (a.kind === "tuple" && b.kind === "array") {
192
- return a.elements.every((el) => isSubtypeOf(el, b.element));
193
- }
194
-
195
- if (a.kind === "promise" && b.kind === "promise") {
196
- return isSubtypeOf(a.value, b.value);
197
- }
198
-
199
- if (a.kind === "instance" && b.kind === "instance") {
200
- return a.className === b.className || isErrorSubclass(a.className, b.className);
201
- }
202
-
203
- if (a.kind === "union") {
204
- return a.members.every((m) => isSubtypeOf(m, b));
205
- }
206
-
207
- if (b.kind === "union") {
208
- return b.members.some((m) => isSubtypeOf(a, m));
209
- }
210
-
211
- return false;
212
- }
213
-
214
- const errorHierarchy: Record<string, string> = {
215
- TypeError: "Error",
216
- SyntaxError: "Error",
217
- RangeError: "Error",
218
- ReferenceError: "Error",
219
- URIError: "Error",
220
- EvalError: "Error",
221
- };
222
-
223
- function isErrorSubclass(child: string, parent: string): boolean {
224
- if (child === parent) return true;
225
- const sup = errorHierarchy[child];
226
- return sup ? isErrorSubclass(sup, parent) : false;
227
- }
228
-
229
- export function deepCloneTypeValue(tv: TypeValue, idMap?: Map<symbol, symbol>): TypeValue {
230
- const map = idMap ?? new Map<symbol, symbol>();
231
- if (tv.kind === "object") {
232
- let newId = map.get(tv.id);
233
- if (!newId) {
234
- newId = Symbol("object");
235
- map.set(tv.id, newId);
236
- }
237
- const newProps: Record<string, TypeValue> = {};
238
- for (const [k, v] of Object.entries(tv.properties)) {
239
- newProps[k] = deepCloneTypeValue(v, map);
240
- }
241
- return { kind: "object", properties: newProps, id: newId };
242
- }
243
- if (tv.kind === "array") {
244
- return { kind: "array", element: deepCloneTypeValue(tv.element, map) };
245
- }
246
- if (tv.kind === "tuple") {
247
- return { kind: "tuple", elements: tv.elements.map((e) => deepCloneTypeValue(e, map)) };
248
- }
249
- if (tv.kind === "promise") {
250
- return { kind: "promise", value: deepCloneTypeValue(tv.value, map) };
251
- }
252
- if (tv.kind === "instance") {
253
- const newProps: Record<string, TypeValue> = {};
254
- for (const [k, v] of Object.entries(tv.properties)) {
255
- newProps[k] = deepCloneTypeValue(v, map);
256
- }
257
- return { kind: "instance", className: tv.className, properties: newProps };
258
- }
259
- if (tv.kind === "refined") {
260
- return { kind: "refined", base: deepCloneTypeValue(tv.base, map), refinement: tv.refinement };
261
- }
262
- if (tv.kind === "union") {
263
- return simplifyUnion(tv.members.map((m) => deepCloneTypeValue(m, map)));
264
- }
265
- return tv;
266
- }
267
-
268
- export function mergeObjectProperties(
269
- a: TypeValue & { kind: "object" },
270
- b: TypeValue & { kind: "object" },
271
- ): TypeValue {
272
- const allKeys = new Set([...Object.keys(a.properties), ...Object.keys(b.properties)]);
273
- const merged: Record<string, TypeValue> = {};
274
- for (const k of allKeys) {
275
- const av = a.properties[k];
276
- const bv = b.properties[k];
277
- if (av && bv) {
278
- merged[k] = simplifyUnion([av, bv]);
279
- } else {
280
- merged[k] = av ?? bv;
281
- }
282
- }
283
- return { kind: "object", properties: merged, id: a.id };
284
- }
285
-
286
- export function typeValueToString(tv: TypeValue): string {
287
- switch (tv.kind) {
288
- case "literal": {
289
- const v = tv.value;
290
- if (v === null) return "null";
291
- if (v === undefined) return "undefined";
292
- if (typeof v === "string") return JSON.stringify(v);
293
- return String(v);
294
- }
295
- case "primitive":
296
- return tv.type;
297
- case "refined":
298
- return tv.refinement.name;
299
- case "object": {
300
- const entries = Object.entries(tv.properties);
301
- if (entries.length === 0) return "{}";
302
- const inner = entries
303
- .map(([k, v]) => `${k}: ${typeValueToString(v)}`)
304
- .join(", ");
305
- return `{ ${inner} }`;
306
- }
307
- case "array":
308
- return `${typeValueToString(tv.element)}[]`;
309
- case "tuple": {
310
- const inner = tv.elements.map(typeValueToString).join(", ");
311
- return `[${inner}]`;
312
- }
313
- case "function": {
314
- const params = tv.params.join(", ");
315
- return `(${params}) => ...`;
316
- }
317
- case "promise":
318
- return `Promise<${typeValueToString(tv.value)}>`;
319
- case "instance": {
320
- const entries = Object.entries(tv.properties);
321
- if (entries.length === 0) return tv.className;
322
- const inner = entries
323
- .map(([k, v]) => `${k}: ${typeValueToString(v)}`)
324
- .join(", ");
325
- return `${tv.className} { ${inner} }`;
326
- }
327
- case "union": {
328
- return tv.members.map(typeValueToString).join(" | ");
329
- }
330
- case "never":
331
- return "never";
332
- case "unknown":
333
- return "unknown";
334
- }
335
- }
336
-
337
- export function narrowType(
338
- tv: TypeValue,
339
- predicate: (member: TypeValue) => boolean,
340
- ): TypeValue {
341
- if (tv.kind === "union") {
342
- return simplifyUnion(tv.members.filter(predicate));
343
- }
344
- return predicate(tv) ? tv : T.never;
345
- }
346
-
347
- export function subtractType(
348
- tv: TypeValue,
349
- predicate: (member: TypeValue) => boolean,
350
- ): TypeValue {
351
- return narrowType(tv, (m) => !predicate(m));
352
- }
353
-
354
- export function getPrimitiveTypeOf(tv: TypeValue): string | undefined {
355
- if (tv.kind === "literal") {
356
- const v = tv.value;
357
- if (v === null) return "object";
358
- return typeof v;
359
- }
360
- if (tv.kind === "primitive") return tv.type;
361
- if (tv.kind === "refined") return getPrimitiveTypeOf(tv.base);
362
- if (tv.kind === "object") return "object";
363
- if (tv.kind === "array" || tv.kind === "tuple") return "object";
364
- if (tv.kind === "function") return "function";
365
- if (tv.kind === "promise") return "object";
366
- if (tv.kind === "instance") return "object";
367
- return undefined;
368
- }
369
-
370
- export function getRefinedBase(tv: TypeValue): TypeValue {
371
- return tv.kind === "refined" ? getRefinedBase(tv.base) : tv;
372
- }
package/tsconfig.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "outDir": "dist",
5
- "rootDir": "src"
6
- },
7
- "include": ["src"]
8
- }