diff --git a/implementations/javascript/packages/core/src/pexpr.ts b/implementations/javascript/packages/core/src/pexpr.ts index f66e292..7315a46 100644 --- a/implementations/javascript/packages/core/src/pexpr.ts +++ b/implementations/javascript/packages/core/src/pexpr.ts @@ -1,18 +1,26 @@ // Preserves-Expressions. https://preserves.dev/preserves-expressions.html import { ReaderBase } from './reader'; -import { Atom } from './values'; -import { Position } from './annotated'; +import { Atom, Value } from './values'; +import { Position, annotate } from './annotated'; +import { Record as VRecord } from './record'; +import { GenericEmbedded } from './embedded'; +import { fromJS } from './fromjs'; export type Expr = SimpleExpr | Punct; export type SimpleExpr = Atom | Compound | Embedded; export class Punct { constructor(public text: string) {} + __as_preserve__(): Value { return VRecord(Symbol.for('p'), [Symbol.for(this.text)]); } } export class Embedded { constructor(public expr: SimpleExpr, public annotations?: Annotations) {} + __as_preserve__(): Value { + const v = fromJS(this.expr); + return new GenericEmbedded(this.annotations?.wrap(v) ?? v); + } } export class BaseCompound { @@ -33,36 +41,65 @@ export class BaseCompound { } return this.annotations[index]; } + + preservesValues(): Value[] { + return this.exprs.map((p, i) => { + const v = fromJS(p); + if (this.annotations?.[i] !== void 0) { + return this.annotations[i].wrap(v); + } else { + return v; + } + }); + } } -export class Document extends BaseCompound {} +export class Document extends BaseCompound { + __as_preserve__(): Value { + return this.preservesValues(); + } +} -export class Annotations extends BaseCompound {} +export class Annotations extends BaseCompound { + wrap(v: Value): Value { + return annotate(v, ... this.preservesValues()); + } +} export type CompoundVariant = 'sequence' | 'record' | 'block' | 'group' | 'set'; export abstract class Compound extends BaseCompound { abstract get variant(): CompoundVariant; + __as_preserve__(): Value { + const vs = this.preservesValues(); + switch (this.variant) { + case 'sequence': return vs; + case 'record': return VRecord(Symbol.for('r'), vs); + case 'block': return VRecord(Symbol.for('b'), vs); + case 'group': return VRecord(Symbol.for('g'), vs); + case 'set': return VRecord(Symbol.for('s'), vs); + } + } } export class Sequence extends Compound { - readonly variant = 'sequence'; + get variant(): CompoundVariant { return 'sequence'; } } export class Record extends Compound { - readonly variant = 'record'; + get variant(): CompoundVariant { return 'record'; } } export class Block extends Compound { - readonly variant = 'block'; + get variant(): CompoundVariant { return 'block'; } } export class Group extends Compound { - readonly variant = 'group'; + get variant(): CompoundVariant { return 'group'; } } export class Set extends Compound { - readonly variant = 'set'; + get variant(): CompoundVariant { return 'set'; } } export class Reader extends ReaderBase { diff --git a/implementations/javascript/packages/core/test/pexpr.test.ts b/implementations/javascript/packages/core/test/pexpr.test.ts index f93ed6a..7a19d5a 100644 --- a/implementations/javascript/packages/core/test/pexpr.test.ts +++ b/implementations/javascript/packages/core/test/pexpr.test.ts @@ -1,4 +1,4 @@ -import { Pexpr } from '../src/index'; +import { Pexpr, stringify } from '../src/index'; import './test-utils'; describe('basics', () => { @@ -6,5 +6,6 @@ describe('basics', () => { const r = new Pexpr.Reader('#!foo\n'); const d = r.nextDocument(); console.dir(d, { depth: null }); + console.log(stringify(d, { indent: 4 })); }); });