forked from syndicate-lang/preserves
Constrain names/identifiers in schemas to be lowest-common-denominator.
This commit is contained in:
parent
da513a249e
commit
fdb43f6292
|
@ -28,9 +28,11 @@ class Checker {
|
||||||
const name = sym.description!;
|
const name = sym.description!;
|
||||||
if (scope.has(name)) {
|
if (scope.has(name)) {
|
||||||
this.recordProblem(context, `duplicate binding named ${JSON.stringify(name)}`);
|
this.recordProblem(context, `duplicate binding named ${JSON.stringify(name)}`);
|
||||||
} else {
|
|
||||||
scope.add(name);
|
|
||||||
}
|
}
|
||||||
|
if (!M.isValidToken(name)) {
|
||||||
|
this.recordProblem(context, `invalid binding name ${JSON.stringify(name)}`);
|
||||||
|
}
|
||||||
|
scope.add(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkDefinition(def: M.Definition, name: symbol): void {
|
checkDefinition(def: M.Definition, name: symbol): void {
|
||||||
|
@ -42,6 +44,9 @@ class Checker {
|
||||||
if (labels.has(variantLabel)) {
|
if (labels.has(variantLabel)) {
|
||||||
this.recordProblem(context, `duplicate variant label`);
|
this.recordProblem(context, `duplicate variant label`);
|
||||||
}
|
}
|
||||||
|
if (!M.isValidToken(variantLabel)) {
|
||||||
|
this.recordProblem(context, `invalid variant label`);
|
||||||
|
}
|
||||||
labels.add(variantLabel);
|
labels.add(variantLabel);
|
||||||
this.checkPattern(new Set(), pattern, context, ValueAvailability.AVAILABLE);
|
this.checkPattern(new Set(), pattern, context, ValueAvailability.AVAILABLE);
|
||||||
});
|
});
|
||||||
|
@ -87,6 +92,12 @@ class Checker {
|
||||||
if (p.value._variant !== 'lit' && availability === ValueAvailability.NOT_AVAILABLE) {
|
if (p.value._variant !== 'lit' && availability === ValueAvailability.NOT_AVAILABLE) {
|
||||||
this.recordProblem(context, 'cannot recover serialization of non-literal pattern');
|
this.recordProblem(context, 'cannot recover serialization of non-literal pattern');
|
||||||
}
|
}
|
||||||
|
if (p.value._variant === 'Ref' &&
|
||||||
|
!(M.isValidToken(p.value.value.name.description!) &&
|
||||||
|
p.value.value.module.every(n => M.isValidToken(n.description!))))
|
||||||
|
{
|
||||||
|
this.recordProblem(context, 'invalid reference name');
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'CompoundPattern':
|
case 'CompoundPattern':
|
||||||
((p: M.CompoundPattern): void => {
|
((p: M.CompoundPattern): void => {
|
||||||
|
@ -99,7 +110,7 @@ class Checker {
|
||||||
p.patterns.forEach((pp, i) =>
|
p.patterns.forEach((pp, i) =>
|
||||||
this.checkNamedPattern(scope, pp, `item ${i} of ${context}`));
|
this.checkNamedPattern(scope, pp, `item ${i} of ${context}`));
|
||||||
break;
|
break;
|
||||||
case 'tuple*':
|
case 'tuplePrefix':
|
||||||
p.fixed.forEach((pp, i) =>
|
p.fixed.forEach((pp, i) =>
|
||||||
this.checkNamedPattern(scope, pp, `item ${i} of ${context}`));
|
this.checkNamedPattern(scope, pp, `item ${i} of ${context}`));
|
||||||
this.checkNamedPattern(
|
this.checkNamedPattern(
|
||||||
|
|
|
@ -210,7 +210,7 @@ function converterForCompound(
|
||||||
converterFor(ctx, p.fields, src, ks, true))))];
|
converterFor(ctx, p.fields, src, ks, true))))];
|
||||||
case 'tuple':
|
case 'tuple':
|
||||||
return converterForTuple(ctx, p.patterns, src, knownArray, void 0, ks);
|
return converterForTuple(ctx, p.patterns, src, knownArray, void 0, ks);
|
||||||
case 'tuple*':
|
case 'tuplePrefix':
|
||||||
return converterForTuple(ctx, p.fixed, src, knownArray, p.variable, ks);
|
return converterForTuple(ctx, p.fixed, src, knownArray, p.variable, ks);
|
||||||
case 'dict': {
|
case 'dict': {
|
||||||
const entries = Array.from(p.entries);
|
const entries = Array.from(p.entries);
|
||||||
|
|
|
@ -71,7 +71,7 @@ function compoundFields(fs: FieldMap, resolver: RefResolver, p: M.CompoundPatter
|
||||||
case 'tuple':
|
case 'tuple':
|
||||||
p.patterns.forEach(pp => gatherFields(fs, resolver, pp));
|
p.patterns.forEach(pp => gatherFields(fs, resolver, pp));
|
||||||
break;
|
break;
|
||||||
case 'tuple*':
|
case 'tuplePrefix':
|
||||||
p.fixed.forEach(pp => gatherFields(fs, resolver, pp));
|
p.fixed.forEach(pp => gatherFields(fs, resolver, pp));
|
||||||
gatherFields(fs, resolver, M.promoteNamedSimplePattern(p.variable));
|
gatherFields(fs, resolver, M.promoteNamedSimplePattern(p.variable));
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -85,7 +85,7 @@ function unconverterFor(ctx: FunctionContext, p: M.Pattern, src: string): Item {
|
||||||
case 'tuple':
|
case 'tuple':
|
||||||
return brackets(... p.patterns.map(pp =>
|
return brackets(... p.patterns.map(pp =>
|
||||||
unconverterForNamed(ctx, pp, src)));
|
unconverterForNamed(ctx, pp, src)));
|
||||||
case 'tuple*': {
|
case 'tuplePrefix': {
|
||||||
const varExp =
|
const varExp =
|
||||||
unconverterForNamed(ctx, M.promoteNamedSimplePattern(p.variable), src);
|
unconverterForNamed(ctx, M.promoteNamedSimplePattern(p.variable), src);
|
||||||
if (p.fixed.length === 0) {
|
if (p.fixed.length === 0) {
|
||||||
|
|
|
@ -26,7 +26,7 @@ export const $schema = Symbol.for("schema");
|
||||||
export const $seqof = Symbol.for("seqof");
|
export const $seqof = Symbol.for("seqof");
|
||||||
export const $setof = Symbol.for("setof");
|
export const $setof = Symbol.for("setof");
|
||||||
export const $tuple = Symbol.for("tuple");
|
export const $tuple = Symbol.for("tuple");
|
||||||
export const $tuple$STAR$ = Symbol.for("tuple*");
|
export const $tuplePrefix = Symbol.for("tuplePrefix");
|
||||||
export const $version = Symbol.for("version");
|
export const $version = Symbol.for("version");
|
||||||
export const __lit6 = false;
|
export const __lit6 = false;
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ export type CompoundPattern = (
|
||||||
{"_variant": "rec", "label": NamedPattern, "fields": NamedPattern} |
|
{"_variant": "rec", "label": NamedPattern, "fields": NamedPattern} |
|
||||||
{"_variant": "tuple", "patterns": Array<NamedPattern>} |
|
{"_variant": "tuple", "patterns": Array<NamedPattern>} |
|
||||||
{
|
{
|
||||||
"_variant": "tuple*",
|
"_variant": "tuplePrefix",
|
||||||
"fixed": Array<NamedPattern>,
|
"fixed": Array<NamedPattern>,
|
||||||
"variable": NamedSimplePattern
|
"variable": NamedSimplePattern
|
||||||
} |
|
} |
|
||||||
|
@ -190,7 +190,7 @@ export namespace SimplePattern {
|
||||||
export namespace CompoundPattern {
|
export namespace CompoundPattern {
|
||||||
export function rec({label, fields}: {label: NamedPattern, fields: NamedPattern}): CompoundPattern {return {"_variant": "rec", "label": label, "fields": fields};};
|
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(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 tuplePrefix({fixed, variable}: {fixed: Array<NamedPattern>, variable: NamedSimplePattern}): CompoundPattern {return {"_variant": "tuplePrefix", "fixed": fixed, "variable": variable};};
|
||||||
export function dict(entries: DictionaryEntries): CompoundPattern {return {"_variant": "dict", "entries": entries};};
|
export function dict(entries: DictionaryEntries): CompoundPattern {return {"_variant": "dict", "entries": entries};};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -685,7 +685,7 @@ export function toCompoundPattern(v: _val): undefined | CompoundPattern {
|
||||||
if (result === void 0) {
|
if (result === void 0) {
|
||||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
if (_.Record.isRecord<_val, _.Tuple<_val>, _embedded>(v)) {
|
||||||
let _tmp7: (null) | undefined;
|
let _tmp7: (null) | undefined;
|
||||||
_tmp7 = _.is(v.label, $tuple$STAR$) ? null : void 0;
|
_tmp7 = _.is(v.label, $tuplePrefix) ? null : void 0;
|
||||||
if (_tmp7 !== void 0) {
|
if (_tmp7 !== void 0) {
|
||||||
let _tmp8: (Array<NamedPattern>) | undefined;
|
let _tmp8: (Array<NamedPattern>) | undefined;
|
||||||
_tmp8 = void 0;
|
_tmp8 = void 0;
|
||||||
|
@ -702,7 +702,7 @@ export function toCompoundPattern(v: _val): undefined | CompoundPattern {
|
||||||
if (_tmp8 !== void 0) {
|
if (_tmp8 !== void 0) {
|
||||||
let _tmp11: (NamedSimplePattern) | undefined;
|
let _tmp11: (NamedSimplePattern) | undefined;
|
||||||
_tmp11 = toNamedSimplePattern(v[1]);
|
_tmp11 = toNamedSimplePattern(v[1]);
|
||||||
if (_tmp11 !== void 0) {result = {"_variant": "tuple*", "fixed": _tmp8, "variable": _tmp11};};
|
if (_tmp11 !== void 0) {result = {"_variant": "tuplePrefix", "fixed": _tmp8, "variable": _tmp11};};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -728,9 +728,9 @@ export function fromCompoundPattern(_v: CompoundPattern): _val {
|
||||||
return _.Record($rec, [fromNamedPattern(_v["label"]), fromNamedPattern(_v["fields"])]);
|
return _.Record($rec, [fromNamedPattern(_v["label"]), fromNamedPattern(_v["fields"])]);
|
||||||
};
|
};
|
||||||
case "tuple": {return _.Record($tuple, [_v["patterns"].map(v => fromNamedPattern(v))]);};
|
case "tuple": {return _.Record($tuple, [_v["patterns"].map(v => fromNamedPattern(v))]);};
|
||||||
case "tuple*": {
|
case "tuplePrefix": {
|
||||||
return _.Record(
|
return _.Record(
|
||||||
$tuple$STAR$,
|
$tuplePrefix,
|
||||||
[
|
[
|
||||||
_v["fixed"].map(v => fromNamedPattern(v)),
|
_v["fixed"].map(v => fromNamedPattern(v)),
|
||||||
fromNamedSimplePattern(_v["variable"])
|
fromNamedSimplePattern(_v["variable"])
|
||||||
|
|
|
@ -7,16 +7,25 @@ export * from './gen/schema';
|
||||||
|
|
||||||
export type Input = M._val;
|
export type Input = M._val;
|
||||||
|
|
||||||
|
export function qidLast(s: string): string {
|
||||||
|
const m = s.match(/^(.*\.)?([^.]+)$/);
|
||||||
|
return m![2];
|
||||||
|
}
|
||||||
|
|
||||||
export function isValidToken(s: string): boolean {
|
export function isValidToken(s: string): boolean {
|
||||||
return /^[a-zA-Z][a-zA-Z_0-9]*$/.test(s);
|
return /^[a-zA-Z][a-zA-Z_0-9]*$/.test(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isValidQid(s: string): boolean {
|
||||||
|
return s.split('.').every(isValidToken);
|
||||||
|
}
|
||||||
|
|
||||||
export function isValidJsId(s: string): boolean {
|
export function isValidJsId(s: string): boolean {
|
||||||
return /^[$_a-zA-Z][$_a-zA-Z0-9]*$/.test(s) && !isJsKeyword(s);
|
return /^[$_a-zA-Z][$_a-zA-Z0-9]*$/.test(s) && !isJsKeyword(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function jsId(v: string, kf?: () => string): string {
|
export function jsId(v: string, kf?: () => string): string {
|
||||||
return jsToken(v.replace('$', '$$').replace('*', '$STAR$'), kf);
|
return jsToken(v.replace('$', '$$'), kf);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function jsToken(s: string, kf?: () => string): string {
|
export function jsToken(s: string, kf?: () => string): string {
|
||||||
|
|
|
@ -93,7 +93,7 @@ export function parseSchema(toplevelTokens: Array<Input>, options: SchemaReaderO
|
||||||
const stx = peel(clause[1]);
|
const stx = peel(clause[1]);
|
||||||
if (stx === false) {
|
if (stx === false) {
|
||||||
embeddedType = M.EmbeddedTypeName.$false();
|
embeddedType = M.EmbeddedTypeName.$false();
|
||||||
} else if (typeof stx === 'symbol') {
|
} else if (typeof stx === 'symbol' && M.isValidQid(stx.description!)) {
|
||||||
embeddedType = M.EmbeddedTypeName.Ref(parseRef(stx.description!, pos));
|
embeddedType = M.EmbeddedTypeName.Ref(parseRef(stx.description!, pos));
|
||||||
} else {
|
} else {
|
||||||
invalidPattern('embedded type name specification', stx, pos);
|
invalidPattern('embedded type name specification', stx, pos);
|
||||||
|
@ -140,7 +140,8 @@ function parseDefinition(name: symbol, pos: Position | null, body: Array<Input>)
|
||||||
p.value.label._variant === 'anonymous' &&
|
p.value.label._variant === 'anonymous' &&
|
||||||
p.value.label.value._variant === 'SimplePattern' &&
|
p.value.label.value._variant === 'SimplePattern' &&
|
||||||
p.value.label.value.value._variant === 'lit' &&
|
p.value.label.value.value._variant === 'lit' &&
|
||||||
typeof p.value.label.value.value.value === 'symbol')
|
typeof p.value.label.value.value.value === 'symbol' &&
|
||||||
|
M.isValidToken(p.value.label.value.value.value.description!))
|
||||||
{
|
{
|
||||||
return M.NamedAlternative({
|
return M.NamedAlternative({
|
||||||
variantLabel: p.value.label.value.value.value.description!,
|
variantLabel: p.value.label.value.value.value.description!,
|
||||||
|
@ -148,10 +149,11 @@ function parseDefinition(name: symbol, pos: Position | null, body: Array<Input>)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (p._variant === 'SimplePattern' &&
|
if (p._variant === 'SimplePattern' &&
|
||||||
p.value._variant === 'Ref')
|
p.value._variant === 'Ref' &&
|
||||||
|
M.isValidQid(p.value.value.name.description!))
|
||||||
{
|
{
|
||||||
return M.NamedAlternative({
|
return M.NamedAlternative({
|
||||||
variantLabel: p.value.value.name.description!,
|
variantLabel: M.qidLast(p.value.value.name.description!),
|
||||||
pattern: p
|
pattern: p
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -224,9 +226,15 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
|
||||||
case 'string': return ks(M.SimplePattern.atom(M.AtomKind.String()));
|
case 'string': return ks(M.SimplePattern.atom(M.AtomKind.String()));
|
||||||
case 'bytes': return ks(M.SimplePattern.atom(M.AtomKind.ByteString()));
|
case 'bytes': return ks(M.SimplePattern.atom(M.AtomKind.ByteString()));
|
||||||
case 'symbol': return ks(M.SimplePattern.atom(M.AtomKind.Symbol()));
|
case 'symbol': return ks(M.SimplePattern.atom(M.AtomKind.Symbol()));
|
||||||
default: return ks((str[0] === '=')
|
default: {
|
||||||
? M.SimplePattern.lit(Symbol.for(str.slice(1)))
|
if (str[0] === '=') {
|
||||||
: M.SimplePattern.Ref(parseRef(str, pos)));
|
return ks(M.SimplePattern.lit(Symbol.for(str.slice(1))));
|
||||||
|
} else if (M.isValidQid(str)) {
|
||||||
|
return ks(M.SimplePattern.Ref(parseRef(str, pos)));
|
||||||
|
} else {
|
||||||
|
complain();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (Record.isRecord<Input, Tuple<Input>, M._embedded>(item)) {
|
} else if (Record.isRecord<Input, Tuple<Input>, M._embedded>(item)) {
|
||||||
const label = item.label;
|
const label = item.label;
|
||||||
|
@ -294,7 +302,7 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
|
||||||
const variableTemplateInput = item[item.length - 2];
|
const variableTemplateInput = item[item.length - 2];
|
||||||
const variablePart =
|
const variablePart =
|
||||||
transferAnnotations([variableTemplateInput, M.DOTDOTDOT], variableTemplateInput);
|
transferAnnotations([variableTemplateInput, M.DOTDOTDOT], variableTemplateInput);
|
||||||
return M.CompoundPattern.tuple$STAR$({
|
return M.CompoundPattern.tuplePrefix({
|
||||||
fixed: item.slice(0, item.length - 2).map(maybeNamed),
|
fixed: item.slice(0, item.length - 2).map(maybeNamed),
|
||||||
variable: maybeNamedSimple(variablePart),
|
variable: maybeNamedSimple(variablePart),
|
||||||
});
|
});
|
||||||
|
@ -330,7 +338,10 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
|
||||||
return (b: Input) => {
|
return (b: Input) => {
|
||||||
let name = findName(b);
|
let name = findName(b);
|
||||||
if (name === false) {
|
if (name === false) {
|
||||||
if (literalName !== void 0 && typeof literalName === 'symbol') {
|
if (literalName !== void 0 &&
|
||||||
|
typeof literalName === 'symbol' &&
|
||||||
|
M.isValidToken(literalName.description!))
|
||||||
|
{
|
||||||
name = literalName;
|
name = literalName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -358,7 +369,7 @@ function findName(x: Input): symbol | false {
|
||||||
if (!Annotated.isAnnotated<never>(x)) return false;
|
if (!Annotated.isAnnotated<never>(x)) return false;
|
||||||
for (const a0 of x.annotations) {
|
for (const a0 of x.annotations) {
|
||||||
const a = peel(a0);
|
const a = peel(a0);
|
||||||
if (typeof a === 'symbol') return a;
|
if (typeof a === 'symbol') return M.isValidToken(a.description!) && a;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#lang racket/base
|
#lang racket/base
|
||||||
|
|
||||||
(provide schema-check-problems
|
(provide schema-check-problems
|
||||||
schema-check-problems!)
|
schema-check-problems!
|
||||||
|
valid-id?)
|
||||||
|
|
||||||
(require racket/match)
|
(require racket/match)
|
||||||
(require (only-in racket/list check-duplicates))
|
(require (only-in racket/list check-duplicates))
|
||||||
|
@ -11,6 +12,10 @@
|
||||||
(require (only-in "type.rkt" unwrap))
|
(require (only-in "type.rkt" unwrap))
|
||||||
(require "gen/schema.rkt")
|
(require "gen/schema.rkt")
|
||||||
|
|
||||||
|
(define (valid-id? x)
|
||||||
|
(and (symbol? x)
|
||||||
|
(regexp-match? #px"^[a-zA-Z][a-zA-Z_0-9]*$" (symbol->string x))))
|
||||||
|
|
||||||
(define (schema-check-problems schema)
|
(define (schema-check-problems schema)
|
||||||
(define problems '())
|
(define problems '())
|
||||||
|
|
||||||
|
@ -20,20 +25,27 @@
|
||||||
(define (check-binding context scope n)
|
(define (check-binding context scope n)
|
||||||
(when (hash-has-key? scope n)
|
(when (hash-has-key? scope n)
|
||||||
(problem! context "duplicate binding ~v" n))
|
(problem! context "duplicate binding ~v" n))
|
||||||
|
(when (not (valid-id? n))
|
||||||
|
(problem! context "invalid binding name ~v" n))
|
||||||
(hash-set! scope n #t))
|
(hash-set! scope n #t))
|
||||||
|
|
||||||
(define (check-pattern context scope p value-available?)
|
(define (check-pattern context scope p value-available?)
|
||||||
(match (unwrap p)
|
(match (unwrap p)
|
||||||
[(SimplePattern-lit _)
|
[(SimplePattern-lit _)
|
||||||
(void)]
|
(void)]
|
||||||
[(? SimplePattern?)
|
[(? SimplePattern? u)
|
||||||
(when (not value-available?) (problem! context "necessary information not captured"))]
|
(when (not value-available?) (problem! context "necessary information not captured"))
|
||||||
|
(match u
|
||||||
|
[(SimplePattern-Ref (Ref (ModulePath ids) id))
|
||||||
|
(when (not (andmap valid-id? (cons id ids)))
|
||||||
|
(problem! context "invalid reference name"))]
|
||||||
|
[_ (void)])]
|
||||||
[(CompoundPattern-rec l f)
|
[(CompoundPattern-rec l f)
|
||||||
(check-named-pattern (cons "label" context) scope l)
|
(check-named-pattern (cons "label" context) scope l)
|
||||||
(check-named-pattern (cons "fields" context) scope f)]
|
(check-named-pattern (cons "fields" context) scope f)]
|
||||||
[(CompoundPattern-tuple ps)
|
[(CompoundPattern-tuple ps)
|
||||||
(for [(p (in-list ps)) (i (in-naturals))] (check-named-pattern (cons i context) scope p))]
|
(for [(p (in-list ps)) (i (in-naturals))] (check-named-pattern (cons i context) scope p))]
|
||||||
[(CompoundPattern-tuple* ps v)
|
[(CompoundPattern-tuplePrefix ps v)
|
||||||
(for [(p (in-list ps)) (i (in-naturals))] (check-named-pattern (cons i context) scope p))
|
(for [(p (in-list ps)) (i (in-naturals))] (check-named-pattern (cons i context) scope p))
|
||||||
(check-named-pattern (cons "tail" context) scope v)]
|
(check-named-pattern (cons "tail" context) scope v)]
|
||||||
[(CompoundPattern-dict (DictionaryEntries entries))
|
[(CompoundPattern-dict (DictionaryEntries entries))
|
||||||
|
@ -55,7 +67,9 @@
|
||||||
(unless (void? (check-duplicates alts #:key NamedAlternative-variantLabel #:default (void)))
|
(unless (void? (check-duplicates alts #:key NamedAlternative-variantLabel #:default (void)))
|
||||||
(problem! context "duplicate variant label"))
|
(problem! context "duplicate variant label"))
|
||||||
(for [(a (in-list alts))]
|
(for [(a (in-list alts))]
|
||||||
(check-pattern context (make-hash) (NamedAlternative-pattern a) #t))]
|
(define label (string->symbol (NamedAlternative-variantLabel a)))
|
||||||
|
(when (not (valid-id? label)) (problem! context "invalid variant label ~v" label))
|
||||||
|
(check-pattern (cons label context) (make-hash) (NamedAlternative-pattern a) #t))]
|
||||||
[(Definition-and p0 p1 pN)
|
[(Definition-and p0 p1 pN)
|
||||||
(define scope (make-hash))
|
(define scope (make-hash))
|
||||||
(for [(p (in-list (list* p0 p1 pN)))]
|
(for [(p (in-list (list* p0 p1 pN)))]
|
||||||
|
|
|
@ -73,7 +73,7 @@
|
||||||
(walk fields-named-pat)]
|
(walk fields-named-pat)]
|
||||||
[(CompoundPattern-tuple named-pats)
|
[(CompoundPattern-tuple named-pats)
|
||||||
(for-each walk named-pats)]
|
(for-each walk named-pats)]
|
||||||
[(CompoundPattern-tuple* fixed-named-pats variable-named-pat)
|
[(CompoundPattern-tuplePrefix fixed-named-pats variable-named-pat)
|
||||||
(for-each walk fixed-named-pats)
|
(for-each walk fixed-named-pats)
|
||||||
(walk variable-named-pat)]
|
(walk variable-named-pat)]
|
||||||
[(CompoundPattern-dict (DictionaryEntries entries))
|
[(CompoundPattern-dict (DictionaryEntries entries))
|
||||||
|
|
|
@ -120,7 +120,7 @@
|
||||||
(define (CompoundPattern? p)
|
(define (CompoundPattern? p)
|
||||||
(or (CompoundPattern-rec? p)
|
(or (CompoundPattern-rec? p)
|
||||||
(CompoundPattern-tuple? p)
|
(CompoundPattern-tuple? p)
|
||||||
(CompoundPattern-tuple*? p)
|
(CompoundPattern-tuplePrefix? p)
|
||||||
(CompoundPattern-dict? p)))
|
(CompoundPattern-dict? p)))
|
||||||
(struct
|
(struct
|
||||||
CompoundPattern-rec
|
CompoundPattern-rec
|
||||||
|
@ -150,7 +150,7 @@
|
||||||
(list
|
(list
|
||||||
(for/list ((item (in-list ?patterns))) (*->preserve item)))))))))
|
(for/list ((item (in-list ?patterns))) (*->preserve item)))))))))
|
||||||
(struct
|
(struct
|
||||||
CompoundPattern-tuple*
|
CompoundPattern-tuplePrefix
|
||||||
(fixed variable)
|
(fixed variable)
|
||||||
#:transparent
|
#:transparent
|
||||||
#:methods
|
#:methods
|
||||||
|
@ -159,9 +159,9 @@
|
||||||
(define (->preserve preservable)
|
(define (->preserve preservable)
|
||||||
(match
|
(match
|
||||||
preservable
|
preservable
|
||||||
((CompoundPattern-tuple* ?fixed ?variable)
|
((CompoundPattern-tuplePrefix ?fixed ?variable)
|
||||||
(record
|
(record
|
||||||
'tuple*
|
'tuplePrefix
|
||||||
(list
|
(list
|
||||||
(for/list ((item (in-list ?fixed))) (*->preserve item))
|
(for/list ((item (in-list ?fixed))) (*->preserve item))
|
||||||
(*->preserve ?variable))))))))
|
(*->preserve ?variable))))))))
|
||||||
|
@ -197,11 +197,11 @@
|
||||||
(CompoundPattern-tuple ?patterns))
|
(CompoundPattern-tuple ?patterns))
|
||||||
((and dest
|
((and dest
|
||||||
(record
|
(record
|
||||||
'tuple*
|
'tuplePrefix
|
||||||
(list
|
(list
|
||||||
(list (app parse-NamedPattern (and ?fixed (not (== eof)))) ...)
|
(list (app parse-NamedPattern (and ?fixed (not (== eof)))) ...)
|
||||||
(app parse-NamedSimplePattern (and ?variable (not (== eof)))))))
|
(app parse-NamedSimplePattern (and ?variable (not (== eof)))))))
|
||||||
(CompoundPattern-tuple* ?fixed ?variable))
|
(CompoundPattern-tuplePrefix ?fixed ?variable))
|
||||||
((and dest
|
((and dest
|
||||||
(record
|
(record
|
||||||
'dict
|
'dict
|
||||||
|
@ -300,7 +300,7 @@
|
||||||
((Definitions src)
|
((Definitions src)
|
||||||
(for/hash
|
(for/hash
|
||||||
(((key value) (in-dict src)))
|
(((key value) (in-dict src)))
|
||||||
(values key (*->preserve value))))))))
|
(values (*->preserve key) (*->preserve value))))))))
|
||||||
(define (parse-Definitions input)
|
(define (parse-Definitions input)
|
||||||
(match
|
(match
|
||||||
input
|
input
|
||||||
|
@ -330,7 +330,7 @@
|
||||||
((DictionaryEntries src)
|
((DictionaryEntries src)
|
||||||
(for/hash
|
(for/hash
|
||||||
(((key value) (in-dict src)))
|
(((key value) (in-dict src)))
|
||||||
(values key (*->preserve value))))))))
|
(values (*->preserve key) (*->preserve value))))))))
|
||||||
(define (parse-DictionaryEntries input)
|
(define (parse-DictionaryEntries input)
|
||||||
(match
|
(match
|
||||||
input
|
input
|
||||||
|
@ -383,7 +383,8 @@
|
||||||
(define (->preserve preservable)
|
(define (->preserve preservable)
|
||||||
(match
|
(match
|
||||||
preservable
|
preservable
|
||||||
((ModulePath src) (for/list ((item (in-list src))) item))))))
|
((ModulePath src)
|
||||||
|
(for/list ((item (in-list src))) (*->preserve item)))))))
|
||||||
(define (parse-ModulePath input)
|
(define (parse-ModulePath input)
|
||||||
(match
|
(match
|
||||||
input
|
input
|
||||||
|
@ -431,7 +432,7 @@
|
||||||
(match
|
(match
|
||||||
preservable
|
preservable
|
||||||
((NamedAlternative ?variantLabel ?pattern)
|
((NamedAlternative ?variantLabel ?pattern)
|
||||||
(list ?variantLabel (*->preserve ?pattern)))))))
|
(list (*->preserve ?variantLabel) (*->preserve ?pattern)))))))
|
||||||
(define (parse-NamedAlternative input)
|
(define (parse-NamedAlternative input)
|
||||||
(match
|
(match
|
||||||
input
|
input
|
||||||
|
@ -518,7 +519,7 @@
|
||||||
(match
|
(match
|
||||||
preservable
|
preservable
|
||||||
((NamedSimplePattern_ ?name ?pattern)
|
((NamedSimplePattern_ ?name ?pattern)
|
||||||
(record 'named (list ?name (*->preserve ?pattern))))))))
|
(record 'named (list (*->preserve ?name) (*->preserve ?pattern))))))))
|
||||||
(define (parse-NamedSimplePattern_ input)
|
(define (parse-NamedSimplePattern_ input)
|
||||||
(match
|
(match
|
||||||
input
|
input
|
||||||
|
@ -574,7 +575,7 @@
|
||||||
(match
|
(match
|
||||||
preservable
|
preservable
|
||||||
((Ref ?module ?name)
|
((Ref ?module ?name)
|
||||||
(record 'ref (list (*->preserve ?module) ?name)))))))
|
(record 'ref (list (*->preserve ?module) (*->preserve ?name))))))))
|
||||||
(define (parse-Ref input)
|
(define (parse-Ref input)
|
||||||
(match
|
(match
|
||||||
input
|
input
|
||||||
|
@ -678,7 +679,8 @@
|
||||||
(define (->preserve preservable)
|
(define (->preserve preservable)
|
||||||
(match
|
(match
|
||||||
preservable
|
preservable
|
||||||
((SimplePattern-lit ?value) (record 'lit (list ?value)))))))
|
((SimplePattern-lit ?value)
|
||||||
|
(record 'lit (list (*->preserve ?value))))))))
|
||||||
(struct
|
(struct
|
||||||
SimplePattern-seqof
|
SimplePattern-seqof
|
||||||
(pattern)
|
(pattern)
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
[(CompoundPattern-tuple named-pats)
|
[(CompoundPattern-tuple named-pats)
|
||||||
(maybe-dest dest-pat-stx
|
(maybe-dest dest-pat-stx
|
||||||
`(list ,@(map (lambda (p) (pattern->match-pattern p '_)) named-pats)))]
|
`(list ,@(map (lambda (p) (pattern->match-pattern p '_)) named-pats)))]
|
||||||
[(CompoundPattern-tuple* fixed-named-pats variable-named-pat)
|
[(CompoundPattern-tuplePrefix fixed-named-pats variable-named-pat)
|
||||||
(maybe-dest dest-pat-stx
|
(maybe-dest dest-pat-stx
|
||||||
(if (null? fixed-named-pats)
|
(if (null? fixed-named-pats)
|
||||||
(pattern->match-pattern variable-named-pat '_)
|
(pattern->match-pattern variable-named-pat '_)
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
(require (only-in racket/string string-split))
|
(require (only-in racket/string string-split))
|
||||||
(require preserves)
|
(require preserves)
|
||||||
|
|
||||||
(require (only-in "type.rkt" namelike))
|
(require (only-in "checker.rkt" valid-id?))
|
||||||
(require "gen/schema.rkt")
|
(require "gen/schema.rkt")
|
||||||
|
|
||||||
(define (split-by items separator)
|
(define (split-by items separator)
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
(set! version (parse-Version! (strip-annotations v)))]
|
(set! version (parse-Version! (strip-annotations v)))]
|
||||||
[`(,(peel-annotations 'embeddedType) ,(peel-annotations #f))
|
[`(,(peel-annotations 'embeddedType) ,(peel-annotations #f))
|
||||||
(set! embeddedType (EmbeddedTypeName-false))]
|
(set! embeddedType (EmbeddedTypeName-false))]
|
||||||
[`(,(peel-annotations 'embeddedType) ,(peel-annotations (? symbol? r)))
|
[`(,(peel-annotations 'embeddedType) ,(peel-annotations (? valid-qid? r)))
|
||||||
(set! embeddedType (EmbeddedTypeName-Ref (parse-ref-dsl r)))]
|
(set! embeddedType (EmbeddedTypeName-Ref (parse-ref-dsl r)))]
|
||||||
[`(,(peel-annotations 'include) ,(peel-annotations (? string? path)))
|
[`(,(peel-annotations 'include) ,(peel-annotations (? string? path)))
|
||||||
(when (not read-include)
|
(when (not read-include)
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
[(not source) (error 'parse-schema-dsl "Cannot resolve relative include path")]
|
[(not source) (error 'parse-schema-dsl "Cannot resolve relative include path")]
|
||||||
[else (simplify-path (build-path source 'up path) #f)]))
|
[else (simplify-path (build-path source 'up path) #f)]))
|
||||||
(process (read-include new-source) new-source)]
|
(process (read-include new-source) new-source)]
|
||||||
[`(,(peel-annotations (? symbol? name)) ,(peel-annotations '=) ,@def-stx)
|
[`(,(peel-annotations (? valid-id? name)) ,(peel-annotations '=) ,@def-stx)
|
||||||
(when (hash-has-key? definitions name)
|
(when (hash-has-key? definitions name)
|
||||||
(error 'parse-schema-dsl "Duplicate definition: ~a" name))
|
(error 'parse-schema-dsl "Duplicate definition: ~a" name))
|
||||||
(hash-set! definitions name (parse-def-dsl name def-stx))]
|
(hash-set! definitions name (parse-def-dsl name def-stx))]
|
||||||
|
@ -64,11 +64,28 @@
|
||||||
(when (not version) (error 'parse-schema "Missing version declaration"))
|
(when (not version) (error 'parse-schema "Missing version declaration"))
|
||||||
(Schema (Definitions definitions) embeddedType version))
|
(Schema (Definitions definitions) embeddedType version))
|
||||||
|
|
||||||
|
(define (symbol-pieces s)
|
||||||
|
(map string->symbol (string-split (symbol->string s) ".")))
|
||||||
|
|
||||||
|
(define (valid-qid? x)
|
||||||
|
(and (symbol? x)
|
||||||
|
(andmap valid-id? (symbol-pieces x))))
|
||||||
|
|
||||||
|
(define (qid-last n)
|
||||||
|
(car (reverse (symbol-pieces n))))
|
||||||
|
|
||||||
(define (parse-ref-dsl s)
|
(define (parse-ref-dsl s)
|
||||||
(match-define (list module-path ... final-id)
|
(match-define (list module-path ... final-id) (symbol-pieces s))
|
||||||
(map string->symbol (string-split (symbol->string s) ".")))
|
|
||||||
(Ref (ModulePath module-path) final-id))
|
(Ref (ModulePath module-path) final-id))
|
||||||
|
|
||||||
|
(define (namelike v)
|
||||||
|
(match v
|
||||||
|
[(? string? s) (string->symbol s)]
|
||||||
|
[(? symbol? s) s]
|
||||||
|
[(? number? n) (string->symbol (number->string n))]
|
||||||
|
[(? boolean? b) (if b 'true 'false)]
|
||||||
|
[_ #f]))
|
||||||
|
|
||||||
(define (parse-def-dsl name def-stx)
|
(define (parse-def-dsl name def-stx)
|
||||||
(define (and-branch input)
|
(define (and-branch input)
|
||||||
(define p (parse-pattern-dsl name input))
|
(define p (parse-pattern-dsl name input))
|
||||||
|
@ -88,12 +105,12 @@
|
||||||
(CompoundPattern-rec
|
(CompoundPattern-rec
|
||||||
(NamedPattern-anonymous
|
(NamedPattern-anonymous
|
||||||
(Pattern-SimplePattern
|
(Pattern-SimplePattern
|
||||||
(SimplePattern-lit (? symbol? n))))
|
(SimplePattern-lit (? valid-id? n))))
|
||||||
_))
|
_))
|
||||||
(NamedAlternative (symbol->string n) p)]
|
(NamedAlternative (symbol->string n) p)]
|
||||||
[(Pattern-SimplePattern (SimplePattern-Ref (Ref _ n)))
|
[(Pattern-SimplePattern (SimplePattern-Ref (Ref _ (? valid-qid? n))))
|
||||||
(NamedAlternative (symbol->string n) p)]
|
(NamedAlternative (symbol->string (qid-last n)) p)]
|
||||||
[(Pattern-SimplePattern (SimplePattern-lit (app namelike (? symbol? n))))
|
[(Pattern-SimplePattern (SimplePattern-lit (app namelike (? valid-id? n))))
|
||||||
(NamedAlternative (symbol->string n) p)]
|
(NamedAlternative (symbol->string n) p)]
|
||||||
[_
|
[_
|
||||||
(error 'parse-def-dsl "Name missing for alternative: ~a" (input->string input))])]))
|
(error 'parse-def-dsl "Name missing for alternative: ~a" (input->string input))])]))
|
||||||
|
@ -123,9 +140,13 @@
|
||||||
['symbol (ks (SimplePattern-atom (AtomKind-Symbol)))]
|
['symbol (ks (SimplePattern-atom (AtomKind-Symbol)))]
|
||||||
[(? symbol? sym)
|
[(? symbol? sym)
|
||||||
(define str (symbol->string sym))
|
(define str (symbol->string sym))
|
||||||
(if (and (> (string-length str) 0) (string=? (substring str 0 1) "="))
|
(cond
|
||||||
(ks (SimplePattern-lit (string->symbol (substring str 1))))
|
[(and (> (string-length str) 0) (string=? (substring str 0 1) "="))
|
||||||
(ks (SimplePattern-Ref (parse-ref-dsl sym))))]
|
(ks (SimplePattern-lit (string->symbol (substring str 1))))]
|
||||||
|
[(valid-qid? sym)
|
||||||
|
(ks (SimplePattern-Ref (parse-ref-dsl sym)))]
|
||||||
|
[else
|
||||||
|
(error 'parse-simple-dsl "Invalid schema name reference: ~a" sym)])]
|
||||||
[(strip-annotations (record (record 'lit '()) lit-pat))
|
[(strip-annotations (record (record 'lit '()) lit-pat))
|
||||||
(match lit-pat
|
(match lit-pat
|
||||||
[(list v) (ks (SimplePattern-lit v))]
|
[(list v) (ks (SimplePattern-lit v))]
|
||||||
|
@ -152,9 +173,9 @@
|
||||||
(CompoundPattern-rec (NamedPattern-anonymous (Pattern-SimplePattern (SimplePattern-lit label)))
|
(CompoundPattern-rec (NamedPattern-anonymous (Pattern-SimplePattern (SimplePattern-lit label)))
|
||||||
(NamedPattern-anonymous (walk fields)))]
|
(NamedPattern-anonymous (walk fields)))]
|
||||||
[(list fixed ... variable (peel-annotations '...))
|
[(list fixed ... variable (peel-annotations '...))
|
||||||
(CompoundPattern-tuple* (map maybe-named fixed)
|
(CompoundPattern-tuplePrefix (map maybe-named fixed)
|
||||||
(maybe-named-simple
|
(maybe-named-simple
|
||||||
(apply annotate (list variable '...) (annotations variable))))]
|
(apply annotate (list variable '...) (annotations variable))))]
|
||||||
[(list item ...)
|
[(list item ...)
|
||||||
(CompoundPattern-tuple (map maybe-named item))]
|
(CompoundPattern-tuple (map maybe-named item))]
|
||||||
[(? dict? d) #:when (not (dict-has-key? (strip-annotations d) '...))
|
[(? dict? d) #:when (not (dict-has-key? (strip-annotations d) '...))
|
||||||
|
@ -175,7 +196,7 @@
|
||||||
|
|
||||||
(define ((maybe-named* knamed kanonymous recur [literal-name #f]) b)
|
(define ((maybe-named* knamed kanonymous recur [literal-name #f]) b)
|
||||||
(define n (or (find-name b)
|
(define n (or (find-name b)
|
||||||
(and (symbol? literal-name) literal-name)))
|
(and (valid-id? literal-name) literal-name)))
|
||||||
(if n
|
(if n
|
||||||
(let ((p (parse-simple-dsl
|
(let ((p (parse-simple-dsl
|
||||||
b
|
b
|
||||||
|
@ -198,7 +219,7 @@
|
||||||
(lambda () (Pattern-CompoundPattern (parse-compound-dsl (car input)))))))
|
(lambda () (Pattern-CompoundPattern (parse-compound-dsl (car input)))))))
|
||||||
|
|
||||||
(define (find-name input)
|
(define (find-name input)
|
||||||
(findf symbol? (map peel-annotations (annotations input))))
|
(findf valid-id? (map peel-annotations (annotations input))))
|
||||||
|
|
||||||
(define (port->schema src [p (current-input-port)])
|
(define (port->schema src [p (current-input-port)])
|
||||||
(parse-schema-dsl (port->preserves p
|
(parse-schema-dsl (port->preserves p
|
||||||
|
|
|
@ -47,7 +47,7 @@ SimplePattern =
|
||||||
; =symbol, <<lit> any>, or plain non-symbol atom
|
; =symbol, <<lit> any>, or plain non-symbol atom
|
||||||
/ <lit @value any>
|
/ <lit @value any>
|
||||||
|
|
||||||
; [p ...] ----> <seqof <ref p>>; see also tuple* below.
|
; [p ...] ----> <seqof <ref p>>; see also tuplePrefix below.
|
||||||
/ <seqof @pattern SimplePattern>
|
/ <seqof @pattern SimplePattern>
|
||||||
|
|
||||||
; #{p} ----> <setof <ref p>>
|
; #{p} ----> <setof <ref p>>
|
||||||
|
@ -69,9 +69,9 @@ CompoundPattern =
|
||||||
; [a b c] ----> <tuple [<ref a> <ref b> <ref c>]>
|
; [a b c] ----> <tuple [<ref a> <ref b> <ref c>]>
|
||||||
/ <tuple @patterns [NamedPattern ...]>
|
/ <tuple @patterns [NamedPattern ...]>
|
||||||
|
|
||||||
; [a b c ...] ----> <tuple* [<ref a> <ref b>] <seqof <ref c>>>
|
; [a b c ...] ----> <tuplePrefix [<ref a> <ref b>] <seqof <ref c>>>
|
||||||
; TODO: [@fixed0 NamedPattern @fixedN NamedPattern ...]
|
; TODO: [@fixed0 NamedPattern @fixedN NamedPattern ...]
|
||||||
/ <tuple* @fixed [NamedPattern ...] @variable NamedSimplePattern>
|
/ <tuplePrefix @fixed [NamedPattern ...] @variable NamedSimplePattern>
|
||||||
|
|
||||||
; {a: b, c: d} ----> <dict {a: <ref b>, c: <ref d>}>
|
; {a: b, c: d} ----> <dict {a: <ref b>, c: <ref d>}>
|
||||||
/ <dict @entries DictionaryEntries>
|
/ <dict @entries DictionaryEntries>
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
|
|
||||||
definition-ty
|
definition-ty
|
||||||
unwrap
|
unwrap
|
||||||
namelike
|
|
||||||
escape
|
escape
|
||||||
module-path-prefix)
|
module-path-prefix)
|
||||||
|
|
||||||
|
@ -76,7 +75,7 @@
|
||||||
(gather-fields label-named-pat (gather-fields fields-named-pat acc))]
|
(gather-fields label-named-pat (gather-fields fields-named-pat acc))]
|
||||||
[(CompoundPattern-tuple named-pats)
|
[(CompoundPattern-tuple named-pats)
|
||||||
(gather-fields* named-pats acc)]
|
(gather-fields* named-pats acc)]
|
||||||
[(CompoundPattern-tuple* fixed-named-pats variable-named-pat)
|
[(CompoundPattern-tuplePrefix fixed-named-pats variable-named-pat)
|
||||||
(gather-fields* fixed-named-pats (gather-fields variable-named-pat acc))]
|
(gather-fields* fixed-named-pats (gather-fields variable-named-pat acc))]
|
||||||
[(CompoundPattern-dict (DictionaryEntries entries))
|
[(CompoundPattern-dict (DictionaryEntries entries))
|
||||||
(gather-fields* (map cdr (sorted-dict-entries entries)) acc)]))
|
(gather-fields* (map cdr (sorted-dict-entries entries)) acc)]))
|
||||||
|
@ -93,14 +92,6 @@
|
||||||
[(SimplePattern-Ref _r) (ty-value)]
|
[(SimplePattern-Ref _r) (ty-value)]
|
||||||
[(? CompoundPattern?) (product-ty (list p))]))
|
[(? CompoundPattern?) (product-ty (list p))]))
|
||||||
|
|
||||||
(define (namelike v)
|
|
||||||
(match v
|
|
||||||
[(? string? s) (string->symbol s)]
|
|
||||||
[(? symbol? s) s]
|
|
||||||
[(? number? n) (string->symbol (number->string n))]
|
|
||||||
[(? boolean? b) (if b 'true 'false)]
|
|
||||||
[_ #f]))
|
|
||||||
|
|
||||||
(define (escape s)
|
(define (escape s)
|
||||||
(format-symbol "?~a" s))
|
(format-symbol "?~a" s))
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
`(record ,(pattern->unparser label-pat src-stx) ,(pattern->unparser fields-pat src-stx))]
|
`(record ,(pattern->unparser label-pat src-stx) ,(pattern->unparser fields-pat src-stx))]
|
||||||
[(CompoundPattern-tuple named-pats)
|
[(CompoundPattern-tuple named-pats)
|
||||||
`(list ,@(for/list [(p (in-list named-pats))] (pattern->unparser p src-stx)))]
|
`(list ,@(for/list [(p (in-list named-pats))] (pattern->unparser p src-stx)))]
|
||||||
[(CompoundPattern-tuple* fixed-named-pats variable-named-pat)
|
[(CompoundPattern-tuplePrefix fixed-named-pats variable-named-pat)
|
||||||
`(list* ,@(for/list [(p (in-list fixed-named-pats))] (pattern->unparser p src-stx))
|
`(list* ,@(for/list [(p (in-list fixed-named-pats))] (pattern->unparser p src-stx))
|
||||||
,(pattern->unparser variable-named-pat src-stx))]
|
,(pattern->unparser variable-named-pat src-stx))]
|
||||||
[(CompoundPattern-dict (DictionaryEntries entries))
|
[(CompoundPattern-dict (DictionaryEntries entries))
|
||||||
|
|
|
@ -4,7 +4,7 @@ title: "Preserves Schema"
|
||||||
---
|
---
|
||||||
|
|
||||||
Tony Garnock-Jones <tonyg@leastfixedpoint.com>
|
Tony Garnock-Jones <tonyg@leastfixedpoint.com>
|
||||||
May 2021. Version 0.1.0.
|
June 2021. Version 0.1.1.
|
||||||
|
|
||||||
[abnf]: https://tools.ietf.org/html/rfc7405
|
[abnf]: https://tools.ietf.org/html/rfc7405
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ A bundle of schema files is a directory tree containing `.prs` files.
|
||||||
Version = "version" "1"
|
Version = "version" "1"
|
||||||
EmbeddedTypeName = "embeddedType" ("#f" / Ref)
|
EmbeddedTypeName = "embeddedType" ("#f" / Ref)
|
||||||
Include = "include" string
|
Include = "include" string
|
||||||
Definition = symbol "=" (OrPattern / AndPattern / Pattern)
|
Definition = id "=" (OrPattern / AndPattern / Pattern)
|
||||||
|
|
||||||
**Version specification.** Mandatory. Names the version of the schema
|
**Version specification.** Mandatory. Names the version of the schema
|
||||||
language used in the file. This version of the specification is
|
language used in the file. This version of the specification is
|
||||||
|
@ -155,11 +155,11 @@ Each alternative with an `OrPattern` must have a definition-unique
|
||||||
discussion of `NamedPattern` below) or inferred. It can only be
|
discussion of `NamedPattern` below) or inferred. It can only be
|
||||||
inferred from the label of a record pattern, from the name of a
|
inferred from the label of a record pattern, from the name of a
|
||||||
reference to another definition, or from the text of a "sufficiently
|
reference to another definition, or from the text of a "sufficiently
|
||||||
stringlike" literal pattern - one that matches a string, symbol,
|
identifierlike" literal pattern - one that matches a string, symbol,
|
||||||
number or boolean:
|
number or boolean:
|
||||||
|
|
||||||
AltPattern = "@" symbol SimplePattern
|
AltPattern = "@" id SimplePattern
|
||||||
/ "<" symbol *(NamedPattern) ">"
|
/ "<" id *(NamedPattern) ">"
|
||||||
/ Ref
|
/ Ref
|
||||||
/ LiteralPattern -- with a side condition
|
/ LiteralPattern -- with a side condition
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ completely clear.
|
||||||
Patterns come in two kinds:
|
Patterns come in two kinds:
|
||||||
|
|
||||||
- the parsers for *simple patterns* yield a single host-language
|
- the parsers for *simple patterns* yield a single host-language
|
||||||
value such as a string, number, or pointer.
|
value; for example, a string, an array, a pointer, and so on.
|
||||||
|
|
||||||
- the parsers for *compound patterns* yield zero or more *fields*
|
- the parsers for *compound patterns* yield zero or more *fields*
|
||||||
which combine into an overall record type associated with a
|
which combine into an overall record type associated with a
|
||||||
|
@ -258,6 +258,9 @@ Periods "`.`" in such symbols are special:
|
||||||
- `Name` refers to the definition named `Name` in the current schema.
|
- `Name` refers to the definition named `Name` in the current schema.
|
||||||
- `Mod.Submod.Name` refers to definition `Name` in `Mod.Submod`, some other schema in the bundle.
|
- `Mod.Submod.Name` refers to definition `Name` in `Mod.Submod`, some other schema in the bundle.
|
||||||
|
|
||||||
|
Each period-separated portion of a reference name must be an `id`, an
|
||||||
|
identifier.
|
||||||
|
|
||||||
[^interface-schema]: Embedded patterns are experimental. One
|
[^interface-schema]: Embedded patterns are experimental. One
|
||||||
interpretation is that an embedded value denotes a reference to
|
interpretation is that an embedded value denotes a reference to
|
||||||
some stateful actor in a potentially-distributed system, and that
|
some stateful actor in a potentially-distributed system, and that
|
||||||
|
@ -299,19 +302,24 @@ that symbol is used as the name for that dictionary entry.
|
||||||
|
|
||||||
DictionaryPattern = "{" *(value ":" NamedSimplePattern) "}"
|
DictionaryPattern = "{" *(value ":" NamedSimplePattern) "}"
|
||||||
|
|
||||||
### Bindings: NamedPattern and NamedSimplePattern
|
### Identifiers and Bindings: NamedPattern and NamedSimplePattern
|
||||||
|
|
||||||
Compound patterns specifications contain `NamedPattern`s or
|
Compound patterns specifications contain `NamedPattern`s or
|
||||||
`NamedSimplePattern`s rather than ordinary `Pattern`s:
|
`NamedSimplePattern`s rather than ordinary `Pattern`s:
|
||||||
|
|
||||||
NamedPattern = "@" symbol SimplePattern / Pattern
|
NamedPattern = "@" id SimplePattern / Pattern
|
||||||
NamedSimplePattern = "@" symbol SimplePattern / SimplePattern
|
NamedSimplePattern = "@" id SimplePattern / SimplePattern
|
||||||
|
|
||||||
Use of an `@name` prefix generally results in creation of a field with
|
Use of an `@name` prefix generally results in creation of a field with
|
||||||
the given name in the overall record type for a definition. The type
|
the given name in the overall record type for a definition. The type
|
||||||
of value contained in the field will correspond to the `Pattern` or
|
of value contained in the field will correspond to the `Pattern` or
|
||||||
`SimplePattern` given.
|
`SimplePattern` given.
|
||||||
|
|
||||||
|
An `id` is a symbol that matches the regular expression
|
||||||
|
`^[a-zA-Z][a-zA-Z_0-9]*$`. This is a lowest-common-denominator
|
||||||
|
constraint that allows for a reasonable mapping to the identifiers of
|
||||||
|
many programming languages.
|
||||||
|
|
||||||
## Appendix: Metaschema
|
## Appendix: Metaschema
|
||||||
|
|
||||||
The metaschema defines the structure of the abstract syntax (AST) of
|
The metaschema defines the structure of the abstract syntax (AST) of
|
||||||
|
@ -388,7 +396,7 @@ Simple patterns are as described above:
|
||||||
; =symbol, <<lit> any>, or plain non-symbol atom
|
; =symbol, <<lit> any>, or plain non-symbol atom
|
||||||
/ <lit @value any>
|
/ <lit @value any>
|
||||||
|
|
||||||
; [p ...] ----> <seqof <ref p>>; see also tuple* below.
|
; [p ...] ----> <seqof <ref p>>; see also tuplePrefix below.
|
||||||
/ <seqof @pattern SimplePattern>
|
/ <seqof @pattern SimplePattern>
|
||||||
|
|
||||||
; #{p} ----> <setof <ref p>>
|
; #{p} ----> <setof <ref p>>
|
||||||
|
@ -420,8 +428,8 @@ Compound patterns involve optionally-named subpatterns:
|
||||||
; [a b c] ----> <tuple [<ref a> <ref b> <ref c>]>
|
; [a b c] ----> <tuple [<ref a> <ref b> <ref c>]>
|
||||||
/ <tuple @patterns [NamedPattern ...]>
|
/ <tuple @patterns [NamedPattern ...]>
|
||||||
|
|
||||||
; [a b c ...] ----> <tuple* [<ref a> <ref b>] <seqof <ref c>>>
|
; [a b c ...] ----> <tuplePrefix [<ref a> <ref b>] <seqof <ref c>>>
|
||||||
/ <tuple* @fixed [NamedPattern ...] @variable NamedSimplePattern>
|
/ <tuplePrefix @fixed [NamedPattern ...] @variable NamedSimplePattern>
|
||||||
|
|
||||||
; {a: b, c: d} ----> <dict {a: <ref b>, c: <ref d>}>
|
; {a: b, c: d} ----> <dict {a: <ref b>, c: <ref d>}>
|
||||||
/ <dict @entries DictionaryEntries>
|
/ <dict @entries DictionaryEntries>
|
||||||
|
@ -462,7 +470,7 @@ metaschema.
|
||||||
<named fields <ref [] NamedPattern>>
|
<named fields <ref [] NamedPattern>>
|
||||||
]>>],
|
]>>],
|
||||||
["tuple", <rec <lit tuple> <tuple [<named patterns <seqof <ref [] NamedPattern>>>]>>],
|
["tuple", <rec <lit tuple> <tuple [<named patterns <seqof <ref [] NamedPattern>>>]>>],
|
||||||
["tuple*", <rec <lit tuple*> <tuple [
|
["tuplePrefix", <rec <lit tuplePrefix> <tuple [
|
||||||
<named fixed <seqof <ref [] NamedPattern>>>,
|
<named fixed <seqof <ref [] NamedPattern>>>,
|
||||||
<named variable <ref [] NamedSimplePattern>>
|
<named variable <ref [] NamedSimplePattern>>
|
||||||
]>>],
|
]>>],
|
||||||
|
@ -484,11 +492,11 @@ metaschema.
|
||||||
]>>,
|
]>>,
|
||||||
|
|
||||||
Definition: <or [
|
Definition: <or [
|
||||||
["or", <rec <lit or> <tuple [<tuple* [
|
["or", <rec <lit or> <tuple [<tuplePrefix [
|
||||||
<named pattern0 <ref [] NamedAlternative>>,
|
<named pattern0 <ref [] NamedAlternative>>,
|
||||||
<named pattern1 <ref [] NamedAlternative>>
|
<named pattern1 <ref [] NamedAlternative>>
|
||||||
] <named patternN <seqof <ref [] NamedAlternative>>>>]>>],
|
] <named patternN <seqof <ref [] NamedAlternative>>>>]>>],
|
||||||
["and", <rec <lit and> <tuple [<tuple* [
|
["and", <rec <lit and> <tuple [<tuplePrefix [
|
||||||
<named pattern0 <ref [] NamedPattern>>,
|
<named pattern0 <ref [] NamedPattern>>,
|
||||||
<named pattern1 <ref [] NamedPattern>>
|
<named pattern1 <ref [] NamedPattern>>
|
||||||
] <named patternN <seqof <ref [] NamedPattern>>>>]>>],
|
] <named patternN <seqof <ref [] NamedPattern>>>>]>>],
|
||||||
|
@ -621,7 +629,7 @@ definitions for the metaschema.
|
||||||
{"_variant": "rec", "label": NamedPattern, "fields": NamedPattern} |
|
{"_variant": "rec", "label": NamedPattern, "fields": NamedPattern} |
|
||||||
{"_variant": "tuple", "patterns": Array<NamedPattern>} |
|
{"_variant": "tuple", "patterns": Array<NamedPattern>} |
|
||||||
{
|
{
|
||||||
"_variant": "tuple*",
|
"_variant": "tuplePrefix",
|
||||||
"fixed": Array<NamedPattern>,
|
"fixed": Array<NamedPattern>,
|
||||||
"variable": NamedSimplePattern
|
"variable": NamedSimplePattern
|
||||||
} |
|
} |
|
||||||
|
@ -671,7 +679,7 @@ definitions for the metaschema.
|
||||||
(struct Bundle (modules) #:prefab)
|
(struct Bundle (modules) #:prefab)
|
||||||
|
|
||||||
(struct CompoundPattern-dict (entries) #:prefab)
|
(struct CompoundPattern-dict (entries) #:prefab)
|
||||||
(struct CompoundPattern-tuple* (fixed variable) #:prefab)
|
(struct CompoundPattern-tuplePrefix (fixed variable) #:prefab)
|
||||||
(struct CompoundPattern-tuple (patterns) #:prefab)
|
(struct CompoundPattern-tuple (patterns) #:prefab)
|
||||||
(struct CompoundPattern-rec (label fields) #:prefab)
|
(struct CompoundPattern-rec (label fields) #:prefab)
|
||||||
|
|
||||||
|
|
|
@ -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„„µ±
|
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´³lit³
|
||||||
ByteString„„µ±Symbol´³lit³Symbol„„„„³
|
ByteString„„µ±Symbol´³lit³Symbol„„„„³
|
||||||
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„„„„³
|
Definition´³orµµ±or´³rec´³lit³or„´³tupleµ´³tuplePrefixµ´³named³pattern0´³refµ„³NamedAlternative„„´³named³pattern1´³refµ„³NamedAlternative„„„´³named³patternN´³seqof´³refµ„³NamedAlternative„„„„„„„„µ±and´³rec´³lit³and„´³tupleµ´³tuplePrefixµ´³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µ„³
|
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µ´³named³ interface´³refµ„³
SimplePattern„„„„„„µ±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€„„
|
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µ´³named³ interface´³refµ„³
SimplePattern„„„„„„µ±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„„„„„„„µ±tuplePrefix´³rec´³lit³tuplePrefix„´³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,7 +47,7 @@ SimplePattern =
|
||||||
; =symbol, <<lit> any>, or plain non-symbol atom
|
; =symbol, <<lit> any>, or plain non-symbol atom
|
||||||
/ <lit @value any>
|
/ <lit @value any>
|
||||||
|
|
||||||
; [p ...] ----> <seqof <ref p>>; see also tuple* below.
|
; [p ...] ----> <seqof <ref p>>; see also tuplePrefix below.
|
||||||
/ <seqof @pattern SimplePattern>
|
/ <seqof @pattern SimplePattern>
|
||||||
|
|
||||||
; #{p} ----> <setof <ref p>>
|
; #{p} ----> <setof <ref p>>
|
||||||
|
@ -69,9 +69,9 @@ CompoundPattern =
|
||||||
; [a b c] ----> <tuple [<ref a> <ref b> <ref c>]>
|
; [a b c] ----> <tuple [<ref a> <ref b> <ref c>]>
|
||||||
/ <tuple @patterns [NamedPattern ...]>
|
/ <tuple @patterns [NamedPattern ...]>
|
||||||
|
|
||||||
; [a b c ...] ----> <tuple* [<ref a> <ref b>] <seqof <ref c>>>
|
; [a b c ...] ----> <tuplePrefix [<ref a> <ref b>] <seqof <ref c>>>
|
||||||
; TODO: [@fixed0 NamedPattern @fixedN NamedPattern ...]
|
; TODO: [@fixed0 NamedPattern @fixedN NamedPattern ...]
|
||||||
/ <tuple* @fixed [NamedPattern ...] @variable NamedSimplePattern>
|
/ <tuplePrefix @fixed [NamedPattern ...] @variable NamedSimplePattern>
|
||||||
|
|
||||||
; {a: b, c: d} ----> <dict {a: <ref b>, c: <ref d>}>
|
; {a: b, c: d} ----> <dict {a: <ref b>, c: <ref d>}>
|
||||||
/ <dict @entries DictionaryEntries>
|
/ <dict @entries DictionaryEntries>
|
||||||
|
|
Loading…
Reference in New Issue