diff --git a/implementations/javascript/packages/core/src/annotated.ts b/implementations/javascript/packages/core/src/annotated.ts index cbdb2c4..054f570 100644 --- a/implementations/javascript/packages/core/src/annotated.ts +++ b/implementations/javascript/packages/core/src/annotated.ts @@ -110,6 +110,10 @@ export function annotate(v0: Value, ...anns: Value[]) return v; } +export function annotations(v: Value): Array> { + return Annotated.isAnnotated(v) ? v.annotations : []; +} + export function position(v: Value): Position | null { return Annotated.isAnnotated(v) ? v.pos : null; } diff --git a/implementations/javascript/packages/schema/src/checker.ts b/implementations/javascript/packages/schema/src/checker.ts index 9f9f066..8e8b118 100644 --- a/implementations/javascript/packages/schema/src/checker.ts +++ b/implementations/javascript/packages/schema/src/checker.ts @@ -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, 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)!; -} diff --git a/implementations/javascript/packages/schema/src/compiler/context.ts b/implementations/javascript/packages/schema/src/compiler/context.ts index 13b36a8..7636719 100644 --- a/implementations/javascript/packages/schema/src/compiler/context.ts +++ b/implementations/javascript/packages/schema/src/compiler/context.ts @@ -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 { diff --git a/implementations/javascript/packages/schema/src/compiler/genconverter.ts b/implementations/javascript/packages/schema/src/compiler/genconverter.ts index 0e6a014..16e0689 100644 --- a/implementations/javascript/packages/schema/src/compiler/genconverter.ts +++ b/implementations/javascript/packages/schema/src/compiler/genconverter.ts @@ -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[] { diff --git a/implementations/javascript/packages/schema/src/compiler/genunconverter.ts b/implementations/javascript/packages/schema/src/compiler/genunconverter.ts index e891910..70ed0bd 100644 --- a/implementations/javascript/packages/schema/src/compiler/genunconverter.ts +++ b/implementations/javascript/packages/schema/src/compiler/genunconverter.ts @@ -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]) => diff --git a/implementations/javascript/packages/schema/src/gen/schema.ts b/implementations/javascript/packages/schema/src/gen/schema.ts index 2ff8905..737bb25 100644 --- a/implementations/javascript/packages/schema/src/gen/schema.ts +++ b/implementations/javascript/packages/schema/src/gen/schema.ts @@ -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, "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): CompoundPattern {return {"_variant": "tuple", "patterns": patterns};}; export function tuple$STAR$({fixed, variable}: {fixed: Array, 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) | 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) | 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,18 +425,16 @@ export function toDefinition(v: _val): undefined | Definition { let _tmp3: (Array<_val>) | undefined; let _tmp4: (Array) | undefined; _tmp3 = v[0].slice(2); - { - _tmp4 = []; - for (const _tmp5 of _tmp3) { - let _tmp6: (NamedAlternative) | undefined; - _tmp6 = toNamedAlternative(_tmp5); - if (_tmp6 !== void 0) {_tmp4.push(_tmp6); continue;}; - _tmp4 = void 0; - break; - }; - if (_tmp4 !== void 0) { - result = {"_variant": "or", "pattern0": _tmp1, "pattern1": _tmp2, "patternN": _tmp4}; - }; + _tmp4 = []; + for (const _tmp5 of _tmp3) { + let _tmp6: (NamedAlternative) | undefined; + _tmp6 = toNamedAlternative(_tmp5); + if (_tmp6 !== void 0) {_tmp4.push(_tmp6); continue;}; + _tmp4 = void 0; + break; + }; + if (_tmp4 !== void 0) { + result = {"_variant": "or", "pattern0": _tmp1, "pattern1": _tmp2, "patternN": _tmp4}; }; }; }; @@ -453,18 +456,16 @@ export function toDefinition(v: _val): undefined | Definition { let _tmp10: (Array<_val>) | undefined; let _tmp11: (Array) | undefined; _tmp10 = v[0].slice(2); - { - _tmp11 = []; - for (const _tmp12 of _tmp10) { - let _tmp13: (NamedPattern) | undefined; - _tmp13 = toNamedPattern(_tmp12); - if (_tmp13 !== void 0) {_tmp11.push(_tmp13); continue;}; - _tmp11 = void 0; - break; - }; - if (_tmp11 !== void 0) { - result = {"_variant": "and", "pattern0": _tmp8, "pattern1": _tmp9, "patternN": _tmp11}; - }; + _tmp11 = []; + for (const _tmp12 of _tmp10) { + let _tmp13: (NamedPattern) | undefined; + _tmp13 = toNamedPattern(_tmp12); + if (_tmp13 !== void 0) {_tmp11.push(_tmp13); continue;}; + _tmp11 = void 0; + break; + }; + if (_tmp11 !== void 0) { + result = {"_variant": "and", "pattern0": _tmp8, "pattern1": _tmp9, "patternN": _tmp11}; }; }; }; @@ -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) | undefined; + _tmp4 = void 0; if (_.Array.isArray(v[0])) { - let _tmp4: (Array<_val>) | undefined; - let _tmp5: (Array) | 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; - break; - }; - if (_tmp5 !== void 0) {result = {"_variant": "tuple", "patterns": _tmp5};}; + _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 (_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; - if (_tmp8 !== void 0) { + let _tmp7: (null) | undefined; + _tmp7 = _.is(v.label, $tuple$STAR$) ? null : void 0; + if (_tmp7 !== void 0) { + let _tmp8: (Array) | undefined; + _tmp8 = void 0; if (_.Array.isArray(v[0])) { - let _tmp9: (Array<_val>) | undefined; - let _tmp10: (Array) | 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};}; - }; + _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) { + 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 _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};}; - }; - }; - }; - 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 _tmp0: (Array) | undefined; let result: undefined | ModulePath; + _tmp0 = void 0; if (_.Array.isArray(v)) { - let _tmp0: (Array) | undefined; _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; } diff --git a/implementations/javascript/packages/schema/src/gentype.ts b/implementations/javascript/packages/schema/src/gentype.ts index 22ccea5..33249b6 100644 --- a/implementations/javascript/packages/schema/src/gentype.ts +++ b/implementations/javascript/packages/schema/src/gentype.ts @@ -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); } diff --git a/implementations/javascript/packages/schema/src/meta.ts b/implementations/javascript/packages/schema/src/meta.ts index 8d839b1..84b5a6e 100644 --- a/implementations/javascript/packages/schema/src/meta.ts +++ b/implementations/javascript/packages/schema/src/meta.ts @@ -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!; diff --git a/implementations/javascript/packages/schema/src/reader.ts b/implementations/javascript/packages/schema/src/reader.ts index ce47e54..5f90ee6 100644 --- a/implementations/javascript/packages/schema/src/reader.ts +++ b/implementations/javascript/packages/schema/src/reader.ts @@ -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) 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): Pattern { function parseSimple(item0: Input, ks: (p: SimplePattern) => A, kf: () => A): A { const pos = position(item0); @@ -236,6 +240,20 @@ function parsePattern(name: symbol, body0: Array): 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(item)) { + if (item.size !== 1) complain(); + const [vp] = item.entries(); + return ks(M.SimplePattern.setof(walkSimple(vp))); + } else if (Dictionary.isDictionary(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,47 +266,6 @@ function parsePattern(name: symbol, body0: Array): Pattern { const item = peel(item0); function complain(): never { invalidPattern(stringify(name), item, pos); } - 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( - named: (p: M.NamedSimplePattern_) => R, - anonymous: (p: P) => R, - recur: (b: Input) => P, - literalName?: Input): (b: Input) => R - { - return (b: Input) => { - let name = findName(b); - if (name === false) { - if (literalName !== void 0 && typeof literalName === 'symbol') { - name = literalName; - } - } - if (name === false) { - return anonymous(recur(b)); - } - return named(M.NamedSimplePattern_({ name, pattern: parseSimple(b, p => p, () => - namedMustBeSimple(position(b))) })); - }; - } - const maybeNamed = _maybeNamed(M.NamedPattern.named, M.NamedPattern.anonymous, walk); - const maybeNamedSimple = - _maybeNamed(M.NamedSimplePattern.named, M.NamedSimplePattern.anonymous, walkSimple); - - function parseArrayLike(item: Array): 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, M._embedded>(item)) { const label = item.label; if (Record.isRecord(label)) { @@ -306,38 +283,64 @@ function parsePattern(name: symbol, body0: Array): Pattern { } 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))) + 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 parseArrayLike(item); - } else if (Dictionary.isDictionary(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( - ([k, vp]) => [ - strip(k), - _maybeNamed( - M.NamedSimplePattern.named, - M.NamedSimplePattern.anonymous, - walkSimple, - k)(vp) - ]))); - } - } else if (Set.isSet(item)) { - if (item.size !== 1) complain(); - const [vp] = item.entries(); - return M.CompoundPattern.setof(walkSimple(vp)); + return M.CompoundPattern.tuple(item.map(maybeNamed)); + } else if (Dictionary.isDictionary(item) && !item.has(M.DOTDOTDOT)) { + return M.CompoundPattern.dict( + M.DictionaryEntries(item.mapEntries( + ([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)); + }); + + function _maybeNamed( + named: (p: M.NamedSimplePattern_) => R, + anonymous: (p: P) => R, + recur: (b: Input) => P, + literalName?: Input): (b: Input) => R + { + return (b: Input) => { + let name = findName(b); + if (name === false) { + if (literalName !== void 0 && typeof literalName === 'symbol') { + name = literalName; + } + } + if (name === false) { + return anonymous(recur(b)); + } + return named(M.NamedSimplePattern_({ name, pattern: parseSimple(b, p => p, () => + namedMustBeSimple(position(b))) })); + }; + } + const maybeNamed = _maybeNamed(M.NamedPattern.named, M.NamedPattern.anonymous, walk); + const maybeNamedSimple = + _maybeNamed(M.NamedSimplePattern.named, M.NamedSimplePattern.anonymous, walkSimple); + const body = peel(body0) as Array; if (body.length !== 1) { invalidPattern(stringify(name), body, body.length > 0 ? position(body[0]) : position(body)); diff --git a/implementations/javascript/packages/schema/src/type.ts b/implementations/javascript/packages/schema/src/type.ts index e03d1de..1329b97 100644 --- a/implementations/javascript/packages/schema/src/type.ts +++ b/implementations/javascript/packages/schema/src/type.ts @@ -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; export type FieldMap = Map; 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'); diff --git a/schema/schema.bin b/schema/schema.bin index 07d59f6..6b74e32 100644 --- a/schema/schema.bin +++ b/schema/schema.bin @@ -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€„„ \ No newline at end of file +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€„„ \ No newline at end of file diff --git a/schema/schema.prs b/schema/schema.prs index 9f20584..3b2cb6f 100644 --- a/schema/schema.prs +++ b/schema/schema.prs @@ -47,6 +47,15 @@ SimplePattern = ; =symbol, < any>, or plain non-symbol atom / + ; [p ...] ----> >; see also tuple* below. + / + + ; #{p} ----> > + / + + ; {k: v, ...:...} ----> > + / + ; symbol, symbol.symbol, symbol.symbol.symbol, ... / Ref . @@ -58,16 +67,10 @@ CompoundPattern = / ; [a b c] ----> ]> - / + / - ; [a b c ...] ----> ] ]> - / - - ; #{p} ----> > - / - - ; {k: v, ...:...} ----> > - / + ; [a b c ...] ----> ] >> + / ; {a: b, c: d} ----> , c: }> /