The Great Renaming: Pointer -> Embedded

This commit is contained in:
Tony Garnock-Jones 2021-05-17 14:54:06 +02:00
parent 6fc41ead6f
commit e4a2503899
60 changed files with 525 additions and 515 deletions

View File

@ -38,7 +38,7 @@ representations of their keys.[^no-need-for-by-value]
**Other kinds of `Value`.** **Other kinds of `Value`.**
There are no special canonicalization restrictions on There are no special canonicalization restrictions on
`SignedInteger`s, `String`s, `ByteString`s, `Symbol`s, `Boolean`s, `SignedInteger`s, `String`s, `ByteString`s, `Symbol`s, `Boolean`s,
`Float`s, `Double`s, `Record`s, `Sequence`s, or `Pointer`s. The `Float`s, `Double`s, `Record`s, `Sequence`s, or `Embedded`s. The
constraints given for these `Value`s in the [specification][spec] constraints given for these `Value`s in the [specification][spec]
suffice to ensure canonicity. suffice to ensure canonicity.

View File

@ -1,6 +1,6 @@
{ {
"name": "@preserves/core", "name": "@preserves/core",
"version": "0.14.0", "version": "0.15.0",
"description": "Preserves data serialization format", "description": "Preserves data serialization format",
"homepage": "https://gitlab.com/preserves/preserves", "homepage": "https://gitlab.com/preserves/preserves",
"license": "Apache-2.0", "license": "Apache-2.0",

View File

@ -4,7 +4,7 @@ import { AsPreserve, PreserveOn } from "./symbols";
import { Value } from "./values"; import { Value } from "./values";
import { is, isAnnotated, IsPreservesAnnotated } from "./is"; import { is, isAnnotated, IsPreservesAnnotated } from "./is";
import { stringify } from "./text"; import { stringify } from "./text";
import { GenericPointer } from "./pointer"; import { GenericEmbedded } from "./embedded";
export interface Position { export interface Position {
line?: number; line?: number;
@ -53,7 +53,7 @@ export function formatPosition(p: Position | null | string): string {
} }
} }
export class Annotated<T = GenericPointer> { export class Annotated<T = GenericEmbedded> {
readonly annotations: Array<Value<T>>; readonly annotations: Array<Value<T>>;
readonly pos: Position | null; readonly pos: Position | null;
readonly item: Value<T>; readonly item: Value<T>;
@ -99,17 +99,17 @@ export class Annotated<T = GenericPointer> {
return true; return true;
} }
static isAnnotated<T = GenericPointer>(x: any): x is Annotated<T> { static isAnnotated<T = GenericEmbedded>(x: any): x is Annotated<T> {
return isAnnotated(x); return isAnnotated(x);
} }
} }
export function annotate<T = GenericPointer>(v0: Value<T>, ...anns: Value<T>[]): Annotated<T> { export function annotate<T = GenericEmbedded>(v0: Value<T>, ...anns: Value<T>[]): Annotated<T> {
const v = Annotated.isAnnotated<T>(v0) ? v0 : new Annotated(v0); const v = Annotated.isAnnotated<T>(v0) ? v0 : new Annotated(v0);
anns.forEach((a) => v.annotations.push(a)); anns.forEach((a) => v.annotations.push(a));
return v; return v;
} }
export function position<T = GenericPointer>(v: Value<T>): Position | null { export function position<T = GenericEmbedded>(v: Value<T>): Position | null {
return Annotated.isAnnotated<T>(v) ? v.pos : null; return Annotated.isAnnotated<T>(v) ? v.pos : null;
} }

View File

@ -2,7 +2,7 @@ import { Tag } from './constants';
import { AsPreserve, PreserveOn } from './symbols'; import { AsPreserve, PreserveOn } from './symbols';
import { Encoder, Preservable } from './encoder'; import { Encoder, Preservable } from './encoder';
import { Value } from './values'; import { Value } from './values';
import { GenericPointer } from './pointer'; import { GenericEmbedded } from './embedded';
const textEncoder = new TextEncoder(); const textEncoder = new TextEncoder();
const textDecoder = new TextDecoder(); const textDecoder = new TextDecoder();
@ -127,7 +127,7 @@ export class Bytes implements Preservable<never> {
return this.asPreservesText(); return this.asPreservesText();
} }
[AsPreserve]<T = GenericPointer>(): Value<T> { [AsPreserve]<T = GenericEmbedded>(): Value<T> {
return this; return this;
} }

View File

@ -1,8 +1,8 @@
import type { Compound, Value } from "./values"; import type { Compound, Value } from "./values";
import type { GenericPointer } from "./pointer"; import type { GenericEmbedded } from "./embedded";
import { Dictionary, Set } from "./dictionary"; import { Dictionary, Set } from "./dictionary";
export function isCompound<T = GenericPointer>(x: Value<T>): x is Compound<T> export function isCompound<T = GenericEmbedded>(x: Value<T>): x is Compound<T>
{ {
return (Array.isArray(x) || Set.isSet(x) || Dictionary.isDictionary(x)); return (Array.isArray(x) || Set.isSet(x) || Dictionary.isDictionary(x));
} }

View File

@ -5,7 +5,7 @@ export enum Tag {
Double, Double,
End, End,
Annotation, Annotation,
Pointer, Embedded,
SmallInteger_lo = 0x90, SmallInteger_lo = 0x90,
MediumInteger_lo = 0xa0, MediumInteger_lo = 0xa0,

View File

@ -7,14 +7,14 @@ import { Record } from "./record";
import { Bytes, BytesLike, underlying } from "./bytes"; import { Bytes, BytesLike, underlying } from "./bytes";
import { Value } from "./values"; import { Value } from "./values";
import { is } from "./is"; import { is } from "./is";
import { embed, GenericPointer, Pointer, PointerTypeDecode } from "./pointer"; import { embed, GenericEmbedded, Embedded, EmbeddedTypeDecode } from "./embedded";
export interface DecoderOptions { export interface DecoderOptions {
includeAnnotations?: boolean; includeAnnotations?: boolean;
} }
export interface DecoderPointerOptions<T> extends DecoderOptions { export interface DecoderEmbeddedOptions<T> extends DecoderOptions {
pointerDecode?: PointerTypeDecode<T>; embeddedDecode?: EmbeddedTypeDecode<T>;
} }
export interface TypedDecoder<T> { export interface TypedDecoder<T> {
@ -25,14 +25,14 @@ export interface TypedDecoder<T> {
skip(): void; skip(): void;
next(): Value<T>; next(): Value<T>;
withPointerDecode<S, R>( withEmbeddedDecode<S, R>(
pointerDecode: PointerTypeDecode<S>, embeddedDecode: EmbeddedTypeDecode<S>,
body: (d: TypedDecoder<S>) => R): R; body: (d: TypedDecoder<S>) => R): R;
nextBoolean(): boolean | undefined; nextBoolean(): boolean | undefined;
nextFloat(): SingleFloat | undefined; nextFloat(): SingleFloat | undefined;
nextDouble(): DoubleFloat | undefined; nextDouble(): DoubleFloat | undefined;
nextPointer(): Pointer<T> | undefined; nextEmbedded(): Embedded<T> | undefined;
nextSignedInteger(): number | undefined; nextSignedInteger(): number | undefined;
nextString(): string | undefined; nextString(): string | undefined;
nextByteString(): Bytes | undefined; nextByteString(): Bytes | undefined;
@ -161,33 +161,33 @@ export class DecoderState {
} }
} }
export const neverPointerTypeDecode: PointerTypeDecode<never> = { export const neverEmbeddedTypeDecode: EmbeddedTypeDecode<never> = {
decode(_s: DecoderState): never { decode(_s: DecoderState): never {
throw new Error("Pointers not permitted at this point in Preserves document"); throw new Error("Embeddeds not permitted at this point in Preserves document");
}, },
fromValue(_v: Value<GenericPointer>): never { fromValue(_v: Value<GenericEmbedded>): never {
throw new Error("Pointers not permitted at this point in Preserves document"); throw new Error("Embeddeds not permitted at this point in Preserves document");
}, },
}; };
export class Decoder<T = never> implements TypedDecoder<T> { export class Decoder<T = never> implements TypedDecoder<T> {
state: DecoderState; state: DecoderState;
pointerDecode: PointerTypeDecode<T>; embeddedDecode: EmbeddedTypeDecode<T>;
constructor(state: DecoderState, pointerDecode?: PointerTypeDecode<T>); constructor(state: DecoderState, embeddedDecode?: EmbeddedTypeDecode<T>);
constructor(packet?: BytesLike, options?: DecoderPointerOptions<T>); constructor(packet?: BytesLike, options?: DecoderEmbeddedOptions<T>);
constructor( constructor(
packet_or_state: (DecoderState | BytesLike) = new Uint8Array(0), packet_or_state: (DecoderState | BytesLike) = new Uint8Array(0),
options_or_pointerDecode?: (DecoderPointerOptions<T> | PointerTypeDecode<T>)) options_or_embeddedDecode?: (DecoderEmbeddedOptions<T> | EmbeddedTypeDecode<T>))
{ {
if (packet_or_state instanceof DecoderState) { if (packet_or_state instanceof DecoderState) {
this.state = packet_or_state; this.state = packet_or_state;
this.pointerDecode = (options_or_pointerDecode as PointerTypeDecode<T>) ?? neverPointerTypeDecode; this.embeddedDecode = (options_or_embeddedDecode as EmbeddedTypeDecode<T>) ?? neverEmbeddedTypeDecode;
} else { } else {
const options = (options_or_pointerDecode as DecoderPointerOptions<T>) ?? {}; const options = (options_or_embeddedDecode as DecoderEmbeddedOptions<T>) ?? {};
this.state = new DecoderState(packet_or_state, options); this.state = new DecoderState(packet_or_state, options);
this.pointerDecode = options.pointerDecode ?? neverPointerTypeDecode; this.embeddedDecode = options.embeddedDecode ?? neverEmbeddedTypeDecode;
} }
} }
@ -223,7 +223,7 @@ export class Decoder<T = never> implements TypedDecoder<T> {
const v = this.next() as Annotated<T>; const v = this.next() as Annotated<T>;
return this.state.unshiftAnnotation(a, v); return this.state.unshiftAnnotation(a, v);
} }
case Tag.Pointer: return this.state.wrap<T>(embed(this.pointerDecode.decode(this.state))); case Tag.Embedded: return this.state.wrap<T>(embed(this.embeddedDecode.decode(this.state)));
case Tag.SignedInteger: return this.state.wrap<T>(this.state.nextint(this.state.varint())); case Tag.SignedInteger: return this.state.wrap<T>(this.state.nextint(this.state.varint()));
case Tag.String: return this.state.wrap<T>(Bytes.from(this.state.nextbytes(this.state.varint())).fromUtf8()); case Tag.String: return this.state.wrap<T>(Bytes.from(this.state.nextbytes(this.state.varint())).fromUtf8());
case Tag.ByteString: return this.state.wrap<T>(Bytes.from(this.state.nextbytes(this.state.varint()))); case Tag.ByteString: return this.state.wrap<T>(Bytes.from(this.state.nextbytes(this.state.varint())));
@ -267,11 +267,11 @@ export class Decoder<T = never> implements TypedDecoder<T> {
this.next(); this.next();
} }
withPointerDecode<S, R>( withEmbeddedDecode<S, R>(
pointerDecode: PointerTypeDecode<S>, embeddedDecode: EmbeddedTypeDecode<S>,
body: (d: TypedDecoder<S>) => R): R body: (d: TypedDecoder<S>) => R): R
{ {
return body(new Decoder(this.state, pointerDecode)); return body(new Decoder(this.state, embeddedDecode));
} }
skipAnnotations(): void { skipAnnotations(): void {
@ -306,10 +306,10 @@ export class Decoder<T = never> implements TypedDecoder<T> {
} }
} }
nextPointer(): Pointer<T> | undefined { nextEmbedded(): Embedded<T> | undefined {
this.skipAnnotations(); this.skipAnnotations();
switch (this.state.nextbyte()) { switch (this.state.nextbyte()) {
case Tag.Pointer: return embed(this.pointerDecode.decode(this.state)); case Tag.Embedded: return embed(this.embeddedDecode.decode(this.state));
default: return void 0; default: return void 0;
} }
} }
@ -374,11 +374,11 @@ export class Decoder<T = never> implements TypedDecoder<T> {
} }
} }
export function decode<T>(bs: BytesLike, options: DecoderPointerOptions<T> = {}): Value<T> { export function decode<T>(bs: BytesLike, options: DecoderEmbeddedOptions<T> = {}): Value<T> {
return new Decoder(bs, options).next(); return new Decoder(bs, options).next();
} }
export function decodeWithAnnotations<T>(bs: BytesLike, export function decodeWithAnnotations<T>(bs: BytesLike,
options: DecoderPointerOptions<T> = {}): Annotated<T> { options: DecoderEmbeddedOptions<T> = {}): Annotated<T> {
return decode(bs, { ... options, includeAnnotations: true }) as Annotated<T>; return decode(bs, { ... options, includeAnnotations: true }) as Annotated<T>;
} }

View File

@ -5,17 +5,17 @@ import { PreserveOn } from "./symbols";
import { stringify } from "./text"; import { stringify } from "./text";
import { Value } from "./values"; import { Value } from "./values";
import { Bytes } from './bytes'; import { Bytes } from './bytes';
import { GenericPointer } from "./pointer"; import { GenericEmbedded } from "./embedded";
export type DictionaryType = 'Dictionary' | 'Set'; export type DictionaryType = 'Dictionary' | 'Set';
export const DictionaryType = Symbol.for('DictionaryType'); export const DictionaryType = Symbol.for('DictionaryType');
export class KeyedDictionary<K extends Value<T>, V, T = GenericPointer> extends FlexMap<K, V> { export class KeyedDictionary<K extends Value<T>, V, T = GenericEmbedded> extends FlexMap<K, V> {
get [DictionaryType](): DictionaryType { get [DictionaryType](): DictionaryType {
return 'Dictionary'; return 'Dictionary';
} }
static isKeyedDictionary<K extends Value<T>, V, T = GenericPointer>(x: any): x is KeyedDictionary<K, V, T> { static isKeyedDictionary<K extends Value<T>, V, T = GenericEmbedded>(x: any): x is KeyedDictionary<K, V, T> {
return x?.[DictionaryType] === 'Dictionary'; return x?.[DictionaryType] === 'Dictionary';
} }
@ -25,7 +25,7 @@ export class KeyedDictionary<K extends Value<T>, V, T = GenericPointer> extends
super(canonicalString, items); super(canonicalString, items);
} }
mapEntries<W, S extends Value<R>, R = GenericPointer>(f: (entry: [K, V]) => [S, W]): KeyedDictionary<S, W, R> { mapEntries<W, S extends Value<R>, R = GenericEmbedded>(f: (entry: [K, V]) => [S, W]): KeyedDictionary<S, W, R> {
const result = new KeyedDictionary<S, W, R>(); const result = new KeyedDictionary<S, W, R>();
for (let oldEntry of this.entries()) { for (let oldEntry of this.entries()) {
const newEntry = f(oldEntry); const newEntry = f(oldEntry);
@ -74,18 +74,18 @@ export class KeyedDictionary<K extends Value<T>, V, T = GenericPointer> extends
} }
} }
export class Dictionary<T = GenericPointer, V = Value<T>> extends KeyedDictionary<Value<T>, V, T> { export class Dictionary<T = GenericEmbedded, V = Value<T>> extends KeyedDictionary<Value<T>, V, T> {
static isDictionary<T = GenericPointer, V = Value<T>>(x: any): x is Dictionary<T, V> { static isDictionary<T = GenericEmbedded, V = Value<T>>(x: any): x is Dictionary<T, V> {
return x?.[DictionaryType] === 'Dictionary'; return x?.[DictionaryType] === 'Dictionary';
} }
} }
export class KeyedSet<K extends Value<T>, T = GenericPointer> extends FlexSet<K> { export class KeyedSet<K extends Value<T>, T = GenericEmbedded> extends FlexSet<K> {
get [DictionaryType](): DictionaryType { get [DictionaryType](): DictionaryType {
return 'Set'; return 'Set';
} }
static isKeyedSet<K extends Value<T>, T = GenericPointer>(x: any): x is KeyedSet<K, T> { static isKeyedSet<K extends Value<T>, T = GenericEmbedded>(x: any): x is KeyedSet<K, T> {
return x?.[DictionaryType] === 'Set'; return x?.[DictionaryType] === 'Set';
} }
@ -93,7 +93,7 @@ export class KeyedSet<K extends Value<T>, T = GenericPointer> extends FlexSet<K>
super(canonicalString, items); super(canonicalString, items);
} }
map<S extends Value<R>, R = GenericPointer>(f: (value: K) => S): KeyedSet<S, R> { map<S extends Value<R>, R = GenericEmbedded>(f: (value: K) => S): KeyedSet<S, R> {
return new KeyedSet(_iterMap(this[Symbol.iterator](), f)); return new KeyedSet(_iterMap(this[Symbol.iterator](), f));
} }
@ -130,8 +130,8 @@ export class KeyedSet<K extends Value<T>, T = GenericPointer> extends FlexSet<K>
} }
} }
export class Set<T = GenericPointer> extends KeyedSet<Value<T>, T> { export class Set<T = GenericEmbedded> extends KeyedSet<Value<T>, T> {
static isSet<T = GenericPointer>(x: any): x is Set<T> { static isSet<T = GenericEmbedded>(x: any): x is Set<T> {
return x?.[DictionaryType] === 'Set'; return x?.[DictionaryType] === 'Set';
} }
} }

View File

@ -2,19 +2,19 @@ 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";
export type PointerTypeEncode<T> = { export type EmbeddedTypeEncode<T> = {
encode(s: EncoderState, v: T): void; encode(s: EncoderState, v: T): void;
toValue(v: T): Value<GenericPointer>; toValue(v: T): Value<GenericEmbedded>;
} }
export type PointerTypeDecode<T> = { export type EmbeddedTypeDecode<T> = {
decode(s: DecoderState): T; decode(s: DecoderState): T;
fromValue(v: Value<GenericPointer>): T; fromValue(v: Value<GenericEmbedded>): T;
} }
export type PointerType<T> = PointerTypeEncode<T> & PointerTypeDecode<T>; export type EmbeddedType<T> = EmbeddedTypeEncode<T> & EmbeddedTypeDecode<T>;
export class Pointer<T> { export class Embedded<T> {
embeddedValue: T; embeddedValue: T;
constructor(embeddedValue: T) { constructor(embeddedValue: T) {
@ -22,7 +22,7 @@ export class Pointer<T> {
} }
equals(other: any, is: (a: any, b: any) => boolean) { equals(other: any, is: (a: any, b: any) => boolean) {
return isPointer<T>(other) && is(this.embeddedValue, other.embeddedValue); return isEmbedded<T>(other) && is(this.embeddedValue, other.embeddedValue);
} }
asPreservesText(): string { asPreservesText(): string {
@ -30,15 +30,15 @@ export class Pointer<T> {
} }
} }
export function embed<T>(embeddedValue: T): Pointer<T> { export function embed<T>(embeddedValue: T): Embedded<T> {
return new Pointer(embeddedValue); return new Embedded(embeddedValue);
} }
export function isPointer<T>(v: Value<T>): v is Pointer<T> { export function isEmbedded<T>(v: Value<T>): v is Embedded<T> {
return typeof v === 'object' && 'embeddedValue' in v; return typeof v === 'object' && 'embeddedValue' in v;
} }
export class GenericPointer { export class GenericEmbedded {
generic: Value; generic: Value;
constructor(generic: Value) { constructor(generic: Value) {

View File

@ -0,0 +1,50 @@
import { GenericEmbedded, EmbeddedType, EmbeddedTypeDecode, EmbeddedTypeEncode } from "./embedded";
import { Encoder, EncoderState, identityEmbeddedTypeEncode } from "./encoder";
import { genericEmbeddedTypeDecode } from "./reader";
import { Value } from "./values";
import { DecoderState, neverEmbeddedTypeDecode } from "./decoder";
export const genericEmbeddedTypeEncode: EmbeddedTypeEncode<GenericEmbedded> = {
encode(s: EncoderState, v: GenericEmbedded): void {
new Encoder(s, this).push(v.generic);
},
toValue(v: GenericEmbedded): Value<GenericEmbedded> {
return v.generic;
}
};
export const genericEmbeddedType: EmbeddedType<GenericEmbedded> =
Object.assign({},
genericEmbeddedTypeDecode,
genericEmbeddedTypeEncode);
export const neverEmbeddedTypeEncode: EmbeddedTypeEncode<never> = {
encode(_s: EncoderState, _v: never): void {
throw new Error("Embeddeds not permitted encoding Preserves document");
},
toValue(_v: never): Value<GenericEmbedded> {
throw new Error("Embeddeds not permitted encoding Preserves document");
}
};
export const neverEmbeddedType: EmbeddedType<never> =
Object.assign({},
neverEmbeddedTypeDecode,
neverEmbeddedTypeEncode);
export const identityEmbeddedTypeDecode: EmbeddedTypeDecode<any> = {
decode(_s: DecoderState): any {
throw new Error("Cannot decode identityEmbeddedType");
},
fromValue(_v: Value<GenericEmbedded>): any {
throw new Error("Cannot decode identityEmbeddedType");
},
};
export const identityEmbeddedType: EmbeddedType<any> =
Object.assign({},
identityEmbeddedTypeDecode,
identityEmbeddedTypeEncode);

View File

@ -4,7 +4,7 @@ import { Value } from "./values";
import { PreserveOn } from "./symbols"; import { PreserveOn } from "./symbols";
import { EncodeError } from "./codec"; import { EncodeError } from "./codec";
import { Record, Tuple } from "./record"; import { Record, Tuple } from "./record";
import { GenericPointer, PointerTypeEncode } from "./pointer"; import { GenericEmbedded, EmbeddedTypeEncode } from "./embedded";
export type Encodable<T> = export type Encodable<T> =
Value<T> | Preservable<T> | Iterable<Value<T>> | ArrayBufferView; Value<T> | Preservable<T> | Iterable<Value<T>> | ArrayBufferView;
@ -22,8 +22,8 @@ export interface EncoderOptions {
includeAnnotations?: boolean; includeAnnotations?: boolean;
} }
export interface EncoderPointerOptions<T> extends EncoderOptions { export interface EncoderEmbeddedOptions<T> extends EncoderOptions {
pointerEncode?: PointerTypeEncode<T>; embeddedEncode?: EmbeddedTypeEncode<T>;
} }
export function asLatin1(bs: Uint8Array): string { export function asLatin1(bs: Uint8Array): string {
@ -36,7 +36,7 @@ function isIterable<T>(v: any): v is Iterable<T> {
let _nextId = 0; let _nextId = 0;
const _registry = new WeakMap<object, number>(); const _registry = new WeakMap<object, number>();
export function pointerId(v: any): number { export function embeddedId(v: any): number {
let id = _registry.get(v); let id = _registry.get(v);
if (id === void 0) { if (id === void 0) {
id = _nextId++; id = _nextId++;
@ -45,13 +45,13 @@ export function pointerId(v: any): number {
return id; return id;
} }
export const identityPointerTypeEncode: PointerTypeEncode<any> = { export const identityEmbeddedTypeEncode: EmbeddedTypeEncode<any> = {
encode(s: EncoderState, v: any): void { encode(s: EncoderState, v: any): void {
new Encoder(s, this).push(pointerId(v)); new Encoder(s, this).push(embeddedId(v));
}, },
toValue(v: any): Value<GenericPointer> { toValue(v: any): Value<GenericEmbedded> {
return pointerId(v); return embeddedId(v);
} }
}; };
@ -159,28 +159,28 @@ export class EncoderState {
export class Encoder<T = object> { export class Encoder<T = object> {
state: EncoderState; state: EncoderState;
pointerEncode: PointerTypeEncode<T>; embeddedEncode: EmbeddedTypeEncode<T>;
constructor(options: EncoderPointerOptions<T>); constructor(options: EncoderEmbeddedOptions<T>);
constructor(state: EncoderState, pointerEncode?: PointerTypeEncode<T>); constructor(state: EncoderState, embeddedEncode?: EmbeddedTypeEncode<T>);
constructor( constructor(
state_or_options: (EncoderState | EncoderPointerOptions<T>) = {}, state_or_options: (EncoderState | EncoderEmbeddedOptions<T>) = {},
pointerEncode?: PointerTypeEncode<T>) embeddedEncode?: EmbeddedTypeEncode<T>)
{ {
if (state_or_options instanceof EncoderState) { if (state_or_options instanceof EncoderState) {
this.state = state_or_options; this.state = state_or_options;
this.pointerEncode = pointerEncode ?? identityPointerTypeEncode; this.embeddedEncode = embeddedEncode ?? identityEmbeddedTypeEncode;
} else { } else {
this.state = new EncoderState(state_or_options); this.state = new EncoderState(state_or_options);
this.pointerEncode = state_or_options.pointerEncode ?? identityPointerTypeEncode; this.embeddedEncode = state_or_options.embeddedEncode ?? identityEmbeddedTypeEncode;
} }
} }
withPointerEncode<S>( withEmbeddedEncode<S>(
pointerEncode: PointerTypeEncode<S>, embeddedEncode: EmbeddedTypeEncode<S>,
body: (e: Encoder<S>) => void): this body: (e: Encoder<S>) => void): this
{ {
body(new Encoder(this.state, pointerEncode)); body(new Encoder(this.state, embeddedEncode));
return this; return this;
} }
@ -252,8 +252,8 @@ export class Encoder<T = object> {
this.encodevalues(Tag.Sequence, v as Iterable<Value<T>>); this.encodevalues(Tag.Sequence, v as Iterable<Value<T>>);
} }
else { else {
this.state.emitbyte(Tag.Pointer); this.state.emitbyte(Tag.Embedded);
this.pointerEncode.encode(this.state, v.embeddedValue); this.embeddedEncode.encode(this.state, v.embeddedValue);
} }
return this; // for chaining return this; // for chaining
} }
@ -261,7 +261,7 @@ export class Encoder<T = object> {
export function encode<T>( export function encode<T>(
v: Encodable<T>, v: Encodable<T>,
options: EncoderPointerOptions<T> = {}): Bytes options: EncoderEmbeddedOptions<T> = {}): Bytes
{ {
return new Encoder(options).push(v).contents(); return new Encoder(options).push(v).contents();
} }
@ -269,9 +269,9 @@ export function encode<T>(
const _canonicalEncoder = new Encoder({ canonical: true }); const _canonicalEncoder = new Encoder({ canonical: true });
let _usingCanonicalEncoder = false; let _usingCanonicalEncoder = false;
export function canonicalEncode(v: Encodable<never>, options?: EncoderPointerOptions<never>): Bytes; export function canonicalEncode(v: Encodable<never>, options?: EncoderEmbeddedOptions<never>): Bytes;
export function canonicalEncode(v: Encodable<any>, options?: EncoderPointerOptions<any>): Bytes; export function canonicalEncode(v: Encodable<any>, options?: EncoderEmbeddedOptions<any>): Bytes;
export function canonicalEncode(v: any, options?: EncoderPointerOptions<any>): Bytes { export function canonicalEncode(v: any, options?: EncoderEmbeddedOptions<any>): Bytes {
if (options === void 0 && !_usingCanonicalEncoder) { if (options === void 0 && !_usingCanonicalEncoder) {
_usingCanonicalEncoder = true; _usingCanonicalEncoder = true;
const bs = _canonicalEncoder.push(v).contents(); const bs = _canonicalEncoder.push(v).contents();
@ -294,6 +294,6 @@ export function canonicalString(v: Encodable<any>): string {
} }
export function encodeWithAnnotations<T>(v: Encodable<T>, export function encodeWithAnnotations<T>(v: Encodable<T>,
options: EncoderPointerOptions<T> = {}): Bytes { options: EncoderEmbeddedOptions<T> = {}): Bytes {
return encode(v, { ... options, includeAnnotations: true }); return encode(v, { ... options, includeAnnotations: true });
} }

View File

@ -2,7 +2,7 @@ import { Encoder, Preservable } from "./encoder";
import { Tag } from "./constants"; import { Tag } from "./constants";
import { AsPreserve, PreserveOn } from "./symbols"; import { AsPreserve, PreserveOn } from "./symbols";
import { Value } from "./values"; import { Value } from "./values";
import { GenericPointer } from "./pointer"; import { GenericEmbedded } from "./embedded";
export type FloatType = 'Single' | 'Double'; export type FloatType = 'Single' | 'Double';
export const FloatType = Symbol.for('FloatType'); export const FloatType = Symbol.for('FloatType');
@ -45,7 +45,7 @@ export function floatValue(f: any): number {
} }
export class SingleFloat extends Float implements Preservable<never> { export class SingleFloat extends Float implements Preservable<never> {
[AsPreserve]<T = GenericPointer>(): Value<T> { [AsPreserve]<T = GenericEmbedded>(): Value<T> {
return this; return this;
} }
@ -70,7 +70,7 @@ export function Single(value: number | Float): SingleFloat {
} }
export class DoubleFloat extends Float implements Preservable<never> { export class DoubleFloat extends Float implements Preservable<never> {
[AsPreserve]<T = GenericPointer>(): Value<T> { [AsPreserve]<T = GenericEmbedded>(): Value<T> {
return this; return this;
} }

View File

@ -4,7 +4,7 @@ import { Value } from "./values";
import { Set, Dictionary } from "./dictionary"; import { Set, Dictionary } from "./dictionary";
import { annotate, Annotated } from "./annotated"; import { annotate, Annotated } from "./annotated";
import { Double, Float, Single } from "./float"; import { Double, Float, Single } from "./float";
import { Pointer } from "./pointer"; import { Embedded } from "./embedded";
export type Fold<T, R = Value<T>> = (v: Value<T>) => R; export type Fold<T, R = Value<T>> = (v: Value<T>) => R;
@ -24,7 +24,7 @@ export interface FoldMethods<T, R> {
annotated(a: Annotated<T>, k: Fold<T, R>): R; annotated(a: Annotated<T>, k: Fold<T, R>): R;
pointer(t: Pointer<T>, k: Fold<T, R>): R; embedded(t: Embedded<T>, k: Fold<T, R>): R;
} }
export abstract class ValueFold<T, R = T> implements FoldMethods<T, Value<R>> { export abstract class ValueFold<T, R = T> implements FoldMethods<T, Value<R>> {
@ -64,11 +64,11 @@ export abstract class ValueFold<T, R = T> implements FoldMethods<T, Value<R>> {
annotated(a: Annotated<T>, k: Fold<T, Value<R>>): Value<R> { annotated(a: Annotated<T>, k: Fold<T, Value<R>>): Value<R> {
return annotate(k(a.item), ...a.annotations.map(k)); return annotate(k(a.item), ...a.annotations.map(k));
} }
abstract pointer(t: Pointer<T>, k: Fold<T, Value<R>>): Value<R>; abstract embedded(t: Embedded<T>, k: Fold<T, Value<R>>): Value<R>;
} }
export class IdentityFold<T> extends ValueFold<T, T> { export class IdentityFold<T> extends ValueFold<T, T> {
pointer(t: Pointer<T>, _k: Fold<T, Value<T>>): Value<T> { embedded(t: Embedded<T>, _k: Fold<T, Value<T>>): Value<T> {
return t; return t;
} }
} }
@ -81,7 +81,7 @@ export class MapFold<T, R> extends ValueFold<T, R> {
this.f = f; this.f = f;
} }
pointer(t: Pointer<T>, _k: Fold<T, Value<R>>): Value<R> { embedded(t: Embedded<T>, _k: Fold<T, Value<R>>): Value<R> {
return this.f(t.embeddedValue); return this.f(t.embeddedValue);
} }
} }
@ -122,7 +122,7 @@ export function fold<T, R>(v: Value<T>, o: FoldMethods<T, R>): R {
} else if (Float.isDouble(v)) { } else if (Float.isDouble(v)) {
return o.double(v.value); return o.double(v.value);
} else { } else {
return o.pointer(v, walk); return o.embedded(v, walk);
} }
default: default:
((_v: never): never => { throw new Error("Internal error"); })(v); ((_v: never): never => { throw new Error("Internal error"); })(v);
@ -131,7 +131,7 @@ export function fold<T, R>(v: Value<T>, o: FoldMethods<T, R>): R {
return walk(v); return walk(v);
} }
export function mapPointers<T, R>( export function mapEmbeddeds<T, R>(
v: Value<T>, v: Value<T>,
f: (t: T) => Value<R>, f: (t: T) => Value<R>,
): Value<R> ): Value<R>

View File

@ -1,11 +1,11 @@
import { embed, GenericPointer } from "./pointer"; import { embed, GenericEmbedded } from "./embedded";
import { Bytes } from "./bytes"; import { Bytes } from "./bytes";
import { Record, Tuple } from "./record"; import { Record, Tuple } from "./record";
import { AsPreserve } from "./symbols"; import { AsPreserve } from "./symbols";
import { Value } from "./values"; import { Value } from "./values";
import { Dictionary, Set } from "./dictionary"; import { Dictionary, Set } from "./dictionary";
export function fromJS<T = GenericPointer>(x: any): Value<T> { export function fromJS<T = GenericEmbedded>(x: any): Value<T> {
switch (typeof x) { switch (typeof x) {
case 'number': case 'number':
if (!Number.isInteger(x)) { if (!Number.isInteger(x)) {
@ -61,11 +61,11 @@ export function fromJS<T = GenericPointer>(x: any): Value<T> {
declare module "./dictionary" { declare module "./dictionary" {
namespace Dictionary { namespace Dictionary {
export function fromJS<T = GenericPointer, V = GenericPointer>(x: object): Dictionary<T, Value<V>>; export function fromJS<T = GenericEmbedded, V = GenericEmbedded>(x: object): Dictionary<T, Value<V>>;
} }
} }
Dictionary.fromJS = function <T = GenericPointer, V = GenericPointer>(x: object): Dictionary<T, Value<V>> { Dictionary.fromJS = function <T = GenericEmbedded, V = GenericEmbedded>(x: object): Dictionary<T, Value<V>> {
if (Dictionary.isDictionary<T, Value<V>>(x)) return x; if (Dictionary.isDictionary<T, Value<V>>(x)) return x;
const d = new Dictionary<T, Value<V>>(); const d = new Dictionary<T, Value<V>>();
Object.entries(x).forEach(([key, value]) => d.set(key, fromJS(value))); Object.entries(x).forEach(([key, value]) => d.set(key, fromJS(value)));

View File

@ -1,9 +1,9 @@
import type { GenericPointer } from "./pointer"; import type { GenericEmbedded } from "./embedded";
import type { Annotated } from "./annotated"; import type { Annotated } from "./annotated";
export const IsPreservesAnnotated = Symbol.for('IsPreservesAnnotated'); export const IsPreservesAnnotated = Symbol.for('IsPreservesAnnotated');
export function isAnnotated<T = GenericPointer>(x: any): x is Annotated<T> export function isAnnotated<T = GenericEmbedded>(x: any): x is Annotated<T>
{ {
return !!x?.[IsPreservesAnnotated]; return !!x?.[IsPreservesAnnotated];
} }

View File

@ -6,10 +6,10 @@ import { Value } from "./values";
import { Set, Dictionary } from "./dictionary"; import { Set, Dictionary } from "./dictionary";
import { Annotated } from "./annotated"; import { Annotated } from "./annotated";
import { unannotate } from "./strip"; import { unannotate } from "./strip";
import { embed, isPointer, Pointer } from "./pointer"; import { embed, isEmbedded, Embedded } from "./embedded";
export function merge<T>( export function merge<T>(
mergePointers: (a: T, b: T) => T | undefined, mergeEmbeddeds: (a: T, b: T) => T | undefined,
item0: Value<T>, item0: Value<T>,
... items: Array<Value<T>>): Value<T> ... items: Array<Value<T>>): Value<T>
{ {
@ -54,9 +54,9 @@ export function merge<T>(
return walk(a, unannotate(b)); return walk(a, unannotate(b));
}, },
pointer(t: Pointer<T>) { embedded(t: Embedded<T>) {
if (!isPointer<T>(b)) die(); if (!isEmbedded<T>(b)) die();
const r = mergePointers(t.embeddedValue, b.embeddedValue); const r = mergeEmbeddeds(t.embeddedValue, b.embeddedValue);
if (r === void 0) die(); if (r === void 0) die();
return embed(r); return embed(r);
}, },

View File

@ -1,50 +0,0 @@
import { GenericPointer, PointerType, PointerTypeDecode, PointerTypeEncode } from "./pointer";
import { Encoder, EncoderState, identityPointerTypeEncode } from "./encoder";
import { genericPointerTypeDecode } from "./reader";
import { Value } from "./values";
import { DecoderState, neverPointerTypeDecode } from "./decoder";
export const genericPointerTypeEncode: PointerTypeEncode<GenericPointer> = {
encode(s: EncoderState, v: GenericPointer): void {
new Encoder(s, this).push(v.generic);
},
toValue(v: GenericPointer): Value<GenericPointer> {
return v.generic;
}
};
export const genericPointerType: PointerType<GenericPointer> =
Object.assign({},
genericPointerTypeDecode,
genericPointerTypeEncode);
export const neverPointerTypeEncode: PointerTypeEncode<never> = {
encode(_s: EncoderState, _v: never): void {
throw new Error("Pointers not permitted encoding Preserves document");
},
toValue(_v: never): Value<GenericPointer> {
throw new Error("Pointers not permitted encoding Preserves document");
}
};
export const neverPointerType: PointerType<never> =
Object.assign({},
neverPointerTypeDecode,
neverPointerTypeEncode);
export const identityPointerTypeDecode: PointerTypeDecode<any> = {
decode(_s: DecoderState): any {
throw new Error("Cannot decode identityPointerType");
},
fromValue(_v: Value<GenericPointer>): any {
throw new Error("Cannot decode identityPointerType");
},
};
export const identityPointerType: PointerType<any> =
Object.assign({},
identityPointerTypeDecode,
identityPointerTypeEncode);

View File

@ -5,12 +5,12 @@ import { DecodeError, ShortPacket } from './codec';
import { Dictionary, Set } from './dictionary'; import { Dictionary, Set } from './dictionary';
import { strip, unannotate } from './strip'; import { strip, unannotate } from './strip';
import { Bytes, unhexDigit } from './bytes'; import { Bytes, unhexDigit } from './bytes';
import { decode, Decoder, DecoderState, neverPointerTypeDecode } from './decoder'; import { decode, Decoder, DecoderState, neverEmbeddedTypeDecode } from './decoder';
import { Record } from './record'; import { Record } from './record';
import { Annotated, newPosition, Position, updatePosition } from './annotated'; import { Annotated, newPosition, Position, updatePosition } from './annotated';
import { Double, DoubleFloat, Single, SingleFloat } from './float'; import { Double, DoubleFloat, Single, SingleFloat } from './float';
import { stringify } from './text'; import { stringify } from './text';
import { embed, GenericPointer, PointerTypeDecode } from './pointer'; import { embed, GenericEmbedded, EmbeddedTypeDecode } from './embedded';
export interface ReaderStateOptions { export interface ReaderStateOptions {
includeAnnotations?: boolean; includeAnnotations?: boolean;
@ -18,7 +18,7 @@ export interface ReaderStateOptions {
} }
export interface ReaderOptions<T> extends ReaderStateOptions { export interface ReaderOptions<T> extends ReaderStateOptions {
pointerDecode?: PointerTypeDecode<T>; embeddedDecode?: EmbeddedTypeDecode<T>;
} }
type IntOrFloat = 'int' | 'float'; type IntOrFloat = 'int' | 'float';
@ -275,33 +275,33 @@ export class ReaderState {
} }
} }
export const genericPointerTypeDecode: PointerTypeDecode<GenericPointer> = { export const genericEmbeddedTypeDecode: EmbeddedTypeDecode<GenericEmbedded> = {
decode(s: DecoderState): GenericPointer { decode(s: DecoderState): GenericEmbedded {
return new GenericPointer(new Decoder(s, this).next()); return new GenericEmbedded(new Decoder(s, this).next());
}, },
fromValue(v: Value<GenericPointer>): GenericPointer { fromValue(v: Value<GenericEmbedded>): GenericEmbedded {
return new GenericPointer(strip(v)); return new GenericEmbedded(strip(v));
}, },
}; };
export class Reader<T> { export class Reader<T> {
state: ReaderState; state: ReaderState;
pointerType: PointerTypeDecode<T>; embeddedType: EmbeddedTypeDecode<T>;
constructor(state: ReaderState, pointerType: PointerTypeDecode<T>); constructor(state: ReaderState, embeddedType: EmbeddedTypeDecode<T>);
constructor(buffer: string, options?: ReaderOptions<T>); constructor(buffer: string, options?: ReaderOptions<T>);
constructor( constructor(
state_or_buffer: (ReaderState | string) = '', state_or_buffer: (ReaderState | string) = '',
pointerType_or_options?: (PointerTypeDecode<T> | ReaderOptions<T>)) embeddedType_or_options?: (EmbeddedTypeDecode<T> | ReaderOptions<T>))
{ {
if (state_or_buffer instanceof ReaderState) { if (state_or_buffer instanceof ReaderState) {
this.state = state_or_buffer; this.state = state_or_buffer;
this.pointerType = pointerType_or_options as PointerTypeDecode<T>; this.embeddedType = embeddedType_or_options as EmbeddedTypeDecode<T>;
} else { } else {
const options = (pointerType_or_options as ReaderOptions<T>) ?? {}; const options = (embeddedType_or_options as ReaderOptions<T>) ?? {};
this.state = new ReaderState(state_or_buffer, options); this.state = new ReaderState(state_or_buffer, options);
this.pointerType = options.pointerDecode ?? neverPointerTypeDecode; this.embeddedType = options.embeddedDecode ?? neverEmbeddedTypeDecode;
} }
} }
@ -388,12 +388,12 @@ export class Reader<T> {
if (!Bytes.isBytes(bs)) this.state.error('ByteString must follow #=', if (!Bytes.isBytes(bs)) this.state.error('ByteString must follow #=',
startPos); startPos);
return decode<T>(bs, { return decode<T>(bs, {
pointerDecode: this.pointerType, embeddedDecode: this.embeddedType,
includeAnnotations: this.state.options.includeAnnotations, includeAnnotations: this.state.options.includeAnnotations,
}); });
} }
case '!': return embed(this.pointerType.fromValue( case '!': return embed(this.embeddedType.fromValue(
new Reader<GenericPointer>(this.state, genericPointerTypeDecode).next())); new Reader<GenericEmbedded>(this.state, genericEmbeddedTypeDecode).next()));
default: default:
this.state.error(`Invalid # syntax: ${c}`, startPos); this.state.error(`Invalid # syntax: ${c}`, startPos);
} }

View File

@ -1,10 +1,10 @@
import { GenericPointer } from "./pointer"; import { GenericEmbedded } from "./embedded";
import { is } from "./is"; import { is } from "./is";
import { Value } from "./values"; import { Value } from "./values";
export type Tuple<T> = Array<T> | [T]; export type Tuple<T> = Array<T> | [T];
export type Record<LabelType extends Value<T>, FieldsType extends Tuple<Value<T>>, T = GenericPointer> export type Record<LabelType extends Value<T>, FieldsType extends Tuple<Value<T>>, T = GenericEmbedded>
= FieldsType & { label: LabelType }; = FieldsType & { label: LabelType };
export type RecordGetters<Fs, R> = { export type RecordGetters<Fs, R> = {
@ -14,14 +14,14 @@ export type RecordGetters<Fs, R> = {
export type CtorTypes<Fs, Names extends Tuple<keyof Fs>> = export type CtorTypes<Fs, Names extends Tuple<keyof Fs>> =
{ [K in keyof Names]: Fs[keyof Fs & Names[K]] } & any[]; { [K in keyof Names]: Fs[keyof Fs & Names[K]] } & any[];
export interface RecordConstructor<L extends Value<T>, Fs, Names extends Tuple<keyof Fs>, T = GenericPointer> { export interface RecordConstructor<L extends Value<T>, Fs, Names extends Tuple<keyof Fs>, T = GenericEmbedded> {
(...fields: CtorTypes<Fs, Names>): Record<L, CtorTypes<Fs, Names>, T>; (...fields: CtorTypes<Fs, Names>): Record<L, CtorTypes<Fs, Names>, T>;
constructorInfo: RecordConstructorInfo<L, T>; constructorInfo: RecordConstructorInfo<L, T>;
isClassOf(v: any): v is Record<L, CtorTypes<Fs, Names>, T>; isClassOf(v: any): v is Record<L, CtorTypes<Fs, Names>, T>;
_: RecordGetters<Fs, Record<L, CtorTypes<Fs, Names>, T>>; _: RecordGetters<Fs, Record<L, CtorTypes<Fs, Names>, T>>;
}; };
export interface RecordConstructorInfo<L extends Value<T>, T = GenericPointer> { export interface RecordConstructorInfo<L extends Value<T>, T = GenericEmbedded> {
label: L; label: L;
arity: number; arity: number;
} }
@ -35,7 +35,7 @@ export type InferredRecordType<L, FieldsType extends Tuple<any>> =
L extends Value<infer T> ? (FieldsType extends Tuple<Value<T>> L extends Value<infer T> ? (FieldsType extends Tuple<Value<T>>
? Record<L, FieldsType, T> ? Record<L, FieldsType, T>
: "TYPE_ERROR_cannotMatchFieldsTypeToLabelType" & [never]) : : "TYPE_ERROR_cannotMatchFieldsTypeToLabelType" & [never]) :
"TYPE_ERROR_cannotInferPointerType" & [never]; "TYPE_ERROR_cannotInferEmbeddedType" & [never];
export function Record<L, FieldsType extends Tuple<any>>( export function Record<L, FieldsType extends Tuple<any>>(
label: L, label: L,
@ -46,7 +46,7 @@ export function Record<L, FieldsType extends Tuple<any>>(
} }
export namespace Record { export namespace Record {
export function isRecord<L extends Value<T>, FieldsType extends Tuple<Value<T>>, T = GenericPointer>(x: any): x is Record<L, FieldsType, T> { export function isRecord<L extends Value<T>, FieldsType extends Tuple<Value<T>>, T = GenericEmbedded>(x: any): x is Record<L, FieldsType, T> {
return Array.isArray(x) && 'label' in x; return Array.isArray(x) && 'label' in x;
} }
@ -54,19 +54,19 @@ export namespace Record {
return '<unprintable_preserves_field_value>'; return '<unprintable_preserves_field_value>';
} }
export function constructorInfo<L extends Value<T>, FieldsType extends Tuple<Value<T>>, T = GenericPointer>( export function constructorInfo<L extends Value<T>, FieldsType extends Tuple<Value<T>>, T = GenericEmbedded>(
r: Record<L, FieldsType, T>): RecordConstructorInfo<L, T> r: Record<L, FieldsType, T>): RecordConstructorInfo<L, T>
{ {
return { label: r.label, arity: r.length }; return { label: r.label, arity: r.length };
} }
export function isClassOf<L extends Value<T>, FieldsType extends Tuple<Value<T>>, T = GenericPointer>( export function isClassOf<L extends Value<T>, FieldsType extends Tuple<Value<T>>, T = GenericEmbedded>(
ci: RecordConstructorInfo<L, T>, v: any): v is Record<L, FieldsType, T> ci: RecordConstructorInfo<L, T>, v: any): v is Record<L, FieldsType, T>
{ {
return (Record.isRecord(v)) && is(ci.label, v.label) && (ci.arity === v.length); return (Record.isRecord(v)) && is(ci.label, v.label) && (ci.arity === v.length);
} }
export function makeConstructor<Fs, T = GenericPointer>() export function makeConstructor<Fs, T = GenericEmbedded>()
: (<L extends Value<T>, Names extends Tuple<keyof Fs>>(label: L, fieldNames: Names) => : (<L extends Value<T>, Names extends Tuple<keyof Fs>>(label: L, fieldNames: Names) =>
RecordConstructor<L, Fs, Names, T>) RecordConstructor<L, Fs, Names, T>)
{ {
@ -86,7 +86,7 @@ export namespace Record {
Array.prototype.asPreservesText = function (): string { Array.prototype.asPreservesText = function (): string {
if ('label' in (this as any)) { if ('label' in (this as any)) {
const r = this as Record<Value, Tuple<Value>, GenericPointer>; const r = this as Record<Value, Tuple<Value>, GenericEmbedded>;
return '<' + r.label.asPreservesText() + (r.length > 0 ? ' ': '') + return '<' + r.label.asPreservesText() + (r.length > 0 ? ' ': '') +
r.map(f => { r.map(f => {
try { try {

View File

@ -4,6 +4,8 @@ export * from './codec';
export * from './compound'; export * from './compound';
export * from './decoder'; export * from './decoder';
export * from './dictionary'; export * from './dictionary';
export * from './embedded';
export * from './embeddedTypes';
export * from './encoder'; export * from './encoder';
export * from './flex'; export * from './flex';
export * from './float'; export * from './float';
@ -11,8 +13,6 @@ export * from './fold';
export * from './fromjs'; export * from './fromjs';
export * from './is'; export * from './is';
export * from './merge'; export * from './merge';
export * from './pointer';
export * from './pointerTypes';
export * from './reader'; export * from './reader';
export * from './record'; export * from './record';
export * from './strip'; export * from './strip';

View File

@ -2,17 +2,17 @@ import { Value } from "./values";
import { Annotated } from "./annotated"; import { Annotated } from "./annotated";
import { Record, Tuple } from "./record"; import { Record, Tuple } from "./record";
import { Set, Dictionary } from "./dictionary"; import { Set, Dictionary } from "./dictionary";
import type { GenericPointer } from "./pointer"; import type { GenericEmbedded } from "./embedded";
export function unannotate<T = GenericPointer>(v: Value<T>): Value<T> { export function unannotate<T = GenericEmbedded>(v: Value<T>): Value<T> {
return Annotated.isAnnotated<T>(v) ? v.item : v; return Annotated.isAnnotated<T>(v) ? v.item : v;
} }
export function peel<T = GenericPointer>(v: Value<T>): Value<T> { export function peel<T = GenericEmbedded>(v: Value<T>): Value<T> {
return strip(v, 1); return strip(v, 1);
} }
export function strip<T = GenericPointer>( export function strip<T = GenericEmbedded>(
v: Value<T>, v: Value<T>,
depth: number = Infinity): Value<T> depth: number = Infinity): Value<T>
{ {

View File

@ -4,12 +4,12 @@ import type { Bytes } from './bytes';
import type { DoubleFloat, SingleFloat } from './float'; import type { DoubleFloat, SingleFloat } from './float';
import type { Annotated } from './annotated'; import type { Annotated } from './annotated';
import type { Set, Dictionary } from './dictionary'; import type { Set, Dictionary } from './dictionary';
import type { Pointer, GenericPointer } from './pointer'; import type { Embedded, GenericEmbedded } from './embedded';
export type Value<T = GenericPointer> = export type Value<T = GenericEmbedded> =
| Atom | Atom
| Compound<T> | Compound<T>
| Pointer<T> | Embedded<T>
| Annotated<T>; | Annotated<T>;
export type Atom = export type Atom =
| boolean | boolean
@ -19,7 +19,7 @@ export type Atom =
| string | string
| Bytes | Bytes
| symbol; | symbol;
export type Compound<T = GenericPointer> = export type Compound<T = GenericEmbedded> =
| (Array<Value<T>> | [Value<T>]) & { label: Value<T> } | (Array<Value<T>> | [Value<T>]) & { label: Value<T> }
// ^ expanded from definition of Record<> in record.ts, // ^ expanded from definition of Record<> in record.ts,
// because if we use Record<Value<T>, Tuple<Value<T>>, T>, // because if we use Record<Value<T>, Tuple<Value<T>>, T>,

View File

@ -10,15 +10,15 @@ import {
fromJS, fromJS,
Constants, Constants,
Encoder, Encoder,
GenericPointer, GenericEmbedded,
EncoderState, EncoderState,
PointerType, EmbeddedType,
DecoderState, DecoderState,
Decoder, Decoder,
Pointer, Embedded,
embed, embed,
genericPointerTypeDecode, genericEmbeddedTypeDecode,
genericPointerTypeEncode, genericEmbeddedTypeEncode,
} from '../src/index'; } from '../src/index';
const { Tag } = Constants; const { Tag } = Constants;
import './test-utils'; import './test-utils';
@ -28,9 +28,9 @@ import * as fs from 'fs';
const _discard = Symbol.for('discard'); const _discard = Symbol.for('discard');
const _capture = Symbol.for('capture'); const _capture = Symbol.for('capture');
const _observe = Symbol.for('observe'); const _observe = Symbol.for('observe');
const Discard = Record.makeConstructor<{}, GenericPointer>()(_discard, []); const Discard = Record.makeConstructor<{}, GenericEmbedded>()(_discard, []);
const Capture = Record.makeConstructor<{pattern: Value<GenericPointer>}, GenericPointer>()(_capture, ['pattern']); const Capture = Record.makeConstructor<{pattern: Value<GenericEmbedded>}, GenericEmbedded>()(_capture, ['pattern']);
const Observe = Record.makeConstructor<{pattern: Value<GenericPointer>}, GenericPointer>()(_observe, ['pattern']); const Observe = Record.makeConstructor<{pattern: Value<GenericEmbedded>}, GenericEmbedded>()(_observe, ['pattern']);
describe('record constructors', () => { describe('record constructors', () => {
it('should have constructorInfo', () => { it('should have constructorInfo', () => {
@ -46,11 +46,11 @@ describe('record constructors', () => {
describe('RecordConstructorInfo', () => { describe('RecordConstructorInfo', () => {
const C1 = Record.makeConstructor<{x: number, y: number}>()([1], ['x', 'y']); const C1 = Record.makeConstructor<{x: number, y: number}>()([1], ['x', 'y']);
const C2 = Record.makeConstructor<{z: number, w: number}>()([1], ['z', 'w']); const C2 = Record.makeConstructor<{z: number, w: number}>()([1], ['z', 'w']);
it('instance comparison should ignore pointer and fieldname differences', () => { it('instance comparison should ignore embedded and fieldname differences', () => {
expect(C1(9,9)).is(C2(9,9)); expect(C1(9,9)).is(C2(9,9));
expect(C1(9,9)).not.is(C2(9,8)); expect(C1(9,9)).not.is(C2(9,8));
}); });
it('comparison based on pointer equality should not work', () => { it('comparison based on embedded equality should not work', () => {
expect(C1.constructorInfo).not.toBe(C2.constructorInfo); expect(C1.constructorInfo).not.toBe(C2.constructorInfo);
}); });
it('comparison based on .equals should work', () => { it('comparison based on .equals should work', () => {
@ -87,8 +87,8 @@ describe('reusing buffer space', () => {
}); });
}); });
describe('encoding and decoding pointers', () => { describe('encoding and decoding embeddeds', () => {
class LookasidePointerType implements PointerType<object> { class LookasideEmbeddedType implements EmbeddedType<object> {
readonly objects: object[]; readonly objects: object[];
constructor(objects: object[]) { constructor(objects: object[]) {
@ -96,7 +96,7 @@ describe('encoding and decoding pointers', () => {
} }
decode(d: DecoderState): object { decode(d: DecoderState): object {
return this.fromValue(new Decoder<GenericPointer>(d).next()); return this.fromValue(new Decoder<GenericEmbedded>(d).next());
} }
encode(e: EncoderState, v: object): void { encode(e: EncoderState, v: object): void {
@ -107,9 +107,9 @@ describe('encoding and decoding pointers', () => {
return Object.is(a, b); return Object.is(a, b);
} }
fromValue(v: Value<GenericPointer>): object { fromValue(v: Value<GenericEmbedded>): object {
if (typeof v !== 'number' || v < 0 || v >= this.objects.length) { if (typeof v !== 'number' || v < 0 || v >= this.objects.length) {
throw new Error("Unknown pointer target"); throw new Error("Unknown embedded target");
} }
return this.objects[v]; return this.objects[v];
} }
@ -122,54 +122,54 @@ describe('encoding and decoding pointers', () => {
} }
} }
it('should encode using pointerId when no function has been supplied', () => { it('should encode using embeddedId when no function has been supplied', () => {
const A1 = embed({a: 1}); const A1 = embed({a: 1});
const A2 = embed({a: 1}); const A2 = embed({a: 1});
const bs1 = canonicalEncode(A1); const bs1 = canonicalEncode(A1);
const bs2 = canonicalEncode(A2); const bs2 = canonicalEncode(A2);
const bs3 = canonicalEncode(A1); const bs3 = canonicalEncode(A1);
expect(bs1.get(0)).toBe(Tag.Pointer); expect(bs1.get(0)).toBe(Tag.Embedded);
expect(bs2.get(0)).toBe(Tag.Pointer); expect(bs2.get(0)).toBe(Tag.Embedded);
expect(bs3.get(0)).toBe(Tag.Pointer); expect(bs3.get(0)).toBe(Tag.Embedded);
// Can't really check the value assigned to the object. But we // Can't really check the value assigned to the object. But we
// can check that it's different to a similar object! // can check that it's different to a similar object!
expect(bs1).not.is(bs2); expect(bs1).not.is(bs2);
expect(bs1).is(bs3); expect(bs1).is(bs3);
}); });
it('should refuse to decode pointers when no function has been supplied', () => { it('should refuse to decode embeddeds when no function has been supplied', () => {
expect(() => decode(Bytes.from([Tag.Pointer, Tag.SmallInteger_lo]))) expect(() => decode(Bytes.from([Tag.Embedded, Tag.SmallInteger_lo])))
.toThrow("Pointers not permitted at this point in Preserves document"); .toThrow("Embeddeds not permitted at this point in Preserves document");
}); });
it('should encode properly', () => { it('should encode properly', () => {
const objects: object[] = []; const objects: object[] = [];
const pt = new LookasidePointerType(objects); const pt = new LookasideEmbeddedType(objects);
const A = embed({a: 1}); const A = embed({a: 1});
const B = embed({b: 2}); const B = embed({b: 2});
expect(encode([A, B], { pointerEncode: pt })).is( expect(encode([A, B], { embeddedEncode: pt })).is(
Bytes.from([Tag.Sequence, Bytes.from([Tag.Sequence,
Tag.Pointer, Tag.SmallInteger_lo, Tag.Embedded, Tag.SmallInteger_lo,
Tag.Pointer, Tag.SmallInteger_lo + 1, Tag.Embedded, Tag.SmallInteger_lo + 1,
Tag.End])); Tag.End]));
expect(objects).toEqual([A.embeddedValue, B.embeddedValue]); expect(objects).toEqual([A.embeddedValue, B.embeddedValue]);
}); });
it('should decode properly', () => { it('should decode properly', () => {
const objects: object[] = []; const objects: object[] = [];
const pt = new LookasidePointerType(objects); const pt = new LookasideEmbeddedType(objects);
const X: Pointer<object> = embed({x: 123}); const X: Embedded<object> = embed({x: 123});
const Y: Pointer<object> = embed({y: 456}); const Y: Embedded<object> = embed({y: 456});
objects.push(X.embeddedValue); objects.push(X.embeddedValue);
objects.push(Y.embeddedValue); objects.push(Y.embeddedValue);
expect(decode(Bytes.from([ expect(decode(Bytes.from([
Tag.Sequence, Tag.Sequence,
Tag.Pointer, Tag.SmallInteger_lo, Tag.Embedded, Tag.SmallInteger_lo,
Tag.Pointer, Tag.SmallInteger_lo + 1, Tag.Embedded, Tag.SmallInteger_lo + 1,
Tag.End Tag.End
]), { pointerDecode: pt })).is([X, Y]); ]), { embeddedDecode: pt })).is([X, Y]);
}); });
it('should store pointers embedded in map keys correctly', () => { it('should store embeddeds embedded in map keys correctly', () => {
const A1a = {a: 1}; const A1a = {a: 1};
const A1: Pointer<object> = embed(A1a); const A1: Embedded<object> = embed(A1a);
const A2: Pointer<object> = embed({a: 1}); const A2: Embedded<object> = embed({a: 1});
const m = new Dictionary<object, number>(); const m = new Dictionary<object, number>();
m.set([A1], 1); m.set([A1], 1);
m.set([A2], 2); m.set([A2], 2);
@ -184,61 +184,61 @@ describe('encoding and decoding pointers', () => {
describe('common test suite', () => { describe('common test suite', () => {
const samples_bin = fs.readFileSync(__dirname + '/../../../../../tests/samples.bin'); const samples_bin = fs.readFileSync(__dirname + '/../../../../../tests/samples.bin');
const samples = decodeWithAnnotations(samples_bin, { pointerDecode: genericPointerTypeDecode }); const samples = decodeWithAnnotations(samples_bin, { embeddedDecode: genericEmbeddedTypeDecode });
const TestCases = Record.makeConstructor<{ const TestCases = Record.makeConstructor<{
cases: Dictionary<GenericPointer> cases: Dictionary<GenericEmbedded>
}>()(Symbol.for('TestCases'), ['cases']); }>()(Symbol.for('TestCases'), ['cases']);
type TestCases = ReturnType<typeof TestCases>; type TestCases = ReturnType<typeof TestCases>;
function DS(bs: Bytes) { function DS(bs: Bytes) {
return decode(bs, { pointerDecode: genericPointerTypeDecode }); return decode(bs, { embeddedDecode: genericEmbeddedTypeDecode });
} }
function D(bs: Bytes) { function D(bs: Bytes) {
return decodeWithAnnotations(bs, { pointerDecode: genericPointerTypeDecode }); return decodeWithAnnotations(bs, { embeddedDecode: genericEmbeddedTypeDecode });
} }
function E(v: Value<GenericPointer>) { function E(v: Value<GenericEmbedded>) {
return encodeWithAnnotations(v, { pointerEncode: genericPointerTypeEncode }); return encodeWithAnnotations(v, { embeddedEncode: genericEmbeddedTypeEncode });
} }
interface ExpectedValues { interface ExpectedValues {
[testName: string]: ({ [testName: string]: ({
value: Value<GenericPointer>; value: Value<GenericEmbedded>;
} | { } | {
forward: Value<GenericPointer>; forward: Value<GenericEmbedded>;
back: Value<GenericPointer>; back: Value<GenericEmbedded>;
}); });
} }
const expectedValues: ExpectedValues = { const expectedValues: ExpectedValues = {
annotation1: { forward: annotate<GenericPointer>(9, "abc"), annotation1: { forward: annotate<GenericEmbedded>(9, "abc"),
back: 9 }, back: 9 },
annotation2: { forward: annotate<GenericPointer>([[], annotate<GenericPointer>([], "x")], annotation2: { forward: annotate<GenericEmbedded>([[], annotate<GenericEmbedded>([], "x")],
"abc", "abc",
"def"), "def"),
back: [[], []] }, back: [[], []] },
annotation3: { forward: annotate<GenericPointer>(5, annotation3: { forward: annotate<GenericEmbedded>(5,
annotate<GenericPointer>(2, 1), annotate<GenericEmbedded>(2, 1),
annotate<GenericPointer>(4, 3)), annotate<GenericEmbedded>(4, 3)),
back: 5 }, back: 5 },
annotation5: { annotation5: {
forward: annotate<GenericPointer>( forward: annotate<GenericEmbedded>(
Record<symbol, any>(Symbol.for('R'), Record<symbol, any>(Symbol.for('R'),
[annotate<GenericPointer>(Symbol.for('f'), [annotate<GenericEmbedded>(Symbol.for('f'),
Symbol.for('af'))]), Symbol.for('af'))]),
Symbol.for('ar')), Symbol.for('ar')),
back: Record<Value<GenericPointer>, any>(Symbol.for('R'), [Symbol.for('f')]) back: Record<Value<GenericEmbedded>, any>(Symbol.for('R'), [Symbol.for('f')])
}, },
annotation6: { annotation6: {
forward: Record<Value<GenericPointer>, any>( forward: Record<Value<GenericEmbedded>, any>(
annotate<GenericPointer>(Symbol.for('R'), annotate<GenericEmbedded>(Symbol.for('R'),
Symbol.for('ar')), Symbol.for('ar')),
[annotate<GenericPointer>(Symbol.for('f'), [annotate<GenericEmbedded>(Symbol.for('f'),
Symbol.for('af'))]), Symbol.for('af'))]),
back: Record<symbol, any>(Symbol.for('R'), [Symbol.for('f')]) back: Record<symbol, any>(Symbol.for('R'), [Symbol.for('f')])
}, },
annotation7: { annotation7: {
forward: annotate<GenericPointer>([], Symbol.for('a'), Symbol.for('b'), Symbol.for('c')), forward: annotate<GenericEmbedded>([], Symbol.for('a'), Symbol.for('b'), Symbol.for('c')),
back: [] back: []
}, },
list1: { list1: {
@ -258,7 +258,7 @@ describe('common test suite', () => {
function runTestCase(variety: Variety, function runTestCase(variety: Variety,
tName: string, tName: string,
binaryForm: Bytes, binaryForm: Bytes,
annotatedTextForm: Value<GenericPointer>) annotatedTextForm: Value<GenericEmbedded>)
{ {
describe(tName, () => { describe(tName, () => {
const textForm = strip(annotatedTextForm); const textForm = strip(annotatedTextForm);
@ -287,10 +287,10 @@ describe('common test suite', () => {
} }
const tests = (peel(TestCases._.cases(peel(samples) as TestCases)) as const tests = (peel(TestCases._.cases(peel(samples) as TestCases)) as
Dictionary<GenericPointer>); Dictionary<GenericEmbedded>);
tests.forEach((t0: Value<GenericPointer>, tName0: Value<GenericPointer>) => { tests.forEach((t0: Value<GenericEmbedded>, tName0: Value<GenericEmbedded>) => {
const tName = Symbol.keyFor(strip(tName0) as symbol)!; const tName = Symbol.keyFor(strip(tName0) as symbol)!;
const t = peel(t0) as Record<symbol, any, GenericPointer>; const t = peel(t0) as Record<symbol, any, GenericEmbedded>;
switch (t.label) { switch (t.label) {
case Symbol.for('Test'): case Symbol.for('Test'):
runTestCase('normal', tName, strip(t[0]) as Bytes, t[1]); runTestCase('normal', tName, strip(t[0]) as Bytes, t[1]);

View File

@ -1,4 +1,4 @@
import { Bytes, Decoder, genericPointerType, encode, Reader } from '../src/index'; import { Bytes, Decoder, genericEmbeddedType, encode, Reader } from '../src/index';
import './test-utils'; import './test-utils';
import * as fs from 'fs'; import * as fs from 'fs';
@ -8,21 +8,21 @@ describe('reading common test suite', () => {
const samples_pr = fs.readFileSync(__dirname + '/../../../../../tests/samples.pr', 'utf-8'); const samples_pr = fs.readFileSync(__dirname + '/../../../../../tests/samples.pr', 'utf-8');
it('should read equal to decoded binary without annotations', () => { it('should read equal to decoded binary without annotations', () => {
const s1 = new Reader(samples_pr, { pointerDecode: genericPointerType, includeAnnotations: false }).next(); const s1 = new Reader(samples_pr, { embeddedDecode: genericEmbeddedType, includeAnnotations: false }).next();
const s2 = new Decoder(samples_bin, { pointerDecode: genericPointerType, includeAnnotations: false }).next(); const s2 = new Decoder(samples_bin, { embeddedDecode: genericEmbeddedType, includeAnnotations: false }).next();
expect(s1).is(s2); expect(s1).is(s2);
}); });
it('should read equal to decoded binary with annotations', () => { it('should read equal to decoded binary with annotations', () => {
const s1 = new Reader(samples_pr, { pointerDecode: genericPointerType, includeAnnotations: true }).next(); const s1 = new Reader(samples_pr, { embeddedDecode: genericEmbeddedType, includeAnnotations: true }).next();
const s2 = new Decoder(samples_bin, { pointerDecode: genericPointerType, includeAnnotations: true }).next(); const s2 = new Decoder(samples_bin, { embeddedDecode: genericEmbeddedType, includeAnnotations: true }).next();
expect(s1).is(s2); expect(s1).is(s2);
}); });
it('should read and encode back to binary with annotations', () => { it('should read and encode back to binary with annotations', () => {
const s = new Reader(samples_pr, { pointerDecode: genericPointerType, includeAnnotations: true }).next(); const s = new Reader(samples_pr, { embeddedDecode: genericEmbeddedType, includeAnnotations: true }).next();
const bs = Bytes.toIO(encode(s, { const bs = Bytes.toIO(encode(s, {
pointerEncode: genericPointerType, embeddedEncode: genericEmbeddedType,
includeAnnotations: true, includeAnnotations: true,
canonical: true, canonical: true,
})); }));

View File

@ -1,4 +1,4 @@
import { Single, Double, fromJS, Dictionary, IDENTITY_FOLD, fold, mapPointers, Value, embed } from '../src/index'; import { Single, Double, fromJS, Dictionary, IDENTITY_FOLD, fold, mapEmbeddeds, Value, embed } from '../src/index';
import './test-utils'; import './test-utils';
describe('Single', () => { describe('Single', () => {
@ -33,7 +33,7 @@ describe('fold', () => {
const w1 = new Date(); const w1 = new Date();
const v1 = mkv(w1); const v1 = mkv(w1);
expect(fold(v, IDENTITY_FOLD)).not.is(v1); expect(fold(v, IDENTITY_FOLD)).not.is(v1);
expect(mapPointers(v, _t => embed(w1))).is(v1); expect(mapEmbeddeds(v, _t => embed(w1))).is(v1);
}); });
}); });

View File

@ -1,6 +1,6 @@
{ {
"name": "@preserves/schema", "name": "@preserves/schema",
"version": "0.7.0", "version": "0.8.0",
"description": "Schema support for Preserves data serialization format", "description": "Schema support for Preserves data serialization format",
"homepage": "https://gitlab.com/preserves/preserves", "homepage": "https://gitlab.com/preserves/preserves",
"license": "Apache-2.0", "license": "Apache-2.0",
@ -27,7 +27,7 @@
"preserves-schemac": "./bin/preserves-schemac.js" "preserves-schemac": "./bin/preserves-schemac.js"
}, },
"dependencies": { "dependencies": {
"@preserves/core": "^0.14.0", "@preserves/core": "^0.15.0",
"@types/glob": "^7.1.3", "@types/glob": "^7.1.3",
"@types/minimatch": "^3.0.3", "@types/minimatch": "^3.0.3",
"chalk": "^4.1.0", "chalk": "^4.1.0",

View File

@ -12,13 +12,13 @@ import { sourceCodeFor } from "./compiler/value";
export function compile(env: M.Environment, schema: M.Schema, options: CompilerOptions = {}): string { export function compile(env: M.Environment, schema: M.Schema, options: CompilerOptions = {}): string {
const mod = new ModuleContext(env, schema, options); const mod = new ModuleContext(env, schema, options);
const pointerName = schema.pointer; const embeddedName = schema.embeddedType;
mod.defineType(seq(`export type _ptr = `, mod.defineType(seq(`export type _embedded = `,
renderType(pointerName._variant === 'false' renderType(embeddedName._variant === 'false'
? Type.ref('any') ? Type.ref('any')
: typeForDefinition(mod, M.Definition.Alternative(M.Alternative.Pattern(M.Pattern.SimplePattern(M.SimplePattern.Ref(pointerName.value)))))), : typeForDefinition(mod, M.Definition.Alternative(M.Alternative.Pattern(M.Pattern.SimplePattern(M.SimplePattern.Ref(embeddedName.value)))))),
`;`)); `;`));
mod.defineType(`export type _val = _.Value<_ptr>;`); mod.defineType(`export type _val = _.Value<_embedded>;`);
for (const [name, def] of schema.definitions) { for (const [name, def] of schema.definitions) {
const t = typeForDefinition(mod, def); const t = typeForDefinition(mod, def);

View File

@ -6,7 +6,7 @@ import { ANY_TYPE, renderType, Type, variantInitFor } from "./type";
export interface CompilerOptions { export interface CompilerOptions {
preservesModule?: string; preservesModule?: string;
defaultPointer?: M.Ref; defaultEmbeddedType?: M.Ref;
warn?(message: string, pos: Position | null): void; warn?(message: string, pos: Position | null): void;
} }
@ -22,7 +22,7 @@ export class ModuleContext {
readonly schema: M.Schema; readonly schema: M.Schema;
readonly options: CompilerOptions; readonly options: CompilerOptions;
readonly literals = new Dictionary<M._ptr, string>(); readonly literals = new Dictionary<M._embedded, string>();
readonly typedefs: Item[] = []; readonly typedefs: Item[] = [];
readonly functiondefs: Item[] = []; readonly functiondefs: Item[] = [];
readonly imports = new KeyedSet<[string, string]>(); readonly imports = new KeyedSet<[string, string]>();

View File

@ -134,7 +134,7 @@ function converterFor(
const r = ctx.gentemp(setType(ctx.mod, setPattern)); const r = ctx.gentemp(setType(ctx.mod, setPattern));
const v = ctx.gentempname(); const v = ctx.gentempname();
return [ return [
seq(`if (_.Set.isSet<_ptr>(${src})) `, ctx.block(() => [ seq(`if (_.Set.isSet<_embedded>(${src})) `, ctx.block(() => [
seq(`${r} = new _.KeyedSet()`), seq(`${r} = new _.KeyedSet()`),
seq(`for (const ${v} of ${src}) `, ctx.block(() => [ seq(`for (const ${v} of ${src}) `, ctx.block(() => [
... converterFor(ctx, M.anonymousSimplePattern(setPattern), v, vv => ... converterFor(ctx, M.anonymousSimplePattern(setPattern), v, vv =>
@ -150,7 +150,7 @@ function converterFor(
const v = ctx.gentempname(); const v = ctx.gentempname();
const k = ctx.gentempname(); const k = ctx.gentempname();
return [ return [
seq(`if (_.Dictionary.isDictionary<_ptr>(${src})) `, ctx.block(() => [ seq(`if (_.Dictionary.isDictionary<_embedded>(${src})) `, ctx.block(() => [
seq(`${r} = new _.KeyedDictionary()`), seq(`${r} = new _.KeyedDictionary()`),
seq(`for (const [${k}, ${v}] of ${src}) `, ctx.block(() => [ seq(`for (const [${k}, ${v}] of ${src}) `, ctx.block(() => [
... converterFor(ctx, M.anonymousSimplePattern(keyPattern), k, kk => ... converterFor(ctx, M.anonymousSimplePattern(keyPattern), k, kk =>
@ -205,8 +205,8 @@ export function converterForSimple(
ctx.mod.imports.add([modId, modPath]); ctx.mod.imports.add([modId, modPath]);
return [`${dest} = ${modId}.to${p.value.name.description!}(${src})`]; return [`${dest} = ${modId}.to${p.value.name.description!}(${src})`];
}); });
case 'pointer': case 'embedded':
return [`${dest} = _.isPointer<_ptr>(${src}) ? ${src}.embeddedValue : void 0`]; return [`${dest} = _.isEmbedded<_embedded>(${src}) ? ${src}.embeddedValue : void 0`];
default: default:
((_p: never) => {})(p); ((_p: never) => {})(p);
throw new Error("Unreachable"); throw new Error("Unreachable");
@ -222,7 +222,7 @@ function converterForCompound(
{ {
switch (p._variant) { switch (p._variant) {
case 'rec': case 'rec':
return [seq(`if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(${src})) `, ctx.block(() => return [seq(`if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(${src})) `, ctx.block(() =>
converterFor(ctx, p.label, `${src}.label`, () => converterFor(ctx, p.label, `${src}.label`, () =>
converterFor(ctx, p.fields, src, ks, true))))]; converterFor(ctx, p.fields, src, ks, true))))];
case 'tuple': case 'tuple':
@ -249,7 +249,7 @@ function converterForCompound(
return ks(); return ks();
} }
} }
return [seq(`if (_.Dictionary.isDictionary<_ptr>(${src})) `, ctx.block(() => loop(0)))]; return [seq(`if (_.Dictionary.isDictionary<_embedded>(${src})) `, ctx.block(() => loop(0)))];
} }
default: default:
((_p: never) => {})(p); ((_p: never) => {})(p);

View File

@ -72,8 +72,8 @@ export function simpleType(mod: ModuleContext, p: M.SimplePattern): AtomicType {
case 'ByteString': return Type.ref(`_.Bytes`); case 'ByteString': return Type.ref(`_.Bytes`);
case 'Symbol': return Type.ref(`symbol`); case 'Symbol': return Type.ref(`symbol`);
} }
case 'pointer': case 'embedded':
return Type.ref(`_ptr`); return Type.ref(`_embedded`);
case 'lit': case 'lit':
return Type.unit(); return Type.unit();
case 'Ref': case 'Ref':

View File

@ -103,8 +103,8 @@ function unconverterFor(ctx: FunctionContext, p: M.Pattern, src: string, t: Simp
} }
case 'lit': case 'lit':
return ctx.mod.literal(p.value); return ctx.mod.literal(p.value);
case 'pointer': case 'embedded':
return `_.embed(${src})`; return `_.embedded(${src})`;
case 'Ref': case 'Ref':
return M.lookup( return M.lookup(
refPosition(p.value), p.value, ctx.mod.env, refPosition(p.value), p.value, ctx.mod.env,
@ -167,7 +167,7 @@ function unconverterFor(ctx: FunctionContext, p: M.Pattern, src: string, t: Simp
throw new InsufficientInformationError( throw new InsufficientInformationError(
`C Cannot produce unconverter TODO ${src} ${formatItems([renderType(t)])}`); `C Cannot produce unconverter TODO ${src} ${formatItems([renderType(t)])}`);
} }
return seq(`new _.Set<_ptr>`, parens( return seq(`new _.Set<_embedded>`, parens(
`_.Array.from(${src}.values()).map(v => `, `_.Array.from(${src}.values()).map(v => `,
unconverterFor(ctx, M.Pattern.SimplePattern(p.pattern), 'v', t), unconverterFor(ctx, M.Pattern.SimplePattern(p.pattern), 'v', t),
`)`)); `)`));
@ -176,14 +176,14 @@ function unconverterFor(ctx: FunctionContext, p: M.Pattern, src: string, t: Simp
throw new InsufficientInformationError( throw new InsufficientInformationError(
`D Cannot produce unconverter TODO ${src} ${formatItems([renderType(t)])}`); `D Cannot produce unconverter TODO ${src} ${formatItems([renderType(t)])}`);
} }
return seq(`new _.Dictionary<_ptr>`, parens(seq( return seq(`new _.Dictionary<_embedded>`, parens(seq(
`_.Array.from(${src}.entries()).map(([k, v]) => `, `_.Array.from(${src}.entries()).map(([k, v]) => `,
brackets( brackets(
unconverterFor(ctx, M.Pattern.SimplePattern(p.key), 'k', t), unconverterFor(ctx, M.Pattern.SimplePattern(p.key), 'k', t),
unconverterFor(ctx, M.Pattern.SimplePattern(p.value), 'v', t)), unconverterFor(ctx, M.Pattern.SimplePattern(p.value), 'v', t)),
`)`))); `)`)));
case 'dict': case 'dict':
return seq(`new _.Dictionary<_ptr>`, parens( return seq(`new _.Dictionary<_embedded>`, parens(
brackets(... Array.from(p.entries.entries()).map(([k, n]) => brackets(... Array.from(p.entries.entries()).map(([k, n]) =>
brackets( brackets(
ctx.mod.literal(k), ctx.mod.literal(k),

View File

@ -74,11 +74,11 @@ export function renderType(t: Type): Item {
case 'ref': return t.typeName; case 'ref': return t.typeName;
case 'set': return seq('_.KeyedSet', anglebrackets( case 'set': return seq('_.KeyedSet', anglebrackets(
renderType(t.type), renderType(t.type),
'_ptr')); '_embedded'));
case 'dictionary': return seq('_.KeyedDictionary', anglebrackets( case 'dictionary': return seq('_.KeyedDictionary', anglebrackets(
renderType(t.key), renderType(t.key),
renderType(t.value), renderType(t.value),
'_ptr')); '_embedded'));
case 'array': return seq('Array', anglebrackets(renderType(t.type))); case 'array': return seq('Array', anglebrackets(renderType(t.type)));
case 'record': return braces(... Array.from(t.fields).map(([nn, tt]) => case 'record': return braces(... Array.from(t.fields).map(([nn, tt]) =>
keyvalue(nn, renderType(tt)))); keyvalue(nn, renderType(tt))));

View File

@ -2,7 +2,7 @@ import { Annotated, Bytes, Set, Dictionary, Fold, fold, Record, Tuple, Value, st
import { brackets, Item, parens, seq } from "./block"; import { brackets, Item, parens, seq } from "./block";
import * as M from '../meta'; import * as M from '../meta';
export function sourceCodeFor(v: Value<M._ptr>): Item { export function sourceCodeFor(v: Value<M._embedded>): Item {
return fold(v, { return fold(v, {
boolean(b: boolean): Item { return b.toString(); }, boolean(b: boolean): Item { return b.toString(); },
single(f: number): Item { return f.toString(); }, single(f: number): Item { return f.toString(); },
@ -14,26 +14,26 @@ export function sourceCodeFor(v: Value<M._ptr>): Item {
}, },
symbol(s: symbol): Item { return `Symbol.for(${JSON.stringify(s.description!)})`; }, symbol(s: symbol): Item { return `Symbol.for(${JSON.stringify(s.description!)})`; },
record(r: Record<Value<M._ptr>, Tuple<Value<M._ptr>>, M._ptr>, k: Fold<M._ptr, Item>): Item { record(r: Record<Value<M._embedded>, Tuple<Value<M._embedded>>, M._embedded>, k: Fold<M._embedded, Item>): Item {
return seq(`_.Record<_val, _.Tuple<_val>, _ptr>`, parens(k(r.label), brackets(... r.map(k)))); return seq(`_.Record<_val, _.Tuple<_val>, _embedded>`, parens(k(r.label), brackets(... r.map(k))));
}, },
array(a: Array<Value<M._ptr>>, k: Fold<M._ptr, Item>): Item { array(a: Array<Value<M._embedded>>, k: Fold<M._embedded, Item>): Item {
return brackets(... a.map(k)); return brackets(... a.map(k));
}, },
set(s: Set<M._ptr>, k: Fold<M._ptr, Item>): Item { set(s: Set<M._embedded>, k: Fold<M._embedded, Item>): Item {
return seq('new _.Set<_val>', parens(brackets(... Array.from(s).map(k)))); return seq('new _.Set<_val>', parens(brackets(... Array.from(s).map(k))));
}, },
dictionary(d: Dictionary<M._ptr>, k: Fold<M._ptr, Item>): Item { dictionary(d: Dictionary<M._embedded>, k: Fold<M._embedded, Item>): Item {
return seq('new _.Dictionary<_ptr>', parens(brackets(... Array.from(d).map(([kk,vv]) => return seq('new _.Dictionary<_embedded>', parens(brackets(... Array.from(d).map(([kk,vv]) =>
brackets(k(kk), k(vv)))))); brackets(k(kk), k(vv))))));
}, },
annotated(a: Annotated<M._ptr>, k: Fold<M._ptr, Item>): Item { annotated(a: Annotated<M._embedded>, k: Fold<M._embedded, Item>): Item {
return seq('_.annotate<_ptr>', parens(k(a.item), ... a.annotations.map(k))); return seq('_.annotate<_embedded>', parens(k(a.item), ... a.annotations.map(k)));
}, },
pointer(t: M._ptr, _k: Fold<M._ptr, Item>): Item { embedded(t: M._embedded, _k: Fold<M._embedded, Item>): Item {
throw new Error(`Cannot emit source code for construction of pointer ${stringify(t)}`); throw new Error(`Cannot emit source code for construction of embedded ${stringify(t)}`);
}, },
}); });
} }

View File

@ -15,10 +15,11 @@ export const $bundle = Symbol.for("bundle");
export const $definitions = Symbol.for("definitions"); export const $definitions = Symbol.for("definitions");
export const $dict = Symbol.for("dict"); export const $dict = Symbol.for("dict");
export const $dictof = Symbol.for("dictof"); export const $dictof = Symbol.for("dictof");
export const $embedded = Symbol.for("embedded");
export const $embeddedType = Symbol.for("embeddedType");
export const $lit = Symbol.for("lit"); export const $lit = Symbol.for("lit");
export const $named = Symbol.for("named"); export const $named = Symbol.for("named");
export const $or = Symbol.for("or"); export const $or = Symbol.for("or");
export const $pointer = Symbol.for("pointer");
export const $rec = Symbol.for("rec"); export const $rec = Symbol.for("rec");
export const $ref = Symbol.for("ref"); export const $ref = Symbol.for("ref");
export const $schema = Symbol.for("schema"); export const $schema = Symbol.for("schema");
@ -28,21 +29,25 @@ export const $tuple$STAR$ = Symbol.for("tuple*");
export const $version = Symbol.for("version"); export const $version = Symbol.for("version");
export const __lit6 = false; export const __lit6 = false;
export type _ptr = any; export type _embedded = any;
export type _val = _.Value<_ptr>; export type _val = _.Value<_embedded>;
export type Bundle = {"modules": Modules}; export type Bundle = {"modules": Modules};
export type Modules = _.KeyedDictionary<ModulePath, Schema, _ptr>; export type Modules = _.KeyedDictionary<ModulePath, Schema, _embedded>;
export type Schema = {"version": Version, "pointer": PointerName, "definitions": Definitions}; export type Schema = {
"version": Version,
"embeddedType": EmbeddedTypeName,
"definitions": Definitions
};
export type Version = null; export type Version = null;
export type PointerName = ({"_variant": "Ref", "value": Ref} | {"_variant": "false"}); export type EmbeddedTypeName = ({"_variant": "Ref", "value": Ref} | {"_variant": "false"});
export type Definitions = _.KeyedDictionary<symbol, Definition, _ptr>; export type Definitions = _.KeyedDictionary<symbol, Definition, _embedded>;
export type Definition = ( export type Definition = (
{ {
@ -68,7 +73,7 @@ export type Pattern = (
export type SimplePattern = ( export type SimplePattern = (
{"_variant": "any"} | {"_variant": "any"} |
{"_variant": "atom", "atomKind": AtomKind} | {"_variant": "atom", "atomKind": AtomKind} |
{"_variant": "pointer"} | {"_variant": "embedded"} |
{"_variant": "lit", "value": _val} | {"_variant": "lit", "value": _val} |
{"_variant": "Ref", "value": Ref} {"_variant": "Ref", "value": Ref}
); );
@ -86,7 +91,7 @@ export type CompoundPattern = (
{"_variant": "dict", "entries": DictionaryEntries} {"_variant": "dict", "entries": DictionaryEntries}
); );
export type DictionaryEntries = _.KeyedDictionary<_val, NamedSimplePattern, _ptr>; export type DictionaryEntries = _.KeyedDictionary<_val, NamedSimplePattern, _embedded>;
export type AtomKind = ( export type AtomKind = (
{"_variant": "Boolean"} | {"_variant": "Boolean"} |
@ -117,20 +122,22 @@ export type ModulePath = Array<symbol>;
export function Bundle(modules: Modules): Bundle {return {"modules": modules};} export function Bundle(modules: Modules): Bundle {return {"modules": modules};}
export function Modules(value: _.KeyedDictionary<ModulePath, Schema, _ptr>): Modules {return value;} export function Modules(value: _.KeyedDictionary<ModulePath, Schema, _embedded>): Modules {return value;}
export function Schema( export function Schema(
{version, pointer, definitions}: {version: Version, pointer: PointerName, definitions: Definitions} {version, embeddedType, definitions}: {version: Version, embeddedType: EmbeddedTypeName, definitions: Definitions}
): Schema {return {"version": version, "pointer": pointer, "definitions": definitions};} ): Schema {
return {"version": version, "embeddedType": embeddedType, "definitions": definitions};
}
export function Version(): Version {return null;} export function Version(): Version {return null;}
export namespace PointerName { export namespace EmbeddedTypeName {
export function Ref(value: Ref): PointerName {return {"_variant": "Ref", "value": value};}; export function Ref(value: Ref): EmbeddedTypeName {return {"_variant": "Ref", "value": value};};
export function $false(): PointerName {return {"_variant": "false"};}; export function $false(): EmbeddedTypeName {return {"_variant": "false"};};
} }
export function Definitions(value: _.KeyedDictionary<symbol, Definition, _ptr>): Definitions {return value;} export function Definitions(value: _.KeyedDictionary<symbol, Definition, _embedded>): Definitions {return value;}
export namespace Definition { export namespace Definition {
export function or( export function or(
@ -154,7 +161,7 @@ export namespace Pattern {
export namespace SimplePattern { export namespace SimplePattern {
export function any(): SimplePattern {return {"_variant": "any"};}; export function any(): SimplePattern {return {"_variant": "any"};};
export function atom(atomKind: AtomKind): SimplePattern {return {"_variant": "atom", "atomKind": atomKind};}; export function atom(atomKind: AtomKind): SimplePattern {return {"_variant": "atom", "atomKind": atomKind};};
export function pointer(): SimplePattern {return {"_variant": "pointer"};}; export function embedded(): SimplePattern {return {"_variant": "embedded"};};
export function lit(value: _val): SimplePattern {return {"_variant": "lit", "value": value};}; export function lit(value: _val): SimplePattern {return {"_variant": "lit", "value": value};};
export function Ref(value: Ref): SimplePattern {return {"_variant": "Ref", "value": value};}; export function Ref(value: Ref): SimplePattern {return {"_variant": "Ref", "value": value};};
} }
@ -168,7 +175,7 @@ export namespace CompoundPattern {
export function dict(entries: DictionaryEntries): CompoundPattern {return {"_variant": "dict", "entries": entries};}; export function dict(entries: DictionaryEntries): CompoundPattern {return {"_variant": "dict", "entries": entries};};
} }
export function DictionaryEntries(value: _.KeyedDictionary<_val, NamedSimplePattern, _ptr>): DictionaryEntries {return value;} export function DictionaryEntries(value: _.KeyedDictionary<_val, NamedSimplePattern, _embedded>): DictionaryEntries {return value;}
export namespace AtomKind { export namespace AtomKind {
export function Boolean(): AtomKind {return {"_variant": "Boolean"};}; export function Boolean(): AtomKind {return {"_variant": "Boolean"};};
@ -204,7 +211,7 @@ export function asBundle(v: _val): Bundle {
export function toBundle(v: _val): undefined | Bundle { export function toBundle(v: _val): undefined | Bundle {
let result: undefined | Bundle; let result: undefined | Bundle;
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) { if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
let _tmp0: (null) | undefined; let _tmp0: (null) | undefined;
_tmp0 = _.is(v.label, $bundle) ? null : void 0; _tmp0 = _.is(v.label, $bundle) ? null : void 0;
if (_tmp0 !== void 0) { if (_tmp0 !== void 0) {
@ -225,9 +232,9 @@ export function asModules(v: _val): Modules {
} }
export function toModules(v: _val): undefined | Modules { export function toModules(v: _val): undefined | Modules {
let _tmp0: (_.KeyedDictionary<ModulePath, Schema, _ptr>) | undefined; let _tmp0: (_.KeyedDictionary<ModulePath, Schema, _embedded>) | undefined;
let result: undefined | Modules; let result: undefined | Modules;
if (_.Dictionary.isDictionary<_ptr>(v)) { if (_.Dictionary.isDictionary<_embedded>(v)) {
_tmp0 = new _.KeyedDictionary(); _tmp0 = new _.KeyedDictionary();
for (const [_tmp2, _tmp1] of v) { for (const [_tmp2, _tmp1] of v) {
let _tmp3: (ModulePath) | undefined; let _tmp3: (ModulePath) | undefined;
@ -246,7 +253,7 @@ export function toModules(v: _val): undefined | Modules {
} }
export function fromModules(_v: Modules): _val { export function fromModules(_v: Modules): _val {
return new _.Dictionary<_ptr>(_.Array.from(_v.entries()).map(([k, v]) => [fromModulePath(k), fromSchema(v)])); return new _.Dictionary<_embedded>(_.Array.from(_v.entries()).map(([k, v]) => [fromModulePath(k), fromSchema(v)]));
} }
export function asSchema(v: _val): Schema { export function asSchema(v: _val): Schema {
@ -257,26 +264,26 @@ export function asSchema(v: _val): Schema {
export function toSchema(v: _val): undefined | Schema { export function toSchema(v: _val): undefined | Schema {
let result: undefined | Schema; let result: undefined | Schema;
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) { if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
let _tmp0: (null) | undefined; let _tmp0: (null) | undefined;
_tmp0 = _.is(v.label, $schema) ? null : void 0; _tmp0 = _.is(v.label, $schema) ? null : void 0;
if (_tmp0 !== void 0) { if (_tmp0 !== void 0) {
if (_.Dictionary.isDictionary<_ptr>(v[0])) { if (_.Dictionary.isDictionary<_embedded>(v[0])) {
let _tmp1: (_val) | undefined; let _tmp1: (_val) | undefined;
if ((_tmp1 = v[0].get($version)) !== void 0) { if ((_tmp1 = v[0].get($version)) !== void 0) {
let _tmp2: (Version) | undefined; let _tmp2: (Version) | undefined;
_tmp2 = toVersion(_tmp1); _tmp2 = toVersion(_tmp1);
if (_tmp2 !== void 0) { if (_tmp2 !== void 0) {
let _tmp3: (_val) | undefined; let _tmp3: (_val) | undefined;
if ((_tmp3 = v[0].get($pointer)) !== void 0) { if ((_tmp3 = v[0].get($embeddedType)) !== void 0) {
let _tmp4: (PointerName) | undefined; let _tmp4: (EmbeddedTypeName) | undefined;
_tmp4 = toPointerName(_tmp3); _tmp4 = toEmbeddedTypeName(_tmp3);
if (_tmp4 !== void 0) { if (_tmp4 !== void 0) {
let _tmp5: (_val) | undefined; let _tmp5: (_val) | undefined;
if ((_tmp5 = v[0].get($definitions)) !== void 0) { if ((_tmp5 = v[0].get($definitions)) !== void 0) {
let _tmp6: (Definitions) | undefined; let _tmp6: (Definitions) | undefined;
_tmp6 = toDefinitions(_tmp5); _tmp6 = toDefinitions(_tmp5);
if (_tmp6 !== void 0) {result = {"version": _tmp2, "pointer": _tmp4, "definitions": _tmp6};}; if (_tmp6 !== void 0) {result = {"version": _tmp2, "embeddedType": _tmp4, "definitions": _tmp6};};
}; };
}; };
}; };
@ -292,10 +299,10 @@ export function fromSchema(_v: Schema): _val {
return _.Record( return _.Record(
$schema, $schema,
[ [
new _.Dictionary<_ptr>( new _.Dictionary<_embedded>(
[ [
[$version, fromVersion(_v["version"])], [$version, fromVersion(_v["version"])],
[$pointer, fromPointerName(_v["pointer"])], [$embeddedType, fromEmbeddedTypeName(_v["embeddedType"])],
[$definitions, fromDefinitions(_v["definitions"])] [$definitions, fromDefinitions(_v["definitions"])]
] ]
) )
@ -319,15 +326,15 @@ export function toVersion(v: _val): undefined | Version {
export function fromVersion(_v: Version): _val {return $1;} export function fromVersion(_v: Version): _val {return $1;}
export function asPointerName(v: _val): PointerName { export function asEmbeddedTypeName(v: _val): EmbeddedTypeName {
let result = toPointerName(v); let result = toEmbeddedTypeName(v);
if (result === void 0) throw new TypeError(`Invalid PointerName: ${_.stringify(v)}`); if (result === void 0) throw new TypeError(`Invalid EmbeddedTypeName: ${_.stringify(v)}`);
return result; return result;
} }
export function toPointerName(v: _val): undefined | PointerName { export function toEmbeddedTypeName(v: _val): undefined | EmbeddedTypeName {
let _tmp0: (Ref) | undefined; let _tmp0: (Ref) | undefined;
let result: undefined | PointerName; let result: undefined | EmbeddedTypeName;
_tmp0 = toRef(v); _tmp0 = toRef(v);
if (_tmp0 !== void 0) {result = {"_variant": "Ref", "value": _tmp0};}; if (_tmp0 !== void 0) {result = {"_variant": "Ref", "value": _tmp0};};
if (result === void 0) { if (result === void 0) {
@ -338,7 +345,7 @@ export function toPointerName(v: _val): undefined | PointerName {
return result; return result;
} }
export function fromPointerName(_v: PointerName): _val { export function fromEmbeddedTypeName(_v: EmbeddedTypeName): _val {
switch (_v._variant) {case "Ref": {return fromRef(_v.value);}; case "false": {return __lit6;};}; switch (_v._variant) {case "Ref": {return fromRef(_v.value);}; case "false": {return __lit6;};};
} }
@ -349,9 +356,9 @@ export function asDefinitions(v: _val): Definitions {
} }
export function toDefinitions(v: _val): undefined | Definitions { export function toDefinitions(v: _val): undefined | Definitions {
let _tmp0: (_.KeyedDictionary<symbol, Definition, _ptr>) | undefined; let _tmp0: (_.KeyedDictionary<symbol, Definition, _embedded>) | undefined;
let result: undefined | Definitions; let result: undefined | Definitions;
if (_.Dictionary.isDictionary<_ptr>(v)) { if (_.Dictionary.isDictionary<_embedded>(v)) {
_tmp0 = new _.KeyedDictionary(); _tmp0 = new _.KeyedDictionary();
for (const [_tmp2, _tmp1] of v) { for (const [_tmp2, _tmp1] of v) {
let _tmp3: (symbol) | undefined; let _tmp3: (symbol) | undefined;
@ -370,7 +377,7 @@ export function toDefinitions(v: _val): undefined | Definitions {
} }
export function fromDefinitions(_v: Definitions): _val { export function fromDefinitions(_v: Definitions): _val {
return new _.Dictionary<_ptr>(_.Array.from(_v.entries()).map(([k, v]) => [k, fromDefinition(v)])); return new _.Dictionary<_embedded>(_.Array.from(_v.entries()).map(([k, v]) => [k, fromDefinition(v)]));
} }
export function asDefinition(v: _val): Definition { export function asDefinition(v: _val): Definition {
@ -381,7 +388,7 @@ export function asDefinition(v: _val): Definition {
export function toDefinition(v: _val): undefined | Definition { export function toDefinition(v: _val): undefined | Definition {
let result: undefined | Definition; let result: undefined | Definition;
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) { if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
let _tmp0: (null) | undefined; let _tmp0: (null) | undefined;
_tmp0 = _.is(v.label, $or) ? null : void 0; _tmp0 = _.is(v.label, $or) ? null : void 0;
if (_tmp0 !== void 0) { if (_tmp0 !== void 0) {
@ -462,7 +469,7 @@ export function asAlternative(v: _val): Alternative {
export function toAlternative(v: _val): undefined | Alternative { export function toAlternative(v: _val): undefined | Alternative {
let result: undefined | Alternative; let result: undefined | Alternative;
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) { if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
let _tmp0: (null) | undefined; let _tmp0: (null) | undefined;
_tmp0 = _.is(v.label, $and) ? null : void 0; _tmp0 = _.is(v.label, $and) ? null : void 0;
if (_tmp0 !== void 0) { if (_tmp0 !== void 0) {
@ -551,7 +558,7 @@ export function toSimplePattern(v: _val): undefined | SimplePattern {
_tmp0 = _.is(v, $any) ? null : void 0; _tmp0 = _.is(v, $any) ? null : void 0;
if (_tmp0 !== void 0) {result = {"_variant": "any"};}; if (_tmp0 !== void 0) {result = {"_variant": "any"};};
if (result === void 0) { if (result === void 0) {
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) { if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
let _tmp1: (null) | undefined; let _tmp1: (null) | undefined;
_tmp1 = _.is(v.label, $atom) ? null : void 0; _tmp1 = _.is(v.label, $atom) ? null : void 0;
if (_tmp1 !== void 0) { if (_tmp1 !== void 0) {
@ -561,13 +568,13 @@ export function toSimplePattern(v: _val): undefined | SimplePattern {
}; };
}; };
if (result === void 0) { if (result === void 0) {
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) { if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
let _tmp3: (null) | undefined; let _tmp3: (null) | undefined;
_tmp3 = _.is(v.label, $pointer) ? null : void 0; _tmp3 = _.is(v.label, $embedded) ? null : void 0;
if (_tmp3 !== void 0) {result = {"_variant": "pointer"};}; if (_tmp3 !== void 0) {result = {"_variant": "embedded"};};
}; };
if (result === void 0) { if (result === void 0) {
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) { if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
let _tmp4: (null) | undefined; let _tmp4: (null) | undefined;
_tmp4 = _.is(v.label, $lit) ? null : void 0; _tmp4 = _.is(v.label, $lit) ? null : void 0;
if (_tmp4 !== void 0) { if (_tmp4 !== void 0) {
@ -591,7 +598,7 @@ export function fromSimplePattern(_v: SimplePattern): _val {
switch (_v._variant) { switch (_v._variant) {
case "any": {return $any;}; case "any": {return $any;};
case "atom": {return _.Record($atom, [fromAtomKind(_v["atomKind"])]);}; case "atom": {return _.Record($atom, [fromAtomKind(_v["atomKind"])]);};
case "pointer": {return _.Record($pointer, []);}; case "embedded": {return _.Record($embedded, []);};
case "lit": {return _.Record($lit, [_v["value"]]);}; case "lit": {return _.Record($lit, [_v["value"]]);};
case "Ref": {return fromRef(_v.value);}; case "Ref": {return fromRef(_v.value);};
}; };
@ -605,7 +612,7 @@ export function asCompoundPattern(v: _val): CompoundPattern {
export function toCompoundPattern(v: _val): undefined | CompoundPattern { export function toCompoundPattern(v: _val): undefined | CompoundPattern {
let result: undefined | CompoundPattern; let result: undefined | CompoundPattern;
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) { if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
let _tmp0: (null) | undefined; let _tmp0: (null) | undefined;
_tmp0 = _.is(v.label, $rec) ? null : void 0; _tmp0 = _.is(v.label, $rec) ? null : void 0;
if (_tmp0 !== void 0) { if (_tmp0 !== void 0) {
@ -619,7 +626,7 @@ export function toCompoundPattern(v: _val): undefined | CompoundPattern {
}; };
}; };
if (result === void 0) { if (result === void 0) {
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) { if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
let _tmp3: (null) | undefined; let _tmp3: (null) | undefined;
_tmp3 = _.is(v.label, $tuple) ? null : void 0; _tmp3 = _.is(v.label, $tuple) ? null : void 0;
if (_tmp3 !== void 0) { if (_tmp3 !== void 0) {
@ -642,7 +649,7 @@ export function toCompoundPattern(v: _val): undefined | CompoundPattern {
}; };
}; };
if (result === void 0) { if (result === void 0) {
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) { if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
let _tmp8: (null) | undefined; let _tmp8: (null) | undefined;
_tmp8 = _.is(v.label, $tuple$STAR$) ? null : void 0; _tmp8 = _.is(v.label, $tuple$STAR$) ? null : void 0;
if (_tmp8 !== void 0) { if (_tmp8 !== void 0) {
@ -669,7 +676,7 @@ export function toCompoundPattern(v: _val): undefined | CompoundPattern {
}; };
}; };
if (result === void 0) { if (result === void 0) {
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) { if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
let _tmp14: (null) | undefined; let _tmp14: (null) | undefined;
_tmp14 = _.is(v.label, $setof) ? null : void 0; _tmp14 = _.is(v.label, $setof) ? null : void 0;
if (_tmp14 !== void 0) { if (_tmp14 !== void 0) {
@ -679,7 +686,7 @@ export function toCompoundPattern(v: _val): undefined | CompoundPattern {
}; };
}; };
if (result === void 0) { if (result === void 0) {
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) { if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
let _tmp16: (null) | undefined; let _tmp16: (null) | undefined;
_tmp16 = _.is(v.label, $dictof) ? null : void 0; _tmp16 = _.is(v.label, $dictof) ? null : void 0;
if (_tmp16 !== void 0) { if (_tmp16 !== void 0) {
@ -693,7 +700,7 @@ export function toCompoundPattern(v: _val): undefined | CompoundPattern {
}; };
}; };
if (result === void 0) { if (result === void 0) {
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) { if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
let _tmp19: (null) | undefined; let _tmp19: (null) | undefined;
_tmp19 = _.is(v.label, $dict) ? null : void 0; _tmp19 = _.is(v.label, $dict) ? null : void 0;
if (_tmp19 !== void 0) { if (_tmp19 !== void 0) {
@ -740,9 +747,9 @@ export function asDictionaryEntries(v: _val): DictionaryEntries {
} }
export function toDictionaryEntries(v: _val): undefined | DictionaryEntries { export function toDictionaryEntries(v: _val): undefined | DictionaryEntries {
let _tmp0: (_.KeyedDictionary<_val, NamedSimplePattern, _ptr>) | undefined; let _tmp0: (_.KeyedDictionary<_val, NamedSimplePattern, _embedded>) | undefined;
let result: undefined | DictionaryEntries; let result: undefined | DictionaryEntries;
if (_.Dictionary.isDictionary<_ptr>(v)) { if (_.Dictionary.isDictionary<_embedded>(v)) {
_tmp0 = new _.KeyedDictionary(); _tmp0 = new _.KeyedDictionary();
for (const [_tmp2, _tmp1] of v) { for (const [_tmp2, _tmp1] of v) {
let _tmp3: (_val) | undefined; let _tmp3: (_val) | undefined;
@ -761,7 +768,7 @@ export function toDictionaryEntries(v: _val): undefined | DictionaryEntries {
} }
export function fromDictionaryEntries(_v: DictionaryEntries): _val { export function fromDictionaryEntries(_v: DictionaryEntries): _val {
return new _.Dictionary<_ptr>(_.Array.from(_v.entries()).map(([k, v]) => [k, fromNamedSimplePattern(v)])); return new _.Dictionary<_embedded>(_.Array.from(_v.entries()).map(([k, v]) => [k, fromNamedSimplePattern(v)]));
} }
export function asAtomKind(v: _val): AtomKind { export function asAtomKind(v: _val): AtomKind {
@ -880,7 +887,7 @@ export function asNamedSimplePattern_(v: _val): NamedSimplePattern_ {
export function toNamedSimplePattern_(v: _val): undefined | NamedSimplePattern_ { export function toNamedSimplePattern_(v: _val): undefined | NamedSimplePattern_ {
let result: undefined | NamedSimplePattern_; let result: undefined | NamedSimplePattern_;
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) { if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
let _tmp0: (null) | undefined; let _tmp0: (null) | undefined;
_tmp0 = _.is(v.label, $named) ? null : void 0; _tmp0 = _.is(v.label, $named) ? null : void 0;
if (_tmp0 !== void 0) { if (_tmp0 !== void 0) {
@ -906,7 +913,7 @@ export function asRef(v: _val): Ref {
export function toRef(v: _val): undefined | Ref { export function toRef(v: _val): undefined | Ref {
let result: undefined | Ref; let result: undefined | Ref;
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) { if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
let _tmp0: (null) | undefined; let _tmp0: (null) | undefined;
_tmp0 = _.is(v.label, $ref) ? null : void 0; _tmp0 = _.is(v.label, $ref) ? null : void 0;
if (_tmp0 !== void 0) { if (_tmp0 !== void 0) {

View File

@ -65,8 +65,8 @@ export function parseSchema(toplevelTokens: Array<Input>,
options: ReaderOptions<never> & SchemaReaderOptions): Schema options: ReaderOptions<never> & SchemaReaderOptions): Schema
{ {
let version: M.Version | undefined = void 0; let version: M.Version | undefined = void 0;
let pointer: M.PointerName = M.PointerName.$false(); let embeddedType: M.EmbeddedTypeName = M.EmbeddedTypeName.$false();
let definitions = new KeyedDictionary<symbol, Definition, M._ptr>(); let definitions = new KeyedDictionary<symbol, Definition, M._embedded>();
function process(toplevelTokens: Array<Input>): void { function process(toplevelTokens: Array<Input>): void {
const toplevelClauses = splitBy(peel(toplevelTokens) as Array<Input>, M.DOT); const toplevelClauses = splitBy(peel(toplevelTokens) as Array<Input>, M.DOT);
@ -86,15 +86,15 @@ export function parseSchema(toplevelTokens: Array<Input>,
definitions.set(name, parseDefinition(name, pos, clause.slice(2))); definitions.set(name, parseDefinition(name, pos, clause.slice(2)));
} else if (clause.length === 2 && is(clause[0], M.$version)) { } else if (clause.length === 2 && is(clause[0], M.$version)) {
version = M.asVersion(peel(clause[1])); version = M.asVersion(peel(clause[1]));
} else if (clause.length === 2 && is(clause[0], M.$pointer)) { } else if (clause.length === 2 && is(clause[0], M.$embeddedType)) {
const pos = position(clause[1]); const pos = position(clause[1]);
const stx = peel(clause[1]); const stx = peel(clause[1]);
if (stx === false) { if (stx === false) {
pointer = M.PointerName.$false(); embeddedType = M.EmbeddedTypeName.$false();
} else if (typeof stx === 'symbol') { } else if (typeof stx === 'symbol') {
pointer = M.PointerName.Ref(parseRef(stx.description!, pos)); embeddedType = M.EmbeddedTypeName.Ref(parseRef(stx.description!, pos));
} else { } else {
invalidPattern('pointer name specification', stx, pos); invalidPattern('embedded type name specification', stx, pos);
} }
} else if (clause.length === 2 && is(clause[0], M.INCLUDE)) { } else if (clause.length === 2 && is(clause[0], M.INCLUDE)) {
const pos = position(clause[1]); const pos = position(clause[1]);
@ -118,7 +118,7 @@ export function parseSchema(toplevelTokens: Array<Input>,
throw new SchemaSyntaxError("Schema: missing version declaration.", null); throw new SchemaSyntaxError("Schema: missing version declaration.", null);
} }
return M.Schema({ version: M.Version(), pointer, definitions }); return M.Schema({ version: M.Version(), embeddedType, definitions });
} }
function namedMustBeSimple(p: Position | null): never { function namedMustBeSimple(p: Position | null): never {
@ -218,14 +218,14 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
case 'string': return ks(M.SimplePattern.atom(M.AtomKind.String())); case 'string': return ks(M.SimplePattern.atom(M.AtomKind.String()));
case 'bytes': return ks(M.SimplePattern.atom(M.AtomKind.ByteString())); case 'bytes': return ks(M.SimplePattern.atom(M.AtomKind.ByteString()));
case 'symbol': return ks(M.SimplePattern.atom(M.AtomKind.Symbol())); case 'symbol': return ks(M.SimplePattern.atom(M.AtomKind.Symbol()));
case 'ref': return ks(M.SimplePattern.pointer()); case 'embedded': return ks(M.SimplePattern.embedded());
default: return ks((str[0] === '=') default: return ks((str[0] === '=')
? M.SimplePattern.lit(Symbol.for(str.slice(1))) ? M.SimplePattern.lit(Symbol.for(str.slice(1)))
: M.SimplePattern.Ref(parseRef(str, pos))); : M.SimplePattern.Ref(parseRef(str, pos)));
} }
} else if (Record.isRecord<Input, Tuple<Input>, M._ptr>(item)) { } else if (Record.isRecord<Input, Tuple<Input>, M._embedded>(item)) {
const label = item.label; const label = item.label;
if (Record.isRecord<Input, [], M._ptr>(label)) { if (Record.isRecord<Input, [], M._embedded>(label)) {
if (label.length !== 0) complain(); if (label.length !== 0) complain();
switch (label.label) { switch (label.label) {
case M.$lit: case M.$lit:
@ -290,9 +290,9 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
} }
} }
if (Record.isRecord<Input, Tuple<Input>, M._ptr>(item)) { if (Record.isRecord<Input, Tuple<Input>, M._embedded>(item)) {
const label = item.label; const label = item.label;
if (Record.isRecord<Input, [], M._ptr>(label)) { if (Record.isRecord<Input, [], M._embedded>(label)) {
if (label.length !== 0) complain(); if (label.length !== 0) complain();
switch (label.label) { switch (label.label) {
case M.$rec: case M.$rec:
@ -312,7 +312,7 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
} }
} else if (Array.isArray(item)) { } else if (Array.isArray(item)) {
return parseArrayLike(item); return parseArrayLike(item);
} else if (Dictionary.isDictionary<M._ptr, Input>(item)) { } else if (Dictionary.isDictionary<M._embedded, Input>(item)) {
if (item.size === 2 && item.has(M.DOTDOTDOT)) { if (item.size === 2 && item.has(M.DOTDOTDOT)) {
const v = item.clone(); const v = item.clone();
v.delete(M.DOTDOTDOT); v.delete(M.DOTDOTDOT);
@ -320,7 +320,7 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
return M.CompoundPattern.dictof({ key: walkSimple(kp), value: walkSimple(vp) }); return M.CompoundPattern.dictof({ key: walkSimple(kp), value: walkSimple(vp) });
} else { } else {
return M.CompoundPattern.dict( return M.CompoundPattern.dict(
M.DictionaryEntries(item.mapEntries<M.NamedSimplePattern, Input, M._ptr>( M.DictionaryEntries(item.mapEntries<M.NamedSimplePattern, Input, M._embedded>(
([k, vp]) => [ ([k, vp]) => [
strip(k), strip(k),
_maybeNamed( _maybeNamed(

View File

@ -257,12 +257,12 @@ def annotate(v, *anns):
return v return v
class Decoder(Codec): class Decoder(Codec):
def __init__(self, packet=b'', include_annotations=False, decode_pointer=None): def __init__(self, packet=b'', include_annotations=False, decode_embedded=None):
super(Decoder, self).__init__() super(Decoder, self).__init__()
self.packet = packet self.packet = packet
self.index = 0 self.index = 0
self.include_annotations = include_annotations self.include_annotations = include_annotations
self.decode_pointer = decode_pointer self.decode_embedded = decode_embedded
def extend(self, data): def extend(self, data):
self.packet = self.packet[self.index:] + data self.packet = self.packet[self.index:] + data
@ -329,9 +329,9 @@ class Decoder(Codec):
v = self.next() v = self.next()
return self.unshift_annotation(a, v) return self.unshift_annotation(a, v)
if tag == 0x86: if tag == 0x86:
if self.decode_pointer is None: if self.decode_embedded is None:
raise DecodeError('No decode_pointer function supplied') raise DecodeError('No decode_embedded function supplied')
return self.wrap(self.decode_pointer(self.next())) return self.wrap(self.decode_embedded(self.next()))
if tag >= 0x90 and tag <= 0x9f: return self.wrap(tag - (0xa0 if tag > 0x9c else 0x90)) if tag >= 0x90 and tag <= 0x9f: return self.wrap(tag - (0xa0 if tag > 0x9c else 0x90))
if tag >= 0xa0 and tag <= 0xaf: return self.wrap(self.nextint(tag - 0xa0 + 1)) if tag >= 0xa0 and tag <= 0xaf: return self.wrap(self.nextint(tag - 0xa0 + 1))
if tag == 0xb0: return self.wrap(self.nextint(self.varint())) if tag == 0xb0: return self.wrap(self.nextint(self.varint()))
@ -362,10 +362,10 @@ def decode_with_annotations(bs, **kwargs):
return Decoder(packet=bs, include_annotations=True, **kwargs).next() return Decoder(packet=bs, include_annotations=True, **kwargs).next()
class Encoder(Codec): class Encoder(Codec):
def __init__(self, encode_pointer=id): def __init__(self, encode_embedded=id):
super(Encoder, self).__init__() super(Encoder, self).__init__()
self.buffer = bytearray() self.buffer = bytearray()
self.encode_pointer = encode_pointer self.encode_embedded = encode_embedded
def contents(self): def contents(self):
return bytes(self.buffer) return bytes(self.buffer)
@ -435,7 +435,7 @@ class Encoder(Codec):
i = iter(v) i = iter(v)
except TypeError: except TypeError:
self.buffer.append(0x86) self.buffer.append(0x86)
self.append(self.encode_pointer(v)) self.append(self.encode_embedded(v))
return return
self.encodevalues(5, i) self.encodevalues(5, i)

View File

@ -157,7 +157,7 @@ class CodecTests(unittest.TestCase):
self._roundtrip((False,) * 100, _buf(0xb5, b'\x80' * 100, 0x84)) self._roundtrip((False,) * 100, _buf(0xb5, b'\x80' * 100, 0x84))
self._roundtrip((False,) * 200, _buf(0xb5, b'\x80' * 200, 0x84)) self._roundtrip((False,) * 200, _buf(0xb5, b'\x80' * 200, 0x84))
def test_pointer_id(self): def test_embedded_id(self):
class A: class A:
def __init__(self, a): def __init__(self, a):
self.a = a self.a = a
@ -169,23 +169,23 @@ class CodecTests(unittest.TestCase):
self.assertEqual(_ord(_e(a1)[0]), 0x86) self.assertEqual(_ord(_e(a1)[0]), 0x86)
self.assertEqual(_ord(_e(a2)[0]), 0x86) self.assertEqual(_ord(_e(a2)[0]), 0x86)
def test_decode_pointer_absent(self): def test_decode_embedded_absent(self):
with self.assertRaises(DecodeError): with self.assertRaises(DecodeError):
decode(b'\x86\xa0\xff') decode(b'\x86\xa0\xff')
def test_encode_pointer(self): def test_encode_embedded(self):
objects = [] objects = []
def enc(p): def enc(p):
objects.append(p) objects.append(p)
return len(objects) - 1 return len(objects) - 1
self.assertEqual(encode([object(), object()], encode_pointer = enc), self.assertEqual(encode([object(), object()], encode_embedded = enc),
b'\xb5\x86\x90\x86\x91\x84') b'\xb5\x86\x90\x86\x91\x84')
def test_decode_pointer(self): def test_decode_embedded(self):
objects = [123, 234] objects = [123, 234]
def dec(v): def dec(v):
return objects[v] return objects[v]
self.assertEqual(decode(b'\xb5\x86\x90\x86\x91\x84', decode_pointer = dec), self.assertEqual(decode(b'\xb5\x86\x90\x86\x91\x84', decode_embedded = dec),
(123, 234)) (123, 234))
def add_method(d, tName, fn): def add_method(d, tName, fn):
@ -254,7 +254,7 @@ def install_exn_test(d, tName, bs, check_proc):
self.fail('did not fail as expected') self.fail('did not fail as expected')
add_method(d, tName, test_exn) add_method(d, tName, test_exn)
class Pointer: class Embedded:
def __init__(self, v): def __init__(self, v):
self.v = strip_annotations(v) self.v = strip_annotations(v)
@ -273,7 +273,7 @@ class CommonTestSuite(unittest.TestCase):
import os import os
with open(os.path.join(os.path.dirname(__file__), with open(os.path.join(os.path.dirname(__file__),
'../../../tests/samples.bin'), 'rb') as f: '../../../tests/samples.bin'), 'rb') as f:
samples = Decoder(f.read(), include_annotations=True, decode_pointer=Pointer).next() samples = Decoder(f.read(), include_annotations=True, decode_embedded=Embedded).next()
TestCases = Record.makeConstructor('TestCases', 'cases') TestCases = Record.makeConstructor('TestCases', 'cases')
@ -303,13 +303,13 @@ class CommonTestSuite(unittest.TestCase):
raise Exception('Unsupported test kind', t.key) raise Exception('Unsupported test kind', t.key)
def DS(self, bs): def DS(self, bs):
return decode(bs, decode_pointer=Pointer) return decode(bs, decode_embedded=Embedded)
def D(self, bs): def D(self, bs):
return decode_with_annotations(bs, decode_pointer=Pointer) return decode_with_annotations(bs, decode_embedded=Embedded)
def E(self, v): def E(self, v):
return encode(v, encode_pointer=Pointer.value) return encode(v, encode_embedded=Embedded.value)
class RecordTests(unittest.TestCase): class RecordTests(unittest.TestCase):
def test_getters(self): def test_getters(self):

View File

@ -5,7 +5,7 @@ except ImportError:
setup( setup(
name="preserves", name="preserves",
version="0.5.0", version="0.6.0",
author="Tony Garnock-Jones", author="Tony Garnock-Jones",
author_email="tonyg@leastfixedpoint.com", author_email="tonyg@leastfixedpoint.com",
license="Apache Software License", license="Apache Software License",

View File

@ -1,5 +1,5 @@
PACKAGENAME=preserves PACKAGENAME=preserves
COLLECTS=preserves COLLECTS=preserves preserves-schema
all: setup all: setup

View File

@ -11,7 +11,7 @@
(struct record (label fields) #:transparent) (struct record (label fields) #:transparent)
(struct float (value) #:transparent) ;; a marker for single-precision I/O (struct float (value) #:transparent) ;; a marker for single-precision I/O
(struct annotated (annotations item) #:transparent) (struct annotated (annotations item) #:transparent)
(struct pointer (value) #:transparent) (struct embedded (value) #:transparent)
;;--------------------------------------------------------------------------- ;;---------------------------------------------------------------------------
;; Reader ;; Reader
@ -30,7 +30,7 @@
(match (next) (match (next)
[(annotated as i) (annotated (cons a as) i)] [(annotated as i) (annotated (cons a as) i)]
[i (annotated (list a) i)]))] [i (annotated (list a) i)]))]
[#x86 (pointer (next))] [#x86 (embedded (next))]
[(? (between #x90 #x9C) v) (- v #x90)] [(? (between #x90 #x9C) v) (- v #x90)]
[(? (between #x9D #x9F) v) (- v #xA0)] [(? (between #x9D #x9F) v) (- v #xA0)]
[(? (between #xA0 #xAF) v) (next-integer (- v #xA0 -1))] [(? (between #xA0 #xAF) v) (next-integer (- v #xA0 -1))]
@ -87,7 +87,7 @@
(for [(a (in-list as))] (write-byte #x85 out-port) (output a)) (for [(a (in-list as))] (write-byte #x85 out-port) (output a))
(output v)] (output v)]
[(pointer v) (write-byte #x86 out-port) (output v)] [(embedded v) (write-byte #x86 out-port) (output v)]
[(? integer?) [(? integer?)
(cond [(<= -3 v -1) (write-byte (+ v #xA0) out-port)] (cond [(<= -3 v -1) (write-byte (+ v #xA0) out-port)]

View File

@ -25,14 +25,14 @@
(define (read-preserve [in-port (current-input-port)] (define (read-preserve [in-port (current-input-port)]
#:read-syntax? [read-syntax? #f] #:read-syntax? [read-syntax? #f]
#:decode-pointer [decode-pointer #f] #:decode-embedded [decode-embedded #f]
#:source [source (object-name in-port)]) #:source [source (object-name in-port)])
(define b (peek-byte in-port)) (define b (peek-byte in-port))
(cond [(eof-object? b) b] (cond [(eof-object? b) b]
[(<= #x80 b #xBF) (read-preserve/binary in-port [(<= #x80 b #xBF) (read-preserve/binary in-port
#:read-syntax? read-syntax? #:read-syntax? read-syntax?
#:decode-pointer decode-pointer)] #:decode-embedded decode-embedded)]
[else (read-preserve/text in-port [else (read-preserve/text in-port
#:read-syntax? read-syntax? #:read-syntax? read-syntax?
#:decode-pointer decode-pointer #:decode-embedded decode-embedded
#:source source)])) #:source source)]))

View File

@ -13,12 +13,12 @@
(define (default-on-short) (error 'read-preserve/binary "Short Preserves binary")) (define (default-on-short) (error 'read-preserve/binary "Short Preserves binary"))
(define (default-on-fail message . args) (error 'read-preserve/binary (apply format message args))) (define (default-on-fail message . args) (error 'read-preserve/binary (apply format message args)))
(define (default-decode-pointer v) (define (default-decode-embedded v)
(error 'read-preserve/binary "No decode-pointer function supplied")) (error 'read-preserve/binary "No decode-embedded function supplied"))
(define (bytes->preserve bs (define (bytes->preserve bs
#:read-syntax? [read-syntax? #f] #:read-syntax? [read-syntax? #f]
#:decode-pointer [decode-pointer #f] #:decode-embedded [decode-embedded #f]
#:on-short [on-short default-on-short] #:on-short [on-short default-on-short]
[on-fail default-on-fail]) [on-fail default-on-fail])
(call-with-input-bytes (call-with-input-bytes
@ -26,7 +26,7 @@
(lambda (p) (lambda (p)
(match (read-preserve/binary p (match (read-preserve/binary p
#:read-syntax? read-syntax? #:read-syntax? read-syntax?
#:decode-pointer decode-pointer #:decode-embedded decode-embedded
#:on-short on-short #:on-short on-short
on-fail) on-fail)
[(? eof-object?) (on-short)] [(? eof-object?) (on-short)]
@ -36,11 +36,11 @@
(define (read-preserve/binary [in-port (current-input-port)] (define (read-preserve/binary [in-port (current-input-port)]
#:read-syntax? [read-syntax? #f] #:read-syntax? [read-syntax? #f]
#:decode-pointer [decode-pointer0 #f] #:decode-embedded [decode-embedded0 #f]
#:on-short [on-short default-on-short] #:on-short [on-short default-on-short]
[on-fail default-on-fail]) [on-fail default-on-fail])
(define read-annotations? read-syntax?) (define read-annotations? read-syntax?)
(define decode-pointer (or decode-pointer0 default-decode-pointer)) (define decode-embedded (or decode-embedded0 default-decode-embedded))
(let/ec return (let/ec return
(define (next) (wrap (pos) (next* (next-byte)))) (define (next) (wrap (pos) (next* (next-byte))))
@ -76,7 +76,7 @@
(if read-annotations? (if read-annotations?
(annotate (next) a) (annotate (next) a)
(next)))] (next)))]
[#x86 (decode-pointer (next))] [#x86 (decode-embedded (next))]
[(? (between #x90 #x9C) v) (- v #x90)] [(? (between #x90 #x9C) v) (- v #x90)]
[(? (between #x9D #x9F) v) (- v #xA0)] [(? (between #x9D #x9F) v) (- v #xA0)]
[(? (between #xA0 #xAF) v) (next-integer (- v #xA0 -1))] [(? (between #xA0 #xAF) v) (next-integer (- v #xA0 -1))]

View File

@ -24,18 +24,18 @@
pos pos
#f)) #f))
(define (default-decode-pointer v) (define (default-decode-embedded v)
(error 'read-preserve/text "No decode-pointer function supplied")) (error 'read-preserve/text "No decode-embedded function supplied"))
(define (string->preserve s (define (string->preserve s
#:read-syntax? [read-syntax? #f] #:read-syntax? [read-syntax? #f]
#:decode-pointer [decode-pointer #f] #:decode-embedded [decode-embedded #f]
#:source [source "<string>"]) #:source [source "<string>"])
(define p (open-input-string s)) (define p (open-input-string s))
(when read-syntax? (port-count-lines! p)) (when read-syntax? (port-count-lines! p))
(define v (read-preserve/text p (define v (read-preserve/text p
#:read-syntax? read-syntax? #:read-syntax? read-syntax?
#:decode-pointer decode-pointer #:decode-embedded decode-embedded
#:source source)) #:source source))
(when (eof-object? v) (when (eof-object? v)
(parse-error* #:raise-proc raise-read-eof-error p source "Unexpected end of input")) (parse-error* #:raise-proc raise-read-eof-error p source "Unexpected end of input"))
@ -53,10 +53,10 @@
(define (read-preserve/text [in-port (current-input-port)] (define (read-preserve/text [in-port (current-input-port)]
#:read-syntax? [read-syntax? #f] #:read-syntax? [read-syntax? #f]
#:decode-pointer [decode-pointer0 #f] #:decode-embedded [decode-embedded0 #f]
#:source [source (object-name in-port)]) #:source [source (object-name in-port)])
(define read-annotations? read-syntax?) (define read-annotations? read-syntax?)
(define decode-pointer (or decode-pointer0 default-decode-pointer)) (define decode-embedded (or decode-embedded0 default-decode-embedded))
;;--------------------------------------------------------------------------- ;;---------------------------------------------------------------------------
;; Core of parser ;; Core of parser
@ -96,7 +96,7 @@
(apply parse-error (string-append "Embedded binary value: " message) args)) (apply parse-error (string-append "Embedded binary value: " message) args))
#:read-syntax? read-syntax? #:read-syntax? read-syntax?
#:on-short (lambda () (parse-error "Incomplete embedded binary value")))] #:on-short (lambda () (parse-error "Incomplete embedded binary value")))]
[#\! (decode-pointer (next))] [#\! (decode-embedded (next))]
[c (parse-error "Invalid # syntax: ~v" c)])] [c (parse-error "Invalid # syntax: ~v" c)])]
[#\< (match (read-sequence #\>) [#\< (match (read-sequence #\>)

View File

@ -9,22 +9,22 @@
(require racket/runtime-path) (require racket/runtime-path)
(require syntax/srcloc) (require syntax/srcloc)
(struct pointer (value) #:transparent) (struct embedded (value) #:transparent)
(define (pointer/no-annotations v) (define (embedded/no-annotations v)
(pointer (strip-annotations v))) (embedded (strip-annotations v)))
(define (d bs #:allow-invalid-prefix? [allow-invalid-prefix? #f]) (define (d bs #:allow-invalid-prefix? [allow-invalid-prefix? #f])
(for [(i (in-range 1 (- (bytes-length bs) 1)))] (for [(i (in-range 1 (- (bytes-length bs) 1)))]
(define result (bytes->preserve (subbytes bs 0 i) (define result (bytes->preserve (subbytes bs 0 i)
#:decode-pointer pointer/no-annotations #:decode-embedded embedded/no-annotations
#:on-short (lambda () 'short) void)) #:on-short (lambda () 'short) void))
(when (and (not (eq? result 'short)) (when (and (not (eq? result 'short))
(not (and allow-invalid-prefix? (void? result)))) (not (and allow-invalid-prefix? (void? result))))
(error 'd "~a-byte prefix of ~v does not read as short; result: ~v" i bs result))) (error 'd "~a-byte prefix of ~v does not read as short; result: ~v" i bs result)))
(bytes->preserve bs (bytes->preserve bs
#:read-syntax? #t #:read-syntax? #t
#:decode-pointer pointer/no-annotations #:decode-embedded embedded/no-annotations
#:on-short (lambda () 'short) #:on-short (lambda () 'short)
void)) void))
@ -134,28 +134,28 @@
[(asymmetric f b) (values f b #f)] ;; #f because e.g. annotation4 includes annotations [(asymmetric f b) (values f b #f)] ;; #f because e.g. annotation4 includes annotations
[v (values v v #t)])) [v (values v v #t)]))
(check-equal? text-form back loc) ;; expectation 1 (check-equal? text-form back loc) ;; expectation 1
(check-equal? (d-strip (preserve->bytes #:encode-pointer pointer-value text-form)) (check-equal? (d-strip (preserve->bytes #:encode-embedded embedded-value text-form))
back back
loc) ;; expectation 2 loc) ;; expectation 2
(check-equal? (d-strip (preserve->bytes #:encode-pointer pointer-value forward)) (check-equal? (d-strip (preserve->bytes #:encode-embedded embedded-value forward))
back back
loc) ;; expectation 3 loc) ;; expectation 3
(check-equal? (d-strip binary-form) back loc) ;; expectation 4 (check-equal? (d-strip binary-form) back loc) ;; expectation 4
(check-equal? (d binary-form) annotated-text-form loc) ;; expectation 5 (check-equal? (d binary-form) annotated-text-form loc) ;; expectation 5
(check-equal? (d (preserve->bytes #:encode-pointer pointer-value annotated-text-form)) (check-equal? (d (preserve->bytes #:encode-embedded embedded-value annotated-text-form))
annotated-text-form annotated-text-form
loc) ;; expectation 6 loc) ;; expectation 6
(check-equal? (string->preserve #:decode-pointer pointer/no-annotations (check-equal? (string->preserve #:decode-embedded embedded/no-annotations
(preserve->string #:encode-pointer pointer-value text-form)) (preserve->string #:encode-embedded embedded-value text-form))
back back
loc) ;; expectation 7 loc) ;; expectation 7
(check-equal? (string->preserve #:decode-pointer pointer/no-annotations (check-equal? (string->preserve #:decode-embedded embedded/no-annotations
(preserve->string #:encode-pointer pointer-value forward)) (preserve->string #:encode-embedded embedded-value forward))
back back
loc) ;; expectation 8 loc) ;; expectation 8
;; similar to 8: ;; similar to 8:
(check-equal? (string->preserve #:decode-pointer pointer/no-annotations (check-equal? (string->preserve #:decode-embedded embedded/no-annotations
(preserve->string #:encode-pointer pointer-value (preserve->string #:encode-embedded embedded-value
annotated-text-form) annotated-text-form)
#:read-syntax? #t) #:read-syntax? #t)
annotated-text-form annotated-text-form
@ -165,7 +165,7 @@
(and can-execute-nondet-with-canonicalization?))) (and can-execute-nondet-with-canonicalization?)))
;; expectations 9 and 10 ;; expectations 9 and 10
(check-equal? (preserve->bytes forward (check-equal? (preserve->bytes forward
#:encode-pointer pointer-value #:encode-embedded embedded-value
#:canonicalizing? #t #:canonicalizing? #t
#:write-annotations? #t) #:write-annotations? #t)
binary-form binary-form
@ -173,19 +173,19 @@
(unless (memq variety '(decode nondeterministic)) (unless (memq variety '(decode nondeterministic))
;; expectation 11 ;; expectation 11
(check-equal? (preserve->bytes annotated-text-form (check-equal? (preserve->bytes annotated-text-form
#:encode-pointer pointer-value #:encode-embedded embedded-value
#:write-annotations? #t) #:write-annotations? #t)
binary-form binary-form
loc))) loc)))
(define-runtime-path tests-path "../../../../../tests") (define-runtime-path tests-path "../../../../../tests")
(let* ((path (build-path tests-path "samples.txt")) (let* ((path (build-path tests-path "samples.pr"))
(testfile (call-with-input-file path (testfile (call-with-input-file path
(lambda (p) (lambda (p)
(port-count-lines! p) (port-count-lines! p)
(read-preserve p (read-preserve p
#:read-syntax? #t #:read-syntax? #t
#:decode-pointer pointer/no-annotations #:decode-embedded embedded/no-annotations
#:source path))))) #:source path)))))
(match-define (peel-annotations `#s(TestCases ,tests)) testfile) (match-define (peel-annotations `#s(TestCases ,tests)) testfile)
(for [((t-name* t*) (in-hash (annotated-item tests)))] (for [((t-name* t*) (in-hash (annotated-item tests)))]

View File

@ -43,21 +43,21 @@
["--no-annotations" "Strip annotations" ["--no-annotations" "Strip annotations"
(set! annotations? #f)]) (set! annotations? #f)])
(struct pointer (value) #:transparent) (struct embedded (value) #:transparent)
(let loop ((count count)) (let loop ((count count))
(when (positive? count) (when (positive? count)
(define v ((if annotations? values strip-annotations) (define v ((if annotations? values strip-annotations)
(match input-format (match input-format
['any (read-preserve #:read-syntax? #t #:decode-pointer pointer #:source "<stdin>")] ['any (read-preserve #:read-syntax? #t #:decode-embedded embedded #:source "<stdin>")]
['text (read-preserve/text #:read-syntax? #t #:decode-pointer pointer #:source "<stdin>")] ['text (read-preserve/text #:read-syntax? #t #:decode-embedded embedded #:source "<stdin>")]
['binary (read-preserve/binary #:decode-pointer pointer #:read-syntax? #t)]))) ['binary (read-preserve/binary #:decode-embedded embedded #:read-syntax? #t)])))
(when (not (eof-object? v)) (when (not (eof-object? v))
(void (match output-format (void (match output-format
['text ['text
(write-preserve/text v #:indent indent? #:encode-pointer pointer-value) (write-preserve/text v #:indent indent? #:encode-embedded embedded-value)
(newline)] (newline)]
['binary ['binary
(write-preserve/binary v #:encode-pointer pointer-value #:write-annotations? #t)])) (write-preserve/binary v #:encode-embedded embedded-value #:write-annotations? #t)]))
(flush-output) (flush-output)
(loop (- count 1)))))) (loop (- count 1))))))

View File

@ -16,19 +16,19 @@
(define (preserve->bytes v (define (preserve->bytes v
#:canonicalizing? [canonicalizing? #t] #:canonicalizing? [canonicalizing? #t]
#:encode-pointer [encode-pointer #f] #:encode-embedded [encode-embedded #f]
#:write-annotations? [write-annotations? (not canonicalizing?)]) #:write-annotations? [write-annotations? (not canonicalizing?)])
(call-with-output-bytes (call-with-output-bytes
(lambda (p) (write-preserve/binary v p (lambda (p) (write-preserve/binary v p
#:canonicalizing? canonicalizing? #:canonicalizing? canonicalizing?
#:encode-pointer encode-pointer #:encode-embedded encode-embedded
#:write-annotations? write-annotations?)))) #:write-annotations? write-annotations?))))
(define (write-preserve/binary v [out-port (current-output-port)] (define (write-preserve/binary v [out-port (current-output-port)]
#:canonicalizing? [canonicalizing? #t] #:canonicalizing? [canonicalizing? #t]
#:encode-pointer [encode-pointer0 #f] #:encode-embedded [encode-embedded0 #f]
#:write-annotations? [write-annotations? (not canonicalizing?)]) #:write-annotations? [write-annotations? (not canonicalizing?)])
(define encode-pointer (or encode-pointer0 object-id)) (define encode-embedded (or encode-embedded0 object-id))
(define (output-byte b) (define (output-byte b)
(write-byte b out-port)) (write-byte b out-port))
@ -122,6 +122,6 @@
[other [other
(output-byte #x86) (output-byte #x86)
(output (encode-pointer other))])) (output (encode-embedded other))]))
(output v)) (output v))

View File

@ -25,9 +25,9 @@
(define (write-preserve/text v0 [o (current-output-port)] (define (write-preserve/text v0 [o (current-output-port)]
#:indent [indent-amount0 #f] #:indent [indent-amount0 #f]
#:encode-pointer [encode-pointer0 #f] #:encode-embedded [encode-embedded0 #f]
#:write-annotations? [write-annotations? #t]) #:write-annotations? [write-annotations? #t])
(define encode-pointer (or encode-pointer0 object-id)) (define encode-embedded (or encode-embedded0 object-id))
(define indent-amount (match indent-amount0 (define indent-amount (match indent-amount0
[#f 0] [#f 0]
[#t 2] ;; a default [#t 2] ;; a default
@ -169,16 +169,16 @@
[(? dict?) (write-sequence distance "{" "," "}" write-key-value (dict->list v))] [(? dict?) (write-sequence distance "{" "," "}" write-key-value (dict->list v))]
[other [other
(! "#!") (! "#!")
(write-value distance (encode-pointer other))])) (write-value distance (encode-embedded other))]))
(write-value 0 v0)) (write-value 0 v0))
(define (preserve->string v0 (define (preserve->string v0
#:indent [indent-amount #f] #:indent [indent-amount #f]
#:encode-pointer [encode-pointer #f] #:encode-embedded [encode-embedded #f]
#:write-annotations? [write-annotations? #t]) #:write-annotations? [write-annotations? #t])
(with-output-to-string (with-output-to-string
(lambda () (write-preserve/text v0 (lambda () (write-preserve/text v0
#:indent indent-amount #:indent indent-amount
#:encode-pointer encode-pointer #:encode-embedded encode-embedded
#:write-annotations? write-annotations?)))) #:write-annotations? write-annotations?))))

View File

@ -1,6 +1,6 @@
[package] [package]
name = "preserves" name = "preserves"
version = "0.12.0" version = "0.13.0"
authors = ["Tony Garnock-Jones <tonyg@leastfixedpoint.com>"] authors = ["Tony Garnock-Jones <tonyg@leastfixedpoint.com>"]
edition = "2018" edition = "2018"
description = "Implementation of the Preserves serialization format via serde." description = "Implementation of the Preserves serialization format via serde."

View File

@ -41,7 +41,7 @@ pub enum ExpectedKind {
Set, Set,
Dictionary, Dictionary,
Pointer, Embedded,
SequenceOrSet, // Because of hacking up serde's data model: see open_sequence_or_set etc. SequenceOrSet, // Because of hacking up serde's data model: see open_sequence_or_set etc.

View File

@ -8,7 +8,7 @@ pub enum Tag {
Double, Double,
End, End,
Annotation, Annotation,
Pointer, Embedded,
SmallInteger(i8), SmallInteger(i8),
MediumInteger(u8), MediumInteger(u8),
SignedInteger, SignedInteger,
@ -47,7 +47,7 @@ impl TryFrom<u8> for Tag {
0x83 => Ok(Self::Double), 0x83 => Ok(Self::Double),
0x84 => Ok(Self::End), 0x84 => Ok(Self::End),
0x85 => Ok(Self::Annotation), 0x85 => Ok(Self::Annotation),
0x86 => Ok(Self::Pointer), 0x86 => Ok(Self::Embedded),
0x90..=0x9c => Ok(Self::SmallInteger((v - 0x90) as i8)), 0x90..=0x9c => Ok(Self::SmallInteger((v - 0x90) as i8)),
0x9d..=0x9f => Ok(Self::SmallInteger((v - 0x90) as i8 - 16)), 0x9d..=0x9f => Ok(Self::SmallInteger((v - 0x90) as i8 - 16)),
0xa0..=0xaf => Ok(Self::MediumInteger(v - 0xa0 + 1)), 0xa0..=0xaf => Ok(Self::MediumInteger(v - 0xa0 + 1)),
@ -73,7 +73,7 @@ impl From<Tag> for u8 {
Tag::Double => 0x83, Tag::Double => 0x83,
Tag::End => 0x84, Tag::End => 0x84,
Tag::Annotation => 0x85, Tag::Annotation => 0x85,
Tag::Pointer => 0x86, Tag::Embedded => 0x86,
Tag::SmallInteger(v) => if v < 0 { (v + 16) as u8 + 0x90 } else { v as u8 + 0x90 }, Tag::SmallInteger(v) => if v < 0 { (v + 16) as u8 + 0x90 } else { v as u8 + 0x90 },
Tag::MediumInteger(count) => count - 1 + 0xa0, Tag::MediumInteger(count) => count - 1 + 0xa0,
Tag::SignedInteger => 0xb0, Tag::SignedInteger => 0xb0,

View File

@ -262,7 +262,7 @@ impl<'de, S: BinarySource<'de>> Reader<'de> for PackedReader<'de, S> {
self.demand_next(read_annotations)? self.demand_next(read_annotations)?
} }
} }
Tag::Pointer => { Tag::Embedded => {
let v = self.demand_next(read_annotations)?; let v = self.demand_next(read_annotations)?;
Value::Domain(IOValue::from_preserves(v)).wrap() Value::Domain(IOValue::from_preserves(v)).wrap()
} }
@ -362,11 +362,11 @@ impl<'de, S: BinarySource<'de>> Reader<'de> for PackedReader<'de, S> {
Ok(self.peekend()?) Ok(self.peekend()?)
} }
fn open_pointer(&mut self) -> ReaderResult<()> { fn open_embedded(&mut self) -> ReaderResult<()> {
self.next_compound(Tag::Pointer, ExpectedKind::Pointer) self.next_compound(Tag::Embedded, ExpectedKind::Embedded)
} }
fn close_pointer(&mut self) -> ReaderResult<()> { fn close_embedded(&mut self) -> ReaderResult<()> {
Ok(()) Ok(())
} }

View File

@ -214,7 +214,7 @@ impl Writer for BinaryOrderWriter {
type AnnWriter = PackedWriter<Vec<u8>>; type AnnWriter = PackedWriter<Vec<u8>>;
type SeqWriter = PackedWriter<Vec<u8>>; type SeqWriter = PackedWriter<Vec<u8>>;
type SetWriter = BinaryOrderWriter; type SetWriter = BinaryOrderWriter;
type PointerWriter = PackedWriter<Vec<u8>>; type EmbeddedWriter = PackedWriter<Vec<u8>>;
binary_order_writer_method!(mut align(natural_chunksize: u64) -> Result<()>); binary_order_writer_method!(mut align(natural_chunksize: u64) -> Result<()>);
@ -272,11 +272,11 @@ impl Writer for BinaryOrderWriter {
set.finish(self) set.finish(self)
} }
fn start_pointer(&mut self) -> Result<Self::PointerWriter> { fn start_embedded(&mut self) -> Result<Self::EmbeddedWriter> {
self.write_tag(Tag::Pointer)?; self.write_tag(Tag::Embedded)?;
Ok(self.pop()) Ok(self.pop())
} }
fn end_pointer(&mut self, ptr: Self::PointerWriter) -> Result<()> { fn end_embedded(&mut self, ptr: Self::EmbeddedWriter) -> Result<()> {
self.push(ptr); self.push(ptr);
Ok(()) Ok(())
} }
@ -294,7 +294,7 @@ impl<W: std::io::Write> Writer for PackedWriter<W>
type AnnWriter = Self; type AnnWriter = Self;
type SeqWriter = Self; type SeqWriter = Self;
type SetWriter = BinaryOrderWriter; type SetWriter = BinaryOrderWriter;
type PointerWriter = Self; type EmbeddedWriter = Self;
fn start_annotations(&mut self) -> Result<Self::AnnWriter> { fn start_annotations(&mut self) -> Result<Self::AnnWriter> {
Ok(self.suspend()) Ok(self.suspend())
@ -489,12 +489,12 @@ impl<W: std::io::Write> Writer for PackedWriter<W>
set.finish(self) set.finish(self)
} }
fn start_pointer(&mut self) -> Result<Self::PointerWriter> { fn start_embedded(&mut self) -> Result<Self::EmbeddedWriter> {
self.write_tag(Tag::Pointer)?; self.write_tag(Tag::Embedded)?;
Ok(self.suspend()) Ok(self.suspend())
} }
fn end_pointer(&mut self, ann: Self::PointerWriter) -> Result<()> { fn end_embedded(&mut self, ann: Self::EmbeddedWriter) -> Result<()> {
self.resume(ann); self.resume(ann);
Ok(()) Ok(())
} }

View File

@ -15,8 +15,8 @@ pub trait Reader<'de> {
fn open_set(&mut self) -> ReaderResult<()>; fn open_set(&mut self) -> ReaderResult<()>;
fn open_dictionary(&mut self) -> ReaderResult<()>; fn open_dictionary(&mut self) -> ReaderResult<()>;
fn close_compound(&mut self) -> ReaderResult<bool>; fn close_compound(&mut self) -> ReaderResult<bool>;
fn open_pointer(&mut self) -> ReaderResult<()>; fn open_embedded(&mut self) -> ReaderResult<()>;
fn close_pointer(&mut self) -> ReaderResult<()>; fn close_embedded(&mut self) -> ReaderResult<()>;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -145,12 +145,12 @@ impl<'r, 'de, R: Reader<'de>> Reader<'de> for &'r mut R {
(*self).close_compound() (*self).close_compound()
} }
fn open_pointer(&mut self) -> ReaderResult<()> { fn open_embedded(&mut self) -> ReaderResult<()> {
(*self).open_pointer() (*self).open_embedded()
} }
fn close_pointer(&mut self) -> ReaderResult<()> { fn close_embedded(&mut self) -> ReaderResult<()> {
(*self).close_pointer() (*self).close_embedded()
} }
} }

View File

@ -19,7 +19,7 @@ pub trait Writer: Sized {
type AnnWriter: AnnotationWriter; type AnnWriter: AnnotationWriter;
type SeqWriter: CompoundWriter; type SeqWriter: CompoundWriter;
type SetWriter: CompoundWriter; type SetWriter: CompoundWriter;
type PointerWriter: Writer; type EmbeddedWriter: Writer;
fn align(&mut self, natural_chunksize: u64) -> Result<()>; fn align(&mut self, natural_chunksize: u64) -> Result<()>;
@ -55,8 +55,8 @@ pub trait Writer: Sized {
fn start_dictionary(&mut self, entry_count: Option<usize>) -> Result<Self::SetWriter>; fn start_dictionary(&mut self, entry_count: Option<usize>) -> Result<Self::SetWriter>;
fn end_set(&mut self, set: Self::SetWriter) -> Result<()>; fn end_set(&mut self, set: Self::SetWriter) -> Result<()>;
fn start_pointer(&mut self) -> Result<Self::PointerWriter>; fn start_embedded(&mut self) -> Result<Self::EmbeddedWriter>;
fn end_pointer(&mut self, ptr: Self::PointerWriter) -> Result<()>; fn end_embedded(&mut self, ptr: Self::EmbeddedWriter) -> Result<()>;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -133,9 +133,9 @@ pub trait Writer: Sized {
self.end_set(c) self.end_set(c)
} }
Value::Domain(ref d) => { Value::Domain(ref d) => {
let mut c = self.start_pointer()?; let mut c = self.start_embedded()?;
c.write(&d.as_preserves())?; c.write(&d.as_preserves())?;
self.end_pointer(c) self.end_embedded(c)
} }
} }
} }

View File

@ -29,7 +29,7 @@ fn decode_all(bytes: &'_ [u8]) -> Result<Vec<IOValue>, std::io::Error> {
assert_eq!(&PackedWriter::encode(val)?, bin); assert_eq!(&PackedWriter::encode(val)?, bin);
} }
TestCase::NondeterministicTest(ref bin, ref val) => { TestCase::NondeterministicTest(ref bin, ref val) => {
// The test cases in samples.txt are carefully written // The test cases in samples.pr are carefully written
// so that while strictly "nondeterministic", the // so that while strictly "nondeterministic", the
// order of keys in encoded dictionaries follows // order of keys in encoded dictionaries follows
// Preserves canonical order. // Preserves canonical order.

View File

@ -4,7 +4,7 @@ title: "Preserves: an Expressive Data Language"
--- ---
Tony Garnock-Jones <tonyg@leastfixedpoint.com> Tony Garnock-Jones <tonyg@leastfixedpoint.com>
Jan 2021. Version 0.5.0. May 2021. Version 0.6.0.
[sexp.txt]: http://people.csail.mit.edu/rivest/Sexp.txt [sexp.txt]: http://people.csail.mit.edu/rivest/Sexp.txt
[spki]: http://world.std.com/~cme/html/spki.html [spki]: http://world.std.com/~cme/html/spki.html
@ -36,12 +36,12 @@ definition of the *values* that we want to work with and give them
meaning independent of their syntax. meaning independent of their syntax.
Our `Value`s fall into two broad categories: *atomic* and *compound* Our `Value`s fall into two broad categories: *atomic* and *compound*
data. Every `Value` is finite and non-cyclic. References, called data. Every `Value` is finite and non-cyclic. Embedded values, called
`Pointer`s, are a third, special-case category. `Embedded`s, are a third, special-case category.
Value = Atom Value = Atom
| Compound | Compound
| Pointer | Embedded
Atom = Boolean Atom = Boolean
| Float | Float
@ -63,7 +63,7 @@ values of different kinds is essentially arbitrary, but having a total
order is convenient for many tasks, so we define it as order is convenient for many tasks, so we define it as
follows: follows:
(Values) Atom < Compound < Pointer (Values) Atom < Compound < Embedded
(Compounds) Record < Sequence < Set < Dictionary (Compounds) Record < Sequence < Set < Dictionary
@ -160,43 +160,43 @@ pairwise distinct. Instances of `Dictionary` are compared by
lexicographic comparison of the sequences resulting from ordering each lexicographic comparison of the sequences resulting from ordering each
`Dictionary`'s pairs in ascending order by key. `Dictionary`'s pairs in ascending order by key.
### Pointers. ### Embeddeds.
A `Pointer` embeds *domain-specific*, potentially *stateful* or An `Embedded` allows inclusion of *domain-specific*, potentially
*located* data into a `Value`.[^pointer-rationale] `Pointer`s may be *stateful* or *located* data into a `Value`.[^embedded-rationale]
used to denote stateful objects, network services, object `Embedded`s may be used to denote stateful objects, network services,
capabilities, file descriptors, Unix processes, or other object capabilities, file descriptors, Unix processes, or other
possibly-stateful things. Because each `Pointer` is a domain-specific possibly-stateful things. Because each `Embedded` is a domain-specific
datum, comparison of two `Pointer`s is done according to datum, comparison of two `Embedded`s is done according to
domain-specific rules. domain-specific rules.
[^pointer-rationale]: **Rationale.** Why include `Pointer`s as a [^embedded-rationale]: **Rationale.** Why include `Embedded`s as a
special class, distinct from, say, a specially-labeled `Record`? special class, distinct from, say, a specially-labeled `Record`?
First, a `Record` can only hold other `Value`s: in order to embed First, a `Record` can only hold other `Value`s: in order to embed
values such as live pointers to Java objects, some means of values such as live pointers to Java objects, some means of
"escaping" from the `Value` data type must be provided. Second, "escaping" from the `Value` data type must be provided. Second,
`Pointer`s are meant to be able to denote stateful entities, for `Embedded`s are meant to be able to denote stateful entities, for
which comparison by address is appropriate; however, we do not which comparison by address is appropriate; however, we do not
wish to place restrictions on the *nature* of these entities: if wish to place restrictions on the *nature* of these entities: if
we had used `Record`s instead of distinct `Pointer`s, users would we had used `Record`s instead of distinct `Embedded`s, users would
have to invent an encoding of domain data into `Record`s that have to invent an encoding of domain data into `Record`s that
reflected domain ordering into `Value` ordering. This is often reflected domain ordering into `Value` ordering. This is often
difficult and may not always be possible. Finally, because difficult and may not always be possible. Finally, because
`Pointer`s are intended to be able to represent network and memory `Embedded`s are intended to be able to represent network and
*locations*, they must be able to be rewritten at network and memory *locations*, they must be able to be rewritten at network
process boundaries. Having a distinct class allows generic and process boundaries. Having a distinct class allows generic
`Pointer` rewriting without the quotation-related complications of `Embedded` rewriting without the quotation-related complications
encoding references as, say, `Record`s. of encoding references as, say, `Record`s.
*Examples.* In a Java or Python implementation, a `Pointer` may denote *Examples.* In a Java or Python implementation, an `Embedded` may
a reference to a Java or Python object; comparison would be done via denote a reference to a Java or Python object; comparison would be
the language's own rules for equivalence and ordering. In a Unix done via the language's own rules for equivalence and ordering. In a
application, a `Pointer` may denote an open file descriptor or a Unix application, an `Embedded` may denote an open file descriptor or
process ID. In an HTTP-based application, each `Pointer` might be a a process ID. In an HTTP-based application, each `Embedded` might be a
URL, compared according to URL, compared according to
[RFC 6943](https://tools.ietf.org/html/rfc6943#section-3.3). When a [RFC 6943](https://tools.ietf.org/html/rfc6943#section-3.3). When a
`Value` is serialized for storage or transfer, embedded `Pointer`s `Value` is serialized for storage or transfer, `Embedded`s will
will usually be represented as ordinary `Value`s, in which case the usually be represented as ordinary `Value`s, in which case the
ordinary rules for comparing `Value`s will apply. ordinary rules for comparing `Value`s will apply.
## Textual Syntax ## Textual Syntax
@ -241,7 +241,7 @@ Standalone documents may have trailing whitespace.
Any `Value` may be preceded by whitespace. Any `Value` may be preceded by whitespace.
Value = ws (Record / Collection / Atom / Pointer / Compact) Value = ws (Record / Collection / Atom / Embedded / Compact)
Collection = Sequence / Dictionary / Set Collection = Sequence / Dictionary / Set
Atom = Boolean / Float / Double / SignedInteger / Atom = Boolean / Float / Double / SignedInteger /
String / ByteString / Symbol String / ByteString / Symbol
@ -401,10 +401,10 @@ double quote mark.
definition of “token representation”, and with the definition of “token representation”, and with the
[R6RS definition of identifiers](http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-7.html#node_sec_4.2.4). [R6RS definition of identifiers](http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-7.html#node_sec_4.2.4).
A `Pointer` is written as a `Value` chosen to represent the denoted An `Embedded` is written as a `Value` chosen to represent the denoted
object, prefixed with `#!`. object, prefixed with `#!`.
Pointer = "#!" Value Embedded = "#!" Value
Finally, any `Value` may be represented by escaping from the textual Finally, any `Value` may be represented by escaping from the textual
syntax to the [compact binary syntax](#compact-binary-syntax) by syntax to the [compact binary syntax](#compact-binary-syntax) by
@ -621,9 +621,9 @@ contained within the `Value` unmodified.
The functions `binary32(F)` and `binary64(D)` yield big-endian 4- and The functions `binary32(F)` and `binary64(D)` yield big-endian 4- and
8-byte IEEE 754 binary representations of `F` and `D`, respectively. 8-byte IEEE 754 binary representations of `F` and `D`, respectively.
### Pointers. ### Embeddeds.
The `Repr` of a `Pointer` is the `Repr` of a `Value` chosen to The `Repr` of an `Embedded` is the `Repr` of a `Value` chosen to
represent the denoted object, prefixed with `[0x86]`. represent the denoted object, prefixed with `[0x86]`.
«#!V» = [0x86] ++ «V» «#!V» = [0x86] ++ «V»
@ -855,7 +855,7 @@ a binary-syntax document; otherwise, it should be interpreted as text.
83 - Double 83 - Double
84 - End marker 84 - End marker
85 - Annotation 85 - Annotation
86 - Pointer 86 - Embedded
(8x) RESERVED 87-8F (8x) RESERVED 87-8F
9x - Small integers 0..12,-3..-1 9x - Small integers 0..12,-3..-1

View File

@ -1,8 +1,8 @@
´³schema·³pointer€³version³ definitions·³Ref´³rec´³lit³ref„´³tupleµ´³named³module´³refµ„³ ´³schema·³version³ definitions·³Ref´³rec´³lit³ref„´³tupleµ´³named³module´³refµ„³
ModulePath„„´³named³name´³atom³Symbol„„„„„³Bundle´³rec´³lit³bundle„´³tupleµ´³named³modules´³refµ„³Modules„„„„„³Schema´³rec´³lit³schema„´³tupleµ´³dict·³pointer´³refµ„³ PointerName„³version´³refµ„³Version„³ definitions´³refµ„³ Definitions„„„„„„³Modules´³dictof´³refµ„³ ModulePath„„´³named³name´³atom³Symbol„„„„„³Bundle´³rec´³lit³bundle„´³tupleµ´³named³modules´³refµ„³Modules„„„„„³Schema´³rec´³lit³schema„´³tupleµ´³dict·³version´³refµ„³Version„³ definitions´³refµ„³ Definitions„³ embeddedType´³refµ„³EmbeddedTypeName„„„„„„³Modules´³dictof´³refµ„³
ModulePath„´³refµ„³Schema„„³Pattern´³orµµ± SimplePattern´³refµ„³ SimplePattern„„µ±CompoundPattern´³refµ„³CompoundPattern„„„„³Version´³lit„³AtomKind´³orµµ±Boolean´³lit³Boolean„„µ±Float´³lit³Float„„µ±Double´³lit³Double„„µ± SignedInteger´³lit³ SignedInteger„„µ±String´³lit³String„„µ± ModulePath„´³refµ„³Schema„„³Pattern´³orµµ± SimplePattern´³refµ„³ SimplePattern„„µ±CompoundPattern´³refµ„³CompoundPattern„„„„³Version´³lit„³AtomKind´³orµµ±Boolean´³lit³Boolean„„µ±Float´³lit³Float„„µ±Double´³lit³Double„„µ± SignedInteger´³lit³ SignedInteger„„µ±String´³lit³String„„µ±
ByteString´³lit³ ByteString´³lit³
ByteString„„µ±Symbol´³lit³Symbol„„„„³ ByteString„„µ±Symbol´³lit³Symbol„„„„³
Definition´³orµµ±or´³rec´³lit³or„´³tupleµ´³tuple*µ´³named³pattern´³refµ„³NamedAlternative„„„´³named³patterns´³refµ„³NamedAlternative„„„„„„„µ± Alternative´³refµ„³ Alternative„„„„³ Definition´³orµµ±or´³rec´³lit³or„´³tupleµ´³tuple*µ´³named³pattern´³refµ„³NamedAlternative„„„´³named³patterns´³refµ„³NamedAlternative„„„„„„„µ± Alternative´³refµ„³ Alternative„„„„³
ModulePath´³tuple*µ„´³atom³Symbol„„³ Alternative´³orµµ±and´³rec´³lit³and„´³tupleµ´³tuple*µ´³named³pattern´³refµ„³ NamedPattern„„„´³named³patterns´³refµ„³ NamedPattern„„„„„„„µ±Pattern´³refµ„³Pattern„„„„³ Definitions´³dictof´³atom³Symbol„´³refµ„³ ModulePath´³tuple*µ„´³atom³Symbol„„³ Alternative´³orµµ±and´³rec´³lit³and„´³tupleµ´³tuple*µ´³named³pattern´³refµ„³ NamedPattern„„„´³named³patterns´³refµ„³ NamedPattern„„„„„„„µ±Pattern´³refµ„³Pattern„„„„³ Definitions´³dictof´³atom³Symbol„´³refµ„³
Definition„„³ PointerName´³orµµ±Ref´³refµ„³Ref„„µ±false´³lit€„„„„³ NamedPattern´³orµµ±named´³refµ„³NamedSimplePattern_„„µ± anonymous´³refµ„³Pattern„„„„³ SimplePattern´³orµµ±any´³lit³any„„µ±atom´³rec´³lit³atom„´³tupleµ´³named³atomKind´³refµ„³AtomKind„„„„„„µ±pointer´³rec´³lit³pointer„´³tupleµ„„„„µ±lit´³rec´³lit³lit„´³tupleµ´³named³value³any„„„„„µ±Ref´³refµ„³Ref„„„„³CompoundPattern´³orµµ±rec´³rec´³lit³rec„´³tupleµ´³named³label´³refµ„³ NamedPattern„„´³named³fields´³refµ„³ NamedPattern„„„„„„µ±tuple´³rec´³lit³tuple„´³tupleµ´³tuple*µ„´³named³patterns´³refµ„³ NamedPattern„„„„„„„µ±tuple*´³rec´³lit³tuple*„´³tupleµ´³tuple*µ„´³named³fixed´³refµ„³ NamedPattern„„„´³named³variable´³refµ„³NamedSimplePattern„„„„„„µ±setof´³rec´³lit³setof„´³tupleµ´³named³pattern´³refµ„³ SimplePattern„„„„„„µ±dictof´³rec´³lit³dictof„´³tupleµ´³named³key´³refµ„³ SimplePattern„„´³named³value´³refµ„³ SimplePattern„„„„„„µ±dict´³rec´³lit³dict„´³tupleµ´³named³entries´³refµ„³DictionaryEntries„„„„„„„„³NamedAlternative´³tupleµ´³named³ variantLabel´³atom³String„„´³named³ alternative´³refµ„³ Alternative„„„„³DictionaryEntries´³dictof³any´³refµ„³NamedSimplePattern„„³NamedSimplePattern´³orµµ±named´³refµ„³NamedSimplePattern_„„µ± anonymous´³refµ„³ SimplePattern„„„„³NamedSimplePattern_´³rec´³lit³named„´³tupleµ´³named³name´³atom³Symbol„„´³named³pattern´³refµ„³ SimplePattern„„„„„„„„ Definition„„³ NamedPattern´³orµµ±named´³refµ„³NamedSimplePattern_„„µ± anonymous´³refµ„³Pattern„„„„³ SimplePattern´³orµµ±any´³lit³any„„µ±atom´³rec´³lit³atom„´³tupleµ´³named³atomKind´³refµ„³AtomKind„„„„„„µ±embedded´³rec´³lit³embedded„´³tupleµ„„„„µ±lit´³rec´³lit³lit„´³tupleµ´³named³value³any„„„„„µ±Ref´³refµ„³Ref„„„„³CompoundPattern´³orµµ±rec´³rec´³lit³rec„´³tupleµ´³named³label´³refµ„³ NamedPattern„„´³named³fields´³refµ„³ NamedPattern„„„„„„µ±tuple´³rec´³lit³tuple„´³tupleµ´³tuple*µ„´³named³patterns´³refµ„³ NamedPattern„„„„„„„µ±tuple*´³rec´³lit³tuple*„´³tupleµ´³tuple*µ„´³named³fixed´³refµ„³ NamedPattern„„„´³named³variable´³refµ„³NamedSimplePattern„„„„„„µ±setof´³rec´³lit³setof„´³tupleµ´³named³pattern´³refµ„³ SimplePattern„„„„„„µ±dictof´³rec´³lit³dictof„´³tupleµ´³named³key´³refµ„³ SimplePattern„„´³named³value´³refµ„³ SimplePattern„„„„„„µ±dict´³rec´³lit³dict„´³tupleµ´³named³entries´³refµ„³DictionaryEntries„„„„„„„„³EmbeddedTypeName´³orµµ±Ref´³refµ„³Ref„„µ±false´³lit€„„„„³NamedAlternative´³tupleµ´³named³ variantLabel´³atom³String„„´³named³ alternative´³refµ„³ Alternative„„„„³DictionaryEntries´³dictof³any´³refµ„³NamedSimplePattern„„³NamedSimplePattern´³orµµ±named´³refµ„³NamedSimplePattern_„„µ± anonymous´³refµ„³ SimplePattern„„„„³NamedSimplePattern_´³rec´³lit³named„´³tupleµ´³named³name´³atom³Symbol„„´³named³pattern´³refµ„³ SimplePattern„„„„„„³ embeddedType€„„

View File

@ -1,5 +1,8 @@
@<EmacsMode "-*- preserves -*-"> @<EmacsMode "-*- preserves -*-">
; TODO: some kind of constants
; TODO: rename "version" to "schema-version" ?
version 1 . version 1 .
Bundle = <bundle @modules Modules>. Bundle = <bundle @modules Modules>.
@ -7,14 +10,14 @@ Modules = { ModulePath: Schema ...:... }.
Schema = <schema { Schema = <schema {
version: Version version: Version
pointer: PointerName embeddedType: EmbeddedTypeName
definitions: Definitions definitions: Definitions
}>. }>.
; version 1 . ; version 1 .
Version = 1 . Version = 1 .
PointerName = Ref / #f. EmbeddedTypeName = Ref / #f.
Definitions = { symbol: Definition ...:... }. Definitions = { symbol: Definition ...:... }.
@ -37,8 +40,8 @@ SimplePattern =
; special builtins: bool, float, double, int, string, bytes, symbol ; special builtins: bool, float, double, int, string, bytes, symbol
/ <atom @atomKind AtomKind> / <atom @atomKind AtomKind>
; matches a pointer in the input: ref ; matches an embedded value in the input: embedded
/ <pointer> / <embedded>
; =symbol, <<lit> any>, or plain non-symbol atom ; =symbol, <<lit> any>, or plain non-symbol atom
/ <lit @value any> / <lit @value any>

Binary file not shown.

View File

@ -112,9 +112,9 @@
list9: @"Unexpected close bracket" <ParseError "]"> list9: @"Unexpected close bracket" <ParseError "]">
list10: @"Missing end byte" <DecodeShort #x"b58080"> list10: @"Missing end byte" <DecodeShort #x"b58080">
noinput0: @"No input at all" <DecodeEOF #x""> noinput0: @"No input at all" <DecodeEOF #x"">
pointer0: <Test #x"8690" #!0> embed0: <Test #x"8690" #!0>
pointer1: <Test #x"868690" #!#!0> embed1: <Test #x"868690" #!#!0>
pointer2: <Test #x"b5869086b10568656c6c6f84" [#!0 #!"hello"]> embed2: <Test #x"b5869086b10568656c6c6f84" [#!0 #!"hello"]>
record1: <Test #x"b4 b30763617074757265 b4 b30764697363617264 84 84" <capture <discard>>> record1: <Test #x"b4 b30763617074757265 b4 b30764697363617264 84 84" <capture <discard>>>
record2: <Test #x"b4 b3076f627365727665 b4 b305737065616b b4 b30764697363617264 84 b4 b30763617074757265 b4 b30764697363617264 84 84 84 84" <observe <speak <discard>, <capture <discard>>>>> record2: <Test #x"b4 b3076f627365727665 b4 b305737065616b b4 b30764697363617264 84 b4 b30763617074757265 b4 b30764697363617264 84 84 84 84" <observe <speak <discard>, <capture <discard>>>>>
record3: <Test #x"b4 b5 b3067469746c6564 b306706572736f6e 92 b3057468696e67 91 84 a065 b109426c61636b77656c6c b4 b30464617465 a1071d 92 93 84 b1024472 84" <[titled person 2 thing 1] 101 "Blackwell" <date 1821 2 3> "Dr">> record3: <Test #x"b4 b5 b3067469746c6564 b306706572736f6e 92 b3057468696e67 91 84 a065 b109426c61636b77656c6c b4 b30464617465 a1071d 92 93 84 b1024472 84" <[titled person 2 thing 1] 101 "Blackwell" <date 1821 2 3> "Dr">>