@calcit/ternary-tree 0.0.18 → 0.0.19-a1

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/map.ts DELETED
@@ -1,1341 +0,0 @@
1
- import { TernaryTreeMap, TernaryTreeKind, TernaryTreeMapTheLeaf, TernaryTreeMapTheBranch, RefInt, Hash, hashGenerator, TernaryTreeMapHashEntry } from "./types";
2
- import { divideTernarySizes, roughIntPow, cmp, dataEqual } from "./utils";
3
-
4
- let emptyBranch: TernaryTreeMap<any, any> = null as any;
5
- let nilResult = null as any;
6
-
7
- function getMax<K, V>(tree: TernaryTreeMap<K, V>): Hash {
8
- if (tree == null) {
9
- throw new Error("Cannot find max hash of nil");
10
- }
11
- switch (tree.kind) {
12
- case TernaryTreeKind.ternaryTreeLeaf:
13
- return tree.hash;
14
- case TernaryTreeKind.ternaryTreeBranch:
15
- return tree.maxHash;
16
- default:
17
- throw new Error("Unknown");
18
- }
19
- }
20
-
21
- function getMin<K, V>(tree: TernaryTreeMap<K, V>): Hash {
22
- if (tree == null) {
23
- throw new Error("Cannot find min hash of nil");
24
- }
25
- switch (tree.kind) {
26
- case TernaryTreeKind.ternaryTreeLeaf:
27
- return tree.hash;
28
- case TernaryTreeKind.ternaryTreeBranch:
29
- return tree.minHash;
30
- default:
31
- throw new Error("Unknown");
32
- }
33
- }
34
-
35
- export function getMapDepth<K, V>(tree: TernaryTreeMap<K, V>): number {
36
- // console.log( "calling...", tree)
37
- if (tree == null) {
38
- return 0;
39
- }
40
- switch (tree.kind) {
41
- case TernaryTreeKind.ternaryTreeLeaf:
42
- return 1;
43
- case TernaryTreeKind.ternaryTreeBranch:
44
- return Math.max(getMapDepth(tree.left), getMapDepth(tree.middle), getMapDepth(tree.right)) + 1;
45
- default:
46
- throw new Error("Unknown");
47
- }
48
- }
49
-
50
- function createLeaf<K, T>(k: K, v: T): TernaryTreeMap<K, T> {
51
- let result: TernaryTreeMapTheLeaf<K, T> = {
52
- kind: TernaryTreeKind.ternaryTreeLeaf,
53
- hash: hashGenerator(k),
54
- elements: [[k, v]],
55
- };
56
- return result;
57
- }
58
-
59
- function createLeafFromHashEntry<K, T>(item: TernaryTreeMapHashEntry<K, T>): TernaryTreeMap<K, T> {
60
- let result: TernaryTreeMap<K, T> = {
61
- kind: TernaryTreeKind.ternaryTreeLeaf,
62
- hash: item.hash,
63
- elements: item.pairs,
64
- };
65
- return result;
66
- }
67
-
68
- // this proc is not exported, pick up next proc as the entry.
69
- // pairs must be sorted before passing to proc.
70
- function makeTernaryTreeMap<K, T>(size: number, offset: number, xs: /* var */ Array<TernaryTreeMapHashEntry<K, T>>): TernaryTreeMap<K, T> {
71
- switch (size) {
72
- case 0: {
73
- let result: TernaryTreeMap<K, T> = emptyBranch;
74
- return result;
75
- }
76
- case 1: {
77
- let leftPair = xs[offset];
78
- let result: TernaryTreeMap<K, T> = createLeafFromHashEntry(leftPair);
79
- return result;
80
- }
81
- case 2: {
82
- let leftPair = xs[offset];
83
- let middlePair = xs[offset + 1];
84
- let result: TernaryTreeMap<K, T> = {
85
- kind: TernaryTreeKind.ternaryTreeBranch,
86
- maxHash: middlePair.hash,
87
- minHash: leftPair.hash,
88
- left: createLeafFromHashEntry(leftPair),
89
- middle: createLeafFromHashEntry(middlePair),
90
- right: emptyBranch,
91
- depth: 1,
92
- };
93
- return result;
94
- }
95
- case 3: {
96
- let leftPair = xs[offset];
97
- let middlePair = xs[offset + 1];
98
- let rightPair = xs[offset + 2];
99
- let result: TernaryTreeMap<K, T> = {
100
- kind: TernaryTreeKind.ternaryTreeBranch,
101
- maxHash: rightPair.hash,
102
- minHash: leftPair.hash,
103
- left: createLeafFromHashEntry(leftPair),
104
- middle: createLeafFromHashEntry(middlePair),
105
- right: createLeafFromHashEntry(rightPair),
106
- depth: 1,
107
- };
108
- return result;
109
- }
110
- default: {
111
- let divided = divideTernarySizes(size);
112
-
113
- let left = makeTernaryTreeMap(divided.left, offset, xs);
114
- let middle = makeTernaryTreeMap(divided.middle, offset + divided.left, xs);
115
- let right = makeTernaryTreeMap(divided.right, offset + divided.left + divided.middle, xs);
116
-
117
- let result: TernaryTreeMap<K, T> = {
118
- kind: TernaryTreeKind.ternaryTreeBranch,
119
- maxHash: getMax(right),
120
- minHash: getMin(left),
121
- left: left,
122
- middle: middle,
123
- right: right,
124
- depth: Math.max(getMapDepth(left), getMapDepth(middle), getMapDepth(right)) + 1,
125
- };
126
- return result;
127
- }
128
- }
129
- }
130
-
131
- export function initTernaryTreeMapFromHashEntries<K, T>(xs: Array<TernaryTreeMapHashEntry<K, T>>): TernaryTreeMap<K, T> {
132
- return makeTernaryTreeMap(xs.length, 0, xs);
133
- }
134
-
135
- export function initTernaryTreeMap<K, T>(t: Map<K, T>): TernaryTreeMap<K, T> {
136
- let groupBuffers: Map<number, Array<[K, T]>> = new Map();
137
- let xs: Array<TernaryTreeMapHashEntry<K, T>> = [];
138
- for (let [k, v] of t) {
139
- let h = hashGenerator(k);
140
- if (groupBuffers.has(h)) {
141
- let branch = groupBuffers.get(h);
142
- if (branch != null) {
143
- branch.push([k, v]);
144
- } else {
145
- throw new Error("Expected referece to pairs");
146
- }
147
- } else {
148
- let pairs: [K, T][] = [[k, v]];
149
- groupBuffers.set(h, pairs);
150
- xs.push({
151
- hash: h,
152
- pairs,
153
- });
154
- }
155
- }
156
-
157
- for (let [k, v] of groupBuffers) {
158
- if (v != null) {
159
- } else {
160
- throw new Error("Expected reference to paris");
161
- }
162
- }
163
-
164
- // MUTABLE in-place sort
165
- xs.sort((a, b) => cmp(a.hash, b.hash));
166
-
167
- let result = initTernaryTreeMapFromHashEntries(xs);
168
- // checkMapStructure(result);
169
- return result;
170
- }
171
-
172
- // use for..in for performance
173
- export function initTernaryTreeMapFromArray<K, T>(t: Array<[K, T]>): TernaryTreeMap<K, T> {
174
- let groupBuffers: Record<number, Array<[K, T]>> = {};
175
- let xs: Array<TernaryTreeMapHashEntry<K, T>> = [];
176
- for (let idx = 0; idx < t.length; idx++) {
177
- let k = t[idx][0];
178
- let v = t[idx][1];
179
- let h = hashGenerator(k);
180
- if (groupBuffers[h] != null) {
181
- let branch = groupBuffers[h];
182
- if (branch != null) {
183
- branch.push([k, v]);
184
- } else {
185
- throw new Error("Expected referece to pairs");
186
- }
187
- } else {
188
- let pairs: [K, T][] = [[k, v]];
189
- groupBuffers[h] = pairs;
190
- xs.push({
191
- hash: h,
192
- pairs: pairs,
193
- });
194
- }
195
- }
196
-
197
- // MUTABLE in-place sort
198
- xs.sort((a, b) => cmp(a.hash, b.hash));
199
-
200
- let result = initTernaryTreeMapFromHashEntries(xs);
201
- // checkMapStructure(result);
202
- return result;
203
- }
204
-
205
- // for empty map
206
- export function initEmptyTernaryTreeMap<K, T>(): TernaryTreeMap<K, T> {
207
- let result: TernaryTreeMap<K, T> = emptyBranch;
208
- return result;
209
- }
210
-
211
- export function mapToString<K, V>(tree: TernaryTreeMap<K, V>): string {
212
- return `TernaryTreeMap[${mapLen(tree)}, ...]`;
213
- }
214
-
215
- export function mapLen<K, V>(tree: TernaryTreeMap<K, V>): number {
216
- if (tree == null) {
217
- return 0;
218
- }
219
- switch (tree.kind) {
220
- case TernaryTreeKind.ternaryTreeLeaf:
221
- return tree.elements.length;
222
- case TernaryTreeKind.ternaryTreeBranch:
223
- return mapLen(tree.left) + mapLen(tree.middle) + mapLen(tree.right); // TODO
224
- default:
225
- throw new Error("Unknown");
226
- }
227
- }
228
-
229
- // when size succeeds bound, no longer counting, faster than traversing whole tree
230
- export function mapLenBound<K, V>(tree: TernaryTreeMap<K, V>, bound: number): number {
231
- if (tree == null) {
232
- return 0;
233
- }
234
- switch (tree.kind) {
235
- case TernaryTreeKind.ternaryTreeLeaf:
236
- return tree.elements.length;
237
- case TernaryTreeKind.ternaryTreeBranch:
238
- let ret = mapLenBound(tree.left, bound);
239
- if (ret > bound) {
240
- return ret;
241
- }
242
- ret = ret + mapLenBound(tree.middle, bound);
243
- if (ret > bound) {
244
- return ret;
245
- }
246
- ret = ret + mapLenBound(tree.right, bound);
247
- return ret;
248
- default:
249
- throw new Error("Unknown");
250
- }
251
- }
252
-
253
- export function formatMapInline<K, V>(tree: TernaryTreeMap<K, V>, withHash: boolean = false): string {
254
- if (tree == null) {
255
- return "_";
256
- }
257
- switch (tree.kind) {
258
- case TernaryTreeKind.ternaryTreeLeaf:
259
- if (withHash) {
260
- return `${tree.hash}->${tree.elements[0][0]}:${tree.elements[0][1]}`; // TODO show whole list
261
- } else {
262
- return `${tree.elements[0][0]}:${tree.elements[0][1]}`;
263
- }
264
- case TernaryTreeKind.ternaryTreeBranch: {
265
- return "(" + formatMapInline(tree.left, withHash) + " " + formatMapInline(tree.middle, withHash) + " " + formatMapInline(tree.right, withHash) + ")";
266
- }
267
-
268
- default:
269
- throw new Error("Unknown");
270
- }
271
- }
272
-
273
- export function isMapEmpty<K, V>(tree: TernaryTreeMap<K, V>): boolean {
274
- if (tree == null) {
275
- return true;
276
- }
277
- switch (tree.kind) {
278
- case TernaryTreeKind.ternaryTreeLeaf:
279
- return false;
280
- case TernaryTreeKind.ternaryTreeBranch:
281
- return tree.left == null && tree.middle == null && tree.right == null;
282
- default:
283
- throw new Error("Unknown");
284
- }
285
- }
286
-
287
- export function isMapOfOne<K, V>(tree: TernaryTreeMap<K, V>, counted: number = 0): boolean {
288
- if (tree == null) {
289
- return true;
290
- }
291
- switch (tree.kind) {
292
- case TernaryTreeKind.ternaryTreeLeaf:
293
- return false;
294
- case TernaryTreeKind.ternaryTreeBranch:
295
- return tree.left == null && tree.middle == null && tree.right == null;
296
- default:
297
- throw new Error("Unknown");
298
- }
299
- }
300
-
301
- function collectHashSortedArray<K, T>(tree: TernaryTreeMap<K, T>, acc: /* var */ Array<[K, T]>, idx: RefInt): void {
302
- if (tree == null || isMapEmpty(tree)) {
303
- // discard
304
- } else {
305
- switch (tree.kind) {
306
- case TernaryTreeKind.ternaryTreeLeaf: {
307
- for (let i = 0; i < tree.elements.length; i++) {
308
- let item = tree.elements[i];
309
- acc[idx.value] = item;
310
- idx.value = idx.value + 1;
311
- }
312
- break;
313
- }
314
- case TernaryTreeKind.ternaryTreeBranch: {
315
- collectHashSortedArray(tree.left, acc, idx);
316
- collectHashSortedArray(tree.middle, acc, idx);
317
- collectHashSortedArray(tree.right, acc, idx);
318
- break;
319
- }
320
- default:
321
- throw new Error("Unknown");
322
- }
323
- }
324
- }
325
-
326
- // sorted by hash(tree.key)
327
- export function toHashSortedPairs<K, T>(tree: TernaryTreeMap<K, T>): Array<[K, T]> {
328
- let acc = new Array<[K, T]>(mapLen(tree));
329
- let idx: RefInt = { value: 0 };
330
- collectHashSortedArray(tree, acc, idx);
331
- return acc;
332
- }
333
-
334
- function collectOrderedHashEntries<K, T>(tree: TernaryTreeMap<K, T>, acc: /* var */ Array<TernaryTreeMapHashEntry<K, T>>, idx: RefInt): void {
335
- if (tree == null || isMapEmpty(tree)) {
336
- // discard
337
- } else {
338
- switch (tree.kind) {
339
- case TernaryTreeKind.ternaryTreeLeaf: {
340
- acc[idx.value] = { hash: tree.hash, pairs: tree.elements };
341
- idx.value = idx.value + 1;
342
- break;
343
- }
344
- case TernaryTreeKind.ternaryTreeBranch: {
345
- collectOrderedHashEntries(tree.left, acc, idx);
346
- collectOrderedHashEntries(tree.middle, acc, idx);
347
- collectOrderedHashEntries(tree.right, acc, idx);
348
- break;
349
- }
350
- default: {
351
- throw new Error("Unknown");
352
- }
353
- }
354
- }
355
- }
356
-
357
- // for reusing leaves during rebalancing
358
- function toOrderedHashEntries<K, T>(tree: TernaryTreeMap<K, T>): Array<TernaryTreeMapHashEntry<K, T>> {
359
- let acc = new Array<TernaryTreeMapHashEntry<K, T>>(mapLen(tree));
360
- let idx: RefInt = { value: 0 };
361
- collectOrderedHashEntries(tree, acc, idx);
362
- return acc;
363
- }
364
-
365
- export function contains<K, T>(originalTree: TernaryTreeMap<K, T>, item: K): boolean {
366
- if (originalTree == null) {
367
- return false;
368
- }
369
-
370
- // TODO
371
-
372
- // reduce redundant computation by reusing hash result
373
- let hx = hashGenerator(item);
374
-
375
- let tree = originalTree;
376
-
377
- whileLoop: while (tree != null) {
378
- if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
379
- if (hx === tree.hash) {
380
- let size = tree.elements.length;
381
- for (let idx = 0; idx < size; idx++) {
382
- let pair = tree.elements[idx];
383
- if (dataEqual(pair[0], item)) {
384
- return true;
385
- }
386
- }
387
- }
388
- return false;
389
- }
390
-
391
- // echo "looking for: ", hx, " ", item, " in ", tree.formatInline(true)
392
- if (tree.left == null) {
393
- return false;
394
- }
395
- if (tree.left.kind === TernaryTreeKind.ternaryTreeLeaf) {
396
- if (hx < tree.left.hash) {
397
- return false;
398
- }
399
- if (tree.left.hash === hx) {
400
- tree = tree.left;
401
- continue whileLoop; // notice, it jumps to while loop
402
- }
403
- } else {
404
- if (hx < tree.left.minHash) {
405
- return false;
406
- }
407
- if (hx <= tree.left.maxHash) {
408
- tree = tree.left;
409
- continue whileLoop; // notice, it jumps to while loop
410
- }
411
- }
412
-
413
- if (tree.middle == null) {
414
- return false;
415
- }
416
- if (tree.middle.kind === TernaryTreeKind.ternaryTreeLeaf) {
417
- if (hx < tree.middle.hash) {
418
- return false;
419
- }
420
- if (tree.middle.hash === hx) {
421
- tree = tree.middle;
422
- continue whileLoop; // notice, it jumps to while loop
423
- }
424
- } else {
425
- if (hx < tree.middle.minHash) {
426
- return false;
427
- }
428
- if (hx <= tree.middle.maxHash) {
429
- tree = tree.middle;
430
- continue whileLoop; // notice, it jumps to while loop
431
- }
432
- }
433
-
434
- if (tree.right == null) {
435
- return false;
436
- }
437
- if (tree.right.kind === TernaryTreeKind.ternaryTreeLeaf) {
438
- if (hx < tree.right.hash) {
439
- return false;
440
- }
441
- if (tree.right.hash === hx) {
442
- tree = tree.right;
443
- continue whileLoop; // notice, it jumps to while loop
444
- }
445
- } else {
446
- if (hx < tree.right.minHash) {
447
- return false;
448
- }
449
- if (hx <= tree.right.maxHash) {
450
- tree = tree.right;
451
- continue whileLoop; // notice, it jumps to while loop
452
- }
453
- }
454
- return false;
455
- }
456
-
457
- return false;
458
- }
459
-
460
- export function mapGetDefault<K, T>(originalTree: TernaryTreeMap<K, T>, item: K, v0: T): T {
461
- let hx = hashGenerator(item);
462
-
463
- let tree = originalTree;
464
-
465
- whileLoop: while (tree != null) {
466
- if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
467
- let size = tree.elements.length;
468
- for (let i = 0; i < size; i++) {
469
- let pair = tree.elements[i];
470
- if (dataEqual(pair[0], item)) {
471
- return pair[1];
472
- }
473
- }
474
- return v0;
475
- }
476
-
477
- // echo "looking for: ", hx, " ", item, " in ", tree.formatInline
478
-
479
- if (tree.left == null) {
480
- return v0;
481
- }
482
- if (tree.left.kind == TernaryTreeKind.ternaryTreeLeaf) {
483
- if (hx < tree.left.hash) {
484
- return v0;
485
- }
486
- if (tree.left.hash === hx) {
487
- tree = tree.left;
488
- continue whileLoop; // notice, it jumps to while loop
489
- }
490
- } else {
491
- if (hx < tree.left.minHash) {
492
- return v0;
493
- }
494
- if (hx <= tree.left.maxHash) {
495
- tree = tree.left;
496
- continue whileLoop; // notice, it jumps to while loop
497
- }
498
- }
499
-
500
- if (tree.middle == null) {
501
- return v0;
502
- }
503
- if (tree.middle.kind == TernaryTreeKind.ternaryTreeLeaf) {
504
- if (hx < tree.middle.hash) {
505
- return v0;
506
- }
507
- if (tree.middle.hash === hx) {
508
- tree = tree.middle;
509
- continue whileLoop; // notice, it jumps to while loop
510
- }
511
- } else {
512
- if (hx < tree.middle.minHash) {
513
- return v0;
514
- }
515
- if (hx <= tree.middle.maxHash) {
516
- tree = tree.middle;
517
- continue whileLoop; // notice, it jumps to while loop
518
- }
519
- }
520
-
521
- if (tree.right == null) {
522
- return v0;
523
- }
524
- if (tree.right.kind == TernaryTreeKind.ternaryTreeLeaf) {
525
- if (hx < tree.right.hash) {
526
- return v0;
527
- }
528
- if (tree.right.hash === hx) {
529
- tree = tree.right;
530
- continue whileLoop; // notice, it jumps to while loop
531
- }
532
- } else {
533
- if (hx < tree.right.minHash) {
534
- return v0;
535
- }
536
- if (hx <= tree.right.maxHash) {
537
- tree = tree.right;
538
- continue whileLoop; // notice, it jumps to while loop
539
- }
540
- }
541
-
542
- return v0;
543
- }
544
-
545
- return v0;
546
- }
547
-
548
- // leaves on the left has smaller hashes
549
- // TODO check sizes, hashes
550
- export function checkMapStructure<K, V>(tree: TernaryTreeMap<K, V>): boolean {
551
- if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
552
- for (let i = 0; i < tree.elements.length; i++) {
553
- let pair = tree.elements[i];
554
- if (pair.length !== 2) {
555
- throw new Error("Expected pair to br [k,v] :" + pair);
556
- }
557
- if (tree.hash !== hashGenerator(pair[0])) {
558
- throw new Error(`Bad hash at leaf node ${tree}`);
559
- }
560
- }
561
-
562
- if (mapLenBound(tree, 2) !== 1) {
563
- throw new Error(`Bad len at leaf node ${tree}`);
564
- }
565
- } else {
566
- if (tree.left == null) {
567
- if (tree.middle != null) {
568
- throw new Error("Layout is not compact");
569
- }
570
- if (tree.middle != null) {
571
- throw new Error("Layout is not compact");
572
- }
573
- }
574
- if (tree.middle == null) {
575
- if (tree.right != null) {
576
- throw new Error("Layout is not compact");
577
- }
578
- }
579
- if (tree.left != null && tree.middle != null) {
580
- if (getMax(tree.left) >= getMin(tree.middle)) {
581
- throw new Error(`Wrong hash order at left/middle branches ${formatMapInline(tree, true)}`);
582
- }
583
- }
584
-
585
- if (tree.left != null && tree.right != null) {
586
- if (getMax(tree.left) >= getMin(tree.right)) {
587
- console.log(getMax(tree.left), getMin(tree.right));
588
- throw new Error(`Wrong hash order at left/right branches ${formatMapInline(tree, true)}`);
589
- }
590
- }
591
- if (tree.middle != null && tree.right != null) {
592
- if (getMax(tree.middle) >= getMin(tree.right)) {
593
- throw new Error(`Wrong hash order at middle/right branches ${formatMapInline(tree, true)}`);
594
- }
595
- }
596
-
597
- if (tree.left != null) {
598
- checkMapStructure(tree.left);
599
- }
600
- if (tree.middle != null) {
601
- checkMapStructure(tree.middle);
602
- }
603
- if (tree.right != null) {
604
- checkMapStructure(tree.right);
605
- }
606
- }
607
-
608
- return true;
609
- }
610
-
611
- function rangeContainsHash<K, T>(tree: TernaryTreeMap<K, T>, thisHash: Hash): boolean {
612
- if (tree == null) {
613
- return false;
614
- } else if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
615
- return tree.hash === thisHash;
616
- } else {
617
- return thisHash >= tree.minHash && thisHash <= tree.maxHash;
618
- }
619
- }
620
-
621
- function assocExisted<K, T>(tree: TernaryTreeMap<K, T>, key: K, item: T, thisHash: Hash = null as any): TernaryTreeMap<K, T> {
622
- if (tree == null || isMapEmpty(tree)) {
623
- throw new Error("Cannot call assoc on nil");
624
- }
625
-
626
- thisHash = thisHash ?? hashGenerator(key);
627
-
628
- if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
629
- if (tree.hash !== thisHash) {
630
- throw new Error("Expected hashes to be identical, otherwise element is missing");
631
- }
632
- let newPairs = new Array<[K, T]>(tree.elements.length);
633
- let replaced = false;
634
- let size = tree.elements.length;
635
- for (let idx = 0; idx < size; idx++) {
636
- let pair = tree.elements[idx];
637
- if (dataEqual(pair[0], key)) {
638
- newPairs[idx] = [key, item];
639
- replaced = true;
640
- } else {
641
- newPairs[idx] = pair;
642
- }
643
- }
644
- if (replaced) {
645
- let result: TernaryTreeMap<K, T> = { kind: TernaryTreeKind.ternaryTreeLeaf, hash: thisHash, elements: newPairs };
646
- return result;
647
- } else {
648
- throw new Error("Unexpected missing hash in assoc, invalid branch");
649
- }
650
- }
651
-
652
- if (thisHash < tree.minHash) throw new Error("Unexpected missing hash in assoc, hash too small");
653
- else if (thisHash > tree.maxHash) throw new Error("Unexpected missing hash in assoc, hash too large");
654
-
655
- if (tree.left == null) {
656
- throw new Error("Unexpected missing hash in assoc, found not branch");
657
- }
658
- if (rangeContainsHash(tree.left, thisHash)) {
659
- let result: TernaryTreeMapTheBranch<K, T> = {
660
- kind: TernaryTreeKind.ternaryTreeBranch,
661
- maxHash: tree.maxHash,
662
- minHash: tree.minHash,
663
- left: assocExisted(tree.left, key, item, thisHash),
664
- middle: tree.middle,
665
- right: tree.right,
666
- depth: 0, // TODO
667
- };
668
- return result;
669
- }
670
-
671
- if (tree.middle == null) {
672
- throw new Error("Unexpected missing hash in assoc, found not branch");
673
- }
674
- if (rangeContainsHash(tree.middle, thisHash)) {
675
- let result: TernaryTreeMapTheBranch<K, T> = {
676
- kind: TernaryTreeKind.ternaryTreeBranch,
677
- maxHash: tree.maxHash,
678
- minHash: tree.minHash,
679
- left: tree.left,
680
- middle: assocExisted(tree.middle, key, item, thisHash),
681
- right: tree.right,
682
- depth: 0, // TODO
683
- };
684
- return result;
685
- }
686
-
687
- if (tree.right == null) {
688
- throw new Error("Unexpected missing hash in assoc, found not branch");
689
- }
690
- if (rangeContainsHash(tree.right, thisHash)) {
691
- let result: TernaryTreeMapTheBranch<K, T> = {
692
- kind: TernaryTreeKind.ternaryTreeBranch,
693
- maxHash: tree.maxHash,
694
- minHash: tree.minHash,
695
- left: tree.left,
696
- middle: tree.middle,
697
- right: assocExisted(tree.right, key, item, thisHash),
698
- depth: 0, // TODO
699
- };
700
- return result;
701
- }
702
- throw new Error("Unexpected missing hash in assoc, found not branch");
703
- }
704
-
705
- function assocNew<K, T>(tree: TernaryTreeMap<K, T>, key: K, item: T, thisHash: Hash = null as any): TernaryTreeMap<K, T> {
706
- // echo fmt"assoc new: {key} to {tree.formatInline}"
707
- if (tree == null || isMapEmpty(tree)) {
708
- return createLeaf(key, item);
709
- }
710
-
711
- thisHash = thisHash ?? hashGenerator(key);
712
-
713
- if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
714
- if (thisHash > tree.hash) {
715
- let childBranch: TernaryTreeMapTheLeaf<K, T> = {
716
- kind: TernaryTreeKind.ternaryTreeLeaf,
717
- hash: thisHash,
718
- elements: [[key, item]],
719
- };
720
- let result: TernaryTreeMapTheBranch<K, T> = {
721
- kind: TernaryTreeKind.ternaryTreeBranch,
722
- maxHash: thisHash,
723
- minHash: tree.hash,
724
- left: tree,
725
- middle: childBranch,
726
- right: emptyBranch,
727
- depth: 0, // TODO
728
- };
729
- return result;
730
- } else if (thisHash < tree.hash) {
731
- let childBranch: TernaryTreeMapTheLeaf<K, T> = {
732
- kind: TernaryTreeKind.ternaryTreeLeaf,
733
- hash: thisHash,
734
- elements: [[key, item]],
735
- };
736
- let result: TernaryTreeMapTheBranch<K, T> = {
737
- kind: TernaryTreeKind.ternaryTreeBranch,
738
- maxHash: tree.hash,
739
- minHash: thisHash,
740
- left: childBranch,
741
- middle: tree,
742
- right: emptyBranch,
743
- depth: 0, // TODO
744
- };
745
- return result;
746
- } else {
747
- let size = tree.elements.length;
748
- for (let i = 0; i < size; i++) {
749
- let pair = tree.elements[i];
750
- if (dataEqual(pair[0], key)) {
751
- throw new Error("Unexpected existed key in assoc");
752
- }
753
- }
754
- let newPairs = new Array<[K, T]>(tree.elements.length + 1);
755
- for (let idx = 0; idx < size; idx++) {
756
- let pair = tree.elements[idx];
757
- newPairs[idx] = pair;
758
- }
759
- newPairs[tree.elements.length] = [key, item];
760
- let result: TernaryTreeMapTheLeaf<K, T> = {
761
- kind: TernaryTreeKind.ternaryTreeLeaf,
762
- hash: tree.hash,
763
- elements: newPairs,
764
- };
765
- return result;
766
- }
767
- } else {
768
- if (thisHash < tree.minHash) {
769
- if (tree.right == null) {
770
- let childBranch: TernaryTreeMapTheLeaf<K, T> = {
771
- kind: TernaryTreeKind.ternaryTreeLeaf,
772
- hash: thisHash,
773
- elements: [[key, item]],
774
- };
775
- let result: TernaryTreeMapTheBranch<K, T> = {
776
- kind: TernaryTreeKind.ternaryTreeBranch,
777
- maxHash: tree.maxHash,
778
- minHash: thisHash,
779
- left: childBranch,
780
- middle: tree.left,
781
- right: tree.middle,
782
- depth: 0, // TODO
783
- };
784
- return result;
785
- } else {
786
- let childBranch: TernaryTreeMapTheLeaf<K, T> = {
787
- kind: TernaryTreeKind.ternaryTreeLeaf,
788
- hash: thisHash,
789
- elements: [[key, item]],
790
- };
791
- let result: TernaryTreeMapTheBranch<K, T> = {
792
- kind: TernaryTreeKind.ternaryTreeBranch,
793
- maxHash: tree.maxHash,
794
- minHash: thisHash,
795
- left: childBranch,
796
- middle: tree,
797
- right: emptyBranch,
798
- depth: 0, // TODO
799
- };
800
- return result;
801
- }
802
- }
803
-
804
- if (thisHash > tree.maxHash) {
805
- // in compact layout, left arm must be existed
806
- if (tree.middle == null) {
807
- let childBranch: TernaryTreeMapTheLeaf<K, T> = {
808
- kind: TernaryTreeKind.ternaryTreeLeaf,
809
- hash: thisHash,
810
- elements: [[key, item]],
811
- };
812
- let result: TernaryTreeMapTheBranch<K, T> = {
813
- kind: TernaryTreeKind.ternaryTreeBranch,
814
- maxHash: thisHash,
815
- minHash: tree.minHash,
816
- left: tree.left,
817
- middle: childBranch,
818
- right: emptyBranch,
819
- depth: 0, // TODO
820
- };
821
- return result;
822
- } else if (tree.right == null) {
823
- let childBranch: TernaryTreeMapTheLeaf<K, T> = {
824
- kind: TernaryTreeKind.ternaryTreeLeaf,
825
- hash: thisHash,
826
- elements: [[key, item]],
827
- };
828
- let result: TernaryTreeMapTheBranch<K, T> = {
829
- kind: TernaryTreeKind.ternaryTreeBranch,
830
- maxHash: thisHash,
831
- minHash: tree.minHash,
832
- left: tree.left,
833
- middle: tree.middle,
834
- right: childBranch,
835
- depth: 0, // TODO
836
- };
837
- return result;
838
- } else {
839
- let childBranch: TernaryTreeMapTheLeaf<K, T> = {
840
- kind: TernaryTreeKind.ternaryTreeLeaf,
841
- hash: thisHash,
842
- elements: [[key, item]],
843
- };
844
- let result: TernaryTreeMapTheBranch<K, T> = {
845
- kind: TernaryTreeKind.ternaryTreeBranch,
846
- maxHash: thisHash,
847
- minHash: tree.minHash,
848
- left: tree,
849
- middle: childBranch,
850
- right: emptyBranch,
851
- depth: 0, // TODO
852
- };
853
-
854
- return result;
855
- }
856
- }
857
-
858
- if (rangeContainsHash(tree.left, thisHash)) {
859
- let result: TernaryTreeMapTheBranch<K, T> = {
860
- kind: TernaryTreeKind.ternaryTreeBranch,
861
- maxHash: tree.maxHash,
862
- minHash: tree.minHash,
863
- left: assocNew(tree.left, key, item, thisHash),
864
- middle: tree.middle,
865
- right: tree.right,
866
- depth: 0, // TODO
867
- };
868
- return result;
869
- }
870
- if (rangeContainsHash(tree.middle, thisHash)) {
871
- let result: TernaryTreeMapTheBranch<K, T> = {
872
- kind: TernaryTreeKind.ternaryTreeBranch,
873
- maxHash: tree.maxHash,
874
- minHash: tree.minHash,
875
- left: tree.left,
876
- middle: assocNew(tree.middle, key, item, thisHash),
877
- right: tree.right,
878
- depth: 0, // TODO
879
- };
880
- return result;
881
- }
882
- if (rangeContainsHash(tree.right, thisHash)) {
883
- let result: TernaryTreeMapTheBranch<K, T> = {
884
- kind: TernaryTreeKind.ternaryTreeBranch,
885
- maxHash: tree.maxHash,
886
- minHash: tree.minHash,
887
- left: tree.left,
888
- middle: tree.middle,
889
- right: assocNew(tree.right, key, item, thisHash),
890
- depth: 0, // TODO
891
- };
892
- return result;
893
- }
894
-
895
- if (tree.middle == null) {
896
- throw new Error("unreachable. if inside range, then middle should be here");
897
- }
898
- if (thisHash < getMin(tree.middle)) {
899
- let result: TernaryTreeMapTheBranch<K, T> = {
900
- kind: TernaryTreeKind.ternaryTreeBranch,
901
- maxHash: tree.maxHash,
902
- minHash: tree.minHash,
903
- left: assocNew(tree.left, key, item, thisHash),
904
- middle: tree.middle,
905
- right: tree.right,
906
- depth: 0, // TODO
907
- };
908
- return result;
909
- } else {
910
- let result: TernaryTreeMap<K, T> = {
911
- kind: TernaryTreeKind.ternaryTreeBranch,
912
- maxHash: tree.maxHash,
913
- minHash: tree.minHash,
914
- left: tree.left,
915
- middle: tree.middle,
916
- right: assocNew(tree.right, key, item, thisHash),
917
- depth: 0, // TODO
918
- };
919
- return result;
920
- }
921
- }
922
- }
923
-
924
- export function assocMap<K, T>(tree: TernaryTreeMap<K, T>, key: K, item: T, disableBalancing: boolean = false): TernaryTreeMap<K, T> {
925
- if (tree == null || isMapEmpty(tree)) {
926
- return createLeaf(key, item);
927
- }
928
-
929
- if (contains(tree, key)) {
930
- return assocExisted(tree, key, item);
931
- } else {
932
- return assocNew(tree, key, item);
933
- }
934
- }
935
-
936
- function dissocExisted<K, T>(tree: TernaryTreeMap<K, T>, key: K): TernaryTreeMap<K, T> {
937
- if (tree == null) {
938
- throw new Error("Unexpected missing key in dissoc");
939
- }
940
-
941
- if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
942
- if (tree.hash === hashGenerator(key)) {
943
- let size = tree.elements.length;
944
- if (size === 1 && dataEqual(key, tree.elements[0][0])) {
945
- return emptyBranch;
946
- } else {
947
- let newPairs: Array<[K, T]> = [];
948
- for (let i = 0; i < size; i++) {
949
- let pair = tree.elements[i];
950
- if (!dataEqual(pair[0], key)) {
951
- newPairs.push(pair);
952
- }
953
- }
954
- let result: TernaryTreeMapTheLeaf<K, T> = { kind: TernaryTreeKind.ternaryTreeLeaf, hash: tree.hash, elements: newPairs };
955
- return result;
956
- }
957
- } else {
958
- throw new Error("Unexpected missing key in dissoc on leaf");
959
- }
960
- }
961
-
962
- if (mapLenBound(tree, 2) === 1) {
963
- if (!contains(tree, key)) {
964
- throw new Error("Unexpected missing key in dissoc single branch");
965
- }
966
- return emptyBranch;
967
- }
968
-
969
- let thisHash = hashGenerator(key);
970
-
971
- if (rangeContainsHash(tree.left, thisHash)) {
972
- let changedBranch = dissocExisted(tree.left, key);
973
-
974
- if (isMapEmpty(changedBranch)) {
975
- if (isMapEmpty(tree.right)) {
976
- return tree.middle;
977
- }
978
- let result: TernaryTreeMapTheBranch<K, T> = {
979
- kind: TernaryTreeKind.ternaryTreeBranch,
980
- maxHash: tree.maxHash,
981
- minHash: getMin(tree.middle),
982
- left: tree.middle,
983
- middle: tree.right,
984
- right: emptyBranch,
985
- depth: 0, // TODO
986
- };
987
- return result;
988
- } else {
989
- let result: TernaryTreeMapTheBranch<K, T> = {
990
- kind: TernaryTreeKind.ternaryTreeBranch,
991
- maxHash: tree.maxHash,
992
- minHash: getMin(changedBranch),
993
- left: changedBranch,
994
- middle: tree.middle,
995
- right: tree.right,
996
- depth: 0, // TODO
997
- };
998
- return result;
999
- }
1000
- }
1001
-
1002
- if (rangeContainsHash(tree.middle, thisHash)) {
1003
- let changedBranch = dissocExisted(tree.middle, key);
1004
-
1005
- if (isMapEmpty(changedBranch)) {
1006
- if (isMapEmpty(tree.right)) {
1007
- return tree.left;
1008
- }
1009
- let result: TernaryTreeMapTheBranch<K, T> = {
1010
- kind: TernaryTreeKind.ternaryTreeBranch,
1011
- maxHash: tree.maxHash,
1012
- minHash: tree.minHash,
1013
- left: tree.left,
1014
- middle: tree.right,
1015
- right: emptyBranch,
1016
- depth: 0, // TODO
1017
- };
1018
- return result;
1019
- } else {
1020
- let result: TernaryTreeMapTheBranch<K, T> = {
1021
- kind: TernaryTreeKind.ternaryTreeBranch,
1022
- maxHash: tree.maxHash,
1023
- minHash: tree.minHash,
1024
- left: tree.left,
1025
- middle: changedBranch,
1026
- right: tree.right,
1027
- depth: 0, // TODO
1028
- };
1029
- return result;
1030
- }
1031
- }
1032
-
1033
- if (rangeContainsHash(tree.right, thisHash)) {
1034
- let changedBranch = dissocExisted(tree.right, key);
1035
-
1036
- if (changedBranch == null) {
1037
- let result: TernaryTreeMapTheBranch<K, T> = {
1038
- kind: TernaryTreeKind.ternaryTreeBranch,
1039
- maxHash: getMax(tree.middle),
1040
- minHash: tree.minHash,
1041
- left: tree.left,
1042
- middle: tree.middle,
1043
- right: emptyBranch,
1044
- depth: 0, // TODO
1045
- };
1046
- return result;
1047
- } else {
1048
- let result: TernaryTreeMapTheBranch<K, T> = {
1049
- kind: TernaryTreeKind.ternaryTreeBranch,
1050
- maxHash: getMax(changedBranch),
1051
- minHash: tree.minHash,
1052
- left: tree.left,
1053
- middle: tree.middle,
1054
- right: changedBranch,
1055
- depth: 0, // TODO
1056
- };
1057
- return result;
1058
- }
1059
- }
1060
-
1061
- throw new Error("Cannot find branch in dissoc");
1062
- }
1063
-
1064
- export function dissocMap<K, T>(tree: TernaryTreeMap<K, T>, key: K): TernaryTreeMap<K, T> {
1065
- if (contains(tree, key)) {
1066
- return dissocExisted(tree, key);
1067
- } else {
1068
- return tree;
1069
- }
1070
- }
1071
-
1072
- function collectToPairsArray<K, T>(acc: Array<[K, T]>, tree: TernaryTreeMap<K, T>): void {
1073
- if (tree != null) {
1074
- if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
1075
- for (let i = 0; i < tree.elements.length; i++) {
1076
- let pair = tree.elements[i];
1077
- acc.push(pair);
1078
- }
1079
- } else {
1080
- if (tree.left != null) {
1081
- collectToPairsArray(acc, tree.left);
1082
- }
1083
- if (tree.middle != null) {
1084
- collectToPairsArray(acc, tree.middle);
1085
- }
1086
- if (tree.right != null) {
1087
- collectToPairsArray(acc, tree.right);
1088
- }
1089
- }
1090
- }
1091
- }
1092
-
1093
- /** similar to `toPairs`, but using Array.push directly */
1094
- export function toPairsArray<K, T>(tree: TernaryTreeMap<K, T>): Array<[K, T]> {
1095
- let result: Array<[K, T]> = [];
1096
- collectToPairsArray(result, tree);
1097
- return result;
1098
- }
1099
-
1100
- export function* toPairs<K, T>(tree: TernaryTreeMap<K, T>): Generator<[K, T]> {
1101
- if (tree != null) {
1102
- if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
1103
- for (let pair of tree.elements) {
1104
- yield pair;
1105
- }
1106
- } else {
1107
- if (tree.left != null) {
1108
- for (let item of toPairs(tree.left)) {
1109
- yield item;
1110
- }
1111
- }
1112
- if (tree.middle != null) {
1113
- for (let item of toPairs(tree.middle)) {
1114
- yield item;
1115
- }
1116
- }
1117
- if (tree.right != null) {
1118
- for (let item of toPairs(tree.right)) {
1119
- yield item;
1120
- }
1121
- }
1122
- }
1123
- }
1124
- }
1125
-
1126
- export function* toKeys<K, V>(tree: TernaryTreeMap<K, V>): Generator<K> {
1127
- if (tree != null) {
1128
- if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
1129
- for (let i = 0; i < tree.elements.length; i++) {
1130
- let pair = tree.elements[i];
1131
- yield pair[0];
1132
- }
1133
- } else {
1134
- if (tree.left != null) {
1135
- for (let item of toKeys(tree.left)) {
1136
- yield item;
1137
- }
1138
- }
1139
- if (tree.middle != null) {
1140
- for (let item of toKeys(tree.middle)) {
1141
- yield item;
1142
- }
1143
- }
1144
- if (tree.right != null) {
1145
- for (let item of toKeys(tree.right)) {
1146
- yield item;
1147
- }
1148
- }
1149
- }
1150
- }
1151
- }
1152
-
1153
- export function* toValues<K, V>(tree: TernaryTreeMap<K, V>): Generator<V> {
1154
- if (tree != null) {
1155
- if (tree.kind === TernaryTreeKind.ternaryTreeLeaf) {
1156
- for (let i = 0; i < tree.elements.length; i++) {
1157
- let pair = tree.elements[i];
1158
- yield pair[1];
1159
- }
1160
- } else {
1161
- if (tree.left != null) {
1162
- for (let item of toValues(tree.left)) {
1163
- yield item;
1164
- }
1165
- }
1166
- if (tree.middle != null) {
1167
- for (let item of toValues(tree.middle)) {
1168
- yield item;
1169
- }
1170
- }
1171
- if (tree.right != null) {
1172
- for (let item of toValues(tree.right)) {
1173
- yield item;
1174
- }
1175
- }
1176
- }
1177
- }
1178
- }
1179
-
1180
- export function mapEqual<K, V>(xs: TernaryTreeMap<K, V>, ys: TernaryTreeMap<K, V>): boolean {
1181
- if (xs === ys) {
1182
- return true;
1183
- }
1184
- if (mapLen(xs) !== mapLen(ys)) {
1185
- return false;
1186
- }
1187
-
1188
- if (isMapEmpty(xs)) {
1189
- return true;
1190
- }
1191
-
1192
- for (let pair of toPairsArray(xs)) {
1193
- let key = pair[0];
1194
- let vx = pair[1];
1195
-
1196
- if (!contains(ys, key)) {
1197
- return false;
1198
- }
1199
- let vy = mapGetDefault(ys, key, null);
1200
-
1201
- // TODO compare deep structures
1202
- if (!dataEqual(vx, vy)) {
1203
- return false;
1204
- }
1205
- }
1206
-
1207
- return true;
1208
- }
1209
-
1210
- export function merge<K, T>(xs: TernaryTreeMap<K, T>, ys: TernaryTreeMap<K, T>): TernaryTreeMap<K, T> {
1211
- let ret = xs;
1212
- let counted = 0;
1213
- for (let [key, item] of toPairs(ys)) {
1214
- ret = assocMap(ret, key, item);
1215
- // # TODO pickd loop by experience
1216
- if (counted > 700) {
1217
- forceMapInplaceBalancing(ret);
1218
- counted = 0;
1219
- } else {
1220
- counted = counted + 1;
1221
- }
1222
- }
1223
- return ret;
1224
- }
1225
-
1226
- // # skip a value, mostly for nil
1227
- export function mergeSkip<K, T>(xs: TernaryTreeMap<K, T>, ys: TernaryTreeMap<K, T>, skipped: T): TernaryTreeMap<K, T> {
1228
- let ret = xs;
1229
- let counted = 0;
1230
- for (let [key, item] of toPairs(ys)) {
1231
- if (dataEqual(item, skipped)) {
1232
- continue;
1233
- }
1234
- ret = assocMap(ret, key, item);
1235
- // # TODO pickd loop by experience
1236
- if (counted > 700) {
1237
- forceMapInplaceBalancing(ret);
1238
- counted = 0;
1239
- } else {
1240
- counted = counted + 1;
1241
- }
1242
- }
1243
- return ret;
1244
- }
1245
-
1246
- // this function mutates original tree to make it more balanced
1247
- export function forceMapInplaceBalancing<K, T>(tree: TernaryTreeMap<K, T>): void {
1248
- // echo "Force inplace balancing of list"
1249
- if (tree.kind === TernaryTreeKind.ternaryTreeBranch) {
1250
- let xs = toOrderedHashEntries(tree);
1251
- let newTree = makeTernaryTreeMap(xs.length, 0, xs) as TernaryTreeMapTheBranch<K, T>;
1252
- tree.left = newTree.left;
1253
- tree.middle = newTree.middle;
1254
- tree.right = newTree.right;
1255
- } else {
1256
- // discard
1257
- }
1258
- }
1259
-
1260
- export function sameMapShape<K, T>(xs: TernaryTreeMap<K, T>, ys: TernaryTreeMap<K, T>): boolean {
1261
- if (xs == null) {
1262
- if (ys == null) {
1263
- return true;
1264
- } else {
1265
- return false;
1266
- }
1267
- }
1268
- if (ys == null) {
1269
- return false;
1270
- }
1271
-
1272
- if (mapLen(xs) !== mapLen(ys)) {
1273
- return false;
1274
- }
1275
-
1276
- if (xs.kind !== ys.kind) {
1277
- return false;
1278
- }
1279
-
1280
- if (xs.kind === TernaryTreeKind.ternaryTreeLeaf && ys.kind === TernaryTreeKind.ternaryTreeLeaf) {
1281
- if (xs.elements.length !== ys.elements.length) {
1282
- return false;
1283
- }
1284
- for (let idx = 0; idx < xs.elements.length; idx++) {
1285
- if (!dataEqual(xs.elements[idx], ys.elements[idx])) {
1286
- return false;
1287
- }
1288
- }
1289
- return true;
1290
- } else if (xs.kind === TernaryTreeKind.ternaryTreeBranch && ys.kind === TernaryTreeKind.ternaryTreeBranch) {
1291
- if (!sameMapShape(xs.left, ys.left)) {
1292
- return false;
1293
- }
1294
-
1295
- if (!sameMapShape(xs.middle, ys.middle)) {
1296
- return false;
1297
- }
1298
-
1299
- if (!sameMapShape(xs.right, ys.right)) {
1300
- return false;
1301
- }
1302
-
1303
- return true;
1304
- } else {
1305
- throw new Error("Unknown");
1306
- }
1307
- }
1308
-
1309
- export function mapMapValues<K, T, V>(tree: TernaryTreeMap<K, T>, f: (x: T) => V): TernaryTreeMap<K, V> {
1310
- if (tree == null) {
1311
- return tree;
1312
- }
1313
-
1314
- switch (tree.kind) {
1315
- case TernaryTreeKind.ternaryTreeLeaf: {
1316
- let newElements = new Array<[K, V]>(tree.elements.length);
1317
- let size = tree.elements.length;
1318
- for (let idx = 0; idx < size; idx++) {
1319
- newElements[idx] = [tree.elements[idx][0], f(tree.elements[idx][1])];
1320
- }
1321
- let result: TernaryTreeMap<K, V> = {
1322
- kind: TernaryTreeKind.ternaryTreeLeaf,
1323
- hash: tree.hash,
1324
- elements: newElements,
1325
- };
1326
- return result;
1327
- }
1328
- case TernaryTreeKind.ternaryTreeBranch: {
1329
- let result: TernaryTreeMap<K, V> = {
1330
- kind: TernaryTreeKind.ternaryTreeBranch,
1331
- depth: tree.depth,
1332
- minHash: tree.minHash,
1333
- maxHash: tree.maxHash,
1334
- left: mapMapValues(tree.left, f),
1335
- middle: mapMapValues(tree.middle, f),
1336
- right: mapMapValues(tree.right, f),
1337
- };
1338
- return result;
1339
- }
1340
- }
1341
- }