diff --git a/implementations/javascript/packages/schema/src/compiler/type.ts b/implementations/javascript/packages/schema/src/compiler/type.ts index 8e62cd9..dcf8c54 100644 --- a/implementations/javascript/packages/schema/src/compiler/type.ts +++ b/implementations/javascript/packages/schema/src/compiler/type.ts @@ -3,6 +3,24 @@ import * as M from "../meta"; import { anglebrackets, braces, Item, keyvalue, opseq, seq } from "./block"; import { ModuleContext, variantFor, variantInitFor } from "./context"; +export function typeForDefinition(mod: ModuleContext, d: M.Definition): Item { + if (d.label === M.$or) { + return opseq('never', ' | ', ... d[0].map(a => typeForAlternative(mod, a[1], a[0]))); + } else { + return typeForAlternative(mod, d, void 0); + } +} + +function typeForAlternative(mod: ModuleContext, a: M.Alternative, variantName: string | undefined): Item { + if (a.label === M.$and) { + return opseq('_val', ' & ', + ... variantName === void 0 ? [] : [braces(variantFor(variantName))], + ...a[0].map(p => typeFor(mod, M.unname(p)))); + } else { + return typeFor(mod, a, variantName); + } +} + export function typeFor(mod: ModuleContext, p: M.Pattern, variantName?: string): Item { let typeItem: Item; @@ -68,14 +86,6 @@ function typeForSimple(mod: ModuleContext, p: M.SimplePattern): Item { } } -function typeField(mod: ModuleContext, n: M.NamedPattern): Item[] { - return (n.label === M.$named) - ? [keyvalue(n[0].description!, typeForSimple(mod, n[1]))] - : (M.isCompoundPattern(n) - ? typeForCompound(mod, n) - : []); -} - function typeForCompound(mod: ModuleContext, p: M.CompoundPattern): Item[] { switch (p.label) { case M.$rec: @@ -92,40 +102,19 @@ function typeForCompound(mod: ModuleContext, p: M.CompoundPattern): Item[] { } case M.$setof: case M.$dictof: - return []; + throw new Error('Internal error: setof and dictof are handled in typeFor()'); case M.$dict: - return Array.from(p[0]).flatMap(([k, n]) => { - if (n.label === M.$named) { - return typeField(mod, n); - } else { - const s = M.namelike(k); - if (s !== void 0) { - return [keyvalue(s, typeForSimple(mod, n))]; - } else { - return []; - } - } - }); + return Array.from(p[0]).flatMap(([k, n]) => typeField(mod, M.addNameIfAbsent(n, k))); default: ((_p: never) => {})(p); throw new Error("Unreachable"); } } -export function typeForDefinition(mod: ModuleContext, d: M.Definition): Item { - if (d.label === M.$or) { - return opseq('never', ' | ', ... d[0].map(a => typeForAlternative(mod, a[1], a[0]))); - } else { - return typeForAlternative(mod, d, void 0); - } -} - -function typeForAlternative(mod: ModuleContext, a: M.Alternative, variantName: string | undefined): Item { - if (a.label === M.$and) { - return opseq('_val', ' & ', - ... variantName === void 0 ? [] : [braces(variantFor(variantName))], - ...a[0].map(p => typeFor(mod, M.unname(p)))); - } else { - return typeFor(mod, a, variantName); - } +function typeField(mod: ModuleContext, n: M.NamedPattern): Item[] { + return (n.label === M.$named) + ? [keyvalue(n[0].description!, typeForSimple(mod, n[1]))] + : (M.isCompoundPattern(n) + ? typeForCompound(mod, n) + : []); }