44 lines
1.5 KiB
TypeScript
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 { DefaultPointer } from "./pointer";
|
|
|
|
export function unannotate<T = DefaultPointer>(v: Value<T>): Value<T> {
|
|
return Annotated.isAnnotated<T>(v) ? v.item : v;
|
|
}
|
|
|
|
export function peel<T = DefaultPointer>(v: Value<T>): Value<T> {
|
|
return strip(v, 1);
|
|
}
|
|
|
|
export function strip<T = DefaultPointer>(
|
|
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);
|
|
}
|