41 lines
1.4 KiB
TypeScript
41 lines
1.4 KiB
TypeScript
|
import { DefaultPointer, Value } from "./values";
|
||
|
import { Annotated } from "./annotated";
|
||
|
import { Record, Tuple } from "./record";
|
||
|
import { Set, Dictionary } from "./dictionary";
|
||
|
|
||
|
export function unannotate<T extends object = DefaultPointer>(v: Value<T>): Value<T> {
|
||
|
return Annotated.isAnnotated<T>(v) ? v.item : v;
|
||
|
}
|
||
|
|
||
|
export function peel<T extends object = DefaultPointer>(v: Value<T>): Value<T> {
|
||
|
return strip(v, 1);
|
||
|
}
|
||
|
|
||
|
export function strip<T extends object = 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 (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<Value<T>, T>(v.item)) {
|
||
|
return v.item.mapEntries((e) => [walk(e[0]), walk(e[1])]);
|
||
|
} else if (Annotated.isAnnotated(v.item)) {
|
||
|
throw new Error("Improper annotation structure");
|
||
|
} else {
|
||
|
return v.item;
|
||
|
}
|
||
|
}
|
||
|
return step(v, depth);
|
||
|
}
|