First attempt at a merge() utility
This commit is contained in:
parent
4ded3a484c
commit
1d73289345
|
@ -0,0 +1,71 @@
|
|||
import { Record, Tuple } from "./record";
|
||||
import { Bytes } from "./bytes";
|
||||
import { fold, isPointer } from "./fold";
|
||||
import { is } from "./is";
|
||||
import { Value } from "./values";
|
||||
import { Set, Dictionary } from "./dictionary";
|
||||
import { Annotated } from "./annotated";
|
||||
import { unannotate } from "./strip";
|
||||
|
||||
export function merge<T>(
|
||||
mergePointers: (a: T, b: T) => T | undefined,
|
||||
item0: Value<T>,
|
||||
... items: Array<Value<T>>): Value<T>
|
||||
{
|
||||
function die(): never {
|
||||
throw new Error("Cannot merge items");
|
||||
}
|
||||
|
||||
function walk(a: Value<T>, b: Value<T>): Value<T> {
|
||||
if (a === b) return a;
|
||||
return fold<T, Value<T>>(a, {
|
||||
boolean: die,
|
||||
single(_f: number) { return is(a, b) ? a : die(); },
|
||||
double(_f: number) { return is(a, b) ? a : die(); },
|
||||
integer: die,
|
||||
string: die,
|
||||
bytes(_b: Bytes) { return is(a, b) ? a : die(); },
|
||||
symbol: die,
|
||||
|
||||
record(r: Record<Value<T>, Tuple<Value<T>>, T>) {
|
||||
if (!Record.isRecord<Value<T>, Tuple<Value<T>>, T>(b)) die();
|
||||
return Record(walk(r.label, b.label), walkMany(r, b));
|
||||
},
|
||||
array(a: Array<Value<T>>) {
|
||||
if (!Array.isArray(b) || Record.isRecord(b)) die();
|
||||
return walkMany(a, b);
|
||||
},
|
||||
set(_s: Set<T>) { die(); },
|
||||
dictionary(d: Dictionary<T>) {
|
||||
if (!Dictionary.isDictionary<T>(b)) die();
|
||||
const r = new Dictionary<T>();
|
||||
d.forEach((av,ak) => {
|
||||
const bv = b.get(ak);
|
||||
r.set(ak, bv === void 0 ? av : walk(av, bv));
|
||||
});
|
||||
b.forEach((bv, bk) => {
|
||||
if (!d.has(bk)) r.set(bk, bv);
|
||||
});
|
||||
return r;
|
||||
},
|
||||
|
||||
annotated(a: Annotated<T>) {
|
||||
return walk(a, unannotate(b));
|
||||
},
|
||||
|
||||
pointer(t: T) {
|
||||
if (!isPointer(b)) die();
|
||||
const r = mergePointers(t, b);
|
||||
if (r === void 0) die();
|
||||
return r;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function walkMany(a: Array<Value<T>>, b: Array<Value<T>>): Array<Value<T>> {
|
||||
if (a.length !== b.length) die();
|
||||
return a.map((aa, i) => walk(aa, b[i]));
|
||||
}
|
||||
|
||||
return items.reduce(walk, item0);
|
||||
}
|
|
@ -10,6 +10,7 @@ export * from './float';
|
|||
export * from './fold';
|
||||
export * from './fromjs';
|
||||
export * from './is';
|
||||
export * from './merge';
|
||||
export * from './pointer';
|
||||
export * from './reader';
|
||||
export * from './record';
|
||||
|
|
Loading…
Reference in New Issue