Repair constructor generation; attach schemas
This commit is contained in:
parent
4c0bd3b9d7
commit
7178fb0d9b
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue