"use strict"; // Preserves Annotations. if (require('./singletonmodule.js')('leastfixedpoint.com/preserves', require('../package.json').version, 'annotations.js', module)) return; const { Record, List, Map, Set, is, hash } = require('./values.js'); const { PreserveOn, AsPreserve } = require('./symbols.js'); function Annotated(item) { this.annotations = []; this.item = item; } Annotated.prototype[AsPreserve] = function () { return this; }; Annotated.prototype[PreserveOn] = function (encoder) { for (const a of this.annotations) { encoder.header(0, 0, 5); encoder.push(a); } encoder.push(this.item); }; Annotated.prototype.strip = function (depth) { return stripAnnotations(this, depth); }; Annotated.prototype.peel = function () { return stripAnnotations(this, 1); }; Annotated.prototype.equals = function (other) { return isAnnotated(other) && is(this.item, other.item); }; Annotated.prototype.hashCode = function () { return hash(this.item); }; function isAnnotated(v) { return (v instanceof Annotated); } function stripAnnotations(v, depth) { function step(v, depth) { if (depth === 0) return v; if (!isAnnotated(v)) return v; const nextDepth = depth - 1; function walk(v) { return step(v, nextDepth); } if (v.item instanceof Record) { return new Record(step(v.item.label, depth), v.item.fields.map(walk)); } else if (List.isList(v.item)) { return v.item.map(walk); } else if (Set.isSet(v.item)) { return v.item.map(walk); } else if (Map.isMap(v.item)) { return v.item.mapEntries((e) => [walk(e[0]), walk(e[1])]); } else if (isAnnotated(v.item)) { const e = new Error("Improper annotation structure"); e.irritant = v; throw e; } else { return v.item; } } return step(v, (depth === void 0) ? Infinity : depth); } function annotate(v, ...anns) { if (!isAnnotated(v)) { v = new Annotated(v); } anns.forEach((a) => v.annotations.push(a)); return v; } Object.assign(module.exports, { Annotated, isAnnotated, stripAnnotations, annotate, });