Repair constructor generation; attach schemas

This commit is contained in:
Tony Garnock-Jones 2023-12-17 22:29:09 +13:00
parent 4c0bd3b9d7
commit 7178fb0d9b
1 changed files with 44 additions and 18 deletions

View File

@ -1,4 +1,5 @@
import { EncodableDictionary, KeyedDictionary, Dictionary, Value, is, Record, Float, Bytes, isEmbedded, isSequence, Set, Atom, Embedded, merge as plainMerge, Preservable, PreserveWritable, _iterMap, stringify } from '@preserves/core';
import { EncodableDictionary, KeyedDictionary, Dictionary, Value, is, Record, Float, Bytes, isEmbedded, isSequence, Set, Atom, Embedded, merge as plainMerge, Preservable, PreserveWritable, _iterMap, stringify, fromJS } from '@preserves/core';
import { SchemaDefinition } from './reflection';
import * as M from './meta';
import * as H from './host';
@ -15,12 +16,9 @@ export type BindingName = string;
export type Bindings<V> = { [key: BindingName]: Parsed<V> };
export type TopBindings<V> = Bindings<V> & Top<V>;
export type SingleConstructor<V> = (input: any) => Parsed<V>;
export type SingleConstructor<V> = ((input: any) => Parsed<V>) & { schema(): SchemaDefinition };
export type MultipleConstructors<V> = { [key: string]: SingleConstructor<V> };
export type DefinitionConstructors<V> =
| { single: SingleConstructor<V> }
| { multiple: MultipleConstructors<V> }
;
export type DefinitionConstructors<V> = SingleConstructor<V> | MultipleConstructors<V>;
export namespace Bindings {
export function empty<V>(): Bindings<V> {
@ -111,14 +109,18 @@ export class SchemaInterpreter<V> {
}
}
_lookup<R>(modulePath: M.ModulePath, name: symbol, f: (d: M.Definition<V>) => R): R {
_lookup<R>(
modulePath: M.ModulePath,
name: symbol,
f: (d: M.Definition<V>, schema: M.Schema<V>) => R,
): R {
const { resolved, schema } = this._findModule(modulePath);
return this._withModule(resolved, () => {
const definition = schema.definitions.get(name);
if (definition === void 0) {
throw new Error(`No such preserves-schema definition: ${[... modulePath, name].map(s => s.description!).join('.')}`);
}
return f(definition);
return f(definition, schema);
});
}
@ -134,7 +136,20 @@ export class SchemaInterpreter<V> {
modulePath: M.ModulePath,
name: symbol,
): DefinitionConstructors<V> {
return this._lookup(modulePath, name, (definition): DefinitionConstructors<V> => {
return this._lookup(modulePath, name, (definition, schema): DefinitionConstructors<V> => {
function attachSchema(
f: (input: any) => Parsed<V>,
variant?: symbol,
): SingleConstructor<V> {
const g = f as SingleConstructor<V>;
g.schema = () => ({
schema: fromJS(schema),
imports: {}, // TODO
definitionName: name,
variant,
});
return g;
}
const ty = H.definitionType(definition);
if (ty._variant === 'union') {
const multiple: MultipleConstructors<V> = {};
@ -142,27 +157,38 @@ export class SchemaInterpreter<V> {
const _variant = v.label.description!;
switch (v.type._variant) {
case 'Field':
multiple[_variant] = (value: any) =>
this.makeTop(modulePath, name, { _variant, value });
multiple[_variant] = attachSchema(
(value: any) => this.makeTop(modulePath, name, { _variant, value }),
v.label);
break;
case 'Record':
multiple[_variant] = (fields: object) =>
this.makeTop(modulePath, name, { _variant, ... fields });
multiple[_variant] = attachSchema(
(fields: object) => this.makeTop(modulePath, name, { _variant, ... fields }),
v.label);
break;
}
});
return { multiple };
return multiple;
} else {
const flatName = M.formatModulePath([... modulePath, name]);
switch (ty.value._variant) {
case 'Field': {
const tmp = { [flatName]: (value: any) => value };
return { single: tmp[flatName] };
return attachSchema(tmp[flatName]);
}
case 'Record': {
const tmp = { [flatName]: (fields: Bindings<V>) =>
this.makeTop(modulePath, name, fields) };
return { single: tmp[flatName] };
const rec = ty.value.value;
if (rec.fields.length > 1) {
const tmp = { [flatName]: (fields: Bindings<V>) =>
this.makeTop(modulePath, name, fields) };
return attachSchema(tmp[flatName]);
} else {
const tmp = { [flatName]: (field: Parsed<V>) =>
this.makeTop(modulePath, name, {
[M.jsId(rec.fields[0].name.description!)]: field,
}) };
return attachSchema(tmp[flatName]);
}
}
}
}