diff --git a/implementations/javascript/packages/schema/src/checker.ts b/implementations/javascript/packages/schema/src/checker.ts index a184fbc..f84f770 100644 --- a/implementations/javascript/packages/schema/src/checker.ts +++ b/implementations/javascript/packages/schema/src/checker.ts @@ -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 = []; @@ -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(); - 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, p: M.NamedPattern, context: string, t: SimpleType): void { + checkNamedPattern(scope: Set, 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, p: M.Pattern, context: string, t: SimpleType): void { + checkPattern(scope: Set, + 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);