Much improved refactoring/repair of metaschema
This commit is contained in:
parent
1d6956fa55
commit
2559a4713f
|
@ -110,6 +110,10 @@ export function annotate<T = GenericEmbedded>(v0: Value<T>, ...anns: Value<T>[])
|
|||
return v;
|
||||
}
|
||||
|
||||
export function annotations<T = GenericEmbedded>(v: Value<T>): Array<Value<T>> {
|
||||
return Annotated.isAnnotated<T>(v) ? v.annotations : [];
|
||||
}
|
||||
|
||||
export function position<T = GenericEmbedded>(v: Value<T>): Position | null {
|
||||
return Annotated.isAnnotated<T>(v) ? v.pos : null;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { typeFor, typeForIntersection } from './gentype';
|
||||
import { ANY_TYPE, FieldType, SimpleType } from './type';
|
||||
import { ANY_TYPE, SimpleType } from './type';
|
||||
import * as M from './meta';
|
||||
|
||||
export function checkSchema(schema: M.Schema): M.Schema {
|
||||
|
@ -53,13 +53,19 @@ class Checker {
|
|||
|
||||
checkNamedPattern(scope: Set<string>, p: M.NamedPattern, context: string, t: SimpleType): void {
|
||||
switch (p._variant) {
|
||||
case 'named':
|
||||
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),
|
||||
`${p.value.name.description!} of ${context}`,
|
||||
stepType(t, p.value.name.description!));
|
||||
`${JSON.stringify(p.value.name.description!)} of ${context}`,
|
||||
t.fields.get(key)!);
|
||||
break;
|
||||
}
|
||||
case 'anonymous':
|
||||
this.checkPattern(scope, p.value, context, t);
|
||||
break;
|
||||
|
@ -85,48 +91,10 @@ class Checker {
|
|||
this.checkNamedPattern(scope, pp, `item ${i} of ${context}`, t));
|
||||
break;
|
||||
case 'tuple*':
|
||||
if (p.variable._variant === 'named') {
|
||||
this.checkBinding(scope, p.variable.value.name, context);
|
||||
this.checkPattern(scope,
|
||||
M.Pattern.SimplePattern(p.variable.value.pattern),
|
||||
`${JSON.stringify(p.variable.value.name.description!)} of ${context}`,
|
||||
stepType(t, p.variable.value.name.description!));
|
||||
} else {
|
||||
if (t.kind !== 'array') {
|
||||
this.recordProblem(context, 'unable to reconstruct tail of tuple* pattern');
|
||||
} else {
|
||||
this.checkPattern(scope,
|
||||
M.Pattern.SimplePattern(p.variable.value),
|
||||
`variable-length portion of ${context}`,
|
||||
t.type);
|
||||
}
|
||||
}
|
||||
p.fixed.forEach((pp, i) =>
|
||||
this.checkNamedPattern(scope, pp, `item ${i} of ${context}`, t));
|
||||
break;
|
||||
case 'setof':
|
||||
if (t.kind !== 'set') {
|
||||
this.recordProblem(context, 'unable to reconstruct set');
|
||||
} else {
|
||||
this.checkPattern(scope,
|
||||
M.Pattern.SimplePattern(p.pattern),
|
||||
`set in ${context}`,
|
||||
t.type);
|
||||
}
|
||||
break;
|
||||
case 'dictof':
|
||||
if (t.kind !== 'dictionary') {
|
||||
this.recordProblem(context, 'unable to reconstruct dictionary');
|
||||
} else {
|
||||
this.checkPattern(scope,
|
||||
M.Pattern.SimplePattern(p.key),
|
||||
`key in dictionary in ${context}`,
|
||||
t.key);
|
||||
this.checkPattern(scope,
|
||||
M.Pattern.SimplePattern(p.value),
|
||||
`value in dictionary in ${context}`,
|
||||
t.value);
|
||||
}
|
||||
this.checkNamedPattern(
|
||||
scope, M.promoteNamedSimplePattern(p.variable), `tail of ${context}`, t);
|
||||
break;
|
||||
case 'dict':
|
||||
p.entries.forEach((np, key) =>
|
||||
|
@ -141,11 +109,3 @@ class Checker {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
function stepType(t: SimpleType, key: string): FieldType {
|
||||
if (t.kind !== 'record' || !t.fields.has(key)) {
|
||||
throw new Error(
|
||||
`Internal error: cannot step ${JSON.stringify(t)} by ${JSON.stringify(key)}`);
|
||||
}
|
||||
return t.fields.get(key)!;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Dictionary, KeyedSet, Position } from "@preserves/core";
|
|||
import { refPosition } from "../reader";
|
||||
import * as M from "../meta";
|
||||
import { block, braces, commas, formatItems, Item, keyvalue, seq } from "./block";
|
||||
import { ANY_TYPE, AtomicType, Type } from "../type";
|
||||
import { ANY_TYPE, FieldType, Type } from "../type";
|
||||
import { renderType, variantInitFor } from "./rendertype";
|
||||
|
||||
export interface CompilerOptions {
|
||||
|
@ -69,7 +69,7 @@ export class ModuleContext {
|
|||
this.functiondefs.push(f(new FunctionContext(this)));
|
||||
}
|
||||
|
||||
resolver(): (ref: M.Ref) => AtomicType {
|
||||
resolver(): (ref: M.Ref) => FieldType {
|
||||
return (ref) => M.lookup(refPosition(ref), ref, this.env,
|
||||
(_p) => Type.ref(ref.name.description!),
|
||||
(modId, modPath,_p) => {
|
||||
|
@ -131,10 +131,10 @@ export class FunctionContext {
|
|||
}
|
||||
|
||||
convertCapture(
|
||||
fieldName: string | undefined, sourceExpr: string, ks: (sourceExpr: string) => Item[]): Item
|
||||
fieldName: string | undefined, sourceExpr: string, ks: () => Item[]): Item
|
||||
{
|
||||
return this.withCapture(fieldName, sourceExpr, sourceExpr =>
|
||||
seq(`if (${sourceExpr} !== void 0) `, this.block(() => ks(sourceExpr))));
|
||||
seq(`if (${sourceExpr} !== void 0) `, this.block(() => ks())));
|
||||
}
|
||||
|
||||
buildCapturedCompound(dest: string): Item {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { FunctionContext } from "./context";
|
||||
import * as M from '../meta';
|
||||
import { block, Item, seq } from "./block";
|
||||
import { simpleType, dictionaryType, setType, typeFor } from "../gentype";
|
||||
import { Item, seq } from "./block";
|
||||
import { simpleType, typeFor } from "../gentype";
|
||||
import { refPosition } from "../reader";
|
||||
import { ANY_TYPE, Type } from "../type";
|
||||
|
||||
|
@ -64,7 +64,7 @@ function converterForPattern(
|
|||
function converterForTuple(ctx: FunctionContext,
|
||||
ps: M.NamedPattern[],
|
||||
src: string,
|
||||
recordFields: boolean,
|
||||
knownArray: boolean,
|
||||
variablePattern: M.NamedSimplePattern | undefined,
|
||||
k: () => Item[]): Item[]
|
||||
{
|
||||
|
@ -77,7 +77,7 @@ function converterForTuple(ctx: FunctionContext,
|
|||
} else {
|
||||
const vN = ctx.gentemp(Type.array(ANY_TYPE));
|
||||
return [ps.length > 0 ? `${vN} = ${src}.slice(${ps.length})` : `${vN} = ${src}`,
|
||||
converterForArray(ctx, variablePattern, vN, false, k)];
|
||||
... converterFor(ctx, M.promoteNamedSimplePattern(variablePattern), vN, k, true)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -86,91 +86,27 @@ function converterForTuple(ctx: FunctionContext,
|
|||
? seq(` && ${src}.length === ${ps.length}`)
|
||||
: ((ps.length === 0) ? '' : seq(` && ${src}.length >= ${ps.length}`));
|
||||
|
||||
return recordFields
|
||||
return knownArray
|
||||
? loop(0)
|
||||
: [seq(`if (_.Array.isArray(${src})`, lengthCheck, `) `, ctx.block(() => loop(0)))];
|
||||
}
|
||||
|
||||
function converterForArray(ctx: FunctionContext,
|
||||
arrayType: M.NamedSimplePattern,
|
||||
src: string,
|
||||
checkArray: boolean,
|
||||
k: (dest: string) => Item[]): Item
|
||||
{
|
||||
const postCheck = () => {
|
||||
const r = ctx.gentemp(Type.array(simpleType(ctx.mod.resolver(), M.unnameSimplePattern(arrayType))));
|
||||
const v = ctx.gentempname();
|
||||
return [
|
||||
seq(`${r} = []`),
|
||||
seq(`for (const ${v} of ${src}) `, ctx.block(() => [
|
||||
... converterFor(ctx, M.promoteNamedSimplePattern(arrayType), v, vv =>
|
||||
[`${r}.push(${vv})`, `continue`]),
|
||||
seq(`${r} = void 0`),
|
||||
seq(`break`)])),
|
||||
ctx.convertCapture(M.nameFor(arrayType), r, k)];
|
||||
};
|
||||
return (checkArray
|
||||
? seq(`if (_.Array.isArray(${src})) `, ctx.block(postCheck))
|
||||
: block(... postCheck()));
|
||||
}
|
||||
|
||||
function converterFor(
|
||||
ctx: FunctionContext,
|
||||
np: M.NamedPattern,
|
||||
src: string,
|
||||
ks: (dest: string | undefined) => Item[],
|
||||
recordFields = false): Item[]
|
||||
knownArray = false): Item[]
|
||||
{
|
||||
let p = M.unnamePattern(np);
|
||||
let maybeName = M.nameFor(np);
|
||||
|
||||
if (p._variant === 'SimplePattern') {
|
||||
const dest = ctx.gentemp(simpleType(ctx.mod.resolver(), p.value));
|
||||
return [... converterForSimple(ctx, p.value, src, dest),
|
||||
ctx.convertCapture(maybeName, dest, ks)];
|
||||
return [... converterForSimple(ctx, p.value, src, dest, knownArray),
|
||||
ctx.convertCapture(maybeName, dest, () => ks(dest))];
|
||||
} else {
|
||||
switch (p.value._variant) {
|
||||
case 'setof': {
|
||||
const setPattern = p.value.pattern;
|
||||
const r = ctx.gentemp(setType(ctx.mod.resolver(), setPattern));
|
||||
const v = ctx.gentempname();
|
||||
return [
|
||||
seq(`if (_.Set.isSet<_embedded>(${src})) `, ctx.block(() => [
|
||||
seq(`${r} = new _.KeyedSet()`),
|
||||
seq(`for (const ${v} of ${src}) `, ctx.block(() => [
|
||||
... converterFor(ctx, M.anonymousSimplePattern(setPattern), v, vv =>
|
||||
[`${r}.add(${vv})`, `continue`]),
|
||||
seq(`${r} = void 0`),
|
||||
seq(`break`)])),
|
||||
ctx.convertCapture(maybeName, r, ks)]))];
|
||||
}
|
||||
case 'dictof': {
|
||||
const keyPattern = p.value.key;
|
||||
const valPattern = p.value.value;
|
||||
const r = ctx.gentemp(dictionaryType(ctx.mod.resolver(), keyPattern, valPattern));
|
||||
const v = ctx.gentempname();
|
||||
const k = ctx.gentempname();
|
||||
return [
|
||||
seq(`if (_.Dictionary.isDictionary<_embedded>(${src})) `, ctx.block(() => [
|
||||
seq(`${r} = new _.KeyedDictionary()`),
|
||||
seq(`for (const [${k}, ${v}] of ${src}) `, ctx.block(() => [
|
||||
... converterFor(ctx, M.anonymousSimplePattern(keyPattern), k, kk =>
|
||||
converterFor(ctx, M.anonymousSimplePattern(valPattern), v, vv =>
|
||||
[`${r}.set(${kk}, ${vv})`, `continue`])),
|
||||
seq(`${r} = void 0`),
|
||||
seq(`break`)])),
|
||||
ctx.convertCapture(maybeName, r, ks)]))];
|
||||
}
|
||||
default: {
|
||||
const arrayType = M.simpleArray(p.value);
|
||||
if (arrayType === void 0) {
|
||||
return converterForCompound(ctx, p.value, src, recordFields, () => ks(void 0));
|
||||
} else {
|
||||
return [converterForArray(
|
||||
ctx, M.NamedSimplePattern.anonymous(arrayType), src, !recordFields, ks)];
|
||||
}
|
||||
}
|
||||
}
|
||||
return converterForCompound(ctx, p.value, src, knownArray, () => ks(void 0));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,7 +114,8 @@ export function converterForSimple(
|
|||
ctx: FunctionContext,
|
||||
p: M.SimplePattern,
|
||||
src: string,
|
||||
dest: string): Item[]
|
||||
dest: string,
|
||||
knownArray: boolean): Item[]
|
||||
{
|
||||
switch (p._variant) {
|
||||
case 'any':
|
||||
|
@ -197,8 +134,55 @@ export function converterForSimple(
|
|||
}
|
||||
return [seq(`${dest} = `, test, ` ? `, valexp, ` : void 0`)];
|
||||
}
|
||||
case 'embedded':
|
||||
return [`${dest} = _.isEmbedded<_embedded>(${src}) ? ${src}.embeddedValue : void 0`];
|
||||
case 'lit':
|
||||
return [`${dest} = _.is(${src}, ${ctx.mod.literal(p.value)}) ? null : void 0`];
|
||||
|
||||
case 'seqof': {
|
||||
const kKnownArray = () => {
|
||||
const v = ctx.gentempname();
|
||||
return [
|
||||
seq(`${dest} = []`),
|
||||
seq(`for (const ${v} of ${src}) `, ctx.block(() => [
|
||||
... converterFor(ctx, M.anonymousSimplePattern(p.pattern), v, vv =>
|
||||
[`${dest}.push(${vv})`, `continue`]),
|
||||
seq(`${dest} = void 0`),
|
||||
seq(`break`)]))];
|
||||
};
|
||||
if (knownArray) {
|
||||
return kKnownArray();
|
||||
} else {
|
||||
return [`${dest} = void 0`,
|
||||
seq(`if (_.Array.isArray(${src})) `, ctx.block(kKnownArray))];
|
||||
}
|
||||
}
|
||||
case 'setof':
|
||||
return [`${dest} = void 0`,
|
||||
seq(`if (_.Set.isSet<_embedded>(${src})) `, ctx.block(() => {
|
||||
const v = ctx.gentempname();
|
||||
return [
|
||||
seq(`${dest} = new _.KeyedSet()`),
|
||||
seq(`for (const ${v} of ${src}) `, ctx.block(() => [
|
||||
... converterFor(ctx, M.anonymousSimplePattern(p.pattern), v, vv =>
|
||||
[`${dest}.add(${vv})`, `continue`]),
|
||||
seq(`${dest} = void 0`),
|
||||
seq(`break`)]))];
|
||||
}))];
|
||||
case 'dictof':
|
||||
return [`${dest} = void 0`,
|
||||
seq(`if (_.Dictionary.isDictionary<_embedded>(${src})) `, ctx.block(() => {
|
||||
const v = ctx.gentempname();
|
||||
const k = ctx.gentempname();
|
||||
return [
|
||||
seq(`${dest} = new _.KeyedDictionary()`),
|
||||
seq(`for (const [${k}, ${v}] of ${src}) `, ctx.block(() => [
|
||||
... converterFor(ctx, M.anonymousSimplePattern(p.key), k, kk =>
|
||||
converterFor(ctx, M.anonymousSimplePattern(p.value), v, vv =>
|
||||
[`${dest}.set(${kk}, ${vv})`, `continue`])),
|
||||
seq(`${dest} = void 0`),
|
||||
seq(`break`)]))];
|
||||
}))];
|
||||
case 'Ref':
|
||||
return M.lookup(refPosition(p.value), p.value, ctx.mod.env,
|
||||
(_p) => [`${dest} = to${p.value.name.description!}(${src})`],
|
||||
|
@ -206,8 +190,6 @@ export function converterForSimple(
|
|||
ctx.mod.imports.add([modId, modPath]);
|
||||
return [`${dest} = ${modId}.to${p.value.name.description!}(${src})`];
|
||||
});
|
||||
case 'embedded':
|
||||
return [`${dest} = _.isEmbedded<_embedded>(${src}) ? ${src}.embeddedValue : void 0`];
|
||||
default:
|
||||
((_p: never) => {})(p);
|
||||
throw new Error("Unreachable");
|
||||
|
@ -218,7 +200,7 @@ function converterForCompound(
|
|||
ctx: FunctionContext,
|
||||
p: M.CompoundPattern,
|
||||
src: string,
|
||||
recordFields: boolean,
|
||||
knownArray: boolean,
|
||||
ks: () => Item[]): Item[]
|
||||
{
|
||||
switch (p._variant) {
|
||||
|
@ -227,12 +209,9 @@ function converterForCompound(
|
|||
converterFor(ctx, p.label, `${src}.label`, () =>
|
||||
converterFor(ctx, p.fields, src, ks, true))))];
|
||||
case 'tuple':
|
||||
return converterForTuple(ctx, p.patterns, src, recordFields, void 0, ks);
|
||||
return converterForTuple(ctx, p.patterns, src, knownArray, void 0, ks);
|
||||
case 'tuple*':
|
||||
return converterForTuple(ctx, p.fixed, src, recordFields, p.variable, ks);
|
||||
case 'setof':
|
||||
case 'dictof':
|
||||
throw new Error('Internal error: setof and dictof are handled in converterFor()');
|
||||
return converterForTuple(ctx, p.fixed, src, knownArray, p.variable, ks);
|
||||
case 'dict': {
|
||||
const entries = Array.from(p.entries);
|
||||
function loop(i: number): Item[] {
|
||||
|
|
|
@ -49,6 +49,22 @@ function unconverterFor(ctx: FunctionContext, p: M.Pattern, src: string): Item {
|
|||
return ctx.mod.literal(p.value);
|
||||
case 'embedded':
|
||||
return `_.embed(${src})`;
|
||||
case 'seqof':
|
||||
return seq(`${src}.map(v => `,
|
||||
unconverterFor(ctx, M.Pattern.SimplePattern(p.pattern), 'v'),
|
||||
`)`);
|
||||
case 'setof':
|
||||
return seq(`new _.Set<_embedded>`, parens(
|
||||
`_.Array.from(${src}.values()).map(v => `,
|
||||
unconverterFor(ctx, M.Pattern.SimplePattern(p.pattern), 'v'),
|
||||
`)`));
|
||||
case 'dictof':
|
||||
return seq(`new _.Dictionary<_embedded>`, parens(seq(
|
||||
`_.Array.from(${src}.entries()).map(([k, v]) => `,
|
||||
brackets(
|
||||
unconverterFor(ctx, M.Pattern.SimplePattern(p.key), 'k'),
|
||||
unconverterFor(ctx, M.Pattern.SimplePattern(p.value), 'v')),
|
||||
`)`)));
|
||||
case 'Ref':
|
||||
return M.lookup(
|
||||
refPosition(p.value), p.value, ctx.mod.env,
|
||||
|
@ -70,41 +86,16 @@ function unconverterFor(ctx: FunctionContext, p: M.Pattern, src: string): Item {
|
|||
return brackets(... p.patterns.map(pp =>
|
||||
unconverterForNamed(ctx, pp, src)));
|
||||
case 'tuple*': {
|
||||
let varexp: Item;
|
||||
if (p.variable._variant === 'named') {
|
||||
const steppedSrc = stepSource(src, p.variable.value.name.description!);
|
||||
varexp = seq(steppedSrc, `.map`, parens(
|
||||
seq(`v => `, unconverterFor(
|
||||
ctx,
|
||||
M.Pattern.SimplePattern(p.variable.value.pattern),
|
||||
`v`))));
|
||||
} else {
|
||||
varexp = seq(src, `.map`, parens(
|
||||
seq(`v => `, unconverterFor(
|
||||
ctx,
|
||||
M.Pattern.SimplePattern(p.variable.value),
|
||||
`v`))));
|
||||
}
|
||||
const varExp =
|
||||
unconverterForNamed(ctx, M.promoteNamedSimplePattern(p.variable), src);
|
||||
if (p.fixed.length === 0) {
|
||||
return varexp;
|
||||
return varExp;
|
||||
} else {
|
||||
return brackets(
|
||||
... p.fixed.map(pp => unconverterForNamed(ctx, pp, src)),
|
||||
seq(`... `, varexp));
|
||||
seq(`... `, varExp));
|
||||
}
|
||||
}
|
||||
case 'setof':
|
||||
return seq(`new _.Set<_embedded>`, parens(
|
||||
`_.Array.from(${src}.values()).map(v => `,
|
||||
unconverterFor(ctx, M.Pattern.SimplePattern(p.pattern), 'v'),
|
||||
`)`));
|
||||
case 'dictof':
|
||||
return seq(`new _.Dictionary<_embedded>`, parens(seq(
|
||||
`_.Array.from(${src}.entries()).map(([k, v]) => `,
|
||||
brackets(
|
||||
unconverterFor(ctx, M.Pattern.SimplePattern(p.key), 'k'),
|
||||
unconverterFor(ctx, M.Pattern.SimplePattern(p.value), 'v')),
|
||||
`)`)));
|
||||
case 'dict':
|
||||
return seq(`new _.Dictionary<_embedded>`, parens(
|
||||
brackets(... Array.from(p.entries.entries()).map(([k, n]) =>
|
||||
|
|
|
@ -23,6 +23,7 @@ export const $or = Symbol.for("or");
|
|||
export const $rec = Symbol.for("rec");
|
||||
export const $ref = Symbol.for("ref");
|
||||
export const $schema = Symbol.for("schema");
|
||||
export const $seqof = Symbol.for("seqof");
|
||||
export const $setof = Symbol.for("setof");
|
||||
export const $tuple = Symbol.for("tuple");
|
||||
export const $tuple$STAR$ = Symbol.for("tuple*");
|
||||
|
@ -75,6 +76,9 @@ export type SimplePattern = (
|
|||
{"_variant": "atom", "atomKind": AtomKind} |
|
||||
{"_variant": "embedded"} |
|
||||
{"_variant": "lit", "value": _val} |
|
||||
{"_variant": "seqof", "pattern": SimplePattern} |
|
||||
{"_variant": "setof", "pattern": SimplePattern} |
|
||||
{"_variant": "dictof", "key": SimplePattern, "value": SimplePattern} |
|
||||
{"_variant": "Ref", "value": Ref}
|
||||
);
|
||||
|
||||
|
@ -86,8 +90,6 @@ export type CompoundPattern = (
|
|||
"fixed": Array<NamedPattern>,
|
||||
"variable": NamedSimplePattern
|
||||
} |
|
||||
{"_variant": "setof", "pattern": SimplePattern} |
|
||||
{"_variant": "dictof", "key": SimplePattern, "value": SimplePattern} |
|
||||
{"_variant": "dict", "entries": DictionaryEntries}
|
||||
);
|
||||
|
||||
|
@ -179,6 +181,9 @@ export namespace SimplePattern {
|
|||
export function atom(atomKind: AtomKind): SimplePattern {return {"_variant": "atom", "atomKind": atomKind};};
|
||||
export function embedded(): SimplePattern {return {"_variant": "embedded"};};
|
||||
export function lit(value: _val): SimplePattern {return {"_variant": "lit", "value": value};};
|
||||
export function seqof(pattern: SimplePattern): SimplePattern {return {"_variant": "seqof", "pattern": pattern};};
|
||||
export function setof(pattern: SimplePattern): SimplePattern {return {"_variant": "setof", "pattern": pattern};};
|
||||
export function dictof({key, value}: {key: SimplePattern, value: SimplePattern}): SimplePattern {return {"_variant": "dictof", "key": key, "value": value};};
|
||||
export function Ref(value: Ref): SimplePattern {return {"_variant": "Ref", "value": value};};
|
||||
}
|
||||
|
||||
|
@ -186,8 +191,6 @@ export namespace CompoundPattern {
|
|||
export function rec({label, fields}: {label: NamedPattern, fields: NamedPattern}): CompoundPattern {return {"_variant": "rec", "label": label, "fields": fields};};
|
||||
export function tuple(patterns: Array<NamedPattern>): CompoundPattern {return {"_variant": "tuple", "patterns": patterns};};
|
||||
export function tuple$STAR$({fixed, variable}: {fixed: Array<NamedPattern>, variable: NamedSimplePattern}): CompoundPattern {return {"_variant": "tuple*", "fixed": fixed, "variable": variable};};
|
||||
export function setof(pattern: SimplePattern): CompoundPattern {return {"_variant": "setof", "pattern": pattern};};
|
||||
export function dictof({key, value}: {key: SimplePattern, value: SimplePattern}): CompoundPattern {return {"_variant": "dictof", "key": key, "value": value};};
|
||||
export function dict(entries: DictionaryEntries): CompoundPattern {return {"_variant": "dict", "entries": entries};};
|
||||
}
|
||||
|
||||
|
@ -252,6 +255,7 @@ export function asModules(v: _val): Modules {
|
|||
export function toModules(v: _val): undefined | Modules {
|
||||
let _tmp0: (_.KeyedDictionary<ModulePath, Schema, _embedded>) | undefined;
|
||||
let result: undefined | Modules;
|
||||
_tmp0 = void 0;
|
||||
if (_.Dictionary.isDictionary<_embedded>(v)) {
|
||||
_tmp0 = new _.KeyedDictionary();
|
||||
for (const [_tmp2, _tmp1] of v) {
|
||||
|
@ -265,8 +269,8 @@ export function toModules(v: _val): undefined | Modules {
|
|||
_tmp0 = void 0;
|
||||
break;
|
||||
};
|
||||
if (_tmp0 !== void 0) {result = _tmp0;};
|
||||
};
|
||||
if (_tmp0 !== void 0) {result = _tmp0;};
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -376,6 +380,7 @@ export function asDefinitions(v: _val): Definitions {
|
|||
export function toDefinitions(v: _val): undefined | Definitions {
|
||||
let _tmp0: (_.KeyedDictionary<symbol, Definition, _embedded>) | undefined;
|
||||
let result: undefined | Definitions;
|
||||
_tmp0 = void 0;
|
||||
if (_.Dictionary.isDictionary<_embedded>(v)) {
|
||||
_tmp0 = new _.KeyedDictionary();
|
||||
for (const [_tmp2, _tmp1] of v) {
|
||||
|
@ -389,8 +394,8 @@ export function toDefinitions(v: _val): undefined | Definitions {
|
|||
_tmp0 = void 0;
|
||||
break;
|
||||
};
|
||||
if (_tmp0 !== void 0) {result = _tmp0;};
|
||||
};
|
||||
if (_tmp0 !== void 0) {result = _tmp0;};
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -420,7 +425,6 @@ export function toDefinition(v: _val): undefined | Definition {
|
|||
let _tmp3: (Array<_val>) | undefined;
|
||||
let _tmp4: (Array<NamedAlternative>) | undefined;
|
||||
_tmp3 = v[0].slice(2);
|
||||
{
|
||||
_tmp4 = [];
|
||||
for (const _tmp5 of _tmp3) {
|
||||
let _tmp6: (NamedAlternative) | undefined;
|
||||
|
@ -437,7 +441,6 @@ export function toDefinition(v: _val): undefined | Definition {
|
|||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
if (result === void 0) {
|
||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||
let _tmp7: (null) | undefined;
|
||||
|
@ -453,7 +456,6 @@ export function toDefinition(v: _val): undefined | Definition {
|
|||
let _tmp10: (Array<_val>) | undefined;
|
||||
let _tmp11: (Array<NamedPattern>) | undefined;
|
||||
_tmp10 = v[0].slice(2);
|
||||
{
|
||||
_tmp11 = [];
|
||||
for (const _tmp12 of _tmp10) {
|
||||
let _tmp13: (NamedPattern) | undefined;
|
||||
|
@ -470,7 +472,6 @@ export function toDefinition(v: _val): undefined | Definition {
|
|||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
if (result === void 0) {
|
||||
let _tmp14: (Pattern) | undefined;
|
||||
_tmp14 = toPattern(v);
|
||||
|
@ -574,9 +575,46 @@ export function toSimplePattern(v: _val): undefined | SimplePattern {
|
|||
};
|
||||
};
|
||||
if (result === void 0) {
|
||||
let _tmp6: (Ref) | undefined;
|
||||
_tmp6 = toRef(v);
|
||||
if (_tmp6 !== void 0) {result = {"_variant": "Ref", "value": _tmp6};};
|
||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||
let _tmp6: (null) | undefined;
|
||||
_tmp6 = _.is(v.label, $seqof) ? null : void 0;
|
||||
if (_tmp6 !== void 0) {
|
||||
let _tmp7: (SimplePattern) | undefined;
|
||||
_tmp7 = toSimplePattern(v[0]);
|
||||
if (_tmp7 !== void 0) {result = {"_variant": "seqof", "pattern": _tmp7};};
|
||||
};
|
||||
};
|
||||
if (result === void 0) {
|
||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||
let _tmp8: (null) | undefined;
|
||||
_tmp8 = _.is(v.label, $setof) ? null : void 0;
|
||||
if (_tmp8 !== void 0) {
|
||||
let _tmp9: (SimplePattern) | undefined;
|
||||
_tmp9 = toSimplePattern(v[0]);
|
||||
if (_tmp9 !== void 0) {result = {"_variant": "setof", "pattern": _tmp9};};
|
||||
};
|
||||
};
|
||||
if (result === void 0) {
|
||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||
let _tmp10: (null) | undefined;
|
||||
_tmp10 = _.is(v.label, $dictof) ? null : void 0;
|
||||
if (_tmp10 !== void 0) {
|
||||
let _tmp11: (SimplePattern) | undefined;
|
||||
_tmp11 = toSimplePattern(v[0]);
|
||||
if (_tmp11 !== void 0) {
|
||||
let _tmp12: (SimplePattern) | undefined;
|
||||
_tmp12 = toSimplePattern(v[1]);
|
||||
if (_tmp12 !== void 0) {result = {"_variant": "dictof", "key": _tmp11, "value": _tmp12};};
|
||||
};
|
||||
};
|
||||
};
|
||||
if (result === void 0) {
|
||||
let _tmp13: (Ref) | undefined;
|
||||
_tmp13 = toRef(v);
|
||||
if (_tmp13 !== void 0) {result = {"_variant": "Ref", "value": _tmp13};};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -590,6 +628,11 @@ export function fromSimplePattern(_v: SimplePattern): _val {
|
|||
case "atom": {return _.Record($atom, [fromAtomKind(_v["atomKind"])]);};
|
||||
case "embedded": {return _.Record($embedded, []);};
|
||||
case "lit": {return _.Record($lit, [_v["value"]]);};
|
||||
case "seqof": {return _.Record($seqof, [fromSimplePattern(_v["pattern"])]);};
|
||||
case "setof": {return _.Record($setof, [fromSimplePattern(_v["pattern"])]);};
|
||||
case "dictof": {
|
||||
return _.Record($dictof, [fromSimplePattern(_v["key"]), fromSimplePattern(_v["value"])]);
|
||||
};
|
||||
case "Ref": {return fromRef(_v.value);};
|
||||
};
|
||||
}
|
||||
|
@ -620,85 +663,53 @@ export function toCompoundPattern(v: _val): undefined | CompoundPattern {
|
|||
let _tmp3: (null) | undefined;
|
||||
_tmp3 = _.is(v.label, $tuple) ? null : void 0;
|
||||
if (_tmp3 !== void 0) {
|
||||
let _tmp4: (Array<NamedPattern>) | undefined;
|
||||
_tmp4 = void 0;
|
||||
if (_.Array.isArray(v[0])) {
|
||||
let _tmp4: (Array<_val>) | undefined;
|
||||
let _tmp5: (Array<NamedPattern>) | undefined;
|
||||
_tmp4 = v[0];
|
||||
{
|
||||
_tmp5 = [];
|
||||
for (const _tmp6 of _tmp4) {
|
||||
let _tmp7: (NamedPattern) | undefined;
|
||||
_tmp7 = toNamedPattern(_tmp6);
|
||||
if (_tmp7 !== void 0) {_tmp5.push(_tmp7); continue;};
|
||||
_tmp5 = void 0;
|
||||
_tmp4 = [];
|
||||
for (const _tmp5 of v[0]) {
|
||||
let _tmp6: (NamedPattern) | undefined;
|
||||
_tmp6 = toNamedPattern(_tmp5);
|
||||
if (_tmp6 !== void 0) {_tmp4.push(_tmp6); continue;};
|
||||
_tmp4 = void 0;
|
||||
break;
|
||||
};
|
||||
if (_tmp5 !== void 0) {result = {"_variant": "tuple", "patterns": _tmp5};};
|
||||
};
|
||||
};
|
||||
if (_tmp4 !== void 0) {result = {"_variant": "tuple", "patterns": _tmp4};};
|
||||
};
|
||||
};
|
||||
if (result === void 0) {
|
||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||
let _tmp8: (null) | undefined;
|
||||
_tmp8 = _.is(v.label, $tuple$STAR$) ? null : void 0;
|
||||
let _tmp7: (null) | undefined;
|
||||
_tmp7 = _.is(v.label, $tuple$STAR$) ? null : void 0;
|
||||
if (_tmp7 !== void 0) {
|
||||
let _tmp8: (Array<NamedPattern>) | undefined;
|
||||
_tmp8 = void 0;
|
||||
if (_.Array.isArray(v[0])) {
|
||||
_tmp8 = [];
|
||||
for (const _tmp9 of v[0]) {
|
||||
let _tmp10: (NamedPattern) | undefined;
|
||||
_tmp10 = toNamedPattern(_tmp9);
|
||||
if (_tmp10 !== void 0) {_tmp8.push(_tmp10); continue;};
|
||||
_tmp8 = void 0;
|
||||
break;
|
||||
};
|
||||
};
|
||||
if (_tmp8 !== void 0) {
|
||||
if (_.Array.isArray(v[0])) {
|
||||
let _tmp9: (Array<_val>) | undefined;
|
||||
let _tmp10: (Array<NamedPattern>) | undefined;
|
||||
_tmp9 = v[0];
|
||||
{
|
||||
_tmp10 = [];
|
||||
for (const _tmp11 of _tmp9) {
|
||||
let _tmp12: (NamedPattern) | undefined;
|
||||
_tmp12 = toNamedPattern(_tmp11);
|
||||
if (_tmp12 !== void 0) {_tmp10.push(_tmp12); continue;};
|
||||
_tmp10 = void 0;
|
||||
break;
|
||||
};
|
||||
if (_tmp10 !== void 0) {
|
||||
let _tmp13: (NamedSimplePattern) | undefined;
|
||||
_tmp13 = toNamedSimplePattern(v[1]);
|
||||
if (_tmp13 !== void 0) {result = {"_variant": "tuple*", "fixed": _tmp10, "variable": _tmp13};};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
if (result === void 0) {
|
||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||
let _tmp14: (null) | undefined;
|
||||
_tmp14 = _.is(v.label, $setof) ? null : void 0;
|
||||
if (_tmp14 !== void 0) {
|
||||
let _tmp15: (SimplePattern) | undefined;
|
||||
_tmp15 = toSimplePattern(v[0]);
|
||||
if (_tmp15 !== void 0) {result = {"_variant": "setof", "pattern": _tmp15};};
|
||||
};
|
||||
};
|
||||
if (result === void 0) {
|
||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||
let _tmp16: (null) | undefined;
|
||||
_tmp16 = _.is(v.label, $dictof) ? null : void 0;
|
||||
if (_tmp16 !== void 0) {
|
||||
let _tmp17: (SimplePattern) | undefined;
|
||||
_tmp17 = toSimplePattern(v[0]);
|
||||
if (_tmp17 !== void 0) {
|
||||
let _tmp18: (SimplePattern) | undefined;
|
||||
_tmp18 = toSimplePattern(v[1]);
|
||||
if (_tmp18 !== void 0) {result = {"_variant": "dictof", "key": _tmp17, "value": _tmp18};};
|
||||
let _tmp11: (NamedSimplePattern) | undefined;
|
||||
_tmp11 = toNamedSimplePattern(v[1]);
|
||||
if (_tmp11 !== void 0) {result = {"_variant": "tuple*", "fixed": _tmp8, "variable": _tmp11};};
|
||||
};
|
||||
};
|
||||
};
|
||||
if (result === void 0) {
|
||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||
let _tmp19: (null) | undefined;
|
||||
_tmp19 = _.is(v.label, $dict) ? null : void 0;
|
||||
if (_tmp19 !== void 0) {
|
||||
let _tmp20: (DictionaryEntries) | undefined;
|
||||
_tmp20 = toDictionaryEntries(v[0]);
|
||||
if (_tmp20 !== void 0) {result = {"_variant": "dict", "entries": _tmp20};};
|
||||
};
|
||||
};
|
||||
let _tmp12: (null) | undefined;
|
||||
_tmp12 = _.is(v.label, $dict) ? null : void 0;
|
||||
if (_tmp12 !== void 0) {
|
||||
let _tmp13: (DictionaryEntries) | undefined;
|
||||
_tmp13 = toDictionaryEntries(v[0]);
|
||||
if (_tmp13 !== void 0) {result = {"_variant": "dict", "entries": _tmp13};};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -722,10 +733,6 @@ export function fromCompoundPattern(_v: CompoundPattern): _val {
|
|||
]
|
||||
);
|
||||
};
|
||||
case "setof": {return _.Record($setof, [fromSimplePattern(_v["pattern"])]);};
|
||||
case "dictof": {
|
||||
return _.Record($dictof, [fromSimplePattern(_v["key"]), fromSimplePattern(_v["value"])]);
|
||||
};
|
||||
case "dict": {return _.Record($dict, [fromDictionaryEntries(_v["entries"])]);};
|
||||
};
|
||||
}
|
||||
|
@ -739,6 +746,7 @@ export function asDictionaryEntries(v: _val): DictionaryEntries {
|
|||
export function toDictionaryEntries(v: _val): undefined | DictionaryEntries {
|
||||
let _tmp0: (_.KeyedDictionary<_val, NamedSimplePattern, _embedded>) | undefined;
|
||||
let result: undefined | DictionaryEntries;
|
||||
_tmp0 = void 0;
|
||||
if (_.Dictionary.isDictionary<_embedded>(v)) {
|
||||
_tmp0 = new _.KeyedDictionary();
|
||||
for (const [_tmp2, _tmp1] of v) {
|
||||
|
@ -752,8 +760,8 @@ export function toDictionaryEntries(v: _val): undefined | DictionaryEntries {
|
|||
_tmp0 = void 0;
|
||||
break;
|
||||
};
|
||||
if (_tmp0 !== void 0) {result = _tmp0;};
|
||||
};
|
||||
if (_tmp0 !== void 0) {result = _tmp0;};
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -950,9 +958,10 @@ export function asModulePath(v: _val): ModulePath {
|
|||
}
|
||||
|
||||
export function toModulePath(v: _val): undefined | ModulePath {
|
||||
let result: undefined | ModulePath;
|
||||
if (_.Array.isArray(v)) {
|
||||
let _tmp0: (Array<symbol>) | undefined;
|
||||
let result: undefined | ModulePath;
|
||||
_tmp0 = void 0;
|
||||
if (_.Array.isArray(v)) {
|
||||
_tmp0 = [];
|
||||
for (const _tmp1 of v) {
|
||||
let _tmp2: (symbol) | undefined;
|
||||
|
@ -961,8 +970,8 @@ export function toModulePath(v: _val): undefined | ModulePath {
|
|||
_tmp0 = void 0;
|
||||
break;
|
||||
};
|
||||
if (_tmp0 !== void 0) {result = _tmp0;};
|
||||
};
|
||||
if (_tmp0 !== void 0) {result = _tmp0;};
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as M from "./meta";
|
||||
import { ANY_TYPE, AtomicType, CollectionType, FieldMap, SimpleType, Type } from "./type";
|
||||
import { ANY_TYPE, FieldType, FieldMap, SimpleType, Type } from "./type";
|
||||
|
||||
export type RefResolver = (ref: M.Ref) => AtomicType;
|
||||
export type RefResolver = (ref: M.Ref) => FieldType;
|
||||
|
||||
export function typeForDefinition(resolver: RefResolver, d: M.Definition): Type {
|
||||
switch (d._variant) {
|
||||
|
@ -22,41 +22,15 @@ export function typeForIntersection(resolver: RefResolver, ps: M.NamedPattern[])
|
|||
return fs.size > 0 ? Type.record(fs) : Type.unit();
|
||||
}
|
||||
|
||||
export function setType(resolver: RefResolver, p: M.SimplePattern): CollectionType {
|
||||
return Type.set(simpleType(resolver, p));
|
||||
}
|
||||
|
||||
export function dictionaryType(resolver: RefResolver,
|
||||
kp: M.SimplePattern,
|
||||
vp: M.SimplePattern): CollectionType
|
||||
{
|
||||
return Type.dictionary(simpleType(resolver, kp), simpleType(resolver, vp));
|
||||
}
|
||||
|
||||
export function typeFor(resolver: RefResolver, p: M.Pattern): SimpleType {
|
||||
if (p._variant === 'SimplePattern') {
|
||||
return simpleType(resolver, p.value);
|
||||
} else {
|
||||
switch (p.value._variant) {
|
||||
case 'setof':
|
||||
return setType(resolver, p.value.pattern);
|
||||
case 'dictof':
|
||||
return dictionaryType(resolver, p.value.key, p.value.value);
|
||||
default: {
|
||||
const arrayType = M.simpleArray(p.value);
|
||||
if (arrayType === void 0) {
|
||||
const fs = new Map();
|
||||
compoundFields(fs, resolver, p.value);
|
||||
return fs.size > 0 ? Type.record(fs) : Type.unit();
|
||||
} else {
|
||||
return Type.array(simpleType(resolver, arrayType));
|
||||
}
|
||||
}
|
||||
}
|
||||
return typeForIntersection(resolver, [M.NamedPattern.anonymous(p)]);
|
||||
}
|
||||
}
|
||||
|
||||
export function simpleType(resolver: RefResolver, p: M.SimplePattern): AtomicType {
|
||||
export function simpleType(resolver: RefResolver, p: M.SimplePattern): FieldType {
|
||||
switch (p._variant) {
|
||||
case 'any':
|
||||
return ANY_TYPE;
|
||||
|
@ -74,6 +48,12 @@ export function simpleType(resolver: RefResolver, p: M.SimplePattern): AtomicTyp
|
|||
return Type.ref(`_embedded`);
|
||||
case 'lit':
|
||||
return Type.unit();
|
||||
case 'seqof':
|
||||
return Type.array(simpleType(resolver, p.pattern));
|
||||
case 'setof':
|
||||
return Type.set(simpleType(resolver, p.pattern));
|
||||
case 'dictof':
|
||||
return Type.dictionary(simpleType(resolver, p.key), simpleType(resolver, p.value));
|
||||
case 'Ref':
|
||||
return resolver(p.value);
|
||||
default:
|
||||
|
@ -91,16 +71,9 @@ function compoundFields(fs: FieldMap, resolver: RefResolver, p: M.CompoundPatter
|
|||
case 'tuple':
|
||||
p.patterns.forEach(pp => gatherFields(fs, resolver, pp));
|
||||
break;
|
||||
case 'tuple*': {
|
||||
case 'tuple*':
|
||||
p.fixed.forEach(pp => gatherFields(fs, resolver, pp));
|
||||
const n = p.variable;
|
||||
if (n._variant === 'named') {
|
||||
fs.set(n.value.name.description!, Type.array(simpleType(resolver, n.value.pattern)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'setof':
|
||||
case 'dictof':
|
||||
gatherFields(fs, resolver, M.promoteNamedSimplePattern(p.variable));
|
||||
break;
|
||||
case 'dict':
|
||||
p.entries.forEach((n, k) =>
|
||||
|
@ -114,7 +87,10 @@ function compoundFields(fs: FieldMap, resolver: RefResolver, p: M.CompoundPatter
|
|||
|
||||
function gatherFields(fs: FieldMap, resolver: RefResolver, n: M.NamedPattern): void {
|
||||
if (n._variant === 'named') {
|
||||
fs.set(n.value.name.description!, simpleType(resolver, n.value.pattern));
|
||||
const t = simpleType(resolver, n.value.pattern);
|
||||
if (t.kind !== 'unit') {
|
||||
fs.set(n.value.name.description!, t);
|
||||
}
|
||||
} else if (n.value._variant === 'CompoundPattern') {
|
||||
compoundFields(fs, resolver, n.value.value);
|
||||
}
|
||||
|
|
|
@ -118,16 +118,6 @@ export function addNameIfAbsent(p: M.NamedSimplePattern, k: M._val): M.NamedSimp
|
|||
}
|
||||
}
|
||||
|
||||
// Simple arrays at toplevel for convenience
|
||||
//
|
||||
export function simpleArray(p: M.CompoundPattern): M.SimplePattern | undefined {
|
||||
if (p._variant === 'tuple*' && p.fixed.length === 0 && p.variable._variant !== 'named') {
|
||||
return p.variable.value;
|
||||
} else {
|
||||
return void 0;
|
||||
}
|
||||
}
|
||||
|
||||
export function namelike(x: Input): string | undefined {
|
||||
if (typeof x === 'string') return x;
|
||||
if (typeof x === 'symbol') return x.description!;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Reader, Annotated, Dictionary, is, peel, preserves, Record, strip, Tuple, Position, position, ReaderOptions, stringify, isCompound, KeyedDictionary } from '@preserves/core';
|
||||
import { Reader, Annotated, Dictionary, is, peel, preserves, Record, strip, Tuple, Position, position, ReaderOptions, stringify, isCompound, KeyedDictionary, annotate, annotations } from '@preserves/core';
|
||||
import { Input, Pattern, Schema, Definition, CompoundPattern, SimplePattern } from './meta';
|
||||
import * as M from './meta';
|
||||
import { SchemaSyntaxError } from './error';
|
||||
|
@ -201,6 +201,10 @@ function parseDefinition(name: symbol, pos: Position | null, body: Array<Input>)
|
|||
return M.Definition.Pattern(parsePattern(name, orPieces[0]));
|
||||
}
|
||||
|
||||
function transferAnnotations(dest: Input, src: Input): Input {
|
||||
return annotate(dest, ... annotations(src));
|
||||
}
|
||||
|
||||
function parsePattern(name: symbol, body0: Array<Input>): Pattern {
|
||||
function parseSimple<A>(item0: Input, ks: (p: SimplePattern) => A, kf: () => A): A {
|
||||
const pos = position(item0);
|
||||
|
@ -236,6 +240,20 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
|
|||
} else {
|
||||
return kf();
|
||||
}
|
||||
} else if (Array.isArray(item) && item.length === 2 && is(item[1], M.DOTDOTDOT)) {
|
||||
return ks(M.SimplePattern.seqof(walkSimple(item[0])));
|
||||
} else if (Set.isSet<M._embedded>(item)) {
|
||||
if (item.size !== 1) complain();
|
||||
const [vp] = item.entries();
|
||||
return ks(M.SimplePattern.setof(walkSimple(vp)));
|
||||
} else if (Dictionary.isDictionary<M._embedded, Input>(item)
|
||||
&& item.size === 2
|
||||
&& item.has(M.DOTDOTDOT))
|
||||
{
|
||||
const v = item.clone();
|
||||
v.delete(M.DOTDOTDOT);
|
||||
const [[kp, vp]] = v.entries();
|
||||
return ks(M.SimplePattern.dictof({ key: walkSimple(kp), value: walkSimple(vp) }));
|
||||
} else if (isCompound(item)) {
|
||||
return kf();
|
||||
} else {
|
||||
|
@ -248,10 +266,56 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
|
|||
const item = peel(item0);
|
||||
function complain(): never { invalidPattern(stringify(name), item, pos); }
|
||||
|
||||
if (Record.isRecord<Input, Tuple<Input>, M._embedded>(item)) {
|
||||
const label = item.label;
|
||||
if (Record.isRecord<Input, [], M._embedded>(label)) {
|
||||
if (label.length !== 0) complain();
|
||||
switch (label.label) {
|
||||
case M.$rec:
|
||||
if (item.length !== 2) complain();
|
||||
return M.CompoundPattern.rec({
|
||||
label: maybeNamed(item[0]),
|
||||
fields: maybeNamed(item[1])
|
||||
});
|
||||
default:
|
||||
complain();
|
||||
}
|
||||
} else {
|
||||
return M.CompoundPattern.rec({
|
||||
label: M.NamedPattern.anonymous(M.Pattern.SimplePattern(M.SimplePattern.lit(label))),
|
||||
fields: M.NamedPattern.anonymous(parsePattern(name, [transferAnnotations([... item], item0)])),
|
||||
});
|
||||
}
|
||||
} else if (Array.isArray(item) && item.length > 2 && is(item[item.length - 1], M.DOTDOTDOT)) {
|
||||
const variableTemplateInput = item[item.length - 2];
|
||||
const variablePart =
|
||||
transferAnnotations([variableTemplateInput, M.DOTDOTDOT], variableTemplateInput);
|
||||
return M.CompoundPattern.tuple$STAR$({
|
||||
fixed: item.slice(0, item.length - 2).map(maybeNamed),
|
||||
variable: maybeNamedSimple(variablePart),
|
||||
});
|
||||
} else if (Array.isArray(item)) {
|
||||
return M.CompoundPattern.tuple(item.map(maybeNamed));
|
||||
} else if (Dictionary.isDictionary<M._embedded, Input>(item) && !item.has(M.DOTDOTDOT)) {
|
||||
return M.CompoundPattern.dict(
|
||||
M.DictionaryEntries(item.mapEntries<M.NamedSimplePattern, Input, M._embedded>(
|
||||
([k, vp]) => [
|
||||
strip(k),
|
||||
_maybeNamed(
|
||||
M.NamedSimplePattern.named,
|
||||
M.NamedSimplePattern.anonymous,
|
||||
walkSimple,
|
||||
k)(vp)
|
||||
])));
|
||||
} else {
|
||||
complain();
|
||||
}
|
||||
}
|
||||
|
||||
const walk = (b: Input): Pattern => parsePattern(name, [b]);
|
||||
const walkSimple = (b: Input): SimplePattern => parseSimple(b, p => p, () => {
|
||||
throw new SchemaSyntaxError(`Compound patterns not accepted here`, position(b));
|
||||
});
|
||||
const walk = (b: Input): Pattern => parsePattern(name, [b]);
|
||||
|
||||
function _maybeNamed<R,P>(
|
||||
named: (p: M.NamedSimplePattern_) => R,
|
||||
|
@ -277,67 +341,6 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
|
|||
const maybeNamedSimple =
|
||||
_maybeNamed(M.NamedSimplePattern.named, M.NamedSimplePattern.anonymous, walkSimple);
|
||||
|
||||
function parseArrayLike(item: Array<Input>): CompoundPattern {
|
||||
if (is(item[item.length - 1], M.DOTDOTDOT)) {
|
||||
if (item.length < 2) complain();
|
||||
return M.CompoundPattern.tuple$STAR$({
|
||||
fixed: item.slice(0, item.length - 2).map(maybeNamed),
|
||||
variable: maybeNamedSimple(item[item.length - 2])
|
||||
});
|
||||
} else {
|
||||
return M.CompoundPattern.tuple(item.map(maybeNamed));
|
||||
}
|
||||
}
|
||||
|
||||
if (Record.isRecord<Input, Tuple<Input>, M._embedded>(item)) {
|
||||
const label = item.label;
|
||||
if (Record.isRecord<Input, [], M._embedded>(label)) {
|
||||
if (label.length !== 0) complain();
|
||||
switch (label.label) {
|
||||
case M.$rec:
|
||||
if (item.length !== 2) complain();
|
||||
return M.CompoundPattern.rec({
|
||||
label: maybeNamed(item[0]),
|
||||
fields: maybeNamed(item[1])
|
||||
});
|
||||
default:
|
||||
complain();
|
||||
}
|
||||
} else {
|
||||
return M.CompoundPattern.rec({
|
||||
label: M.NamedPattern.anonymous(M.Pattern.SimplePattern(M.SimplePattern.lit(label))),
|
||||
fields: M.NamedPattern.anonymous(M.Pattern.CompoundPattern(parseArrayLike(item)))
|
||||
});
|
||||
}
|
||||
} else if (Array.isArray(item)) {
|
||||
return parseArrayLike(item);
|
||||
} else if (Dictionary.isDictionary<M._embedded, Input>(item)) {
|
||||
if (item.size === 2 && item.has(M.DOTDOTDOT)) {
|
||||
const v = item.clone();
|
||||
v.delete(M.DOTDOTDOT);
|
||||
const [[kp, vp]] = v.entries();
|
||||
return M.CompoundPattern.dictof({ key: walkSimple(kp), value: walkSimple(vp) });
|
||||
} else {
|
||||
return M.CompoundPattern.dict(
|
||||
M.DictionaryEntries(item.mapEntries<M.NamedSimplePattern, Input, M._embedded>(
|
||||
([k, vp]) => [
|
||||
strip(k),
|
||||
_maybeNamed(
|
||||
M.NamedSimplePattern.named,
|
||||
M.NamedSimplePattern.anonymous,
|
||||
walkSimple,
|
||||
k)(vp)
|
||||
])));
|
||||
}
|
||||
} else if (Set.isSet<never>(item)) {
|
||||
if (item.size !== 1) complain();
|
||||
const [vp] = item.entries();
|
||||
return M.CompoundPattern.setof(walkSimple(vp));
|
||||
} else {
|
||||
complain();
|
||||
}
|
||||
}
|
||||
|
||||
const body = peel(body0) as Array<Input>;
|
||||
if (body.length !== 1) {
|
||||
invalidPattern(stringify(name), body, body.length > 0 ? position(body[0]) : position(body));
|
||||
|
|
|
@ -2,34 +2,30 @@ export type Type =
|
|||
| { kind: 'union', variants: VariantMap } // zero: never
|
||||
| SimpleType
|
||||
|
||||
export type SimpleType = AtomicType | CompoundType
|
||||
export type FieldType = AtomicType | CollectionType;
|
||||
export type SimpleType = FieldType | RecordType
|
||||
|
||||
export type AtomicType =
|
||||
export type FieldType =
|
||||
| { kind: 'unit' }
|
||||
| { kind: 'array', type: FieldType }
|
||||
| { kind: 'set', type: FieldType }
|
||||
| { kind: 'dictionary', key: FieldType, value: FieldType }
|
||||
| { kind: 'ref', typeName: string } // also for base types
|
||||
|
||||
export type CompoundType =
|
||||
| CollectionType
|
||||
export type RecordType =
|
||||
| { kind: 'record', fields: FieldMap }
|
||||
|
||||
export type CollectionType =
|
||||
| { kind: 'array', type: AtomicType }
|
||||
| { kind: 'set', type: AtomicType }
|
||||
| { kind: 'dictionary', key: AtomicType, value: AtomicType }
|
||||
|
||||
export type VariantMap = Map<string, SimpleType>;
|
||||
export type FieldMap = Map<string, FieldType>;
|
||||
|
||||
export namespace Type {
|
||||
export const union = (variants: VariantMap): Type => ({ kind: 'union', variants });
|
||||
export const unit = (): AtomicType => ({ kind: 'unit' });
|
||||
export const ref = (typeName: string): AtomicType => ({ kind: 'ref', typeName });
|
||||
export const record = (fields: FieldMap): CompoundType => ({ kind: 'record', fields });
|
||||
export const array = (type: AtomicType): CollectionType => ({ kind: 'array', type });
|
||||
export const set = (type: AtomicType): CollectionType => ({ kind: 'set', type });
|
||||
export const dictionary = (key: AtomicType, value: AtomicType): CollectionType => (
|
||||
export const unit = (): FieldType => ({ kind: 'unit' });
|
||||
export const ref = (typeName: string): FieldType => ({ kind: 'ref', typeName });
|
||||
export const array = (type: FieldType): FieldType => ({ kind: 'array', type });
|
||||
export const set = (type: FieldType): FieldType => ({ kind: 'set', type });
|
||||
export const dictionary = (key: FieldType, value: FieldType): FieldType => (
|
||||
{ kind: 'dictionary', key, value });
|
||||
export const record = (fields: FieldMap): RecordType => ({ kind: 'record', fields });
|
||||
}
|
||||
|
||||
export const ANY_TYPE: AtomicType = Type.ref('_val');
|
||||
export const ANY_TYPE: FieldType = Type.ref('_val');
|
||||
|
|
|
@ -3,6 +3,6 @@ ModulePath
|
|||
ModulePath„´³refµ„³Schema„„³Pattern´³orµµ±
SimplePattern´³refµ„³
SimplePattern„„µ±CompoundPattern´³refµ„³CompoundPattern„„„„³Version´³lit‘„³AtomKind´³orµµ±Boolean´³lit³Boolean„„µ±Float´³lit³Float„„µ±Double´³lit³Double„„µ±
SignedInteger´³lit³
SignedInteger„„µ±String´³lit³String„„µ±
|
||||
ByteString´³lit³
|
||||
ByteString„„µ±Symbol´³lit³Symbol„„„„³
|
||||
Definition´³orµµ±or´³rec´³lit³or„´³tupleµ´³tuple*µ´³named³pattern0´³refµ„³NamedAlternative„„´³named³pattern1´³refµ„³NamedAlternative„„„´³named³patternN´³refµ„³NamedAlternative„„„„„„„µ±and´³rec´³lit³and„´³tupleµ´³tuple*µ´³named³pattern0´³refµ„³NamedPattern„„´³named³pattern1´³refµ„³NamedPattern„„„´³named³patternN´³refµ„³NamedPattern„„„„„„„µ±Pattern´³refµ„³Pattern„„„„³
|
||||
ModulePath´³tuple*µ„´³atom³Symbol„„³Definitions´³dictof´³atom³Symbol„´³refµ„³
|
||||
Definition„„³NamedPattern´³orµµ±named´³refµ„³NamedSimplePattern_„„µ± anonymous´³refµ„³Pattern„„„„³
SimplePattern´³orµµ±any´³lit³any„„µ±atom´³rec´³lit³atom„´³tupleµ´³named³atomKind´³refµ„³AtomKind„„„„„„µ±embedded´³rec´³lit³embedded„´³tupleµ„„„„µ±lit´³rec´³lit³lit„´³tupleµ´³named³value³any„„„„„µ±Ref´³refµ„³Ref„„„„³CompoundPattern´³orµµ±rec´³rec´³lit³rec„´³tupleµ´³named³label´³refµ„³NamedPattern„„´³named³fields´³refµ„³NamedPattern„„„„„„µ±tuple´³rec´³lit³tuple„´³tupleµ´³tuple*µ„´³named³patterns´³refµ„³NamedPattern„„„„„„„µ±tuple*´³rec´³lit³tuple*„´³tupleµ´³tuple*µ„´³named³fixed´³refµ„³NamedPattern„„„´³named³variable´³refµ„³NamedSimplePattern„„„„„„µ±setof´³rec´³lit³setof„´³tupleµ´³named³pattern´³refµ„³
SimplePattern„„„„„„µ±dictof´³rec´³lit³dictof„´³tupleµ´³named³key´³refµ„³
SimplePattern„„´³named³value´³refµ„³
SimplePattern„„„„„„µ±dict´³rec´³lit³dict„´³tupleµ´³named³entries´³refµ„³DictionaryEntries„„„„„„„„³EmbeddedTypeName´³orµµ±Ref´³refµ„³Ref„„µ±false´³lit€„„„„³NamedAlternative´³tupleµ´³named³variantLabel´³atom³String„„´³named³pattern´³refµ„³Pattern„„„„³DictionaryEntries´³dictof³any´³refµ„³NamedSimplePattern„„³NamedSimplePattern´³orµµ±named´³refµ„³NamedSimplePattern_„„µ± anonymous´³refµ„³
SimplePattern„„„„³NamedSimplePattern_´³rec´³lit³named„´³tupleµ´³named³name´³atom³Symbol„„´³named³pattern´³refµ„³
SimplePattern„„„„„„³embeddedType€„„
|
||||
Definition´³orµµ±or´³rec´³lit³or„´³tupleµ´³tuple*µ´³named³pattern0´³refµ„³NamedAlternative„„´³named³pattern1´³refµ„³NamedAlternative„„„´³named³patternN´³seqof´³refµ„³NamedAlternative„„„„„„„„µ±and´³rec´³lit³and„´³tupleµ´³tuple*µ´³named³pattern0´³refµ„³NamedPattern„„´³named³pattern1´³refµ„³NamedPattern„„„´³named³patternN´³seqof´³refµ„³NamedPattern„„„„„„„„µ±Pattern´³refµ„³Pattern„„„„³
|
||||
ModulePath´³seqof´³atom³Symbol„„³Definitions´³dictof´³atom³Symbol„´³refµ„³
|
||||
Definition„„³NamedPattern´³orµµ±named´³refµ„³NamedSimplePattern_„„µ± anonymous´³refµ„³Pattern„„„„³
SimplePattern´³orµµ±any´³lit³any„„µ±atom´³rec´³lit³atom„´³tupleµ´³named³atomKind´³refµ„³AtomKind„„„„„„µ±embedded´³rec´³lit³embedded„´³tupleµ„„„„µ±lit´³rec´³lit³lit„´³tupleµ´³named³value³any„„„„„µ±seqof´³rec´³lit³seqof„´³tupleµ´³named³pattern´³refµ„³
SimplePattern„„„„„„µ±setof´³rec´³lit³setof„´³tupleµ´³named³pattern´³refµ„³
SimplePattern„„„„„„µ±dictof´³rec´³lit³dictof„´³tupleµ´³named³key´³refµ„³
SimplePattern„„´³named³value´³refµ„³
SimplePattern„„„„„„µ±Ref´³refµ„³Ref„„„„³CompoundPattern´³orµµ±rec´³rec´³lit³rec„´³tupleµ´³named³label´³refµ„³NamedPattern„„´³named³fields´³refµ„³NamedPattern„„„„„„µ±tuple´³rec´³lit³tuple„´³tupleµ´³named³patterns´³seqof´³refµ„³NamedPattern„„„„„„„µ±tuple*´³rec´³lit³tuple*„´³tupleµ´³named³fixed´³seqof´³refµ„³NamedPattern„„„´³named³variable´³refµ„³NamedSimplePattern„„„„„„µ±dict´³rec´³lit³dict„´³tupleµ´³named³entries´³refµ„³DictionaryEntries„„„„„„„„³EmbeddedTypeName´³orµµ±Ref´³refµ„³Ref„„µ±false´³lit€„„„„³NamedAlternative´³tupleµ´³named³variantLabel´³atom³String„„´³named³pattern´³refµ„³Pattern„„„„³DictionaryEntries´³dictof³any´³refµ„³NamedSimplePattern„„³NamedSimplePattern´³orµµ±named´³refµ„³NamedSimplePattern_„„µ± anonymous´³refµ„³
SimplePattern„„„„³NamedSimplePattern_´³rec´³lit³named„´³tupleµ´³named³name´³atom³Symbol„„´³named³pattern´³refµ„³
SimplePattern„„„„„„³embeddedType€„„
|
|
@ -47,6 +47,15 @@ SimplePattern =
|
|||
; =symbol, <<lit> any>, or plain non-symbol atom
|
||||
/ <lit @value any>
|
||||
|
||||
; [p ...] ----> <seqof <ref p>>; see also tuple* below.
|
||||
/ <seqof @pattern SimplePattern>
|
||||
|
||||
; #{p} ----> <setof <ref p>>
|
||||
/ <setof @pattern SimplePattern>
|
||||
|
||||
; {k: v, ...:...} ----> <dictof <ref k> <ref v>>
|
||||
/ <dictof @key SimplePattern @value SimplePattern>
|
||||
|
||||
; symbol, symbol.symbol, symbol.symbol.symbol, ...
|
||||
/ Ref
|
||||
.
|
||||
|
@ -58,16 +67,10 @@ CompoundPattern =
|
|||
/ <rec @label NamedPattern @fields NamedPattern>
|
||||
|
||||
; [a b c] ----> <tuple [<ref a> <ref b> <ref c>]>
|
||||
/ <tuple [@patterns NamedPattern ...]>
|
||||
/ <tuple @patterns [NamedPattern ...]>
|
||||
|
||||
; [a b c ...] ----> <tuple* [<ref a> <ref b>] <ref c>]>
|
||||
/ <tuple* [@fixed NamedPattern ...] @variable NamedSimplePattern>
|
||||
|
||||
; #{p} ----> <setof <ref p>>
|
||||
/ <setof @pattern SimplePattern>
|
||||
|
||||
; {k: v, ...:...} ----> <dictof <ref k> <ref v>>
|
||||
/ <dictof @key SimplePattern @value SimplePattern>
|
||||
; [a b c ...] ----> <tuple* [<ref a> <ref b>] <seqof <ref c>>>
|
||||
/ <tuple* @fixed [NamedPattern ...] @variable NamedSimplePattern>
|
||||
|
||||
; {a: b, c: d} ----> <dict {a: <ref b>, c: <ref d>}>
|
||||
/ <dict @entries DictionaryEntries>
|
||||
|
|
Loading…
Reference in New Issue