Convert P-expressions to preserves values

This commit is contained in:
Tony Garnock-Jones 2024-05-02 21:26:48 +02:00
parent dc61963e16
commit 64c1090938
2 changed files with 48 additions and 10 deletions

View File

@ -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<I> {
@ -33,36 +41,65 @@ export class BaseCompound<I> {
}
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<Expr> {}
export class Document extends BaseCompound<Expr> {
__as_preserve__(): Value {
return this.preservesValues();
}
}
export class Annotations extends BaseCompound<SimpleExpr> {}
export class Annotations extends BaseCompound<SimpleExpr> {
wrap(v: Value): Value {
return annotate(v, ... this.preservesValues());
}
}
export type CompoundVariant = 'sequence' | 'record' | 'block' | 'group' | 'set';
export abstract class Compound extends BaseCompound<Expr> {
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<never> {

View File

@ -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<bar {zot ::quux}, [a; b; c;]>');
const d = r.nextDocument();
console.dir(d, { depth: null });
console.log(stringify(d, { indent: 4 }));
});
});