Much improved refactoring/repair of metaschema

This commit is contained in:
Tony Garnock-Jones 2021-05-24 00:15:31 +02:00
parent 1d6956fa55
commit 2559a4713f
12 changed files with 328 additions and 417 deletions

View File

@ -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;
}

View File

@ -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)!;
}

View File

@ -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 {

View File

@ -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[] {

View File

@ -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]) =>

View File

@ -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;
}

View File

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

View File

@ -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!;

View File

@ -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));

View File

@ -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');

View File

@ -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€„„

View File

@ -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>