Redo bijection checking without using gentype
This commit is contained in:
parent
0db223ede8
commit
46d76dfca7
|
@ -1,5 +1,3 @@
|
|||
import { typeFor, typeForIntersection } from './gentype';
|
||||
import { ANY_TYPE, SimpleType } from './type';
|
||||
import * as M from './meta';
|
||||
|
||||
export function checkSchema(schema: M.Schema): (
|
||||
|
@ -14,6 +12,11 @@ export function checkSchema(schema: M.Schema): (
|
|||
}
|
||||
}
|
||||
|
||||
enum ValueAvailability {
|
||||
AVAILABLE,
|
||||
NOT_AVAILABLE,
|
||||
};
|
||||
|
||||
class Checker {
|
||||
problems: Array<string> = [];
|
||||
|
||||
|
@ -40,49 +43,48 @@ class Checker {
|
|||
this.recordProblem(context, `duplicate variant label`);
|
||||
}
|
||||
labels.add(variantLabel);
|
||||
this.checkPattern(new Set(), pattern, context, typeFor(_ref => ANY_TYPE, pattern));
|
||||
this.checkPattern(new Set(), pattern, context, ValueAvailability.AVAILABLE);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'and': {
|
||||
const ps = [def.pattern0, def.pattern1, ... def.patternN];
|
||||
const scope = new Set<string>();
|
||||
ps.forEach((p) => this.checkNamedPattern(
|
||||
scope, p, name.description!, typeForIntersection(_ref => ANY_TYPE, ps)));
|
||||
ps.forEach((p) => this.checkNamedPattern(scope, p, name.description!));
|
||||
break;
|
||||
}
|
||||
case 'Pattern':
|
||||
this.checkPattern(
|
||||
new Set(), def.value, name.description!, typeFor(_ref => ANY_TYPE, def.value));
|
||||
new Set(), def.value, name.description!, ValueAvailability.AVAILABLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
checkNamedPattern(scope: Set<string>, p: M.NamedPattern, context: string, t: SimpleType): void {
|
||||
checkNamedPattern(scope: Set<string>, p: M.NamedPattern, context: string): void
|
||||
{
|
||||
switch (p._variant) {
|
||||
case 'named': {
|
||||
const key = p.value.name.description!;
|
||||
if (t.kind !== 'record' || !t.fields.has(key)) {
|
||||
throw new Error(
|
||||
`Internal error: cannot step ${JSON.stringify(t)} by ${JSON.stringify(key)}`);
|
||||
}
|
||||
this.checkBinding(scope, p.value.name, context);
|
||||
this.checkPattern(scope,
|
||||
M.Pattern.SimplePattern(p.value.pattern),
|
||||
`${JSON.stringify(p.value.name.description!)} of ${context}`,
|
||||
t.fields.get(key)!);
|
||||
ValueAvailability.AVAILABLE);
|
||||
break;
|
||||
}
|
||||
case 'anonymous':
|
||||
this.checkPattern(scope, p.value, context, t);
|
||||
this.checkPattern(scope, p.value, context, ValueAvailability.NOT_AVAILABLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
checkPattern(scope: Set<string>, p: M.Pattern, context: string, t: SimpleType): void {
|
||||
checkPattern(scope: Set<string>,
|
||||
p: M.Pattern,
|
||||
context: string,
|
||||
availability: ValueAvailability): void
|
||||
{
|
||||
switch (p._variant) {
|
||||
case 'SimplePattern':
|
||||
if (p.value._variant !== 'lit' && (t.kind === 'record' || t.kind === 'unit')) {
|
||||
if (p.value._variant !== 'lit' && availability === ValueAvailability.NOT_AVAILABLE) {
|
||||
this.recordProblem(context, 'cannot recover serialization of non-literal pattern');
|
||||
}
|
||||
break;
|
||||
|
@ -90,26 +92,25 @@ class Checker {
|
|||
((p: M.CompoundPattern): void => {
|
||||
switch (p._variant) {
|
||||
case 'rec':
|
||||
this.checkNamedPattern(scope, p.label, `label of ${context}`, t);
|
||||
this.checkNamedPattern(scope, p.fields, `fields of ${context}`, t);
|
||||
this.checkNamedPattern(scope, p.label, `label of ${context}`);
|
||||
this.checkNamedPattern(scope, p.fields, `fields of ${context}`);
|
||||
break;
|
||||
case 'tuple':
|
||||
p.patterns.forEach((pp, i) =>
|
||||
this.checkNamedPattern(scope, pp, `item ${i} of ${context}`, t));
|
||||
this.checkNamedPattern(scope, pp, `item ${i} of ${context}`));
|
||||
break;
|
||||
case 'tuple*':
|
||||
p.fixed.forEach((pp, i) =>
|
||||
this.checkNamedPattern(scope, pp, `item ${i} of ${context}`, t));
|
||||
this.checkNamedPattern(scope, pp, `item ${i} of ${context}`));
|
||||
this.checkNamedPattern(
|
||||
scope, M.promoteNamedSimplePattern(p.variable), `tail of ${context}`, t);
|
||||
scope, M.promoteNamedSimplePattern(p.variable), `tail of ${context}`);
|
||||
break;
|
||||
case 'dict':
|
||||
p.entries.forEach((np, key) =>
|
||||
this.checkNamedPattern(
|
||||
scope,
|
||||
M.promoteNamedSimplePattern(M.addNameIfAbsent(np, key)),
|
||||
`entry ${key.asPreservesText()} in dictionary in ${context}`,
|
||||
t));
|
||||
`entry ${key.asPreservesText()} in dictionary in ${context}`));
|
||||
break;
|
||||
}
|
||||
})(p.value);
|
||||
|
|
Loading…
Reference in New Issue