import { Encoder } from "./encoder"; import { Tag } from "./constants"; import { AsPreserve, PreserveOn } from "./symbols"; import { DefaultPointer, Value } from "./values"; import { is, isAnnotated, IsPreservesAnnotated } from './is'; export class Annotated { readonly annotations: Array>; readonly item: Value; constructor(item: Value) { this.annotations = []; this.item = item; } [AsPreserve](): Value { return this; } [PreserveOn](encoder: Encoder) { if (encoder.includeAnnotations) { for (const a of this.annotations) { encoder.emitbyte(Tag.Annotation); encoder.push(a); } } encoder.push(this.item); } equals(other: any): boolean { return is(this.item, Annotated.isAnnotated(other) ? other.item : other); } // hashCode(): number { // return hash(this.item); // } toString(): string { return this.asPreservesText(); } asPreservesText(): string { const anns = this.annotations.map((a) => '@' + a.asPreservesText()).join(' '); return (anns ? anns + ' ' : anns) + this.item.asPreservesText(); } get [IsPreservesAnnotated](): boolean { return true; } static isAnnotated(x: any): x is Annotated { return isAnnotated(x); } } export function annotate(v0: Value, ...anns: Value[]): Annotated { const v = Annotated.isAnnotated(v0) ? v0 : new Annotated(v0); anns.forEach((a) => v.annotations.push(a)); return v; }