From 58d2bf6f3ab0289b55c55aa1b9df58ba108439a8 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Sat, 24 Apr 2021 23:49:37 +0200 Subject: [PATCH] Make undeclared pointer type `any` instead of `never`, and take advantage of new explicit pointer wrappers --- .../javascript/packages/schema/src/compiler.ts | 17 +++-------------- .../packages/schema/src/compiler/context.ts | 2 +- .../schema/src/compiler/genconverter.ts | 2 +- .../packages/schema/src/compiler/type.ts | 1 - .../packages/schema/src/compiler/value.ts | 15 ++++++++------- .../packages/schema/src/gen/schema.ts | 4 +--- .../javascript/packages/schema/src/meta.ts | 4 ++-- .../javascript/packages/schema/src/reader.ts | 12 ++++++------ 8 files changed, 22 insertions(+), 35 deletions(-) diff --git a/implementations/javascript/packages/schema/src/compiler.ts b/implementations/javascript/packages/schema/src/compiler.ts index 394e274..e6fa802 100644 --- a/implementations/javascript/packages/schema/src/compiler.ts +++ b/implementations/javascript/packages/schema/src/compiler.ts @@ -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); diff --git a/implementations/javascript/packages/schema/src/compiler/context.ts b/implementations/javascript/packages/schema/src/compiler/context.ts index 81c119d..5450758 100644 --- a/implementations/javascript/packages/schema/src/compiler/context.ts +++ b/implementations/javascript/packages/schema/src/compiler/context.ts @@ -22,7 +22,7 @@ export class ModuleContext { readonly schema: M.Schema; readonly options: CompilerOptions; - readonly literals = new Dictionary(); + readonly literals = new Dictionary(); readonly typedefs: Item[] = []; readonly functiondefs: Item[] = []; readonly imports = new KeyedSet<[string, string]>(); diff --git a/implementations/javascript/packages/schema/src/compiler/genconverter.ts b/implementations/javascript/packages/schema/src/compiler/genconverter.ts index 4225a53..7adf578 100644 --- a/implementations/javascript/packages/schema/src/compiler/genconverter.ts +++ b/implementations/javascript/packages/schema/src/compiler/genconverter.ts @@ -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"); diff --git a/implementations/javascript/packages/schema/src/compiler/type.ts b/implementations/javascript/packages/schema/src/compiler/type.ts index ff72e67..286c5c8 100644 --- a/implementations/javascript/packages/schema/src/compiler/type.ts +++ b/implementations/javascript/packages/schema/src/compiler/type.ts @@ -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)]; diff --git a/implementations/javascript/packages/schema/src/compiler/value.ts b/implementations/javascript/packages/schema/src/compiler/value.ts index 0170b1c..c12e280 100644 --- a/implementations/javascript/packages/schema/src/compiler/value.ts +++ b/implementations/javascript/packages/schema/src/compiler/value.ts @@ -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): Item { +export function sourceCodeFor(v: Value): 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): Item { }, symbol(s: symbol): Item { return `Symbol.for(${JSON.stringify(s.description!)})`; }, - record(r: Record, Tuple>, never>, k: Fold): Item { + record(r: Record, Tuple>, M._ptr>, k: Fold): Item { return seq(`_.Record<_val, _.Tuple<_val>, _ptr>`, parens(k(r.label), brackets(... r.map(k)))); }, - array(a: Array>, k: Fold): Item { + array(a: Array>, k: Fold): Item { return brackets(... a.map(k)); }, - set(s: Set, k: Fold): Item { + set(s: Set, k: Fold): Item { return seq('new _.Set<_val>', parens(brackets(... Array.from(s).map(k)))); }, - dictionary(d: Dictionary, k: Fold): Item { + dictionary(d: Dictionary, k: Fold): Item { return seq('new _.Dictionary<_ptr>', parens(brackets(... Array.from(d).map(([kk,vv]) => brackets(k(kk), k(vv)))))); }, - annotated(a: Annotated, k: Fold): Item { + annotated(a: Annotated, k: Fold): Item { return seq('_.annotate<_ptr>', parens(k(a.item), ... a.annotations.map(k))); }, - pointer(t: never, _k: Fold): Item { + pointer(t: M._ptr, _k: Fold): Item { throw new Error(`Cannot emit source code for construction of pointer ${stringify(t)}`); }, }); diff --git a/implementations/javascript/packages/schema/src/gen/schema.ts b/implementations/javascript/packages/schema/src/gen/schema.ts index f130c8c..d0caa59 100644 --- a/implementations/javascript/packages/schema/src/gen/schema.ts +++ b/implementations/javascript/packages/schema/src/gen/schema.ts @@ -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; -export const _toPtr = () => { throw new _.DecodeError("Pointers forbidden"); }; - export function Bundle(modules: Modules): Bundle {return {"modules": modules};} export function Modules(value: _.KeyedDictionary): Modules {return value;} diff --git a/implementations/javascript/packages/schema/src/meta.ts b/implementations/javascript/packages/schema/src/meta.ts index 1507525..708c139 100644 --- a/implementations/javascript/packages/schema/src/meta.ts +++ b/implementations/javascript/packages/schema/src/meta.ts @@ -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; +export type Input = M._val; export function isValidToken(s: string): boolean { return /^[a-zA-Z][a-zA-Z_0-9]*$/.test(s); diff --git a/implementations/javascript/packages/schema/src/reader.ts b/implementations/javascript/packages/schema/src/reader.ts index 8a188c6..e1d8be6 100644 --- a/implementations/javascript/packages/schema/src/reader.ts +++ b/implementations/javascript/packages/schema/src/reader.ts @@ -49,7 +49,7 @@ export type SchemaReaderOptions = { }; function _readSchema(source: string, options?: ReaderOptions): Array { - return new Reader(source, { + return new Reader(source, { ... options ?? {}, includeAnnotations: true }).readToEnd(); @@ -223,9 +223,9 @@ function parsePattern(name: symbol, body0: Array): Pattern { ? M.SimplePattern.lit(Symbol.for(str.slice(1))) : M.SimplePattern.Ref(parseRef(str, pos))); } - } else if (Record.isRecord, never>(item)) { + } else if (Record.isRecord, M._ptr>(item)) { const label = item.label; - if (Record.isRecord(label)) { + if (Record.isRecord(label)) { if (label.length !== 0) complain(); switch (label.label) { case M.$lit: @@ -290,9 +290,9 @@ function parsePattern(name: symbol, body0: Array): Pattern { } } - if (Record.isRecord, never>(item)) { + if (Record.isRecord, M._ptr>(item)) { const label = item.label; - if (Record.isRecord(label)) { + if (Record.isRecord(label)) { if (label.length !== 0) complain(); switch (label.label) { case M.$rec: @@ -312,7 +312,7 @@ function parsePattern(name: symbol, body0: Array): Pattern { } } else if (Array.isArray(item)) { return parseArrayLike(item); - } else if (Dictionary.isDictionary(item)) { + } else if (Dictionary.isDictionary(item)) { if (item.size === 2 && item.has(M.DOTDOTDOT)) { const v = item.clone(); v.delete(M.DOTDOTDOT);