diff --git a/implementations/javascript/packages/schema/src/bin/cli-utils.ts b/implementations/javascript/packages/schema/src/bin/cli-utils.ts index bdc761e..ba0fe0a 100644 --- a/implementations/javascript/packages/schema/src/bin/cli-utils.ts +++ b/implementations/javascript/packages/schema/src/bin/cli-utils.ts @@ -4,6 +4,7 @@ import { glob } from 'glob'; import { formatPosition, Position } from '@preserves/core'; import { readSchema } from '../reader'; import chalk from 'chalk'; +import * as M from '../meta'; export interface Diagnostic { type: 'warn' | 'error'; @@ -11,6 +12,18 @@ export interface Diagnostic { detail: Error | { message: string, pos: Position | null }; }; +export type Expanded = { + base: string, + inputFiles: Array<{ + inputFilePath: string, + text: string, + baseRelPath: string, + modulePath: M.ModulePath, + schema: M.Schema, + }>, + failures: Array, +}; + export function computeBase(paths: string[]): string { if (paths.length === 0) { return ''; @@ -31,7 +44,7 @@ export function computeBase(paths: string[]): string { } } -export function expandInputGlob(input: string[], base0: string | undefined) { +export function expandInputGlob(input: string[], base0: string | undefined): Expanded { const matches = input.flatMap(i => glob.sync(i)); const base = base0 ?? computeBase(matches); const failures: Array = []; diff --git a/implementations/javascript/packages/schema/src/bin/preserves-schema-ts.ts b/implementations/javascript/packages/schema/src/bin/preserves-schema-ts.ts index a191f9c..09a8aac 100644 --- a/implementations/javascript/packages/schema/src/bin/preserves-schema-ts.ts +++ b/implementations/javascript/packages/schema/src/bin/preserves-schema-ts.ts @@ -74,8 +74,7 @@ export function run(options: CommandLineArguments): void { } } -export function modulePathTo(file1: string, file2: string): string | null { - if (file1 === file2) return null; +export function modulePathTo(file1: string, file2: string): string { let naive = path.relative(path.dirname(file1), file2); if (naive[0] !== '.' && naive[0] !== '/') naive = './' + naive; return changeExt(naive, ''); @@ -107,7 +106,6 @@ export function runOnce(options: CommandLineArguments): CompilationResult { inputFiles.forEach(c => { const env: M.Environment = [ ... extensionEnv.flatMap(e => { - if (e.typescriptModulePath === null) return []; const p = modulePathTo(c.outputFilePath, e.typescriptModulePath); if (p === null) return []; return [{... e, typescriptModulePath: p}]; @@ -121,7 +119,7 @@ export function runOnce(options: CommandLineArguments): CompilationResult { fs.mkdirSync(path.dirname(c.outputFilePath), { recursive: true }); let compiledModule; try { - compiledModule = compile(env, c.schema, { + compiledModule = compile(env, c.schemaPath, c.schema, { preservesModule: options.core, warn: (message: string, pos: Position | null) => failures.push({ type: 'warn', file: c.inputFilePath, detail: { message, pos } }), diff --git a/implementations/javascript/packages/schema/src/bin/preserves-schemac.ts b/implementations/javascript/packages/schema/src/bin/preserves-schemac.ts index 8126a28..974f96a 100644 --- a/implementations/javascript/packages/schema/src/bin/preserves-schemac.ts +++ b/implementations/javascript/packages/schema/src/bin/preserves-schemac.ts @@ -2,7 +2,7 @@ import { Command } from 'commander'; import { canonicalEncode, KeyedDictionary, underlying } from '@preserves/core'; import fs from 'fs'; import path from 'path'; -import { fromSchema, fromBundle } from '../meta'; +import * as M from '../meta'; import { expandInputGlob, formatFailures } from './cli-utils'; export type CommandLineArguments = { @@ -25,11 +25,12 @@ export function run(options: CommandLineArguments): void { if (failures.length === 0) { if (options.bundle) { - fs.writeSync(1, underlying(canonicalEncode(fromBundle({ - modules: new KeyedDictionary(inputFiles.map(i => [i.modulePath, i.schema])), + fs.writeSync(1, underlying(canonicalEncode(M.fromBundle({ + modules: new KeyedDictionary( + inputFiles.map(i => [i.modulePath, i.schema])), })))); } else { - fs.writeSync(1, underlying(canonicalEncode(fromSchema(inputFiles[0].schema)))); + fs.writeSync(1, underlying(canonicalEncode(M.fromSchema(inputFiles[0].schema)))); } } else { process.exit(1); diff --git a/implementations/javascript/packages/schema/src/compiler.ts b/implementations/javascript/packages/schema/src/compiler.ts index dd6d990..fd2f834 100644 --- a/implementations/javascript/packages/schema/src/compiler.ts +++ b/implementations/javascript/packages/schema/src/compiler.ts @@ -4,47 +4,51 @@ import { CompilerOptions, ModuleContext } from "./compiler/context"; import { Formatter, block, seq } from "./compiler/block"; import { typeForDefinition } from "./compiler/gentype"; import { converterForDefinition } from "./compiler/genconverter"; -import { Type } from "./compiler/type"; import { renderType } from "./compiler/rendertype"; import { genConstructor } from "./compiler/genctor"; import { unconverterForDefinition } from "./compiler/genunconverter"; import { sourceCodeFor } from "./compiler/value"; -export function compile(env: M.Environment, schema: M.Schema, options: CompilerOptions = {}): string { - const mod = new ModuleContext(env, schema, options); +export function compile( + env: M.Environment, + modulePath: M.ModulePath, + schema: M.Schema, + options: CompilerOptions = {}, +): string { + const mod = new ModuleContext(env, modulePath, schema, options); const embeddedName = schema.embeddedType; - mod.defineType(seq(`export type _embedded = `, - renderType(embeddedName._variant === 'false' - ? Type.ref('any') - : typeForDefinition(mod.resolver(), M.Definition.Pattern(M.Pattern.SimplePattern(M.SimplePattern.Ref(embeddedName.value))))), - `;`)); - mod.defineType(`export type _val = _.Value<_embedded>;`); + if (embeddedName._variant !== 'false') { + mod.defineType(seq(`export type _embedded = `, mod.embeddedType, `;`)); + } for (const [name, def] of schema.definitions) { const t = typeForDefinition(mod.resolver(), def); const nameStr = stringify(name); + const resultTypeItem = nameStr + mod.genericArgsFor(t); - mod.defineType(seq(`export type ${nameStr} = `, renderType(t), `;`)); + mod.defineType(seq(`export type ${nameStr}`, mod.genericParametersFor(t), + ` = `, renderType(mod, t), `;`)); if (t.kind === 'union') { mod.defineFunction(_ctx => seq(`export namespace ${nameStr} `, block( ... Array.from(t.variants).map(([vn, vt]) => - genConstructor(vn, vn, vt, nameStr)) + genConstructor(mod, vn, vn, vt, t, resultTypeItem)) ))); } else { mod.defineFunction(_ctx => - genConstructor(nameStr, void 0, t, nameStr)); + genConstructor(mod, nameStr, void 0, t, t, resultTypeItem)); } } for (const [name0, def] of schema.definitions) { + const t = typeForDefinition(mod.resolver(), def); const name = name0 as symbol; mod.defineFunction(ctx => - seq(`export function as${name.description!}`, - '(v: _val): ', name.description!, ' ', + seq(`export function as${name.description!}`, mod.genericParameters(), + `(v: _.Value<_embedded>): `, name.description!, mod.genericArgsFor(t), ` `, ctx.block(() => [ seq(`let result = to${name.description!}(v)`), seq(`if (result === void 0) `, @@ -52,16 +56,16 @@ export function compile(env: M.Environment, schema: M.Schema, options: CompilerO seq(`return result`)]))); mod.defineFunction(ctx => - seq(`export function to${name.description!}`, - '(v: _val): undefined | ', name.description!, ' ', - ctx.block(() => [seq(`let result: undefined | `, name.description!), - ... converterForDefinition(ctx, def, 'v', 'result'), + seq(`export function to${name.description!}`, mod.genericParameters(), + `(v: _.Value<_embedded>): undefined | `, name.description!, mod.genericArgsFor(t), ` `, + ctx.block(() => [seq(`let result: undefined | `, name.description!, mod.genericArgsFor(t)), + ... converterForDefinition(ctx, def, `v`, `result`), seq(`return result`)]))); mod.defineFunction(ctx => - seq(`export function from${name.description!}`, - '(_v: ', name.description!, '): _val ', - ctx.block(() => unconverterForDefinition(ctx, def, '_v')))); + seq(`export function from${name.description!}`, mod.genericParameters(), + `(_v: `, name.description!, mod.genericArgsFor(t), `): _.Value<_embedded> `, + ctx.block(() => unconverterForDefinition(ctx, def, `_v`)))); } const f = new Formatter(); diff --git a/implementations/javascript/packages/schema/src/compiler/context.ts b/implementations/javascript/packages/schema/src/compiler/context.ts index 3a3a888..88d4ed1 100644 --- a/implementations/javascript/packages/schema/src/compiler/context.ts +++ b/implementations/javascript/packages/schema/src/compiler/context.ts @@ -1,9 +1,11 @@ -import { Dictionary, KeyedSet, Position } from "@preserves/core"; +import { Dictionary, KeyedSet, FlexSet, Position, stringify, is } from "@preserves/core"; import { refPosition } from "../reader"; import * as M from "../meta"; -import { block, braces, commas, formatItems, Item, keyvalue, seq } from "./block"; -import { ANY_TYPE, FieldType, Type } from "./type"; +import { anglebrackets, block, braces, commas, formatItems, Item, keyvalue, seq } from "./block"; +import { ANY_TYPE, RefType, Type } from "./type"; import { renderType, variantInitFor } from "./rendertype"; +import { typeForDefinition } from "./gentype"; +import { SchemaSyntaxError } from "../error"; export interface CompilerOptions { preservesModule?: string; @@ -20,18 +22,36 @@ export const RECURSION_LIMIT = 128; export class ModuleContext { readonly env: M.Environment; + readonly modulePath: M.ModulePath; readonly schema: M.Schema; readonly options: CompilerOptions; + readonly embeddedType: Item; - readonly literals = new Dictionary(); + readonly literals = new Dictionary(); readonly typedefs: Item[] = []; readonly functiondefs: Item[] = []; readonly imports = new KeyedSet<[string, string]>(); - constructor(env: M.Environment, schema: M.Schema, options: CompilerOptions) { + constructor( + env: M.Environment, + modulePath: M.ModulePath, + schema: M.Schema, + options: CompilerOptions, + ) { this.env = env; + this.modulePath = modulePath; this.schema = schema; this.options = options; + switch (schema.embeddedType._variant) { + case 'false': + this.embeddedType = '_.GenericEmbedded'; + break; + case 'Ref': { + const t = this.resolver()(schema.embeddedType.value); + this.embeddedType = t.typeName; + break; + } + } } literal(v: M.Input): Item { @@ -51,11 +71,9 @@ export class ModuleContext { p.value._variant === 'SimplePattern' && p.value.value._variant === 'Ref') { - return M.lookup(refPosition(p.value.value.value), - p.value.value.value, - this.env, - (p) => this.derefPattern(p, refCount + 1), - (_modId, _modPath, pp) => this.derefPattern(pp ?? p, refCount + 1)); + return this.lookup(p.value.value.value, + (p, _t) => this.derefPattern(p, refCount + 1), + (_modId, _modPath, pp, _tt) => this.derefPattern(pp ?? p, refCount + 1)); } else { return p; } @@ -69,13 +87,101 @@ export class ModuleContext { this.functiondefs.push(f(new FunctionContext(this))); } - resolver(): (ref: M.Ref) => FieldType { - return (ref) => M.lookup(refPosition(ref), ref, this.env, - (_p) => Type.ref(ref.name.description!), - (modId, modPath,_p) => { - this.imports.add([modId, modPath]); - return Type.ref(`${modId}.${ref.name.description!}`); - }); + resolver(modulePath?: M.ModulePath): (ref: M.Ref) => RefType { + return (ref) => this.lookup(ref, + (_p, _t) => Type.ref(ref.name.description!, ref), + (modId, modPath, _p, _t) => { + this.imports.add([modId, modPath]); + return Type.ref(`${modId}.${ref.name.description!}`, ref); + }, + modulePath); + } + + lookupType(name: M.Ref, modulePath?: M.ModulePath): Type | null { + const t = this.lookup(name, (_p, t) => t, (_modId, _modPath, _p, t) => t, modulePath); + return t ? t() : null; + } + + lookup(name: M.Ref, + kLocal: (p: M.Definition, t: () => Type) => R, + kOther: (modId: string, modPath: string, p: M.Definition | null, t: (() => Type) | null) => R, + modulePath?: M.ModulePath): R + { + const soughtModule = name.module.length ? name.module : (modulePath ?? this.modulePath); + + for (const e of this.env) { + if (is(e.schemaModulePath, soughtModule)) { + if (e.schema === null) { + // It's an artificial module, not from a schema. Assume the identifier is present. + return kOther(M.modsymFor(e), e.typescriptModulePath, null, null); + } else { + const p = e.schema.definitions.get(name.name); + if (p !== void 0) { + let t = () => typeForDefinition(this.resolver(soughtModule), p); + if (name.module.length) { + return kOther(M.modsymFor(e), e.typescriptModulePath, p, t); + } else { + return kLocal(p, t); + } + } + } + } + } + + throw new SchemaSyntaxError(`Undefined reference: ${M.formatRef(name)}`, refPosition(name)); + } + + genericParameters(): Item { + return anglebrackets(seq('_embedded = ', this.embeddedType)); + } + + genericParametersFor(t: Type): Item { + return this.hasEmbedded(t) ? this.genericParameters() : ''; + } + + genericArgs(): Item { + return `<_embedded>`; + } + + genericArgsFor(t: Type): Item { + return this.hasEmbedded(t) ? this.genericArgs() : ''; + } + + hasEmbedded(t: Type): boolean { + const self = this; + const state = new WalkState(this.modulePath); + + function walk(t: Type): boolean { + switch (t.kind) { + case 'union': + for (const v of t.variants.values()) { if (walk(v)) return true; }; + return false; + case 'unit': return false; + case 'array': return walk(t.type); + case 'set': return true; // because ref to _embedded in renderType() + case 'dictionary': return true; // because ref to _embedded in renderType() + case 'ref': { + if (t.ref === null) { + switch (t.typeName) { + case '_embedded': return true; + case '_.Value': return true; + default: return false; + } + } else { + return state.cycleCheck( + t.ref, + ref => self.lookupType(ref, state.modulePath), + t => t ? walk(t) : false, + () => false); + } + } + case 'record': + for (const v of t.fields.values()) { if (walk(v)) return true; }; + return false; + } + } + + return walk(t); } } @@ -97,7 +203,7 @@ export class FunctionContext { } gentemp(vartype: Type = ANY_TYPE): string { - const typeitem = renderType(vartype); + const typeitem = renderType(this.mod, vartype); const typestr = formatItems([typeitem], Infinity); const varname = this.gentempname(); let e = this.temps.get(typestr); @@ -146,3 +252,40 @@ export class FunctionContext { return seq(`${dest} = `, fields.length === 0 ? `null` : braces(... fields)); } } + +export class WalkState { + modulePath: M.ModulePath; + readonly seen: FlexSet; + + constructor(modulePath: M.ModulePath) { + this.modulePath = modulePath; + this.seen = new FlexSet(refCanonicalizer); + } + + cycleCheck( + r0: M.Ref, + step: (ref: M.Ref) => E, + ks: (e: E) => R, + kf: () => R, + ): R { + const r = M.Ref({ + module: r0.module.length ? r0.module : this.modulePath, + name: r0.name + }); + if (this.seen.has(r)) { + return kf(); + } else { + this.seen.add(r); + const maybe_e = step(r); + const saved = this.modulePath; + this.modulePath = r.module; + const result = ks(maybe_e); + this.modulePath = saved; + return result; + } + } +} + +function refCanonicalizer(r: M.Ref): string { + return stringify([... r.module, r.name]); +} diff --git a/implementations/javascript/packages/schema/src/compiler/genconverter.ts b/implementations/javascript/packages/schema/src/compiler/genconverter.ts index 4cd60b0..6da657b 100644 --- a/implementations/javascript/packages/schema/src/compiler/genconverter.ts +++ b/implementations/javascript/packages/schema/src/compiler/genconverter.ts @@ -2,7 +2,6 @@ import { FunctionContext } from "./context"; import * as M from '../meta'; import { Item, seq } from "./block"; import { simpleType, typeFor } from "./gentype"; -import { refPosition } from "../reader"; import { ANY_TYPE, Type } from "./type"; export function converterForDefinition( @@ -184,12 +183,12 @@ export function converterForSimple( seq(`break`)]))]; }))]; case 'Ref': - return M.lookup(refPosition(p.value), p.value, ctx.mod.env, - (_p) => [`${dest} = to${p.value.name.description!}(${src})`], - (modId, modPath,_p) => { - ctx.mod.imports.add([modId, modPath]); - return [`${dest} = ${modId}.to${p.value.name.description!}(${src})`]; - }); + return ctx.mod.lookup(p.value, + (_p, _t) => [`${dest} = to${p.value.name.description!}(${src})`], + (modId, modPath, _p, _t) => { + ctx.mod.imports.add([modId, modPath]); + return [`${dest} = ${modId}.to${p.value.name.description!}(${src})`]; + }); default: ((_p: never) => {})(p); throw new Error("Unreachable"); @@ -205,7 +204,7 @@ function converterForCompound( { switch (p._variant) { case 'rec': - return [seq(`if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(${src})) `, ctx.block(() => + return [seq(`if (_.Record.isRecord<_.Value<_embedded>, _.Tuple<_.Value<_embedded>>, _embedded>(${src})) `, ctx.block(() => converterFor(ctx, p.label, `${src}.label`, () => converterFor(ctx, p.fields, src, ks, true))))]; case 'tuple': diff --git a/implementations/javascript/packages/schema/src/compiler/genctor.ts b/implementations/javascript/packages/schema/src/compiler/genctor.ts index 3fafd4b..8e9ebd4 100644 --- a/implementations/javascript/packages/schema/src/compiler/genctor.ts +++ b/implementations/javascript/packages/schema/src/compiler/genctor.ts @@ -1,14 +1,17 @@ import * as M from '../meta'; import { block, braces, Item, keyvalue, parens, seq } from "./block"; -import { FieldType, SimpleType } from "./type"; +import { FieldType, SimpleType, Type } from "./type"; import { renderType } from "./rendertype"; +import { ModuleContext } from './context'; export function genConstructor( + mod: ModuleContext, name: string, variant: string | undefined, arg: SimpleType, - resultType: Item): Item -{ + resultType: Type, + resultTypeItem: Item, +): Item { const formals: Array<[string, FieldType]> = []; let simpleValue = false; @@ -32,12 +35,12 @@ export function genConstructor( const declArgs: Array = (formals.length > 1) ? [seq(braces(...formals.map(f => M.jsId(f[0]))), ': ', - braces(...formals.map(f => seq(M.jsId(f[0]), ': ', renderType(f[1])))))] - : formals.map(f => seq(M.jsId(f[0]), ': ', renderType(f[1]))); + braces(...formals.map(f => seq(M.jsId(f[0]), ': ', renderType(mod, f[1])))))] + : formals.map(f => seq(M.jsId(f[0]), ': ', renderType(mod, f[1]))); - return seq(`export function ${M.jsId(name)}`, + return seq(`export function ${M.jsId(name)}`, mod.genericParametersFor(resultType), parens(... declArgs), - ': ', resultType, ' ', block( + ': ', resultTypeItem, ' ', block( seq(`return `, ((arg.kind === 'unit' && initializers.length === 0) ? 'null' diff --git a/implementations/javascript/packages/schema/src/compiler/gentype.ts b/implementations/javascript/packages/schema/src/compiler/gentype.ts index cb8ddfc..3ea90b9 100644 --- a/implementations/javascript/packages/schema/src/compiler/gentype.ts +++ b/implementations/javascript/packages/schema/src/compiler/gentype.ts @@ -36,16 +36,16 @@ export function simpleType(resolver: RefResolver, p: M.SimplePattern): FieldType return ANY_TYPE; case 'atom': switch (p.atomKind._variant) { - case 'Boolean': return Type.ref(`boolean`); - case 'Float': return Type.ref(`number`); - case 'Double': return Type.ref(`number`); - case 'SignedInteger': return Type.ref(`number`); - case 'String': return Type.ref(`string`); - case 'ByteString': return Type.ref(`_.Bytes`); - case 'Symbol': return Type.ref(`symbol`); + case 'Boolean': return Type.ref(`boolean`, null); + case 'Float': return Type.ref(`number`, null); + case 'Double': return Type.ref(`number`, null); + case 'SignedInteger': return Type.ref(`number`, null); + case 'String': return Type.ref(`string`, null); + case 'ByteString': return Type.ref(`_.Bytes`, null); + case 'Symbol': return Type.ref(`symbol`, null); } case 'embedded': - return Type.ref(`_embedded`); + return Type.ref(`_embedded`, null); case 'lit': return Type.unit(); case 'seqof': diff --git a/implementations/javascript/packages/schema/src/compiler/genunconverter.ts b/implementations/javascript/packages/schema/src/compiler/genunconverter.ts index 1524345..3424b35 100644 --- a/implementations/javascript/packages/schema/src/compiler/genunconverter.ts +++ b/implementations/javascript/packages/schema/src/compiler/genunconverter.ts @@ -1,4 +1,3 @@ -import { refPosition } from '../reader'; import * as M from '../meta'; import { block, brackets, Item, parens, seq } from './block'; import { FunctionContext } from "./context"; @@ -66,13 +65,12 @@ function unconverterFor(ctx: FunctionContext, p: M.Pattern, src: string): Item { unconverterFor(ctx, M.Pattern.SimplePattern(p.value), 'v')), `)`))); case 'Ref': - return M.lookup( - refPosition(p.value), p.value, ctx.mod.env, - (_p) => `from${p.value.name.description!}(${src})`, - (modId, modPath, _p) => { - ctx.mod.imports.add([modId, modPath]); - return `${modId}.from${p.value.name.description!}(${src})`; - }); + return ctx.mod.lookup(p.value, + (_p, _t) => `from${p.value.name.description!}${ctx.mod.genericArgs()}(${src})`, + (modId, modPath, _p, _t) => { + ctx.mod.imports.add([modId, modPath]); + return `${modId}.from${p.value.name.description!}${ctx.mod.genericArgs()}(${src})`; + }); } })(p.value); case 'CompoundPattern': diff --git a/implementations/javascript/packages/schema/src/compiler/rendertype.ts b/implementations/javascript/packages/schema/src/compiler/rendertype.ts index a93bf13..927201e 100644 --- a/implementations/javascript/packages/schema/src/compiler/rendertype.ts +++ b/implementations/javascript/packages/schema/src/compiler/rendertype.ts @@ -1,5 +1,6 @@ import { SimpleType, Type } from "./type"; import { anglebrackets, braces, Item, keyvalue, opseq, seq } from "./block"; +import { ModuleContext } from "./context"; export function variantInitFor(variantName: string | undefined) : Item[] { return variantName === void 0 ? [] : [variantFor(variantName)]; @@ -9,7 +10,7 @@ export function variantFor(variantName: string): Item { return keyvalue('_variant', JSON.stringify(variantName)); } -export function renderVariant([variantName, t]: [string, SimpleType]): Item { +export function renderVariant(ctxt: ModuleContext, [variantName, t]: [string, SimpleType]): Item { let fields: Item[]; switch (t.kind) { case 'unit': @@ -19,10 +20,10 @@ export function renderVariant([variantName, t]: [string, SimpleType]): Item { case 'set': case 'dictionary': case 'array': - fields = [keyvalue('value', renderType(t))]; + fields = [keyvalue('value', renderType(ctxt, t))]; break; case 'record': - fields = Array.from(t.fields).map(([nn, tt]) => keyvalue(nn, renderType(tt))); + fields = Array.from(t.fields).map(([nn, tt]) => keyvalue(nn, renderType(ctxt, tt))); break; default: ((_: never) => {})(t); @@ -31,22 +32,27 @@ export function renderVariant([variantName, t]: [string, SimpleType]): Item { return braces(variantFor(variantName), ... fields); } -export function renderType(t: Type): Item { +export function renderType(ctxt: ModuleContext, t: Type): Item { switch (t.kind) { case 'union': return opseq('never', ' | ', ... - Array.from(t.variants).flatMap(renderVariant)); + Array.from(t.variants).flatMap(entry => renderVariant(ctxt, entry))); case 'unit': return 'null'; - case 'ref': return t.typeName; + case 'ref': + if (t.ref === null && t.typeName === '_embedded') { + return t.typeName; + } else { + return seq(t.typeName, ctxt.genericArgsFor(t)); + } case 'set': return seq('_.KeyedSet', anglebrackets( - renderType(t.type), + renderType(ctxt, t.type), '_embedded')); case 'dictionary': return seq('_.KeyedDictionary', anglebrackets( - renderType(t.key), - renderType(t.value), + renderType(ctxt, t.key), + renderType(ctxt, t.value), '_embedded')); - case 'array': return seq('Array', anglebrackets(renderType(t.type))); + case 'array': return seq('Array', anglebrackets(renderType(ctxt, t.type))); case 'record': return braces(... Array.from(t.fields).map(([nn, tt]) => - keyvalue(nn, renderType(tt)))); + keyvalue(nn, renderType(ctxt, tt)))); default: ((_: never) => {})(t); 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 1329b97..843068c 100644 --- a/implementations/javascript/packages/schema/src/compiler/type.ts +++ b/implementations/javascript/packages/schema/src/compiler/type.ts @@ -1,3 +1,5 @@ +import * as M from '../meta'; + export type Type = | { kind: 'union', variants: VariantMap } // zero: never | SimpleType @@ -9,7 +11,10 @@ export type FieldType = | { kind: 'array', type: FieldType } | { kind: 'set', type: FieldType } | { kind: 'dictionary', key: FieldType, value: FieldType } - | { kind: 'ref', typeName: string } // also for base types + | RefType + +export type RefType = + | { kind: 'ref', typeName: string, ref: M.Ref | null } // ref === null for base types export type RecordType = | { kind: 'record', fields: FieldMap } @@ -20,7 +25,8 @@ export type FieldMap = Map; export namespace Type { export const union = (variants: VariantMap): Type => ({ kind: 'union', variants }); export const unit = (): FieldType => ({ kind: 'unit' }); - export const ref = (typeName: string): FieldType => ({ kind: 'ref', typeName }); + export const ref = (typeName: string, ref: M.Ref | null): RefType => ( + { kind: 'ref', typeName, ref }); export const array = (type: FieldType): FieldType => ({ kind: 'array', type }); export const set = (type: FieldType): FieldType => ({ kind: 'set', type }); export const dictionary = (key: FieldType, value: FieldType): FieldType => ( @@ -28,4 +34,4 @@ export namespace Type { export const record = (fields: FieldMap): RecordType => ({ kind: 'record', fields }); } -export const ANY_TYPE: FieldType = Type.ref('_val'); +export const ANY_TYPE: FieldType = Type.ref('_.Value', null); diff --git a/implementations/javascript/packages/schema/src/compiler/value.ts b/implementations/javascript/packages/schema/src/compiler/value.ts index df28684..b072cbe 100644 --- a/implementations/javascript/packages/schema/src/compiler/value.ts +++ b/implementations/javascript/packages/schema/src/compiler/value.ts @@ -1,8 +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, Embedded } 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(); }, @@ -14,25 +14,25 @@ export function sourceCodeFor(v: Value): Item { }, symbol(s: symbol): Item { return `Symbol.for(${JSON.stringify(s.description!)})`; }, - record(r: Record, Tuple>, M._embedded>, k: Fold): Item { - return seq(`_.Record<_val, _.Tuple<_val>, _embedded>`, parens(k(r.label), brackets(... r.map(k)))); + record(r: Record, Tuple>, M.InputEmbedded>, k: Fold): Item { + return seq(`_.Record<_.Value<_embedded>, _.Tuple<_.Value<_embedded>>, _embedded>`, 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 { - return seq('new _.Set<_val>', parens(brackets(... Array.from(s).map(k)))); + set(s: Set, k: Fold): Item { + return seq('new _.Set<_.Value<_embedded>>', parens(brackets(... Array.from(s).map(k)))); }, - dictionary(d: Dictionary, k: Fold): Item { + dictionary(d: Dictionary, k: Fold): Item { return seq('new _.Dictionary<_embedded>', 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<_embedded>', parens(k(a.item), ... a.annotations.map(k))); }, - embedded(t: M._embedded, _k: Fold): Item { + embedded(t: Embedded, _k: Fold): Item { throw new Error(`Cannot emit source code for construction of embedded ${stringify(t)}`); }, }); diff --git a/implementations/javascript/packages/schema/src/gen/schema.ts b/implementations/javascript/packages/schema/src/gen/schema.ts index 4083c91..4367a28 100644 --- a/implementations/javascript/packages/schema/src/gen/schema.ts +++ b/implementations/javascript/packages/schema/src/gen/schema.ts @@ -30,70 +30,74 @@ export const $tuplePrefix = Symbol.for("tuplePrefix"); export const $version = Symbol.for("version"); export const __lit6 = false; -export type _embedded = any; +export type Bundle<_embedded = _.GenericEmbedded> = {"modules": Modules<_embedded>}; -export type _val = _.Value<_embedded>; +export type Modules<_embedded = _.GenericEmbedded> = _.KeyedDictionary, _embedded>; -export type Bundle = {"modules": Modules}; - -export type Modules = _.KeyedDictionary; - -export type Schema = { +export type Schema<_embedded = _.GenericEmbedded> = { "version": Version, "embeddedType": EmbeddedTypeName, - "definitions": Definitions + "definitions": Definitions<_embedded> }; export type Version = null; export type EmbeddedTypeName = ({"_variant": "Ref", "value": Ref} | {"_variant": "false"}); -export type Definitions = _.KeyedDictionary; +export type Definitions<_embedded = _.GenericEmbedded> = _.KeyedDictionary, _embedded>; -export type Definition = ( +export type Definition<_embedded = _.GenericEmbedded> = ( { "_variant": "or", - "pattern0": NamedAlternative, - "pattern1": NamedAlternative, - "patternN": Array + "pattern0": NamedAlternative<_embedded>, + "pattern1": NamedAlternative<_embedded>, + "patternN": Array> } | { "_variant": "and", - "pattern0": NamedPattern, - "pattern1": NamedPattern, - "patternN": Array + "pattern0": NamedPattern<_embedded>, + "pattern1": NamedPattern<_embedded>, + "patternN": Array> } | - {"_variant": "Pattern", "value": Pattern} + {"_variant": "Pattern", "value": Pattern<_embedded>} ); -export type Pattern = ( - {"_variant": "SimplePattern", "value": SimplePattern} | - {"_variant": "CompoundPattern", "value": CompoundPattern} +export type Pattern<_embedded = _.GenericEmbedded> = ( + {"_variant": "SimplePattern", "value": SimplePattern<_embedded>} | + {"_variant": "CompoundPattern", "value": CompoundPattern<_embedded>} ); -export type SimplePattern = ( +export type SimplePattern<_embedded = _.GenericEmbedded> = ( {"_variant": "any"} | {"_variant": "atom", "atomKind": AtomKind} | - {"_variant": "embedded", "interface": SimplePattern} | - {"_variant": "lit", "value": _val} | - {"_variant": "seqof", "pattern": SimplePattern} | - {"_variant": "setof", "pattern": SimplePattern} | - {"_variant": "dictof", "key": SimplePattern, "value": SimplePattern} | + {"_variant": "embedded", "interface": SimplePattern<_embedded>} | + {"_variant": "lit", "value": _.Value<_embedded>} | + {"_variant": "seqof", "pattern": SimplePattern<_embedded>} | + {"_variant": "setof", "pattern": SimplePattern<_embedded>} | + { + "_variant": "dictof", + "key": SimplePattern<_embedded>, + "value": SimplePattern<_embedded> + } | {"_variant": "Ref", "value": Ref} ); -export type CompoundPattern = ( - {"_variant": "rec", "label": NamedPattern, "fields": NamedPattern} | - {"_variant": "tuple", "patterns": Array} | +export type CompoundPattern<_embedded = _.GenericEmbedded> = ( + { + "_variant": "rec", + "label": NamedPattern<_embedded>, + "fields": NamedPattern<_embedded> + } | + {"_variant": "tuple", "patterns": Array>} | { "_variant": "tuplePrefix", - "fixed": Array, - "variable": NamedSimplePattern + "fixed": Array>, + "variable": NamedSimplePattern<_embedded> } | - {"_variant": "dict", "entries": DictionaryEntries} + {"_variant": "dict", "entries": DictionaryEntries<_embedded>} ); -export type DictionaryEntries = _.KeyedDictionary<_val, NamedSimplePattern, _embedded>; +export type DictionaryEntries<_embedded = _.GenericEmbedded> = _.KeyedDictionary<_.Value<_embedded>, NamedSimplePattern<_embedded>, _embedded>; export type AtomKind = ( {"_variant": "Boolean"} | @@ -105,32 +109,36 @@ export type AtomKind = ( {"_variant": "Symbol"} ); -export type NamedAlternative = {"variantLabel": string, "pattern": Pattern}; +export type NamedAlternative<_embedded = _.GenericEmbedded> = {"variantLabel": string, "pattern": Pattern<_embedded>}; -export type NamedSimplePattern = ( - {"_variant": "named", "value": Binding} | - {"_variant": "anonymous", "value": SimplePattern} +export type NamedSimplePattern<_embedded = _.GenericEmbedded> = ( + {"_variant": "named", "value": Binding<_embedded>} | + {"_variant": "anonymous", "value": SimplePattern<_embedded>} ); -export type NamedPattern = ( - {"_variant": "named", "value": Binding} | - {"_variant": "anonymous", "value": Pattern} +export type NamedPattern<_embedded = _.GenericEmbedded> = ( + {"_variant": "named", "value": Binding<_embedded>} | + {"_variant": "anonymous", "value": Pattern<_embedded>} ); -export type Binding = {"name": symbol, "pattern": SimplePattern}; +export type Binding<_embedded = _.GenericEmbedded> = {"name": symbol, "pattern": SimplePattern<_embedded>}; export type Ref = {"module": ModulePath, "name": symbol}; export type ModulePath = Array; -export function Bundle(modules: Modules): Bundle {return {"modules": modules};} +export function Bundle<_embedded = _.GenericEmbedded>(modules: Modules<_embedded>): Bundle<_embedded> {return {"modules": modules};} -export function Modules(value: _.KeyedDictionary): Modules {return value;} +export function Modules<_embedded = _.GenericEmbedded>(value: _.KeyedDictionary, _embedded>): Modules<_embedded> {return value;} -export function Schema( - {version, embeddedType, definitions}: {version: Version, embeddedType: EmbeddedTypeName, definitions: Definitions} -): Schema { +export function Schema<_embedded = _.GenericEmbedded>( + {version, embeddedType, definitions}: { + version: Version, + embeddedType: EmbeddedTypeName, + definitions: Definitions<_embedded> + } +): Schema<_embedded> { return {"version": version, "embeddedType": embeddedType, "definitions": definitions}; } @@ -141,16 +149,16 @@ export namespace EmbeddedTypeName { export function $false(): EmbeddedTypeName {return {"_variant": "false"};}; } -export function Definitions(value: _.KeyedDictionary): Definitions {return value;} +export function Definitions<_embedded = _.GenericEmbedded>(value: _.KeyedDictionary, _embedded>): Definitions<_embedded> {return value;} export namespace Definition { - export function or( + export function or<_embedded = _.GenericEmbedded>( {pattern0, pattern1, patternN}: { - pattern0: NamedAlternative, - pattern1: NamedAlternative, - patternN: Array + pattern0: NamedAlternative<_embedded>, + pattern1: NamedAlternative<_embedded>, + patternN: Array> } - ): Definition { + ): Definition<_embedded> { return { "_variant": "or", "pattern0": pattern0, @@ -158,9 +166,13 @@ export namespace Definition { "patternN": patternN }; }; - export function and( - {pattern0, pattern1, patternN}: {pattern0: NamedPattern, pattern1: NamedPattern, patternN: Array} - ): Definition { + export function and<_embedded = _.GenericEmbedded>( + {pattern0, pattern1, patternN}: { + pattern0: NamedPattern<_embedded>, + pattern1: NamedPattern<_embedded>, + patternN: Array> + } + ): Definition<_embedded> { return { "_variant": "and", "pattern0": pattern0, @@ -168,33 +180,39 @@ export namespace Definition { "patternN": patternN }; }; - export function Pattern(value: Pattern): Definition {return {"_variant": "Pattern", "value": value};}; + export function Pattern<_embedded = _.GenericEmbedded>(value: Pattern<_embedded>): Definition<_embedded> {return {"_variant": "Pattern", "value": value};}; } export namespace Pattern { - export function SimplePattern(value: SimplePattern): Pattern {return {"_variant": "SimplePattern", "value": value};}; - export function CompoundPattern(value: CompoundPattern): Pattern {return {"_variant": "CompoundPattern", "value": value};}; + export function SimplePattern<_embedded = _.GenericEmbedded>(value: SimplePattern<_embedded>): Pattern<_embedded> {return {"_variant": "SimplePattern", "value": value};}; + export function CompoundPattern<_embedded = _.GenericEmbedded>(value: CompoundPattern<_embedded>): Pattern<_embedded> {return {"_variant": "CompoundPattern", "value": value};}; } export namespace SimplePattern { - export function any(): SimplePattern {return {"_variant": "any"};}; - export function atom(atomKind: AtomKind): SimplePattern {return {"_variant": "atom", "atomKind": atomKind};}; - export function embedded($interface: SimplePattern): SimplePattern {return {"_variant": "embedded", "interface": $interface};}; - export function lit(value: _val): SimplePattern {return {"_variant": "lit", "value": value};}; - export function seqof(pattern: SimplePattern): SimplePattern {return {"_variant": "seqof", "pattern": pattern};}; - export function setof(pattern: SimplePattern): SimplePattern {return {"_variant": "setof", "pattern": pattern};}; - export function dictof({key, value}: {key: SimplePattern, value: SimplePattern}): SimplePattern {return {"_variant": "dictof", "key": key, "value": value};}; - export function Ref(value: Ref): SimplePattern {return {"_variant": "Ref", "value": value};}; + export function any<_embedded = _.GenericEmbedded>(): SimplePattern<_embedded> {return {"_variant": "any"};}; + export function atom<_embedded = _.GenericEmbedded>(atomKind: AtomKind): SimplePattern<_embedded> {return {"_variant": "atom", "atomKind": atomKind};}; + export function embedded<_embedded = _.GenericEmbedded>($interface: SimplePattern<_embedded>): SimplePattern<_embedded> {return {"_variant": "embedded", "interface": $interface};}; + export function lit<_embedded = _.GenericEmbedded>(value: _.Value<_embedded>): SimplePattern<_embedded> {return {"_variant": "lit", "value": value};}; + export function seqof<_embedded = _.GenericEmbedded>(pattern: SimplePattern<_embedded>): SimplePattern<_embedded> {return {"_variant": "seqof", "pattern": pattern};}; + export function setof<_embedded = _.GenericEmbedded>(pattern: SimplePattern<_embedded>): SimplePattern<_embedded> {return {"_variant": "setof", "pattern": pattern};}; + export function dictof<_embedded = _.GenericEmbedded>({key, value}: {key: SimplePattern<_embedded>, value: SimplePattern<_embedded>}): SimplePattern<_embedded> {return {"_variant": "dictof", "key": key, "value": value};}; + export function Ref<_embedded = _.GenericEmbedded>(value: Ref): SimplePattern<_embedded> {return {"_variant": "Ref", "value": value};}; } export namespace CompoundPattern { - export function rec({label, fields}: {label: NamedPattern, fields: NamedPattern}): CompoundPattern {return {"_variant": "rec", "label": label, "fields": fields};}; - export function tuple(patterns: Array): CompoundPattern {return {"_variant": "tuple", "patterns": patterns};}; - export function tuplePrefix({fixed, variable}: {fixed: Array, variable: NamedSimplePattern}): CompoundPattern {return {"_variant": "tuplePrefix", "fixed": fixed, "variable": variable};}; - export function dict(entries: DictionaryEntries): CompoundPattern {return {"_variant": "dict", "entries": entries};}; + export function rec<_embedded = _.GenericEmbedded>( + {label, fields}: {label: NamedPattern<_embedded>, fields: NamedPattern<_embedded>} + ): CompoundPattern<_embedded> {return {"_variant": "rec", "label": label, "fields": fields};}; + export function tuple<_embedded = _.GenericEmbedded>(patterns: Array>): CompoundPattern<_embedded> {return {"_variant": "tuple", "patterns": patterns};}; + export function tuplePrefix<_embedded = _.GenericEmbedded>( + {fixed, variable}: {fixed: Array>, variable: NamedSimplePattern<_embedded>} + ): CompoundPattern<_embedded> {return {"_variant": "tuplePrefix", "fixed": fixed, "variable": variable};}; + export function dict<_embedded = _.GenericEmbedded>(entries: DictionaryEntries<_embedded>): CompoundPattern<_embedded> {return {"_variant": "dict", "entries": entries};}; } -export function DictionaryEntries(value: _.KeyedDictionary<_val, NamedSimplePattern, _embedded>): DictionaryEntries {return value;} +export function DictionaryEntries<_embedded = _.GenericEmbedded>( + value: _.KeyedDictionary<_.Value<_embedded>, NamedSimplePattern<_embedded>, _embedded> +): DictionaryEntries<_embedded> {return value;} export namespace AtomKind { export function Boolean(): AtomKind {return {"_variant": "Boolean"};}; @@ -206,37 +224,37 @@ export namespace AtomKind { export function Symbol(): AtomKind {return {"_variant": "Symbol"};}; } -export function NamedAlternative({variantLabel, pattern}: {variantLabel: string, pattern: Pattern}): NamedAlternative {return {"variantLabel": variantLabel, "pattern": pattern};} +export function NamedAlternative<_embedded = _.GenericEmbedded>({variantLabel, pattern}: {variantLabel: string, pattern: Pattern<_embedded>}): NamedAlternative<_embedded> {return {"variantLabel": variantLabel, "pattern": pattern};} export namespace NamedSimplePattern { - export function named(value: Binding): NamedSimplePattern {return {"_variant": "named", "value": value};}; - export function anonymous(value: SimplePattern): NamedSimplePattern {return {"_variant": "anonymous", "value": value};}; + export function named<_embedded = _.GenericEmbedded>(value: Binding<_embedded>): NamedSimplePattern<_embedded> {return {"_variant": "named", "value": value};}; + export function anonymous<_embedded = _.GenericEmbedded>(value: SimplePattern<_embedded>): NamedSimplePattern<_embedded> {return {"_variant": "anonymous", "value": value};}; } export namespace NamedPattern { - export function named(value: Binding): NamedPattern {return {"_variant": "named", "value": value};}; - export function anonymous(value: Pattern): NamedPattern {return {"_variant": "anonymous", "value": value};}; + export function named<_embedded = _.GenericEmbedded>(value: Binding<_embedded>): NamedPattern<_embedded> {return {"_variant": "named", "value": value};}; + export function anonymous<_embedded = _.GenericEmbedded>(value: Pattern<_embedded>): NamedPattern<_embedded> {return {"_variant": "anonymous", "value": value};}; } -export function Binding({name, pattern}: {name: symbol, pattern: SimplePattern}): Binding {return {"name": name, "pattern": pattern};} +export function Binding<_embedded = _.GenericEmbedded>({name, pattern}: {name: symbol, pattern: SimplePattern<_embedded>}): Binding<_embedded> {return {"name": name, "pattern": pattern};} export function Ref({module, name}: {module: ModulePath, name: symbol}): Ref {return {"module": module, "name": name};} export function ModulePath(value: Array): ModulePath {return value;} -export function asBundle(v: _val): Bundle { +export function asBundle<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): Bundle<_embedded> { let result = toBundle(v); if (result === void 0) throw new TypeError(`Invalid Bundle: ${_.stringify(v)}`); return result; } -export function toBundle(v: _val): undefined | Bundle { - let result: undefined | Bundle; - if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) { +export function toBundle<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): undefined | Bundle<_embedded> { + let result: undefined | Bundle<_embedded>; + if (_.Record.isRecord<_.Value<_embedded>, _.Tuple<_.Value<_embedded>>, _embedded>(v)) { let _tmp0: (null) | undefined; _tmp0 = _.is(v.label, $bundle) ? null : void 0; if (_tmp0 !== void 0) { - let _tmp1: (Modules) | undefined; + let _tmp1: (Modules<_embedded>) | undefined; _tmp1 = toModules(v[0]); if (_tmp1 !== void 0) {result = {"modules": _tmp1};}; }; @@ -244,17 +262,17 @@ export function toBundle(v: _val): undefined | Bundle { return result; } -export function fromBundle(_v: Bundle): _val {return _.Record($bundle, [fromModules(_v["modules"])]);} +export function fromBundle<_embedded = _.GenericEmbedded>(_v: Bundle<_embedded>): _.Value<_embedded> {return _.Record($bundle, [fromModules<_embedded>(_v["modules"])]);} -export function asModules(v: _val): Modules { +export function asModules<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): Modules<_embedded> { let result = toModules(v); if (result === void 0) throw new TypeError(`Invalid Modules: ${_.stringify(v)}`); return result; } -export function toModules(v: _val): undefined | Modules { - let _tmp0: (_.KeyedDictionary) | undefined; - let result: undefined | Modules; +export function toModules<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): undefined | Modules<_embedded> { + let _tmp0: (_.KeyedDictionary, _embedded>) | undefined; + let result: undefined | Modules<_embedded>; _tmp0 = void 0; if (_.Dictionary.isDictionary<_embedded>(v)) { _tmp0 = new _.KeyedDictionary(); @@ -262,7 +280,7 @@ export function toModules(v: _val): undefined | Modules { let _tmp3: (ModulePath) | undefined; _tmp3 = toModulePath(_tmp2); if (_tmp3 !== void 0) { - let _tmp4: (Schema) | undefined; + let _tmp4: (Schema<_embedded>) | undefined; _tmp4 = toSchema(_tmp1); if (_tmp4 !== void 0) {_tmp0.set(_tmp3, _tmp4); continue;}; }; @@ -274,36 +292,38 @@ export function toModules(v: _val): undefined | Modules { return result; } -export function fromModules(_v: Modules): _val { - return new _.Dictionary<_embedded>(_.Array.from(_v.entries()).map(([k, v]) => [fromModulePath(k), fromSchema(v)])); +export function fromModules<_embedded = _.GenericEmbedded>(_v: Modules<_embedded>): _.Value<_embedded> { + return new _.Dictionary<_embedded>( + _.Array.from(_v.entries()).map(([k, v]) => [fromModulePath<_embedded>(k), fromSchema<_embedded>(v)]) + ); } -export function asSchema(v: _val): Schema { +export function asSchema<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): Schema<_embedded> { let result = toSchema(v); if (result === void 0) throw new TypeError(`Invalid Schema: ${_.stringify(v)}`); return result; } -export function toSchema(v: _val): undefined | Schema { - let result: undefined | Schema; - if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) { +export function toSchema<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): undefined | Schema<_embedded> { + let result: undefined | Schema<_embedded>; + if (_.Record.isRecord<_.Value<_embedded>, _.Tuple<_.Value<_embedded>>, _embedded>(v)) { let _tmp0: (null) | undefined; _tmp0 = _.is(v.label, $schema) ? null : void 0; if (_tmp0 !== void 0) { if (_.Dictionary.isDictionary<_embedded>(v[0])) { - let _tmp1: (_val) | undefined; + let _tmp1: (_.Value<_embedded>) | undefined; if ((_tmp1 = v[0].get($version)) !== void 0) { let _tmp2: (Version) | undefined; _tmp2 = toVersion(_tmp1); if (_tmp2 !== void 0) { - let _tmp3: (_val) | undefined; + let _tmp3: (_.Value<_embedded>) | undefined; if ((_tmp3 = v[0].get($embeddedType)) !== void 0) { let _tmp4: (EmbeddedTypeName) | undefined; _tmp4 = toEmbeddedTypeName(_tmp3); if (_tmp4 !== void 0) { - let _tmp5: (_val) | undefined; + let _tmp5: (_.Value<_embedded>) | undefined; if ((_tmp5 = v[0].get($definitions)) !== void 0) { - let _tmp6: (Definitions) | undefined; + let _tmp6: (Definitions<_embedded>) | undefined; _tmp6 = toDefinitions(_tmp5); if (_tmp6 !== void 0) {result = {"version": _tmp2, "embeddedType": _tmp4, "definitions": _tmp6};}; }; @@ -317,28 +337,28 @@ export function toSchema(v: _val): undefined | Schema { return result; } -export function fromSchema(_v: Schema): _val { +export function fromSchema<_embedded = _.GenericEmbedded>(_v: Schema<_embedded>): _.Value<_embedded> { return _.Record( $schema, [ new _.Dictionary<_embedded>( [ - [$version, fromVersion(_v["version"])], - [$embeddedType, fromEmbeddedTypeName(_v["embeddedType"])], - [$definitions, fromDefinitions(_v["definitions"])] + [$version, fromVersion<_embedded>(_v["version"])], + [$embeddedType, fromEmbeddedTypeName<_embedded>(_v["embeddedType"])], + [$definitions, fromDefinitions<_embedded>(_v["definitions"])] ] ) ] ); } -export function asVersion(v: _val): Version { +export function asVersion<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): Version { let result = toVersion(v); if (result === void 0) throw new TypeError(`Invalid Version: ${_.stringify(v)}`); return result; } -export function toVersion(v: _val): undefined | Version { +export function toVersion<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): undefined | Version { let _tmp0: (null) | undefined; let result: undefined | Version; _tmp0 = _.is(v, $1) ? null : void 0; @@ -346,15 +366,15 @@ export function toVersion(v: _val): undefined | Version { return result; } -export function fromVersion(_v: Version): _val {return $1;} +export function fromVersion<_embedded = _.GenericEmbedded>(_v: Version): _.Value<_embedded> {return $1;} -export function asEmbeddedTypeName(v: _val): EmbeddedTypeName { +export function asEmbeddedTypeName<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): EmbeddedTypeName { let result = toEmbeddedTypeName(v); if (result === void 0) throw new TypeError(`Invalid EmbeddedTypeName: ${_.stringify(v)}`); return result; } -export function toEmbeddedTypeName(v: _val): undefined | EmbeddedTypeName { +export function toEmbeddedTypeName<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): undefined | EmbeddedTypeName { let _tmp0: (Ref) | undefined; let result: undefined | EmbeddedTypeName; _tmp0 = toRef(v); @@ -367,19 +387,22 @@ export function toEmbeddedTypeName(v: _val): undefined | EmbeddedTypeName { return result; } -export function fromEmbeddedTypeName(_v: EmbeddedTypeName): _val { - switch (_v._variant) {case "Ref": {return fromRef(_v.value);}; case "false": {return __lit6;};}; +export function fromEmbeddedTypeName<_embedded = _.GenericEmbedded>(_v: EmbeddedTypeName): _.Value<_embedded> { + switch (_v._variant) { + case "Ref": {return fromRef<_embedded>(_v.value);}; + case "false": {return __lit6;}; + }; } -export function asDefinitions(v: _val): Definitions { +export function asDefinitions<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): Definitions<_embedded> { let result = toDefinitions(v); if (result === void 0) throw new TypeError(`Invalid Definitions: ${_.stringify(v)}`); return result; } -export function toDefinitions(v: _val): undefined | Definitions { - let _tmp0: (_.KeyedDictionary) | undefined; - let result: undefined | Definitions; +export function toDefinitions<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): undefined | Definitions<_embedded> { + let _tmp0: (_.KeyedDictionary, _embedded>) | undefined; + let result: undefined | Definitions<_embedded>; _tmp0 = void 0; if (_.Dictionary.isDictionary<_embedded>(v)) { _tmp0 = new _.KeyedDictionary(); @@ -387,7 +410,7 @@ export function toDefinitions(v: _val): undefined | Definitions { let _tmp3: (symbol) | undefined; _tmp3 = typeof _tmp2 === 'symbol' ? _tmp2 : void 0; if (_tmp3 !== void 0) { - let _tmp4: (Definition) | undefined; + let _tmp4: (Definition<_embedded>) | undefined; _tmp4 = toDefinition(_tmp1); if (_tmp4 !== void 0) {_tmp0.set(_tmp3, _tmp4); continue;}; }; @@ -399,35 +422,35 @@ export function toDefinitions(v: _val): undefined | Definitions { return result; } -export function fromDefinitions(_v: Definitions): _val { - return new _.Dictionary<_embedded>(_.Array.from(_v.entries()).map(([k, v]) => [k, fromDefinition(v)])); +export function fromDefinitions<_embedded = _.GenericEmbedded>(_v: Definitions<_embedded>): _.Value<_embedded> { + return new _.Dictionary<_embedded>(_.Array.from(_v.entries()).map(([k, v]) => [k, fromDefinition<_embedded>(v)])); } -export function asDefinition(v: _val): Definition { +export function asDefinition<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): Definition<_embedded> { let result = toDefinition(v); if (result === void 0) throw new TypeError(`Invalid Definition: ${_.stringify(v)}`); return result; } -export function toDefinition(v: _val): undefined | Definition { - let result: undefined | Definition; - if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) { +export function toDefinition<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): undefined | Definition<_embedded> { + let result: undefined | Definition<_embedded>; + if (_.Record.isRecord<_.Value<_embedded>, _.Tuple<_.Value<_embedded>>, _embedded>(v)) { let _tmp0: (null) | undefined; _tmp0 = _.is(v.label, $or) ? null : void 0; if (_tmp0 !== void 0) { if (_.Array.isArray(v[0]) && v[0].length >= 2) { - let _tmp1: (NamedAlternative) | undefined; + let _tmp1: (NamedAlternative<_embedded>) | undefined; _tmp1 = toNamedAlternative(v[0][0]); if (_tmp1 !== void 0) { - let _tmp2: (NamedAlternative) | undefined; + let _tmp2: (NamedAlternative<_embedded>) | undefined; _tmp2 = toNamedAlternative(v[0][1]); if (_tmp2 !== void 0) { - let _tmp3: (Array<_val>) | undefined; - let _tmp4: (Array) | undefined; + let _tmp3: (Array<_.Value<_embedded>>) | undefined; + let _tmp4: (Array>) | undefined; _tmp3 = v[0].slice(2); _tmp4 = []; for (const _tmp5 of _tmp3) { - let _tmp6: (NamedAlternative) | undefined; + let _tmp6: (NamedAlternative<_embedded>) | undefined; _tmp6 = toNamedAlternative(_tmp5); if (_tmp6 !== void 0) {_tmp4.push(_tmp6); continue;}; _tmp4 = void 0; @@ -442,23 +465,23 @@ export function toDefinition(v: _val): undefined | Definition { }; }; if (result === void 0) { - if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) { + if (_.Record.isRecord<_.Value<_embedded>, _.Tuple<_.Value<_embedded>>, _embedded>(v)) { let _tmp7: (null) | undefined; _tmp7 = _.is(v.label, $and) ? null : void 0; if (_tmp7 !== void 0) { if (_.Array.isArray(v[0]) && v[0].length >= 2) { - let _tmp8: (NamedPattern) | undefined; + let _tmp8: (NamedPattern<_embedded>) | undefined; _tmp8 = toNamedPattern(v[0][0]); if (_tmp8 !== void 0) { - let _tmp9: (NamedPattern) | undefined; + let _tmp9: (NamedPattern<_embedded>) | undefined; _tmp9 = toNamedPattern(v[0][1]); if (_tmp9 !== void 0) { - let _tmp10: (Array<_val>) | undefined; - let _tmp11: (Array) | undefined; + let _tmp10: (Array<_.Value<_embedded>>) | undefined; + let _tmp11: (Array>) | undefined; _tmp10 = v[0].slice(2); _tmp11 = []; for (const _tmp12 of _tmp10) { - let _tmp13: (NamedPattern) | undefined; + let _tmp13: (NamedPattern<_embedded>) | undefined; _tmp13 = toNamedPattern(_tmp12); if (_tmp13 !== void 0) {_tmp11.push(_tmp13); continue;}; _tmp11 = void 0; @@ -473,7 +496,7 @@ export function toDefinition(v: _val): undefined | Definition { }; }; if (result === void 0) { - let _tmp14: (Pattern) | undefined; + let _tmp14: (Pattern<_embedded>) | undefined; _tmp14 = toPattern(v); if (_tmp14 !== void 0) {result = {"_variant": "Pattern", "value": _tmp14};}; }; @@ -481,16 +504,16 @@ export function toDefinition(v: _val): undefined | Definition { return result; } -export function fromDefinition(_v: Definition): _val { +export function fromDefinition<_embedded = _.GenericEmbedded>(_v: Definition<_embedded>): _.Value<_embedded> { switch (_v._variant) { case "or": { return _.Record( $or, [ [ - fromNamedAlternative(_v["pattern0"]), - fromNamedAlternative(_v["pattern1"]), - ... _v["patternN"].map(v => fromNamedAlternative(v)) + fromNamedAlternative<_embedded>(_v["pattern0"]), + fromNamedAlternative<_embedded>(_v["pattern1"]), + ... _v["patternN"].map(v => fromNamedAlternative<_embedded>(v)) ] ] ); @@ -500,56 +523,56 @@ export function fromDefinition(_v: Definition): _val { $and, [ [ - fromNamedPattern(_v["pattern0"]), - fromNamedPattern(_v["pattern1"]), - ... _v["patternN"].map(v => fromNamedPattern(v)) + fromNamedPattern<_embedded>(_v["pattern0"]), + fromNamedPattern<_embedded>(_v["pattern1"]), + ... _v["patternN"].map(v => fromNamedPattern<_embedded>(v)) ] ] ); }; - case "Pattern": {return fromPattern(_v.value);}; + case "Pattern": {return fromPattern<_embedded>(_v.value);}; }; } -export function asPattern(v: _val): Pattern { +export function asPattern<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): Pattern<_embedded> { let result = toPattern(v); if (result === void 0) throw new TypeError(`Invalid Pattern: ${_.stringify(v)}`); return result; } -export function toPattern(v: _val): undefined | Pattern { - let _tmp0: (SimplePattern) | undefined; - let result: undefined | Pattern; +export function toPattern<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): undefined | Pattern<_embedded> { + let _tmp0: (SimplePattern<_embedded>) | undefined; + let result: undefined | Pattern<_embedded>; _tmp0 = toSimplePattern(v); if (_tmp0 !== void 0) {result = {"_variant": "SimplePattern", "value": _tmp0};}; if (result === void 0) { - let _tmp1: (CompoundPattern) | undefined; + let _tmp1: (CompoundPattern<_embedded>) | undefined; _tmp1 = toCompoundPattern(v); if (_tmp1 !== void 0) {result = {"_variant": "CompoundPattern", "value": _tmp1};}; }; return result; } -export function fromPattern(_v: Pattern): _val { +export function fromPattern<_embedded = _.GenericEmbedded>(_v: Pattern<_embedded>): _.Value<_embedded> { switch (_v._variant) { - case "SimplePattern": {return fromSimplePattern(_v.value);}; - case "CompoundPattern": {return fromCompoundPattern(_v.value);}; + case "SimplePattern": {return fromSimplePattern<_embedded>(_v.value);}; + case "CompoundPattern": {return fromCompoundPattern<_embedded>(_v.value);}; }; } -export function asSimplePattern(v: _val): SimplePattern { +export function asSimplePattern<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): SimplePattern<_embedded> { let result = toSimplePattern(v); if (result === void 0) throw new TypeError(`Invalid SimplePattern: ${_.stringify(v)}`); return result; } -export function toSimplePattern(v: _val): undefined | SimplePattern { +export function toSimplePattern<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): undefined | SimplePattern<_embedded> { let _tmp0: (null) | undefined; - let result: undefined | SimplePattern; + let result: undefined | SimplePattern<_embedded>; _tmp0 = _.is(v, $any) ? null : void 0; if (_tmp0 !== void 0) {result = {"_variant": "any"};}; if (result === void 0) { - if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) { + if (_.Record.isRecord<_.Value<_embedded>, _.Tuple<_.Value<_embedded>>, _embedded>(v)) { let _tmp1: (null) | undefined; _tmp1 = _.is(v.label, $atom) ? null : void 0; if (_tmp1 !== void 0) { @@ -559,54 +582,54 @@ export function toSimplePattern(v: _val): undefined | SimplePattern { }; }; if (result === void 0) { - if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) { + if (_.Record.isRecord<_.Value<_embedded>, _.Tuple<_.Value<_embedded>>, _embedded>(v)) { let _tmp3: (null) | undefined; _tmp3 = _.is(v.label, $embedded) ? null : void 0; if (_tmp3 !== void 0) { - let _tmp4: (SimplePattern) | undefined; + let _tmp4: (SimplePattern<_embedded>) | undefined; _tmp4 = toSimplePattern(v[0]); if (_tmp4 !== void 0) {result = {"_variant": "embedded", "interface": _tmp4};}; }; }; if (result === void 0) { - if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) { + if (_.Record.isRecord<_.Value<_embedded>, _.Tuple<_.Value<_embedded>>, _embedded>(v)) { let _tmp5: (null) | undefined; _tmp5 = _.is(v.label, $lit) ? null : void 0; if (_tmp5 !== void 0) { - let _tmp6: (_val) | undefined; + let _tmp6: (_.Value<_embedded>) | undefined; _tmp6 = v[0]; if (_tmp6 !== void 0) {result = {"_variant": "lit", "value": _tmp6};}; }; }; if (result === void 0) { - if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) { + if (_.Record.isRecord<_.Value<_embedded>, _.Tuple<_.Value<_embedded>>, _embedded>(v)) { let _tmp7: (null) | undefined; _tmp7 = _.is(v.label, $seqof) ? null : void 0; if (_tmp7 !== void 0) { - let _tmp8: (SimplePattern) | undefined; + let _tmp8: (SimplePattern<_embedded>) | undefined; _tmp8 = toSimplePattern(v[0]); if (_tmp8 !== void 0) {result = {"_variant": "seqof", "pattern": _tmp8};}; }; }; if (result === void 0) { - if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) { + if (_.Record.isRecord<_.Value<_embedded>, _.Tuple<_.Value<_embedded>>, _embedded>(v)) { let _tmp9: (null) | undefined; _tmp9 = _.is(v.label, $setof) ? null : void 0; if (_tmp9 !== void 0) { - let _tmp10: (SimplePattern) | undefined; + let _tmp10: (SimplePattern<_embedded>) | undefined; _tmp10 = toSimplePattern(v[0]); if (_tmp10 !== void 0) {result = {"_variant": "setof", "pattern": _tmp10};}; }; }; if (result === void 0) { - if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) { + if (_.Record.isRecord<_.Value<_embedded>, _.Tuple<_.Value<_embedded>>, _embedded>(v)) { let _tmp11: (null) | undefined; _tmp11 = _.is(v.label, $dictof) ? null : void 0; if (_tmp11 !== void 0) { - let _tmp12: (SimplePattern) | undefined; + let _tmp12: (SimplePattern<_embedded>) | undefined; _tmp12 = toSimplePattern(v[0]); if (_tmp12 !== void 0) { - let _tmp13: (SimplePattern) | undefined; + let _tmp13: (SimplePattern<_embedded>) | undefined; _tmp13 = toSimplePattern(v[1]); if (_tmp13 !== void 0) {result = {"_variant": "dictof", "key": _tmp12, "value": _tmp13};}; }; @@ -626,53 +649,59 @@ export function toSimplePattern(v: _val): undefined | SimplePattern { return result; } -export function fromSimplePattern(_v: SimplePattern): _val { +export function fromSimplePattern<_embedded = _.GenericEmbedded>(_v: SimplePattern<_embedded>): _.Value<_embedded> { switch (_v._variant) { case "any": {return $any;}; - case "atom": {return _.Record($atom, [fromAtomKind(_v["atomKind"])]);}; - case "embedded": {return _.Record($embedded, [fromSimplePattern(_v["interface"])]);}; + case "atom": {return _.Record($atom, [fromAtomKind<_embedded>(_v["atomKind"])]);}; + case "embedded": {return _.Record($embedded, [fromSimplePattern<_embedded>(_v["interface"])]);}; case "lit": {return _.Record($lit, [_v["value"]]);}; - case "seqof": {return _.Record($seqof, [fromSimplePattern(_v["pattern"])]);}; - case "setof": {return _.Record($setof, [fromSimplePattern(_v["pattern"])]);}; + case "seqof": {return _.Record($seqof, [fromSimplePattern<_embedded>(_v["pattern"])]);}; + case "setof": {return _.Record($setof, [fromSimplePattern<_embedded>(_v["pattern"])]);}; case "dictof": { - return _.Record($dictof, [fromSimplePattern(_v["key"]), fromSimplePattern(_v["value"])]); + return _.Record( + $dictof, + [ + fromSimplePattern<_embedded>(_v["key"]), + fromSimplePattern<_embedded>(_v["value"]) + ] + ); }; - case "Ref": {return fromRef(_v.value);}; + case "Ref": {return fromRef<_embedded>(_v.value);}; }; } -export function asCompoundPattern(v: _val): CompoundPattern { +export function asCompoundPattern<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): CompoundPattern<_embedded> { let result = toCompoundPattern(v); if (result === void 0) throw new TypeError(`Invalid CompoundPattern: ${_.stringify(v)}`); return result; } -export function toCompoundPattern(v: _val): undefined | CompoundPattern { - let result: undefined | CompoundPattern; - if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) { +export function toCompoundPattern<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): undefined | CompoundPattern<_embedded> { + let result: undefined | CompoundPattern<_embedded>; + if (_.Record.isRecord<_.Value<_embedded>, _.Tuple<_.Value<_embedded>>, _embedded>(v)) { let _tmp0: (null) | undefined; _tmp0 = _.is(v.label, $rec) ? null : void 0; if (_tmp0 !== void 0) { - let _tmp1: (NamedPattern) | undefined; + let _tmp1: (NamedPattern<_embedded>) | undefined; _tmp1 = toNamedPattern(v[0]); if (_tmp1 !== void 0) { - let _tmp2: (NamedPattern) | undefined; + let _tmp2: (NamedPattern<_embedded>) | undefined; _tmp2 = toNamedPattern(v[1]); if (_tmp2 !== void 0) {result = {"_variant": "rec", "label": _tmp1, "fields": _tmp2};}; }; }; }; if (result === void 0) { - if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) { + if (_.Record.isRecord<_.Value<_embedded>, _.Tuple<_.Value<_embedded>>, _embedded>(v)) { let _tmp3: (null) | undefined; _tmp3 = _.is(v.label, $tuple) ? null : void 0; if (_tmp3 !== void 0) { - let _tmp4: (Array) | undefined; + let _tmp4: (Array>) | undefined; _tmp4 = void 0; if (_.Array.isArray(v[0])) { _tmp4 = []; for (const _tmp5 of v[0]) { - let _tmp6: (NamedPattern) | undefined; + let _tmp6: (NamedPattern<_embedded>) | undefined; _tmp6 = toNamedPattern(_tmp5); if (_tmp6 !== void 0) {_tmp4.push(_tmp6); continue;}; _tmp4 = void 0; @@ -683,16 +712,16 @@ export function toCompoundPattern(v: _val): undefined | CompoundPattern { }; }; if (result === void 0) { - if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) { + if (_.Record.isRecord<_.Value<_embedded>, _.Tuple<_.Value<_embedded>>, _embedded>(v)) { let _tmp7: (null) | undefined; _tmp7 = _.is(v.label, $tuplePrefix) ? null : void 0; if (_tmp7 !== void 0) { - let _tmp8: (Array) | undefined; + let _tmp8: (Array>) | undefined; _tmp8 = void 0; if (_.Array.isArray(v[0])) { _tmp8 = []; for (const _tmp9 of v[0]) { - let _tmp10: (NamedPattern) | undefined; + let _tmp10: (NamedPattern<_embedded>) | undefined; _tmp10 = toNamedPattern(_tmp9); if (_tmp10 !== void 0) {_tmp8.push(_tmp10); continue;}; _tmp8 = void 0; @@ -700,18 +729,18 @@ export function toCompoundPattern(v: _val): undefined | CompoundPattern { }; }; if (_tmp8 !== void 0) { - let _tmp11: (NamedSimplePattern) | undefined; + let _tmp11: (NamedSimplePattern<_embedded>) | undefined; _tmp11 = toNamedSimplePattern(v[1]); if (_tmp11 !== void 0) {result = {"_variant": "tuplePrefix", "fixed": _tmp8, "variable": _tmp11};}; }; }; }; if (result === void 0) { - if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) { + if (_.Record.isRecord<_.Value<_embedded>, _.Tuple<_.Value<_embedded>>, _embedded>(v)) { let _tmp12: (null) | undefined; _tmp12 = _.is(v.label, $dict) ? null : void 0; if (_tmp12 !== void 0) { - let _tmp13: (DictionaryEntries) | undefined; + let _tmp13: (DictionaryEntries<_embedded>) | undefined; _tmp13 = toDictionaryEntries(v[0]); if (_tmp13 !== void 0) {result = {"_variant": "dict", "entries": _tmp13};}; }; @@ -722,42 +751,50 @@ export function toCompoundPattern(v: _val): undefined | CompoundPattern { return result; } -export function fromCompoundPattern(_v: CompoundPattern): _val { +export function fromCompoundPattern<_embedded = _.GenericEmbedded>(_v: CompoundPattern<_embedded>): _.Value<_embedded> { switch (_v._variant) { case "rec": { - return _.Record($rec, [fromNamedPattern(_v["label"]), fromNamedPattern(_v["fields"])]); + return _.Record( + $rec, + [ + fromNamedPattern<_embedded>(_v["label"]), + fromNamedPattern<_embedded>(_v["fields"]) + ] + ); + }; + case "tuple": { + return _.Record($tuple, [_v["patterns"].map(v => fromNamedPattern<_embedded>(v))]); }; - case "tuple": {return _.Record($tuple, [_v["patterns"].map(v => fromNamedPattern(v))]);}; case "tuplePrefix": { return _.Record( $tuplePrefix, [ - _v["fixed"].map(v => fromNamedPattern(v)), - fromNamedSimplePattern(_v["variable"]) + _v["fixed"].map(v => fromNamedPattern<_embedded>(v)), + fromNamedSimplePattern<_embedded>(_v["variable"]) ] ); }; - case "dict": {return _.Record($dict, [fromDictionaryEntries(_v["entries"])]);}; + case "dict": {return _.Record($dict, [fromDictionaryEntries<_embedded>(_v["entries"])]);}; }; } -export function asDictionaryEntries(v: _val): DictionaryEntries { +export function asDictionaryEntries<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): DictionaryEntries<_embedded> { let result = toDictionaryEntries(v); if (result === void 0) throw new TypeError(`Invalid DictionaryEntries: ${_.stringify(v)}`); return result; } -export function toDictionaryEntries(v: _val): undefined | DictionaryEntries { - let _tmp0: (_.KeyedDictionary<_val, NamedSimplePattern, _embedded>) | undefined; - let result: undefined | DictionaryEntries; +export function toDictionaryEntries<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): undefined | DictionaryEntries<_embedded> { + let _tmp0: (_.KeyedDictionary<_.Value<_embedded>, NamedSimplePattern<_embedded>, _embedded>) | undefined; + let result: undefined | DictionaryEntries<_embedded>; _tmp0 = void 0; if (_.Dictionary.isDictionary<_embedded>(v)) { _tmp0 = new _.KeyedDictionary(); for (const [_tmp2, _tmp1] of v) { - let _tmp3: (_val) | undefined; + let _tmp3: (_.Value<_embedded>) | undefined; _tmp3 = _tmp2; if (_tmp3 !== void 0) { - let _tmp4: (NamedSimplePattern) | undefined; + let _tmp4: (NamedSimplePattern<_embedded>) | undefined; _tmp4 = toNamedSimplePattern(_tmp1); if (_tmp4 !== void 0) {_tmp0.set(_tmp3, _tmp4); continue;}; }; @@ -769,17 +806,19 @@ export function toDictionaryEntries(v: _val): undefined | DictionaryEntries { return result; } -export function fromDictionaryEntries(_v: DictionaryEntries): _val { - return new _.Dictionary<_embedded>(_.Array.from(_v.entries()).map(([k, v]) => [k, fromNamedSimplePattern(v)])); +export function fromDictionaryEntries<_embedded = _.GenericEmbedded>(_v: DictionaryEntries<_embedded>): _.Value<_embedded> { + return new _.Dictionary<_embedded>( + _.Array.from(_v.entries()).map(([k, v]) => [k, fromNamedSimplePattern<_embedded>(v)]) + ); } -export function asAtomKind(v: _val): AtomKind { +export function asAtomKind<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): AtomKind { let result = toAtomKind(v); if (result === void 0) throw new TypeError(`Invalid AtomKind: ${_.stringify(v)}`); return result; } -export function toAtomKind(v: _val): undefined | AtomKind { +export function toAtomKind<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): undefined | AtomKind { let _tmp0: (null) | undefined; let result: undefined | AtomKind; _tmp0 = _.is(v, $Boolean) ? null : void 0; @@ -817,7 +856,7 @@ export function toAtomKind(v: _val): undefined | AtomKind { return result; } -export function fromAtomKind(_v: AtomKind): _val { +export function fromAtomKind<_embedded = _.GenericEmbedded>(_v: AtomKind): _.Value<_embedded> { switch (_v._variant) { case "Boolean": {return $Boolean;}; case "Float": {return $Float;}; @@ -829,19 +868,19 @@ export function fromAtomKind(_v: AtomKind): _val { }; } -export function asNamedAlternative(v: _val): NamedAlternative { +export function asNamedAlternative<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): NamedAlternative<_embedded> { let result = toNamedAlternative(v); if (result === void 0) throw new TypeError(`Invalid NamedAlternative: ${_.stringify(v)}`); return result; } -export function toNamedAlternative(v: _val): undefined | NamedAlternative { - let result: undefined | NamedAlternative; +export function toNamedAlternative<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): undefined | NamedAlternative<_embedded> { + let result: undefined | NamedAlternative<_embedded>; if (_.Array.isArray(v) && v.length === 2) { let _tmp0: (string) | undefined; _tmp0 = typeof v[0] === 'string' ? v[0] : void 0; if (_tmp0 !== void 0) { - let _tmp1: (Pattern) | undefined; + let _tmp1: (Pattern<_embedded>) | undefined; _tmp1 = toPattern(v[1]); if (_tmp1 !== void 0) {result = {"variantLabel": _tmp0, "pattern": _tmp1};}; }; @@ -849,76 +888,76 @@ export function toNamedAlternative(v: _val): undefined | NamedAlternative { return result; } -export function fromNamedAlternative(_v: NamedAlternative): _val {return [_v["variantLabel"], fromPattern(_v["pattern"])];} +export function fromNamedAlternative<_embedded = _.GenericEmbedded>(_v: NamedAlternative<_embedded>): _.Value<_embedded> {return [_v["variantLabel"], fromPattern<_embedded>(_v["pattern"])];} -export function asNamedSimplePattern(v: _val): NamedSimplePattern { +export function asNamedSimplePattern<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): NamedSimplePattern<_embedded> { let result = toNamedSimplePattern(v); if (result === void 0) throw new TypeError(`Invalid NamedSimplePattern: ${_.stringify(v)}`); return result; } -export function toNamedSimplePattern(v: _val): undefined | NamedSimplePattern { - let _tmp0: (Binding) | undefined; - let result: undefined | NamedSimplePattern; +export function toNamedSimplePattern<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): undefined | NamedSimplePattern<_embedded> { + let _tmp0: (Binding<_embedded>) | undefined; + let result: undefined | NamedSimplePattern<_embedded>; _tmp0 = toBinding(v); if (_tmp0 !== void 0) {result = {"_variant": "named", "value": _tmp0};}; if (result === void 0) { - let _tmp1: (SimplePattern) | undefined; + let _tmp1: (SimplePattern<_embedded>) | undefined; _tmp1 = toSimplePattern(v); if (_tmp1 !== void 0) {result = {"_variant": "anonymous", "value": _tmp1};}; }; return result; } -export function fromNamedSimplePattern(_v: NamedSimplePattern): _val { +export function fromNamedSimplePattern<_embedded = _.GenericEmbedded>(_v: NamedSimplePattern<_embedded>): _.Value<_embedded> { switch (_v._variant) { - case "named": {return fromBinding(_v.value);}; - case "anonymous": {return fromSimplePattern(_v.value);}; + case "named": {return fromBinding<_embedded>(_v.value);}; + case "anonymous": {return fromSimplePattern<_embedded>(_v.value);}; }; } -export function asNamedPattern(v: _val): NamedPattern { +export function asNamedPattern<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): NamedPattern<_embedded> { let result = toNamedPattern(v); if (result === void 0) throw new TypeError(`Invalid NamedPattern: ${_.stringify(v)}`); return result; } -export function toNamedPattern(v: _val): undefined | NamedPattern { - let _tmp0: (Binding) | undefined; - let result: undefined | NamedPattern; +export function toNamedPattern<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): undefined | NamedPattern<_embedded> { + let _tmp0: (Binding<_embedded>) | undefined; + let result: undefined | NamedPattern<_embedded>; _tmp0 = toBinding(v); if (_tmp0 !== void 0) {result = {"_variant": "named", "value": _tmp0};}; if (result === void 0) { - let _tmp1: (Pattern) | undefined; + let _tmp1: (Pattern<_embedded>) | undefined; _tmp1 = toPattern(v); if (_tmp1 !== void 0) {result = {"_variant": "anonymous", "value": _tmp1};}; }; return result; } -export function fromNamedPattern(_v: NamedPattern): _val { +export function fromNamedPattern<_embedded = _.GenericEmbedded>(_v: NamedPattern<_embedded>): _.Value<_embedded> { switch (_v._variant) { - case "named": {return fromBinding(_v.value);}; - case "anonymous": {return fromPattern(_v.value);}; + case "named": {return fromBinding<_embedded>(_v.value);}; + case "anonymous": {return fromPattern<_embedded>(_v.value);}; }; } -export function asBinding(v: _val): Binding { +export function asBinding<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): Binding<_embedded> { let result = toBinding(v); if (result === void 0) throw new TypeError(`Invalid Binding: ${_.stringify(v)}`); return result; } -export function toBinding(v: _val): undefined | Binding { - let result: undefined | Binding; - if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) { +export function toBinding<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): undefined | Binding<_embedded> { + let result: undefined | Binding<_embedded>; + if (_.Record.isRecord<_.Value<_embedded>, _.Tuple<_.Value<_embedded>>, _embedded>(v)) { let _tmp0: (null) | undefined; _tmp0 = _.is(v.label, $named) ? null : void 0; if (_tmp0 !== void 0) { let _tmp1: (symbol) | undefined; _tmp1 = typeof v[0] === 'symbol' ? v[0] : void 0; if (_tmp1 !== void 0) { - let _tmp2: (SimplePattern) | undefined; + let _tmp2: (SimplePattern<_embedded>) | undefined; _tmp2 = toSimplePattern(v[1]); if (_tmp2 !== void 0) {result = {"name": _tmp1, "pattern": _tmp2};}; }; @@ -927,17 +966,19 @@ export function toBinding(v: _val): undefined | Binding { return result; } -export function fromBinding(_v: Binding): _val {return _.Record($named, [_v["name"], fromSimplePattern(_v["pattern"])]);} +export function fromBinding<_embedded = _.GenericEmbedded>(_v: Binding<_embedded>): _.Value<_embedded> { + return _.Record($named, [_v["name"], fromSimplePattern<_embedded>(_v["pattern"])]); +} -export function asRef(v: _val): Ref { +export function asRef<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): Ref { let result = toRef(v); if (result === void 0) throw new TypeError(`Invalid Ref: ${_.stringify(v)}`); return result; } -export function toRef(v: _val): undefined | Ref { +export function toRef<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): undefined | Ref { let result: undefined | Ref; - if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) { + if (_.Record.isRecord<_.Value<_embedded>, _.Tuple<_.Value<_embedded>>, _embedded>(v)) { let _tmp0: (null) | undefined; _tmp0 = _.is(v.label, $ref) ? null : void 0; if (_tmp0 !== void 0) { @@ -953,15 +994,15 @@ export function toRef(v: _val): undefined | Ref { return result; } -export function fromRef(_v: Ref): _val {return _.Record($ref, [fromModulePath(_v["module"]), _v["name"]]);} +export function fromRef<_embedded = _.GenericEmbedded>(_v: Ref): _.Value<_embedded> {return _.Record($ref, [fromModulePath<_embedded>(_v["module"]), _v["name"]]);} -export function asModulePath(v: _val): ModulePath { +export function asModulePath<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): ModulePath { let result = toModulePath(v); if (result === void 0) throw new TypeError(`Invalid ModulePath: ${_.stringify(v)}`); return result; } -export function toModulePath(v: _val): undefined | ModulePath { +export function toModulePath<_embedded = _.GenericEmbedded>(v: _.Value<_embedded>): undefined | ModulePath { let _tmp0: (Array) | undefined; let result: undefined | ModulePath; _tmp0 = void 0; @@ -979,5 +1020,5 @@ export function toModulePath(v: _val): undefined | ModulePath { return result; } -export function fromModulePath(_v: ModulePath): _val {return _v.map(v => v);} +export function fromModulePath<_embedded = _.GenericEmbedded>(_v: ModulePath): _.Value<_embedded> {return _v.map(v => v);} diff --git a/implementations/javascript/packages/schema/src/meta.ts b/implementations/javascript/packages/schema/src/meta.ts index 250b31c..aaa4c6a 100644 --- a/implementations/javascript/packages/schema/src/meta.ts +++ b/implementations/javascript/packages/schema/src/meta.ts @@ -1,11 +1,11 @@ -import { is, Position } from '@preserves/core'; +import { GenericEmbedded, Value } from '@preserves/core'; import * as M from './gen/schema'; -import { SchemaSyntaxError } from './error'; import { isJsKeyword } from './compiler/jskw'; export * from './gen/schema'; -export type Input = M._val; +export type Input = Value; +export type InputEmbedded = GenericEmbedded; export function qidLast(s: string): string { const m = s.match(/^(.*\.)?([^.]+)$/); @@ -42,51 +42,18 @@ export const EQUALS = Symbol.for('='); export const INCLUDE = Symbol.for('include'); export const ORSYM = Symbol.for('/'); -export type SchemaEnvEntry = { schemaModulePath: M.ModulePath } & ( - ({ - typescriptModulePath: string | null, // null means it's "this module" in disguise - schema: M.Schema, - }) | ({ - typescriptModulePath: string, - schema: null, - }) -); +export type SchemaEnvEntry = { + schemaModulePath: M.ModulePath, + typescriptModulePath: string, + schema: M.Schema | null, // null means it's an artificial one, not corresponding to an input +}; export type Environment = Array; -function modsymFor(e: SchemaEnvEntry): string { +export function modsymFor(e: SchemaEnvEntry): string { return '_i_' + e.schemaModulePath.map(s => s.description!).join('$'); } -export function lookup(namePos: Position | null, - name: M.Ref, - env: Environment, - kLocal: (p: M.Definition) => R, - kOther: (modId: string, modPath: string, p: M.Definition | null) => R): R -{ - for (const e of env) { - if (is(e.schemaModulePath, name.module) || - (e.typescriptModulePath === null && name.module.length === 0)) - { - if (e.schema === null) { - // It's an artificial module, not from a schema. Assume the identifier is present. - return kOther(modsymFor(e), e.typescriptModulePath, null); - } else { - const p = e.schema.definitions.get(name.name); - if (p !== void 0) { - if (e.typescriptModulePath === null) { - return kLocal(p); - } else { - return kOther(modsymFor(e), e.typescriptModulePath, p); - } - } - } - } - } - - throw new SchemaSyntaxError(`Undefined reference: ${formatRef(name)}`, namePos); -} - export function formatRef(r: M.Ref): string { return [... r.module, r.name].map(s => s.description!).join('.'); } diff --git a/implementations/javascript/packages/schema/src/reader.ts b/implementations/javascript/packages/schema/src/reader.ts index 8996b9d..e77fb88 100644 --- a/implementations/javascript/packages/schema/src/reader.ts +++ b/implementations/javascript/packages/schema/src/reader.ts @@ -70,7 +70,7 @@ export function parseSchema(toplevelTokens: Array, options: SchemaReaderO { let version: M.Version | undefined = void 0; let embeddedType: M.EmbeddedTypeName = M.EmbeddedTypeName.$false(); - let definitions = new KeyedDictionary(); + let definitions = new KeyedDictionary(); function process(toplevelTokens: Array): void { const toplevelClauses = splitBy(peel(toplevelTokens) as Array, M.DOT); @@ -236,9 +236,9 @@ function parsePattern(name: symbol, body0: Array): Pattern { } } } - } else if (Record.isRecord, M._embedded>(item)) { + } else if (Record.isRecord, M.InputEmbedded>(item)) { const label = item.label; - if (Record.isRecord(label)) { + if (Record.isRecord(label)) { if (label.length !== 0) complain(); switch (label.label) { case M.$lit: @@ -252,11 +252,11 @@ function parsePattern(name: symbol, body0: Array): Pattern { } } else if (Array.isArray(item) && item.length === 2 && is(item[1], M.DOTDOTDOT)) { return ks(M.SimplePattern.seqof(walkSimple(item[0]))); - } else if (Set.isSet(item)) { + } else if (Set.isSet(item)) { if (item.size !== 1) complain(); const [vp] = item.entries(); return ks(M.SimplePattern.setof(walkSimple(vp))); - } else if (Dictionary.isDictionary(item) + } else if (Dictionary.isDictionary(item) && item.size === 2 && item.has(M.DOTDOTDOT)) { @@ -278,9 +278,9 @@ function parsePattern(name: symbol, body0: Array): Pattern { const item = peel(item0); function complain(): never { invalidPattern(stringify(name), item, pos); } - if (Record.isRecord, M._embedded>(item)) { + if (Record.isRecord, M.InputEmbedded>(item)) { const label = item.label; - if (Record.isRecord(label)) { + if (Record.isRecord(label)) { if (label.length !== 0) complain(); switch (label.label) { case M.$rec: @@ -308,9 +308,9 @@ function parsePattern(name: symbol, body0: Array): Pattern { }); } else if (Array.isArray(item)) { return M.CompoundPattern.tuple(item.map(maybeNamed)); - } else if (Dictionary.isDictionary(item) && !item.has(M.DOTDOTDOT)) { + } else if (Dictionary.isDictionary(item) && !item.has(M.DOTDOTDOT)) { return M.CompoundPattern.dict( - M.DictionaryEntries(item.mapEntries( + M.DictionaryEntries(item.mapEntries( ([k, vp]) => [ strip(k), _maybeNamed(