preserves/implementations/javascript/packages/core/src/strip.ts

44 lines
1.5 KiB
TypeScript

import { Value } from "./values";
import { Annotated } from "./annotated";
import { Record, Tuple } from "./record";
import { Set, Dictionary } from "./dictionary";
import type { GenericEmbedded } from "./embedded";
export function unannotate<T = GenericEmbedded>(v: Value<T>): Value<T> {
return Annotated.isAnnotated<T>(v) ? v.item : v;
}
export function peel<T = GenericEmbedded>(v: Value<T>): Value<T> {
return strip(v, 1);
}
export function strip<T = GenericEmbedded>(
v: Value<T>,
depth: number = Infinity): Value<T>
{
function step(v: Value<T>, depth: number): Value<T> {
if (depth === 0) return v;
if (!Annotated.isAnnotated<T>(v)) return v;
const nextDepth = depth - 1;
function walk(v: Value<T>): Value<T> { return step(v, nextDepth); }
if (Record.isRecord<Value<T>, Tuple<Value<T>>, T>(v.item)) {
return Record(step(v.item.label, depth), v.item.map(walk));
} else if (Annotated.isAnnotated(v.item)) {
throw new Error("Improper annotation structure");
} else if (nextDepth === 0) {
return v.item;
} else if (Array.isArray(v.item)) {
return (v.item as Value<T>[]).map(walk);
} else if (Set.isSet<T>(v.item)) {
return v.item.map(walk);
} else if (Dictionary.isDictionary<T>(v.item)) {
return v.item.mapEntries((e) => [walk(e[0]), walk(e[1])]);
} else {
return v.item;
}
}
return step(v, depth);
}