Refactor type.ts

This commit is contained in:
Tony Garnock-Jones 2021-03-18 22:51:00 +01:00
parent c8b752a73b
commit 1c07573178
1 changed files with 26 additions and 37 deletions

View File

@ -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)
: []);
}