Simplify unconverter generation even further
This commit is contained in:
parent
20b676df27
commit
b5b4effeac
|
@ -1,10 +1,7 @@
|
||||||
import { refPosition } from '../reader';
|
import { refPosition } from '../reader';
|
||||||
import * as M from '../meta';
|
import * as M from '../meta';
|
||||||
import { block, brackets, formatItems, Item, parens, seq } from './block';
|
import { block, brackets, Item, parens, seq } from './block';
|
||||||
import { FunctionContext } from "./context";
|
import { FunctionContext } from "./context";
|
||||||
import { FieldType, SimpleType } from '../type';
|
|
||||||
import { typeFor, typeForIntersection } from '../gentype';
|
|
||||||
import { renderType } from "./rendertype";
|
|
||||||
|
|
||||||
export function unconverterForDefinition(
|
export function unconverterForDefinition(
|
||||||
ctx: FunctionContext,
|
ctx: FunctionContext,
|
||||||
|
@ -17,17 +14,16 @@ export function unconverterForDefinition(
|
||||||
... [def.pattern0, def.pattern1, ... def.patternN].map(p =>
|
... [def.pattern0, def.pattern1, ... def.patternN].map(p =>
|
||||||
seq(`case `, JSON.stringify(p.variantLabel), `: `, ctx.block(() => {
|
seq(`case `, JSON.stringify(p.variantLabel), `: `, ctx.block(() => {
|
||||||
const hasValueField = p.pattern._variant === 'SimplePattern';
|
const hasValueField = p.pattern._variant === 'SimplePattern';
|
||||||
return [seq(`return `, unconverterForPattern(
|
return [seq(`return `, unconverterFor(
|
||||||
ctx, p.pattern, hasValueField ? `${src}.value` : src))];
|
ctx, p.pattern, hasValueField ? `${src}.value` : src))];
|
||||||
})))))];
|
})))))];
|
||||||
case 'and': {
|
case 'and': {
|
||||||
const ps = [def.pattern0, def.pattern1, ... def.patternN];
|
const ps = [def.pattern0, def.pattern1, ... def.patternN];
|
||||||
const t = typeForIntersection(ctx.mod.resolver(), ps);
|
|
||||||
const cs = ps.flatMap(p => {
|
const cs = ps.flatMap(p => {
|
||||||
if (p._variant === 'anonymous' && p.value._variant === 'SimplePattern') {
|
if (p._variant === 'anonymous' && p.value._variant === 'SimplePattern') {
|
||||||
return [];
|
return [];
|
||||||
} else {
|
} else {
|
||||||
return [unconverterForNamed(ctx, p, src, t)];
|
return [unconverterForNamed(ctx, p, src)];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return [seq(`return `, (cs.length === 1)
|
return [seq(`return `, (cs.length === 1)
|
||||||
|
@ -35,31 +31,11 @@ export function unconverterForDefinition(
|
||||||
: seq(`_.merge`, parens(`(a, b) => (a === b) ? a : void 0`, ... cs)))];
|
: seq(`_.merge`, parens(`(a, b) => (a === b) ? a : void 0`, ... cs)))];
|
||||||
}
|
}
|
||||||
case 'Pattern':
|
case 'Pattern':
|
||||||
return [seq(`return `, unconverterForPattern(ctx, def.value, `${src}`))];
|
return [seq(`return `, unconverterFor(ctx, def.value, `${src}`))];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function unconverterForPattern(ctx: FunctionContext, a: M.Pattern, src: string): Item
|
function unconverterFor(ctx: FunctionContext, p: M.Pattern, src: string): Item {
|
||||||
{
|
|
||||||
return unconverterFor(ctx, a, src, typeFor(ctx.mod.resolver(), a));
|
|
||||||
}
|
|
||||||
|
|
||||||
function stepSource(
|
|
||||||
src: string,
|
|
||||||
t: SimpleType,
|
|
||||||
key: string): { steppedSrc: string, steppedType: FieldType }
|
|
||||||
{
|
|
||||||
if (t.kind !== 'record' || !t.fields.has(key)) {
|
|
||||||
throw new Error(
|
|
||||||
`Internal error: attempt to step type ${JSON.stringify(t)} with key ${key}`);
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
steppedSrc: `${src}[${JSON.stringify(key)}]`,
|
|
||||||
steppedType: t.fields.get(key)!
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function unconverterFor(ctx: FunctionContext, p: M.Pattern, src: string, t: SimpleType): Item {
|
|
||||||
switch (p._variant) {
|
switch (p._variant) {
|
||||||
case 'SimplePattern':
|
case 'SimplePattern':
|
||||||
return ((p: M.SimplePattern) => {
|
return ((p: M.SimplePattern) => {
|
||||||
|
@ -91,82 +67,77 @@ function unconverterFor(ctx: FunctionContext, p: M.Pattern, src: string, t: Simp
|
||||||
switch (p._variant) {
|
switch (p._variant) {
|
||||||
case 'rec':
|
case 'rec':
|
||||||
return seq(`_.Record`, parens(
|
return seq(`_.Record`, parens(
|
||||||
unconverterForNamed(ctx, p.label, src, t),
|
unconverterForNamed(ctx, p.label, src),
|
||||||
unconverterForNamed(ctx, p.fields, src, t)));
|
unconverterForNamed(ctx, p.fields, src)));
|
||||||
case 'tuple':
|
case 'tuple':
|
||||||
return brackets(... p.patterns.map(pp =>
|
return brackets(... p.patterns.map(pp =>
|
||||||
unconverterForNamed(ctx, pp, src, t)));
|
unconverterForNamed(ctx, pp, src)));
|
||||||
case 'tuple*': {
|
case 'tuple*': {
|
||||||
let varexp: Item;
|
let varexp: Item;
|
||||||
if (p.variable._variant === 'named') {
|
if (p.variable._variant === 'named') {
|
||||||
const { steppedSrc, steppedType } =
|
const steppedSrc = stepSource(src, p.variable.value.name.description!);
|
||||||
stepSource(src, t, p.variable.value.name.description!);
|
|
||||||
if (steppedType.kind !== 'array') {
|
|
||||||
throw new Error(
|
|
||||||
`Internal error: attempt to visit element type of ` +
|
|
||||||
`${formatItems([renderType(steppedType)])} after ` +
|
|
||||||
`stepping by key ${p.variable.value.name.description!}`);
|
|
||||||
}
|
|
||||||
varexp = seq(steppedSrc, `.map`, parens(
|
varexp = seq(steppedSrc, `.map`, parens(
|
||||||
seq(`v => `, unconverterFor(
|
seq(`v => `, unconverterFor(
|
||||||
ctx,
|
ctx,
|
||||||
M.Pattern.SimplePattern(p.variable.value.pattern),
|
M.Pattern.SimplePattern(p.variable.value.pattern),
|
||||||
`v`,
|
`v`))));
|
||||||
steppedType.type))));
|
|
||||||
} else {
|
} else {
|
||||||
if (t.kind !== 'array') throw new Error("Internal error");
|
|
||||||
varexp = seq(src, `.map`, parens(
|
varexp = seq(src, `.map`, parens(
|
||||||
seq(`v => `, unconverterFor(
|
seq(`v => `, unconverterFor(
|
||||||
ctx,
|
ctx,
|
||||||
M.Pattern.SimplePattern(p.variable.value),
|
M.Pattern.SimplePattern(p.variable.value),
|
||||||
`v`,
|
`v`))));
|
||||||
t.type))));
|
|
||||||
}
|
}
|
||||||
if (p.fixed.length === 0) {
|
if (p.fixed.length === 0) {
|
||||||
return varexp;
|
return varexp;
|
||||||
} else {
|
} else {
|
||||||
return brackets(
|
return brackets(
|
||||||
... p.fixed.map(pp => unconverterForNamed(ctx, pp, src, t)),
|
... p.fixed.map(pp => unconverterForNamed(ctx, pp, src)),
|
||||||
seq(`... `, varexp));
|
seq(`... `, varexp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 'setof':
|
case 'setof':
|
||||||
return seq(`new _.Set<_embedded>`, parens(
|
return seq(`new _.Set<_embedded>`, parens(
|
||||||
`_.Array.from(${src}.values()).map(v => `,
|
`_.Array.from(${src}.values()).map(v => `,
|
||||||
unconverterFor(ctx, M.Pattern.SimplePattern(p.pattern), 'v', t),
|
unconverterFor(ctx, M.Pattern.SimplePattern(p.pattern), 'v'),
|
||||||
`)`));
|
`)`));
|
||||||
case 'dictof':
|
case 'dictof':
|
||||||
return seq(`new _.Dictionary<_embedded>`, parens(seq(
|
return seq(`new _.Dictionary<_embedded>`, parens(seq(
|
||||||
`_.Array.from(${src}.entries()).map(([k, v]) => `,
|
`_.Array.from(${src}.entries()).map(([k, v]) => `,
|
||||||
brackets(
|
brackets(
|
||||||
unconverterFor(ctx, M.Pattern.SimplePattern(p.key), 'k', t),
|
unconverterFor(ctx, M.Pattern.SimplePattern(p.key), 'k'),
|
||||||
unconverterFor(ctx, M.Pattern.SimplePattern(p.value), 'v', t)),
|
unconverterFor(ctx, M.Pattern.SimplePattern(p.value), 'v')),
|
||||||
`)`)));
|
`)`)));
|
||||||
case 'dict':
|
case 'dict':
|
||||||
return seq(`new _.Dictionary<_embedded>`, parens(
|
return seq(`new _.Dictionary<_embedded>`, parens(
|
||||||
brackets(... Array.from(p.entries.entries()).map(([k, n]) =>
|
brackets(... Array.from(p.entries.entries()).map(([k, n]) =>
|
||||||
brackets(
|
brackets(
|
||||||
ctx.mod.literal(k),
|
ctx.mod.literal(k),
|
||||||
unconverterForNamedSimple(ctx, M.addNameIfAbsent(n, k), src, t))))));
|
unconverterForNamedSimple(ctx, M.addNameIfAbsent(n, k), src))))));
|
||||||
}
|
}
|
||||||
})(p.value);
|
})(p.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function unconverterForNamed(ctx: FunctionContext, p: M.NamedPattern, src: string, t: SimpleType): Item {
|
function stepSource(src: string, key: string): string
|
||||||
|
{
|
||||||
|
return `${src}[${JSON.stringify(key)}]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function unconverterForNamed(ctx: FunctionContext, p: M.NamedPattern, src: string): Item {
|
||||||
if (p._variant === 'named') {
|
if (p._variant === 'named') {
|
||||||
const { steppedSrc, steppedType } = stepSource(src, t, p.value.name.description!);
|
const steppedSrc = stepSource(src, p.value.name.description!);
|
||||||
return unconverterFor(ctx, M.Pattern.SimplePattern(p.value.pattern), steppedSrc, steppedType);
|
return unconverterFor(ctx, M.Pattern.SimplePattern(p.value.pattern), steppedSrc);
|
||||||
} else {
|
} else {
|
||||||
return unconverterFor(ctx, p.value, src, t);
|
return unconverterFor(ctx, p.value, src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function unconverterForNamedSimple(ctx: FunctionContext, p: M.NamedSimplePattern, src: string, t: SimpleType): Item {
|
function unconverterForNamedSimple(ctx: FunctionContext, p: M.NamedSimplePattern, src: string): Item {
|
||||||
if (p._variant === 'named') {
|
if (p._variant === 'named') {
|
||||||
const { steppedSrc, steppedType } = stepSource(src, t, p.value.name.description!);
|
const steppedSrc = stepSource(src, p.value.name.description!);
|
||||||
return unconverterFor(ctx, M.Pattern.SimplePattern(p.value.pattern), steppedSrc, steppedType);
|
return unconverterFor(ctx, M.Pattern.SimplePattern(p.value.pattern), steppedSrc);
|
||||||
} else {
|
} else {
|
||||||
return unconverterFor(ctx, M.Pattern.SimplePattern(p.value), src, t);
|
return unconverterFor(ctx, M.Pattern.SimplePattern(p.value), src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue