Make undeclared pointer type `any` instead of `never`, and take advantage of new explicit pointer wrappers

This commit is contained in:
Tony Garnock-Jones 2021-04-24 23:49:37 +02:00
parent 70ce961dd2
commit 58d2bf6f3a
8 changed files with 22 additions and 35 deletions

View File

@ -3,8 +3,8 @@ import * as M from "./meta";
import { CompilerOptions, ModuleContext } from "./compiler/context";
import { Formatter, block, seq } from "./compiler/block";
import { typeForDefinition } from "./compiler/gentype";
import { converterForDefinition, converterForSimple } from "./compiler/genconverter";
import { EMPTY_TYPE, renderType } from "./compiler/type";
import { converterForDefinition } from "./compiler/genconverter";
import { renderType, Type } from "./compiler/type";
import { genConstructor } from "./compiler/genctor";
import { unconverterForDefinition } from "./compiler/genunconverter";
import { sourceCodeFor } from "./compiler/value";
@ -15,22 +15,11 @@ export function compile(env: M.Environment, schema: M.Schema, options: CompilerO
const pointerName = schema.pointer;
mod.defineType(seq(`export type _ptr = `,
renderType(pointerName._variant === 'false'
? EMPTY_TYPE
? Type.ref('any')
: typeForDefinition(mod, M.Definition.Alternative(M.Alternative.Pattern(M.Pattern.SimplePattern(M.SimplePattern.Ref(pointerName.value)))))),
`;`));
mod.defineType(`export type _val = _.Value<_ptr>;`);
mod.defineFunction(ctx =>
seq(`export const _toPtr = `,
(pointerName._variant === 'false'
? '() => { throw new _.DecodeError("Pointers forbidden"); }'
: seq(`(v: _val) => `, ctx.block(() => [
seq(`let result: undefined | _ptr`),
... converterForSimple(
ctx, M.SimplePattern.Ref(pointerName.value), 'v', 'result'),
seq(`return result`)]))),
`;`));
for (const [name, def] of schema.definitions) {
const t = typeForDefinition(mod, def);
const nameStr = stringify(name);

View File

@ -22,7 +22,7 @@ export class ModuleContext {
readonly schema: M.Schema;
readonly options: CompilerOptions;
readonly literals = new Dictionary<never, string>();
readonly literals = new Dictionary<M._ptr, string>();
readonly typedefs: Item[] = [];
readonly functiondefs: Item[] = [];
readonly imports = new KeyedSet<[string, string]>();

View File

@ -206,7 +206,7 @@ export function converterForSimple(
return [`${dest} = ${modId}.to${p.value.name.description!}(${src})`];
});
case 'pointer':
return [`${dest} = _toPtr(${src})`];
return [`${dest} = _.isPointer<_ptr>(${src}) ? ${src}.embeddedValue : void 0`];
default:
((_p: never) => {})(p);
throw new Error("Unreachable");

View File

@ -35,7 +35,6 @@ export namespace Type {
}
export const ANY_TYPE: AtomicType = Type.ref('_val');
export const EMPTY_TYPE: AtomicType = Type.ref('never');
export function variantInitFor(variantName: string | undefined) : Item[] {
return variantName === void 0 ? [] : [variantFor(variantName)];

View File

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

View File

@ -28,7 +28,7 @@ export const $tuple$STAR$ = Symbol.for("tuple*");
export const $version = Symbol.for("version");
export const __lit6 = false;
export type _ptr = never;
export type _ptr = any;
export type _val = _.Value<_ptr>;
@ -115,8 +115,6 @@ export type Ref = {"module": ModulePath, "name": symbol};
export type ModulePath = Array<symbol>;
export const _toPtr = () => { throw new _.DecodeError("Pointers forbidden"); };
export function Bundle(modules: Modules): Bundle {return {"modules": modules};}
export function Modules(value: _.KeyedDictionary<ModulePath, Schema, _ptr>): Modules {return value;}

View File

@ -1,4 +1,4 @@
import { Value, is, Position } from '@preserves/core';
import { is, Position } from '@preserves/core';
import * as M from './gen/schema';
import { SchemaSyntaxError } from './error';
import type { AtomicType } from './compiler/type';
@ -8,7 +8,7 @@ export * from './gen/schema';
export type Builtin = { type: AtomicType, pattern: M.Alternative };
export type Input = Value<never>;
export type Input = M._val;
export function isValidToken(s: string): boolean {
return /^[a-zA-Z][a-zA-Z_0-9]*$/.test(s);

View File

@ -49,7 +49,7 @@ export type SchemaReaderOptions = {
};
function _readSchema(source: string, options?: ReaderOptions<never>): Array<Input> {
return new Reader<never>(source, {
return new Reader<any>(source, {
... options ?? {},
includeAnnotations: true
}).readToEnd();
@ -223,9 +223,9 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
? M.SimplePattern.lit(Symbol.for(str.slice(1)))
: M.SimplePattern.Ref(parseRef(str, pos)));
}
} else if (Record.isRecord<Input, Tuple<Input>, never>(item)) {
} else if (Record.isRecord<Input, Tuple<Input>, M._ptr>(item)) {
const label = item.label;
if (Record.isRecord<Input, [], never>(label)) {
if (Record.isRecord<Input, [], M._ptr>(label)) {
if (label.length !== 0) complain();
switch (label.label) {
case M.$lit:
@ -290,9 +290,9 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
}
}
if (Record.isRecord<Input, Tuple<Input>, never>(item)) {
if (Record.isRecord<Input, Tuple<Input>, M._ptr>(item)) {
const label = item.label;
if (Record.isRecord<Input, [], never>(label)) {
if (Record.isRecord<Input, [], M._ptr>(label)) {
if (label.length !== 0) complain();
switch (label.label) {
case M.$rec:
@ -312,7 +312,7 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
}
} else if (Array.isArray(item)) {
return parseArrayLike(item);
} else if (Dictionary.isDictionary<never, Input>(item)) {
} else if (Dictionary.isDictionary<M._ptr, Input>(item)) {
if (item.size === 2 && item.has(M.DOTDOTDOT)) {
const v = item.clone();
v.delete(M.DOTDOTDOT);