Repair embedded reading; and preserve annotations in generic embedded values

This commit is contained in:
Tony Garnock-Jones 2021-06-01 16:46:23 +02:00
parent 9014a0ffb8
commit 498c63ef67
6 changed files with 22 additions and 9 deletions

View File

@ -8,6 +8,7 @@ import { Bytes, BytesLike, underlying } from "./bytes";
import { Value } from "./values"; import { Value } from "./values";
import { is } from "./is"; import { is } from "./is";
import { embed, GenericEmbedded, Embedded, EmbeddedTypeDecode } from "./embedded"; import { embed, GenericEmbedded, Embedded, EmbeddedTypeDecode } from "./embedded";
import { ReaderStateOptions } from "reader";
export interface DecoderOptions { export interface DecoderOptions {
includeAnnotations?: boolean; includeAnnotations?: boolean;
@ -166,7 +167,7 @@ export const neverEmbeddedTypeDecode: EmbeddedTypeDecode<never> = {
throw new Error("Embeddeds not permitted at this point in Preserves document"); throw new Error("Embeddeds not permitted at this point in Preserves document");
}, },
fromValue(_v: Value<GenericEmbedded>): never { fromValue(_v: Value<GenericEmbedded>, _options: ReaderStateOptions): never {
throw new Error("Embeddeds not permitted at this point in Preserves document"); throw new Error("Embeddeds not permitted at this point in Preserves document");
}, },
}; };

View File

@ -1,6 +1,7 @@
import type { EncoderState } from "./encoder"; import type { EncoderState } from "./encoder";
import type { DecoderState } from "./decoder"; import type { DecoderState } from "./decoder";
import type { Value } from "./values"; import type { Value } from "./values";
import { ReaderStateOptions } from "./reader";
export type EmbeddedTypeEncode<T> = { export type EmbeddedTypeEncode<T> = {
encode(s: EncoderState, v: T): void; encode(s: EncoderState, v: T): void;
@ -9,7 +10,7 @@ export type EmbeddedTypeEncode<T> = {
export type EmbeddedTypeDecode<T> = { export type EmbeddedTypeDecode<T> = {
decode(s: DecoderState): T; decode(s: DecoderState): T;
fromValue(v: Value<GenericEmbedded>): T; fromValue(v: Value<GenericEmbedded>, options: ReaderStateOptions): T;
} }
export type EmbeddedType<T> = EmbeddedTypeEncode<T> & EmbeddedTypeDecode<T>; export type EmbeddedType<T> = EmbeddedTypeEncode<T> & EmbeddedTypeDecode<T>;

View File

@ -1,6 +1,6 @@
import { GenericEmbedded, EmbeddedType, EmbeddedTypeDecode, EmbeddedTypeEncode } from "./embedded"; import { GenericEmbedded, EmbeddedType, EmbeddedTypeDecode, EmbeddedTypeEncode } from "./embedded";
import { Encoder, EncoderState, identityEmbeddedTypeEncode } from "./encoder"; import { Encoder, EncoderState, identityEmbeddedTypeEncode } from "./encoder";
import { genericEmbeddedTypeDecode } from "./reader"; import { genericEmbeddedTypeDecode, ReaderStateOptions } from "./reader";
import { Value } from "./values"; import { Value } from "./values";
import { DecoderState, neverEmbeddedTypeDecode } from "./decoder"; import { DecoderState, neverEmbeddedTypeDecode } from "./decoder";
@ -39,7 +39,7 @@ export const identityEmbeddedTypeDecode: EmbeddedTypeDecode<any> = {
throw new Error("Cannot decode identityEmbeddedType"); throw new Error("Cannot decode identityEmbeddedType");
}, },
fromValue(_v: Value<GenericEmbedded>): any { fromValue(_v: Value<GenericEmbedded>, _options: ReaderStateOptions): any {
throw new Error("Cannot decode identityEmbeddedType"); throw new Error("Cannot decode identityEmbeddedType");
}, },
}; };

View File

@ -280,8 +280,8 @@ export const genericEmbeddedTypeDecode: EmbeddedTypeDecode<GenericEmbedded> = {
return new GenericEmbedded(new Decoder(s, this).next()); return new GenericEmbedded(new Decoder(s, this).next());
}, },
fromValue(v: Value<GenericEmbedded>): GenericEmbedded { fromValue(v: Value<GenericEmbedded>, options: ReaderStateOptions): GenericEmbedded {
return new GenericEmbedded(strip(v)); return new GenericEmbedded(options.includeAnnotations ? v : strip(v));
}, },
}; };
@ -393,7 +393,8 @@ export class Reader<T> {
}); });
} }
case '!': return embed(this.embeddedType.fromValue( case '!': return embed(this.embeddedType.fromValue(
new Reader<GenericEmbedded>(this.state, genericEmbeddedTypeDecode).next())); new Reader<GenericEmbedded>(this.state, genericEmbeddedTypeDecode).next(),
this.state.options));
default: default:
this.state.error(`Invalid # syntax: ${c}`, startPos); this.state.error(`Invalid # syntax: ${c}`, startPos);
} }

View File

@ -259,7 +259,7 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
} else if (isCompound(item)) { } else if (isCompound(item)) {
return kf(); return kf();
} else if (isEmbedded(item)) { } else if (isEmbedded(item)) {
return ks(M.SimplePattern.embedded(walkSimple(item.embeddedValue))); return ks(M.SimplePattern.embedded(walkSimple(item.embeddedValue.generic)));
} else { } else {
return ks(M.SimplePattern.lit(strip(item))); return ks(M.SimplePattern.lit(strip(item)));
} }

View File

@ -1,4 +1,4 @@
import { readSchema } from '../src/index'; import { readSchema, Meta } from '../src/index';
describe('reader schema', () => { describe('reader schema', () => {
it('complains about bad version', () => { it('complains about bad version', () => {
@ -13,4 +13,14 @@ describe('reader schema', () => {
expect(s.definitions.size).toBe(0); expect(s.definitions.size).toBe(0);
expect(s.embeddedType._variant).toBe('false'); expect(s.embeddedType._variant).toBe('false');
}); });
it('understands patterns under embed', () => {
const s = readSchema('version 1 . X = #!0 .');
const def: Meta.Definition = s.definitions.get(Symbol.for('X'))!;
if (def._variant !== 'Pattern') fail('bad definition 1');
if (def.value._variant !== 'SimplePattern') fail ('bad definition 2');
if (def.value.value._variant !== 'embedded') fail('bad definition 3');
const i = def.value.value.interface;
if (i._variant !== 'lit') fail('Non-tuple embedded pattern');
expect(i.value).toBe(0);
});
}); });