deep6 1.1.3 → 1.2.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 (48) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +44 -38
  3. package/llms-full.txt +371 -0
  4. package/llms.txt +154 -0
  5. package/package.json +31 -109
  6. package/src/env.d.ts +174 -0
  7. package/src/env.js +4 -4
  8. package/src/index.d.ts +86 -0
  9. package/src/index.js +10 -7
  10. package/src/traverse/assemble.d.ts +59 -0
  11. package/src/traverse/assemble.js +4 -3
  12. package/src/traverse/clone.d.ts +57 -0
  13. package/src/traverse/clone.js +4 -2
  14. package/src/traverse/deref.d.ts +59 -0
  15. package/src/traverse/deref.js +3 -2
  16. package/src/traverse/preprocess.d.ts +65 -0
  17. package/src/traverse/preprocess.js +2 -1
  18. package/src/traverse/walk.d.ts +219 -0
  19. package/src/traverse/walk.js +9 -4
  20. package/src/unifiers/matchCondition.d.ts +45 -0
  21. package/src/unifiers/matchCondition.js +1 -0
  22. package/src/unifiers/matchInstanceOf.d.ts +37 -0
  23. package/src/unifiers/matchInstanceOf.js +1 -0
  24. package/src/unifiers/matchString.d.ts +56 -0
  25. package/src/unifiers/matchString.js +1 -0
  26. package/src/unifiers/matchTypeOf.d.ts +37 -0
  27. package/src/unifiers/matchTypeOf.js +1 -0
  28. package/src/unifiers/ref.d.ts +52 -0
  29. package/src/unifiers/ref.js +1 -0
  30. package/src/unify.d.ts +95 -0
  31. package/src/unify.js +130 -66
  32. package/src/utils/replaceVars.d.ts +25 -0
  33. package/src/utils/replaceVars.js +23 -19
  34. package/cjs/env.js +0 -227
  35. package/cjs/index.js +0 -57
  36. package/cjs/package.json +0 -1
  37. package/cjs/traverse/assemble.js +0 -145
  38. package/cjs/traverse/clone.js +0 -94
  39. package/cjs/traverse/deref.js +0 -102
  40. package/cjs/traverse/preprocess.js +0 -96
  41. package/cjs/traverse/walk.js +0 -330
  42. package/cjs/unifiers/matchCondition.js +0 -25
  43. package/cjs/unifiers/matchInstanceOf.js +0 -25
  44. package/cjs/unifiers/matchString.js +0 -49
  45. package/cjs/unifiers/matchTypeOf.js +0 -25
  46. package/cjs/unifiers/ref.js +0 -30
  47. package/cjs/unify.js +0 -549
  48. package/cjs/utils/replaceVars.js +0 -37
package/src/unify.d.ts ADDED
@@ -0,0 +1,95 @@
1
+ // Type definitions for deep6 unification
2
+ // Generated from src/unify.js
3
+
4
+ import {Env, Unifier, Variable} from './env.js';
5
+
6
+ /**
7
+ * Options for unification
8
+ */
9
+ export interface UnifyOptions {
10
+ /** Handle circular references (default: false) */
11
+ circular?: boolean;
12
+ /** Include symbol properties (default: false) */
13
+ symbols?: boolean;
14
+ /** Use loose equality for primitives (default: false) */
15
+ loose?: boolean;
16
+ /** Ignore function properties (default: false) */
17
+ ignoreFunctions?: boolean;
18
+ /** Distinguish +0 from -0 (default: false) */
19
+ signedZero?: boolean;
20
+ /** Allow extra keys on target objects (default: false) */
21
+ openObjects?: boolean;
22
+ /** Allow extra elements in target arrays (default: false) */
23
+ openArrays?: boolean;
24
+ /** Allow extra entries in target Maps (default: false) */
25
+ openMaps?: boolean;
26
+ /** Allow extra entries in target Sets (default: false) */
27
+ openSets?: boolean;
28
+ }
29
+
30
+ /**
31
+ * Core unification algorithm
32
+ *
33
+ * Attempts to unify two values, optionally binding variables.
34
+ * Returns an Env with bindings on success, or null on failure.
35
+ *
36
+ * @param l - Left value
37
+ * @param r - Right value
38
+ * @param env - Existing environment, options object, or null
39
+ * @param options - Unification options (when env is provided separately)
40
+ * @returns Environment with bindings, or null on failure
41
+ */
42
+ export declare const unify: (l: unknown, r: unknown, env?: Env | UnifyOptions | null, options?: UnifyOptions) => Env | null;
43
+
44
+ /**
45
+ * Flat array of type-specific unifier pairs: [Constructor, handler, Constructor, handler, ...]
46
+ *
47
+ * Use `registry.push(Type, handler)` to register a custom type handler.
48
+ * Handler signature: `(l, r, ls, rs, env) => boolean`
49
+ */
50
+ export declare const registry: unknown[];
51
+
52
+ /**
53
+ * Flat array of filter pairs: [predicate, handler, predicate, handler, ...]
54
+ *
55
+ * Use `filters.push(predicate, handler)` to register a custom filter.
56
+ */
57
+ export declare const filters: unknown[];
58
+
59
+ /**
60
+ * Wraps a value for open matching (target may have extra properties)
61
+ * @param o - Value to wrap
62
+ * @returns Open-wrapped value
63
+ */
64
+ export declare const open: <T>(o: T) => T;
65
+
66
+ /**
67
+ * Wraps a value for soft matching (bidirectional open, updates both sides)
68
+ * @param o - Value to wrap
69
+ * @returns Soft-wrapped value
70
+ */
71
+ export declare const soft: <T>(o: T) => T;
72
+
73
+ /**
74
+ * Checks if a value is open-wrapped
75
+ * @param o - Value to check
76
+ */
77
+ export declare const isOpen: (o: unknown) => boolean;
78
+
79
+ /**
80
+ * Checks if a value is soft-wrapped
81
+ * @param o - Value to check
82
+ */
83
+ export declare const isSoft: (o: unknown) => boolean;
84
+
85
+ /**
86
+ * Checks if a value is wrapped (open or soft)
87
+ * @param o - Value to check
88
+ */
89
+ export declare const isWrapped: (o: unknown) => boolean;
90
+
91
+ // Re-exports from env.js (value exports, usable as constructors)
92
+ export {Env, Unifier, Variable} from './env.js';
93
+ export {_, any, isUnifier, isVariable, variable} from './env.js';
94
+
95
+ export default unify;
package/src/unify.js CHANGED
@@ -24,18 +24,17 @@ class Wrap extends Unifier {
24
24
  value = isWrapped ? val.object : val;
25
25
  if (!value || typeof value != 'object' || Array.isArray(this.object) !== Array.isArray(value)) return false;
26
26
  if (Array.isArray(this.object)) {
27
- if (!Array.isArray(value)) return false;
28
27
  return isWrapped
29
28
  ? unifyObjects(this.object, this.type, this, val.object, val.type, val, ls, rs, env)
30
29
  : unifyObjects(this.object, this.type, this, val, env.openArrays ? 'open' : 'exact', null, ls, rs, env);
31
30
  }
32
- if (typeof Map == 'function' && this.object instanceof Map) {
31
+ if (this.object instanceof Map) {
33
32
  if (!(value instanceof Map)) return false;
34
33
  return isWrapped
35
34
  ? unifyMaps(this.object, this.type, this, val.object, val.type, val, ls, rs, env)
36
35
  : unifyMaps(this.object, this.type, this, val, env.openMaps ? 'open' : 'exact', null, ls, rs, env);
37
36
  }
38
- if (typeof Set == 'function' && this.object instanceof Set) {
37
+ if (this.object instanceof Set) {
39
38
  if (!(value instanceof Set)) return false;
40
39
  return isWrapped
41
40
  ? unifySets(this.object, this.type, this, val.object, val.type, val, ls, rs, env)
@@ -61,11 +60,12 @@ const registry = [
61
60
  Date,
62
61
  (l, r) => l instanceof Date && r instanceof Date && l.getTime() == r.getTime(),
63
62
  RegExp,
64
- (l, r) =>
65
- l instanceof RegExp && r instanceof RegExp && l.source == r.source && l.global == r.global && l.multiline == r.multiline && l.ignoreCase == r.ignoreCase
63
+ (l, r) => l instanceof RegExp && r instanceof RegExp && l.source == r.source && l.flags == r.flags
66
64
  ],
67
65
  filters = [];
68
66
 
67
+ typeof URL == 'function' && registry.push(URL, (l, r) => l instanceof URL && r instanceof URL && l.href == r.href);
68
+
69
69
  // possible well-known constructors
70
70
 
71
71
  const unifyTypedArrays = Type => (l, r, ls, rs, env) => {
@@ -99,9 +99,10 @@ const unifyDataView = (l, r, ls, rs, env) => {
99
99
  };
100
100
  typeof DataView == 'function' && registry.push(DataView, unifyDataView);
101
101
 
102
+ const unifyUint8Array = unifyTypedArrays(Uint8Array);
102
103
  const unifyArrayBuffer = (l, r, ls, rs, env) => {
103
104
  if (!(l instanceof ArrayBuffer) || !(r instanceof ArrayBuffer) || l.byteLength != r.byteLength) return false;
104
- return unifyTypedArrays(Uint8Array)(new Uint8Array(l), new Uint8Array(r), ls, rs, env);
105
+ return unifyUint8Array(new Uint8Array(l), new Uint8Array(r), ls, rs, env);
105
106
  };
106
107
  typeof ArrayBuffer == 'function' && typeof Uint8Array == 'function' && registry.push(ArrayBuffer, unifyArrayBuffer);
107
108
 
@@ -161,22 +162,28 @@ const mapOps = {
161
162
  }
162
163
  }
163
164
  };
164
- mapOps.exact.exact.compare = mapOps.exact.open.compare = mapOps.exact.soft.compare = (l, r, ls, rs) => {
165
- for (const [key, value] of r) {
166
- if (!l.has(key)) return false;
167
- ls.push(l.get(key));
168
- rs.push(value);
169
- }
170
- return true;
171
- };
172
- mapOps.open.open.compare = mapOps.open.soft.compare = mapOps.soft.soft.compare = (l, r, ls, rs) => {
173
- for (const [key, value] of r) {
174
- if (!l.has(key)) continue;
175
- ls.push(l.get(key));
176
- rs.push(value);
177
- }
178
- return true;
179
- };
165
+ mapOps.exact.exact.compare =
166
+ mapOps.exact.open.compare =
167
+ mapOps.exact.soft.compare =
168
+ (l, r, ls, rs) => {
169
+ for (const [key, value] of r) {
170
+ if (!l.has(key)) return false;
171
+ ls.push(l.get(key));
172
+ rs.push(value);
173
+ }
174
+ return true;
175
+ };
176
+ mapOps.open.open.compare =
177
+ mapOps.open.soft.compare =
178
+ mapOps.soft.soft.compare =
179
+ (l, r, ls, rs) => {
180
+ for (const [key, value] of r) {
181
+ if (!l.has(key)) continue;
182
+ ls.push(l.get(key));
183
+ rs.push(value);
184
+ }
185
+ return true;
186
+ };
180
187
  mapOps.exact.soft.update = mapOps.open.soft.update = function () {
181
188
  for (const [key, value] of this.l) {
182
189
  !this.r.has(key) && this.r.set(key, value);
@@ -186,7 +193,19 @@ mapOps.exact.soft.update = mapOps.open.soft.update = function () {
186
193
  const unifyMaps = (l, lt, lm, r, rt, rm, ls, rs, env) => {
187
194
  const ols = ls;
188
195
  if (lt > rt) {
189
- [l, lt, lm, ls, r, rt, rm, rs] = [r, rt, rm, rs, l, lt, lm, ls];
196
+ let tmp;
197
+ tmp = l;
198
+ l = r;
199
+ r = tmp;
200
+ tmp = lt;
201
+ lt = rt;
202
+ rt = tmp;
203
+ tmp = lm;
204
+ lm = rm;
205
+ rm = tmp;
206
+ tmp = ls;
207
+ ls = rs;
208
+ rs = tmp;
190
209
  }
191
210
  const ops = mapOps[lt][rt];
192
211
  if (ops.precheck && !ops.precheck(l, r)) return false;
@@ -231,8 +250,13 @@ const setOps = {
231
250
  }
232
251
  }
233
252
  };
234
- setOps.exact.exact.compare = setOps.exact.open.compare = setOps.exact.soft.compare = setOps.open.open.compare = setOps.open.soft.compare = setOps.soft.soft.compare = () =>
235
- true;
253
+ setOps.exact.exact.compare =
254
+ setOps.exact.open.compare =
255
+ setOps.exact.soft.compare =
256
+ setOps.open.open.compare =
257
+ setOps.open.soft.compare =
258
+ setOps.soft.soft.compare =
259
+ () => true;
236
260
  setOps.exact.soft.update = setOps.open.soft.update = function () {
237
261
  for (const key of this.l) {
238
262
  this.r.add(key);
@@ -242,7 +266,19 @@ setOps.exact.soft.update = setOps.open.soft.update = function () {
242
266
  const unifySets = (l, lt, lm, r, rt, rm, ls, rs, env) => {
243
267
  const ols = ls;
244
268
  if (lt > rt) {
245
- [l, lt, lm, ls, r, rt, rm, rs] = [r, rt, rm, rs, l, lt, lm, ls];
269
+ let tmp;
270
+ tmp = l;
271
+ l = r;
272
+ r = tmp;
273
+ tmp = lt;
274
+ lt = rt;
275
+ rt = tmp;
276
+ tmp = lm;
277
+ lm = rm;
278
+ rm = tmp;
279
+ tmp = ls;
280
+ ls = rs;
281
+ rs = tmp;
246
282
  }
247
283
  const ops = setOps[lt][rt];
248
284
  if (ops.precheck && !ops.precheck(l, r)) return false;
@@ -267,7 +303,10 @@ const objectOps = {
267
303
  rKeys = rKeys.concat(Object.getOwnPropertySymbols(r));
268
304
  }
269
305
  if (lKeys.length != rKeys.length) return false;
270
- return lKeys.every(k => hasOwnProperty.call(r, k));
306
+ for (let i = 0; i < lKeys.length; ++i) {
307
+ if (!hasOwnProperty.call(r, lKeys[i])) return false;
308
+ }
309
+ return true;
271
310
  }
272
311
  },
273
312
  open: {},
@@ -298,29 +337,34 @@ const objectOps = {
298
337
  }
299
338
  }
300
339
  };
301
- objectOps.exact.exact.compare = objectOps.exact.open.compare = objectOps.exact.soft.compare = (l, r, ls, rs, env) => {
302
- let keys = Object.keys(r);
303
- if (env.symbols) keys = keys.concat(Object.getOwnPropertySymbols(r));
304
- return keys.every(k => {
305
- if (hasOwnProperty.call(l, k)) {
306
- ls.push(l[k]);
307
- rs.push(r[k]);
340
+ objectOps.exact.exact.compare =
341
+ objectOps.exact.open.compare =
342
+ objectOps.exact.soft.compare =
343
+ (l, r, ls, rs, env) => {
344
+ let keys = Object.keys(r);
345
+ if (env.symbols) keys = keys.concat(Object.getOwnPropertySymbols(r));
346
+ for (let i = 0; i < keys.length; ++i) {
347
+ const k = keys[i];
348
+ if (!hasOwnProperty.call(l, k)) return false;
349
+ ls.push(l[k]);
350
+ rs.push(r[k]);
351
+ }
308
352
  return true;
309
- }
310
- return false;
311
- });
312
- };
313
- objectOps.open.open.compare = objectOps.open.soft.compare = objectOps.soft.soft.compare = (l, r, ls, rs, env) => {
314
- let keys = Object.keys(r);
315
- if (env.symbols) keys = keys.concat(Object.getOwnPropertySymbols(r));
316
- for (const k of keys) {
317
- if (hasOwnProperty.call(l, k)) {
318
- ls.push(l[k]);
319
- rs.push(r[k]);
320
- }
321
- }
322
- return true;
323
- };
353
+ };
354
+ objectOps.open.open.compare =
355
+ objectOps.open.soft.compare =
356
+ objectOps.soft.soft.compare =
357
+ (l, r, ls, rs, env) => {
358
+ let keys = Object.keys(r);
359
+ if (env.symbols) keys = keys.concat(Object.getOwnPropertySymbols(r));
360
+ for (const k of keys) {
361
+ if (hasOwnProperty.call(l, k)) {
362
+ ls.push(l[k]);
363
+ rs.push(r[k]);
364
+ }
365
+ }
366
+ return true;
367
+ };
324
368
  objectOps.exact.soft.update = objectOps.open.soft.update = function () {
325
369
  let keys = Object.keys(this.l);
326
370
  if (this.e.symbols) keys = keys.concat(Object.getOwnPropertySymbols(this.l));
@@ -332,7 +376,19 @@ objectOps.exact.soft.update = objectOps.open.soft.update = function () {
332
376
  const unifyObjects = (l, lt, lm, r, rt, rm, ls, rs, env) => {
333
377
  const ols = ls;
334
378
  if (lt > rt) {
335
- [l, lt, lm, ls, r, rt, rm, rs] = [r, rt, rm, rs, l, lt, lm, ls];
379
+ let tmp;
380
+ tmp = l;
381
+ l = r;
382
+ r = tmp;
383
+ tmp = lt;
384
+ lt = rt;
385
+ rt = tmp;
386
+ tmp = lm;
387
+ lm = rm;
388
+ rm = tmp;
389
+ tmp = ls;
390
+ ls = rs;
391
+ rs = tmp;
336
392
  }
337
393
  const ops = objectOps[lt][rt];
338
394
  if (ops.precheck && !ops.precheck(l, r, env)) return false;
@@ -354,36 +410,39 @@ const unify = (l, r, env, options) => {
354
410
  env = Object.assign(env, options);
355
411
  // options: openObjects, openArrays, openMaps, openSets, circular, loose, ignoreFunctions, signedZero, symbols.
356
412
  const ls = [l],
357
- rs = [r],
358
- lSeen = new Map(),
413
+ rs = [r];
414
+ let lSeen, rSeen;
415
+ if (env.circular) {
416
+ lSeen = new Map();
359
417
  rSeen = new Map();
418
+ }
360
419
  main: while (ls.length) {
361
420
  // perform a command, or extract a pair
362
421
  l = ls.pop();
363
- if (l instanceof Command) {
422
+ if (typeof l == 'object' && l instanceof Command) {
364
423
  l.f();
365
424
  continue;
366
425
  }
367
426
  r = rs.pop();
368
427
  // direct equality
369
428
  if (l === r) {
370
- if (env.circular && l && typeof l == 'object' && lSeen.has(l) ^ rSeen.has(r)) return null;
429
+ if (lSeen && l && typeof l == 'object' && lSeen.has(l) ^ rSeen.has(r)) return null;
371
430
  if (env.signedZero && l === 0 && 1 / l !== 1 / r) return null;
372
431
  continue;
373
432
  }
374
433
  // anyvar
375
434
  if (l === _ || r === _) continue;
376
435
  // process variables (variables have priority)
377
- if (l instanceof Variable) {
436
+ if (typeof l == 'object' && l instanceof Variable) {
378
437
  if (l.unify(r, ls, rs, env)) continue;
379
438
  return null;
380
439
  }
381
- if (r instanceof Variable) {
440
+ if (typeof r == 'object' && r instanceof Variable) {
382
441
  if (r.unify(l, ls, rs, env)) continue;
383
442
  return null;
384
443
  }
385
444
  // process circular dependencies
386
- if (env.circular) {
445
+ if (lSeen) {
387
446
  const lIndex = lSeen.get(l);
388
447
  if (typeof lIndex == 'number') {
389
448
  if (lIndex === rSeen.get(r)) continue main;
@@ -396,11 +455,11 @@ const unify = (l, r, env, options) => {
396
455
  r && typeof r == 'object' && rSeen.set(r, rSeen.size);
397
456
  }
398
457
  // invoke custom unifiers
399
- if (l instanceof Unifier) {
458
+ if (typeof l == 'object' && l instanceof Unifier) {
400
459
  if (l.unify(r, ls, rs, env)) continue;
401
460
  return null;
402
461
  }
403
- if (r instanceof Unifier) {
462
+ if (typeof r == 'object' && r instanceof Unifier) {
404
463
  if (r.unify(l, ls, rs, env)) continue;
405
464
  return null;
406
465
  }
@@ -414,12 +473,17 @@ const unify = (l, r, env, options) => {
414
473
  if (typeof l == 'number' && isNaN(l) && isNaN(r)) continue;
415
474
  // cut off impossible combinations
416
475
  if (typeof l != 'object' || !l || !r) return null;
417
- // process registered constructors
418
- const registry = unify.registry;
419
- for (let i = 0; i < registry.length; i += 2) {
420
- if (l instanceof registry[i] || r instanceof registry[i]) {
421
- if (registry[i + 1](l, r, ls, rs, env)) continue main;
422
- return null;
476
+ // fast path: plain objects and arrays skip registry
477
+ const lp = Object.getPrototypeOf(l),
478
+ rp = Object.getPrototypeOf(r);
479
+ if (!((lp === Object.prototype || lp === null || lp === Array.prototype) && (rp === Object.prototype || rp === null || rp === Array.prototype))) {
480
+ // process registered constructors
481
+ const registry = unify.registry;
482
+ for (let i = 0; i < registry.length; i += 2) {
483
+ if (l instanceof registry[i] || r instanceof registry[i]) {
484
+ if (registry[i + 1](l, r, ls, rs, env)) continue main;
485
+ return null;
486
+ }
423
487
  }
424
488
  }
425
489
  // process registered filters
@@ -442,5 +506,5 @@ const unify = (l, r, env, options) => {
442
506
  unify.registry = registry;
443
507
  unify.filters = filters;
444
508
 
445
- export {_, Env, Unifier, isUnifier, Variable, variable, isVariable, _ as any, open, soft, isOpen, isSoft, isWrapped};
509
+ export {_, Env, Unifier, isUnifier, Variable, variable, isVariable, _ as any, open, soft, isOpen, isSoft, isWrapped, unify};
446
510
  export default unify;
@@ -0,0 +1,25 @@
1
+ // Type definitions for deep6 replaceVars utility
2
+ // Generated from src/utils/replaceVars.js
3
+
4
+ import type {Env, Variable} from '../env.js';
5
+
6
+ /**
7
+ * Creates a tagged template function that substitutes variables from an environment
8
+ *
9
+ * Template interpolations can be Variable instances (resolved via `.get(env)`),
10
+ * strings/numbers/symbols (looked up in `env.values`), or other values (coerced to string).
11
+ *
12
+ * @param env - Unification environment with variable bindings
13
+ * @returns A tagged template literal function
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * const x = variable('x');
18
+ * const env = unify({a: x}, {a: 42});
19
+ * const t = replaceVars(env);
20
+ * t`The answer is ${x}!`; // "The answer is 42!"
21
+ * ```
22
+ */
23
+ export declare const replaceVars: (env: Env) => (strings: TemplateStringsArray, ...vars: unknown[]) => string;
24
+
25
+ export default replaceVars;
@@ -1,24 +1,28 @@
1
1
  import {isVariable} from '../env.js';
2
2
 
3
- const replaceVars = env => (strings, ...vars) => {
4
- let buffer = strings[0];
5
- for(let i = 0; i < vars.length;) {
6
- const v = vars[i];
7
- if (isVariable(v)) {
8
- buffer += v.get(env);
9
- } else switch (typeof v) {
10
- case 'string':
11
- case 'number':
12
- case 'symbol':
13
- buffer += env.values[v];
14
- break;
15
- default:
16
- buffer += v;
17
- break;
3
+ const replaceVars =
4
+ env =>
5
+ (strings, ...vars) => {
6
+ let buffer = strings[0];
7
+ for (let i = 0; i < vars.length; ) {
8
+ const v = vars[i];
9
+ if (isVariable(v)) {
10
+ buffer += v.get(env);
11
+ } else
12
+ switch (typeof v) {
13
+ case 'string':
14
+ case 'number':
15
+ case 'symbol':
16
+ buffer += env.values[v];
17
+ break;
18
+ default:
19
+ buffer += v;
20
+ break;
21
+ }
22
+ buffer += strings[++i];
18
23
  }
19
- buffer += strings[++i];
20
- }
21
- return buffer;
22
- };
24
+ return buffer;
25
+ };
23
26
 
27
+ export {replaceVars};
24
28
  export default replaceVars;