diff --git a/implementations/javascript/packages/core/src/merge.ts b/implementations/javascript/packages/core/src/merge.ts new file mode 100644 index 0000000..39761e6 --- /dev/null +++ b/implementations/javascript/packages/core/src/merge.ts @@ -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( + mergePointers: (a: T, b: T) => T | undefined, + item0: Value, + ... items: Array>): Value +{ + function die(): never { + throw new Error("Cannot merge items"); + } + + function walk(a: Value, b: Value): Value { + if (a === b) return a; + return fold>(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, Tuple>, T>) { + if (!Record.isRecord, Tuple>, T>(b)) die(); + return Record(walk(r.label, b.label), walkMany(r, b)); + }, + array(a: Array>) { + if (!Array.isArray(b) || Record.isRecord(b)) die(); + return walkMany(a, b); + }, + set(_s: Set) { die(); }, + dictionary(d: Dictionary) { + if (!Dictionary.isDictionary(b)) die(); + const r = new Dictionary(); + 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) { + 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>, b: Array>): Array> { + if (a.length !== b.length) die(); + return a.map((aa, i) => walk(aa, b[i])); + } + + return items.reduce(walk, item0); +} diff --git a/implementations/javascript/packages/core/src/runtime.ts b/implementations/javascript/packages/core/src/runtime.ts index 7eeb0ff..9befa66 100644 --- a/implementations/javascript/packages/core/src/runtime.ts +++ b/implementations/javascript/packages/core/src/runtime.ts @@ -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';