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 { CompilerOptions, ModuleContext } from "./compiler/context";
import { Formatter, block, seq } from "./compiler/block"; import { Formatter, block, seq } from "./compiler/block";
import { typeForDefinition } from "./compiler/gentype"; import { typeForDefinition } from "./compiler/gentype";
import { converterForDefinition, converterForSimple } from "./compiler/genconverter"; import { converterForDefinition } from "./compiler/genconverter";
import { EMPTY_TYPE, renderType } from "./compiler/type"; import { renderType, Type } from "./compiler/type";
import { genConstructor } from "./compiler/genctor"; import { genConstructor } from "./compiler/genctor";
import { unconverterForDefinition } from "./compiler/genunconverter"; import { unconverterForDefinition } from "./compiler/genunconverter";
import { sourceCodeFor } from "./compiler/value"; import { sourceCodeFor } from "./compiler/value";
@ -15,22 +15,11 @@ export function compile(env: M.Environment, schema: M.Schema, options: CompilerO
const pointerName = schema.pointer; const pointerName = schema.pointer;
mod.defineType(seq(`export type _ptr = `, mod.defineType(seq(`export type _ptr = `,
renderType(pointerName._variant === 'false' 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)))))), : typeForDefinition(mod, M.Definition.Alternative(M.Alternative.Pattern(M.Pattern.SimplePattern(M.SimplePattern.Ref(pointerName.value)))))),
`;`)); `;`));
mod.defineType(`export type _val = _.Value<_ptr>;`); 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) { for (const [name, def] of schema.definitions) {
const t = typeForDefinition(mod, def); const t = typeForDefinition(mod, def);
const nameStr = stringify(name); const nameStr = stringify(name);

View File

@ -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<never, string>(); readonly literals = new Dictionary<M._ptr, 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

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

View File

@ -35,7 +35,6 @@ export namespace Type {
} }
export const ANY_TYPE: AtomicType = Type.ref('_val'); export const ANY_TYPE: AtomicType = Type.ref('_val');
export const EMPTY_TYPE: AtomicType = Type.ref('never');
export function variantInitFor(variantName: string | undefined) : Item[] { export function variantInitFor(variantName: string | undefined) : Item[] {
return variantName === void 0 ? [] : [variantFor(variantName)]; 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 { Annotated, Bytes, Set, Dictionary, Fold, fold, Record, Tuple, Value, stringify } from "@preserves/core";
import { brackets, Item, parens, seq } from "./block"; 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, { 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(); },
@ -13,25 +14,25 @@ export function sourceCodeFor(v: Value<never>): 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<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)))); 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)); 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)))); 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]) => return seq('new _.Dictionary<_ptr>', parens(brackets(... Array.from(d).map(([kk,vv]) =>
brackets(k(kk), k(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))); 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)}`); 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 $version = Symbol.for("version");
export const __lit6 = false; export const __lit6 = false;
export type _ptr = never; export type _ptr = any;
export type _val = _.Value<_ptr>; export type _val = _.Value<_ptr>;
@ -115,8 +115,6 @@ export type Ref = {"module": ModulePath, "name": symbol};
export type ModulePath = Array<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 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, _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 * as M from './gen/schema';
import { SchemaSyntaxError } from './error'; import { SchemaSyntaxError } from './error';
import type { AtomicType } from './compiler/type'; import type { AtomicType } from './compiler/type';
@ -8,7 +8,7 @@ export * from './gen/schema';
export type Builtin = { type: AtomicType, pattern: M.Alternative }; export type Builtin = { type: AtomicType, pattern: M.Alternative };
export type Input = Value<never>; export type Input = M._val;
export function isValidToken(s: string): boolean { export function isValidToken(s: string): boolean {
return /^[a-zA-Z][a-zA-Z_0-9]*$/.test(s); 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> { function _readSchema(source: string, options?: ReaderOptions<never>): Array<Input> {
return new Reader<never>(source, { return new Reader<any>(source, {
... options ?? {}, ... options ?? {},
includeAnnotations: true includeAnnotations: true
}).readToEnd(); }).readToEnd();
@ -223,9 +223,9 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
? 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>, never>(item)) { } else if (Record.isRecord<Input, Tuple<Input>, M._ptr>(item)) {
const label = item.label; const label = item.label;
if (Record.isRecord<Input, [], never>(label)) { if (Record.isRecord<Input, [], M._ptr>(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>, never>(item)) { if (Record.isRecord<Input, Tuple<Input>, M._ptr>(item)) {
const label = item.label; const label = item.label;
if (Record.isRecord<Input, [], never>(label)) { if (Record.isRecord<Input, [], M._ptr>(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<never, Input>(item)) { } else if (Dictionary.isDictionary<M._ptr, 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);