Convert P-expressions to preserves values
This commit is contained in:
parent
dc61963e16
commit
64c1090938
|
@ -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> {
|
||||
|
|
|
@ -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 }));
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue