Bootstrap schema schema

This commit is contained in:
Tony Garnock-Jones 2021-03-10 23:15:53 +01:00
parent 7c587f03d3
commit 932818145b
8 changed files with 359 additions and 170 deletions

View File

@ -10,6 +10,7 @@
"types": "lib/index.d.ts",
"author": "Tony Garnock-Jones <tonyg@leastfixedpoint.com>",
"scripts": {
"regenerate": "./bin/preserves-schema-ts.js ../../../../schema/schema.txt > src/schemaschema.ts",
"clean": "rm -rf lib dist",
"prepare": "tsc && rollup -c",
"rollupwatch": "rollup -c -w",

View File

@ -1,15 +1,18 @@
import { Record, KeyedDictionary } from '@preserves/core';
import { AtomKind, Pattern, Schema } from './meta';
import { Record, Dictionary, Value } from '@preserves/core';
import { Pattern, Schema } from './meta';
import * as M from './meta';
export const BASE: Schema = Record(M.___schema, [1, new KeyedDictionary<symbol, Pattern, never>([
[Symbol.for('any'), Record(M.___and, [[]])],
[Symbol.for('bool'), Record(M.___atom, [M.___Boolean as AtomKind])],
[Symbol.for('float'), Record(M.___atom, [M.___Float as AtomKind])],
[Symbol.for('double'), Record(M.___atom, [M.___Double as AtomKind])],
[Symbol.for('int'), Record(M.___atom, [M.___SignedInteger as AtomKind])],
[Symbol.for('string'), Record(M.___atom, [M.___String as AtomKind])],
[Symbol.for('bytes'), Record(M.___atom, [M.___ByteString as AtomKind])],
[Symbol.for('symbol'), Record(M.___atom, [M.___Symbol as AtomKind])],
[Symbol.for('ref'), Record(M.___pointer, [])],
export const BASE: Schema = Record(M.$schema, [new Dictionary<Value, never>([
[M.$version, 1],
[M.$definitions, new Dictionary<Pattern, never>([
[Symbol.for('any'), Record(M.$and, [[]])],
[Symbol.for('bool'), Record(M.$atom, [M.$Boolean])],
[Symbol.for('float'), Record(M.$atom, [M.$Float])],
[Symbol.for('double'), Record(M.$atom, [M.$Double])],
[Symbol.for('int'), Record(M.$atom, [M.$SignedInteger])],
[Symbol.for('string'), Record(M.$atom, [M.$String])],
[Symbol.for('bytes'), Record(M.$atom, [M.$ByteString])],
[Symbol.for('symbol'), Record(M.$atom, [M.$Symbol])],
[Symbol.for('ref'), Record(M.$pointer, [])],
])],
])]);

View File

@ -2,8 +2,8 @@ import { BASE, compile, readSchema } from '../index';
import fs from 'fs';
export function main(argv: Array<string>) {
console.log('// ' + JSON.stringify(argv));
const src = fs.readFileSync(__dirname + '/../../../../../../schema/schema.txt', 'utf-8');
const [filename] = argv;
const src = fs.readFileSync(filename, 'utf-8');
const sch = readSchema(src);
console.log(compile(
[{ moduleName: 'BASE', modulePath: 'BASE', schema: BASE, inline: true }],

View File

@ -23,11 +23,11 @@ export function compile(env: Array<CompileEnvEntry>, schema: Schema, preservesMo
function environmentWith<R>(name: symbol,
kLocal: () => R,
kOther: (e: CompileEnvEntry, p: Pattern) => R): R {
if (Schema._.definitions(schema).has(name)) {
if (Schema._.details(schema).get(M.$definitions).has(name)) {
return kLocal();
}
for (const e of env) {
const p = Schema._.definitions(e.schema).get(name);
const p = Schema._.details(e.schema).get(M.$definitions).get(name);
if (p !== void 0) {
return kOther(e, p);
}
@ -56,12 +56,10 @@ export function compile(env: Array<CompileEnvEntry>, schema: Schema, preservesMo
function literal(v: Input): Item {
let varname = literals.get(v);
if (varname === void 0) {
const s = '___' + (
v.asPreservesText()
.replace('_', '__')
.replace('*', '_STAR_')
);
varname = M.isValidToken(s, true) ? s : '__lit' + literals.size;
const s = v.asPreservesText()
.replace('_', '__')
.replace('*', '_STAR_');
varname = M.isValidToken('_' + s, true) ? '$' + s : '__lit' + literals.size;
literals.set(v, varname);
}
return varname;
@ -69,19 +67,19 @@ export function compile(env: Array<CompileEnvEntry>, schema: Schema, preservesMo
function typeFor(p: Pattern): Item {
switch (p.label) {
case M.___atom:
case M.$atom:
switch (p[0]) {
case M.___Boolean: return `boolean`;
case M.___Float: return `_.SingleFloat`;
case M.___Double: return `_.DoubleFloat`;
case M.___SignedInteger: return `number`;
case M.___String: return `string`;
case M.___ByteString: return `_.Bytes`;
case M.___Symbol: return `symbol`;
case M.$Boolean: return `boolean`;
case M.$Float: return `_.SingleFloat`;
case M.$Double: return `_.DoubleFloat`;
case M.$SignedInteger: return `number`;
case M.$String: return `string`;
case M.$ByteString: return `_.Bytes`;
case M.$Symbol: return `symbol`;
}
case M.___lit:
case M.$lit:
return `(typeof ${literal(p[0])})`;
case M.___ref:
case M.$ref:
return environmentWith(
p[0],
() => p[0].description!,
@ -92,28 +90,28 @@ export function compile(env: Array<CompileEnvEntry>, schema: Schema, preservesMo
return `${e.moduleName}.${p[0].description!}`;
}
});
case M.___or:
case M.$or:
return opseq('never', ' | ', ... p[0].map(pp => typeFor(pp)));
case M.___and:
case M.$and:
return opseq('_.Value', ' & ', ... p[0].map(pp => typeFor(pp)));
case M.___pointer:
case M.$pointer:
return `any`; // TODO: what to do here?
case M.___rec:
case M.$rec:
return seq('_.Record', anglebrackets(typeFor(p[0]), typeFor(p[1])));
case M.___tuple:
case M.$tuple:
return brackets(... p[0].map(pp => typeFor(unname(pp))));
case M.___tuple_STAR_:
case M.$tuple_STAR_:
if (p[0].length === 0) {
return seq('Array<', typeFor(unname(p[1])), '>');
} else {
return brackets(... p[0].map(pp => typeFor(unname(pp))),
seq('... Array<', typeFor(unname(p[1])), '>'));
}
case M.___setof:
case M.$setof:
return seq('_.KeyedSet<', typeFor(p[0]), '>');
case M.___dictof:
case M.$dictof:
return seq('_.KeyedDictionary', anglebrackets(typeFor(p[0]), typeFor(p[1])));
case M.___dict:
case M.$dict:
return parens(seq(
block(
... Array.from(p[0]).map(([k, vp]) =>
@ -129,17 +127,17 @@ export function compile(env: Array<CompileEnvEntry>, schema: Schema, preservesMo
function walk(v: string, p: Pattern, recordOkAsTuple = false): Item {
switch (p.label) {
case M.___atom:
case M.$atom:
switch (p[0]) {
case M.___Boolean: return `typeof ${v} === 'boolean'`;
case M.___Float: return `_.Float.isSingle(${v})`;
case M.___Double: return `_.Float.isDouble(${v})`;
case M.___SignedInteger: return `typeof ${v} === 'number'`;
case M.___String: return `typeof ${v} === 'string'`;
case M.___ByteString: return `_.Bytes.isBytes(${v})`;
case M.___Symbol: return `typeof ${v} === 'symbol'`;
case M.$Boolean: return `typeof ${v} === 'boolean'`;
case M.$Float: return `_.Float.isSingle(${v})`;
case M.$Double: return `_.Float.isDouble(${v})`;
case M.$SignedInteger: return `typeof ${v} === 'number'`;
case M.$String: return `typeof ${v} === 'string'`;
case M.$ByteString: return `_.Bytes.isBytes(${v})`;
case M.$Symbol: return `typeof ${v} === 'symbol'`;
}
case M.___lit:
case M.$lit:
switch (typeof p[0]) {
case 'boolean':
case 'number':
@ -149,26 +147,26 @@ export function compile(env: Array<CompileEnvEntry>, schema: Schema, preservesMo
default:
return `_.is(${v}, ${literal(p[0])})`;
}
case M.___ref:
case M.$ref:
return applyPredicate(p[0], v);
case M.___or:
case M.$or:
return opseq('false', ' || ', ... p[0].map(pp => walk(v, pp)));
case M.___and:
case M.$and:
return opseq('true', ' && ', ... p[0].map(pp => walk(v, pp)));
case M.___pointer:
case M.$pointer:
return `_.isPointer(${v})`;
case M.___rec:
case M.$rec:
return opseq('true', ' && ',
`_.Record.isRecord(${v})`,
walk(`${v}.label`, p[0]),
walk(v, p[1], true));
case M.___tuple:
case M.$tuple:
return opseq('true', ' && ',
... (recordOkAsTuple ? []
: [`_.Array.isArray(${v})`, `!_.Record.isRecord(${v})`]),
`(${v}.length === ${p[0].length})`,
... p[0].map((pp, i) => walk(`${v}[${i}]`, unname(pp))));
case M.___tuple_STAR_:
case M.$tuple_STAR_:
return opseq('true', ' && ',
... (recordOkAsTuple ? []
: [`_.Array.isArray(${v})`, `!_.Record.isRecord(${v})`]),
@ -178,14 +176,14 @@ export function compile(env: Array<CompileEnvEntry>, schema: Schema, preservesMo
parens(walk('v', unname(p[1]))),
`)`),
... p[0].map((pp, i) => walk(`${v}[${i}]`, unname(pp))));
case M.___setof:
case M.$setof:
return opseq('true', ' && ',
`_.Set.isSet(${v})`,
fnblock(
seq(`for (const vv of ${v}) `, block(
seq('if (!(', walk('vv', p[0]), ')) return false'))),
seq('return true')));
case M.___dictof:
case M.$dictof:
return opseq('true', ' && ',
`_.Dictionary.isDictionary(${v})`,
fnblock(
@ -193,7 +191,7 @@ export function compile(env: Array<CompileEnvEntry>, schema: Schema, preservesMo
seq('if (!(', walk('e[0]', p[0]), ')) return false'),
seq('if (!(', walk('e[1]', p[1]), ')) return false'))),
seq('return true')));
case M.___dict:
case M.$dict:
return opseq('true', ' && ',
`_.Dictionary.isDictionary(${v})`,
... Array.from(p[0]).map(([k, vp]) => {
@ -209,24 +207,24 @@ export function compile(env: Array<CompileEnvEntry>, schema: Schema, preservesMo
}
function unname(p: NamedPattern): Pattern {
return (p.label === M.___named) ? p[1] : p;
return (p.label === M.$named) ? p[1] : p;
}
function fieldName(np: NamedPattern, index: number): string {
return (np.label === M.___named) ? np[0].description! : `_field${index}`;
return (np.label === M.$named) ? np[0].description! : `_field${index}`;
}
function fieldEntry(np: NamedPattern, index: number): Item {
return seq(JSON.stringify(fieldName(np, index)), ': ', typeFor(unname(np)));
}
for (const [name0, pattern] of Schema._.definitions(schema)) {
for (const [name0, pattern] of Schema._.details(schema).get(M.$definitions)) {
const name = name0 as symbol;
temps = [];
const recognizer = walk('v', pattern);
if (pattern.label === M.___rec &&
pattern[0].label === M.___lit &&
pattern[1].label === M.___tuple)
if (pattern.label === M.$rec &&
pattern[0].label === M.$lit &&
pattern[1].label === M.$tuple)
{
types.push(
seq(`export const ${name.description!} = _.Record.makeConstructor<`,

View File

@ -5,37 +5,37 @@ import { Value, Float, Bytes, is, isPointer, Record, Dictionary, Set } from "@pr
export function validator(env: Environment, p: Pattern): (v: Value<any>) => boolean {
function walk(p: Pattern, v: Value<any>, recordOkAsTuple = false): boolean {
switch (p.label) {
case M.___atom:
case M.$atom:
switch (p[0]) {
case M.___Boolean: return typeof v === 'boolean';
case M.___Float: return Float.isSingle(v);
case M.___Double: return Float.isDouble(v);
case M.___SignedInteger: return typeof v === 'number';
case M.___String: return typeof v === 'string';
case M.___ByteString: return Bytes.isBytes(v);
case M.___Symbol: return typeof v === 'symbol';
case M.$Boolean: return typeof v === 'boolean';
case M.$Float: return Float.isSingle(v);
case M.$Double: return Float.isDouble(v);
case M.$SignedInteger: return typeof v === 'number';
case M.$String: return typeof v === 'string';
case M.$ByteString: return Bytes.isBytes(v);
case M.$Symbol: return typeof v === 'symbol';
}
case M.___lit:
case M.$lit:
return is(v, p[0]);
case M.___ref:
case M.$ref:
return walk(lookup(env, p[0]), v);
case M.___or:
case M.$or:
for (const pp of p[0]) {
if (walk(pp, v)) return true;
}
return false;
case M.___and:
case M.$and:
for (const pp of p[0]) {
if (!walk(pp, v)) return false;
}
return true;
case M.___pointer:
case M.$pointer:
return isPointer(v);
case M.___rec:
case M.$rec:
if (!Record.isRecord(v)) return false;
if (!walk(p[0], v.label)) return false;
return walk(p[1], v, true);
case M.___tuple:
case M.$tuple:
if (!Array.isArray(v)) return false;
if (!recordOkAsTuple && Record.isRecord(v)) return false;
if (p[0].length !== v.length) return false;
@ -43,7 +43,7 @@ export function validator(env: Environment, p: Pattern): (v: Value<any>) => bool
if (!walknamed(p[0][i], v[i])) return false;
}
return true;
case M.___tuple_STAR_:
case M.$tuple_STAR_:
if (!Array.isArray(v)) return false;
if (!recordOkAsTuple && Record.isRecord(v)) return false;
if (p[0].length > v.length) return false;
@ -54,20 +54,20 @@ export function validator(env: Environment, p: Pattern): (v: Value<any>) => bool
if (!walknamed(p[1], v[i])) return false;
}
return true;
case M.___setof:
case M.$setof:
if (!Set.isSet(v)) return false;
for (const vv of v) {
if (!walk(p[0], vv)) return false;
}
return true;
case M.___dictof:
case M.$dictof:
if (!Dictionary.isDictionary<Value<any>>(v)) return false;
for (const e of v) {
if (!walk(p[0], e[0])) return false;
if (!walk(p[1], e[1])) return false;
}
return true;
case M.___dict:
case M.$dict:
if (!Dictionary.isDictionary<Value<any>>(v)) return false;
for (const e of p[0]) {
const vv = v.get(e[0]);
@ -82,7 +82,7 @@ export function validator(env: Environment, p: Pattern): (v: Value<any>) => bool
}
function walknamed(p: NamedPattern, v: Value<any>): boolean {
return (p.label === M.___named) ? walk(p[1], v) : walk(p, v);
return (p.label === M.$named) ? walk(p[1], v) : walk(p, v);
}
return v => walk(p, v);

View File

@ -1,4 +1,4 @@
import { Dictionary, KeyedDictionary, Record, Value, preserves } from '@preserves/core';
import { Value, preserves } from '@preserves/core';
export type Input = Value<never>;
@ -15,65 +15,15 @@ export const DOT = Symbol.for('.');
export const DOTDOTDOT = Symbol.for('...');
export const EQUALS = Symbol.for('=');
export const ORSYM = Symbol.for('/');
export const ___Boolean = Symbol.for('Boolean');
export const ___ByteString = Symbol.for('ByteString');
export const ___Double = Symbol.for('Double');
export const ___Float = Symbol.for('Float');
export const ___SignedInteger = Symbol.for('SignedInteger');
export const ___String = Symbol.for('String');
export const ___Symbol = Symbol.for('Symbol');
export const ___and = Symbol.for('and');
export const ___atom = Symbol.for('atom');
export const ___dict = Symbol.for('dict');
export const ___dictof = Symbol.for('dictof');
export const ___lit = Symbol.for('lit');
export const ___named = Symbol.for('named');
export const ___or = Symbol.for('or');
export const ___pointer = Symbol.for('pointer');
export const ___rec = Symbol.for('rec');
export const ___ref = Symbol.for('ref');
export const ___schema = Symbol.for('schema');
export const ___setof = Symbol.for('setof');
export const ___tuple = Symbol.for('tuple');
export const ___tuple_STAR_ = Symbol.for('tuple*');
export const ___version = Symbol.for('version');
export * from './schemaschema';
import { Schema, Pattern, $definitions } from './schemaschema';
export type Environment = Array<Schema>;
export const Schema = Record.makeConstructor<{
version: number,
definitions: KeyedDictionary<symbol, Pattern, never>,
}>()(Symbol.for('schema'), ['version', 'definitions']);
export type Schema = ReturnType<typeof Schema>;
export type AtomKind =
| typeof ___Boolean
| typeof ___Float
| typeof ___Double
| typeof ___SignedInteger
| typeof ___String
| typeof ___ByteString
| typeof ___Symbol;
export type Pattern =
| Record<typeof ___atom, [AtomKind], never>
| Record<typeof ___lit, [Input], never>
| Record<typeof ___ref, [symbol], never>
| Record<typeof ___or, [Array<Pattern>], never>
| Record<typeof ___and, [Array<Pattern>], never>
| Record<typeof ___pointer, [], never>
| Record<typeof ___rec, [Pattern, Pattern], never>
| Record<typeof ___tuple, [Array<NamedPattern>], never>
| Record<typeof ___tuple_STAR_, [Array<NamedPattern>, NamedPattern], never>
| Record<typeof ___setof, [Pattern], never>
| Record<typeof ___dictof, [Pattern, Pattern], never>
| Record<typeof ___dict, [Dictionary<Pattern, never>], never>;
export type NamedPattern = Record<typeof ___named, [symbol, Pattern], never> | Pattern;
export function lookup(env: Environment, name: symbol): Pattern {
for (const s of env) {
const p = Schema._.definitions(s).get(name);
const p = Schema._.details(s).get($definitions).get(name);
if (p !== void 0) return p;
}
throw new Error(preserves`Schema: unbound name ${name}`);

View File

@ -1,4 +1,4 @@
import { Reader, Annotated, Dictionary, is, KeyedDictionary, peel, preserves, Record, strip, Tuple } from '@preserves/core';
import { Reader, Annotated, Dictionary, is, peel, preserves, Record, strip, Tuple, Value } from '@preserves/core';
import { Input, NamedPattern, Pattern, Schema } from './meta';
import * as M from './meta';
@ -37,8 +37,8 @@ export function readSchema(source: string): Schema {
export function parseSchema(toplevelTokens: Array<Input>): Schema {
const toplevelClauses = splitBy(peel(toplevelTokens) as Array<Input>, M.DOT);
let version: number | undefined = void 0;
let definitions = new KeyedDictionary<symbol, Pattern, never>();
let version: M.Version | undefined = void 0;
let definitions = new Dictionary<Pattern, never>();
for (const clause0 of toplevelClauses) {
const clause = clause0.map(peel);
if (!Array.isArray(clause)) {
@ -53,8 +53,9 @@ export function parseSchema(toplevelTokens: Array<Input>): Schema {
throw new Error(preserves`Duplicate definition: ${clause}`);
}
definitions.set(name, parseDefinition(name, clause.slice(2).map(peel)));
} else if (clause.length === 2 && is(clause[0], M.___version)) {
if (typeof clause[1] !== 'number') invalidClause(clause);
} else if (clause.length === 2 && is(clause[0], M.$version)) {
// TODO: use asVersion
if (!M.isVersion(clause[1])) invalidClause(clause);
version = clause[1];
} else {
invalidClause(clause);
@ -63,10 +64,10 @@ export function parseSchema(toplevelTokens: Array<Input>): Schema {
if (version === void 0) {
throw new Error("Schema: missing version declaration.");
}
if (version !== 1) {
throw new Error("Schema: unsupported version " + version);
}
return Record(M.___schema, [version, definitions]);
return Record(M.$schema, [new Dictionary<Value>([
[M.$version, version],
[M.$definitions, definitions],
])]);
}
function parseDefinition(name: symbol, body: Array<Input>): Pattern {
@ -77,8 +78,8 @@ function parseOp(body: Array<Input>, op: Input, k: (p: Array<Input>) => Pattern)
const pieces = splitBy(body, op);
if (pieces.length === 1) return k(pieces[0]);
switch (op) {
case M.ORSYM: return Record(M.___or, [pieces.map(k)]);
case M.ANDSYM: return Record(M.___and, [pieces.map(k)]);
case M.ORSYM: return Record(M.$or, [pieces.map(k)]);
case M.ANDSYM: return Record(M.$and, [pieces.map(k)]);
default: throw new Error("Internal error: unexpected operator");
}
}
@ -100,7 +101,7 @@ function parseBase(name: symbol, body: Array<Input>): Pattern {
const namedwalk = (b: Input): NamedPattern => {
const name = findName(b);
if (name === false) return walk(b);
return Record(M.___named, [name, walk(b)]);
return Record(M.$named, [name, walk(b)]);
};
const walkitems = (b: Input): Pattern[] => {
b = peel(b);
@ -115,56 +116,56 @@ function parseBase(name: symbol, body: Array<Input>): Pattern {
if (typeof item === 'symbol') {
const s = item.description;
if (s === void 0) complain();
if (s[0] === '=') return Record(M.___lit, [Symbol.for(s.slice(1))]);
return Record(M.___ref, [item]);
if (s[0] === '=') return Record(M.$lit, [Symbol.for(s.slice(1))]);
return Record(M.$ref, [item]);
} else if (Record.isRecord<Input, Tuple<Input>, never>(item)) {
const label = item.label;
if (Record.isRecord<Input, [], never>(label)) {
if (label.length !== 0) complain();
switch (label.label) {
case M.___lit:
case M.$lit:
if (item.length !== 1) complain();
return Record(M.___lit, [item[0]]);
case M.___or:
return Record(M.$lit, [item[0]]);
case M.$or:
if (item.length !== 1) complain();
return Record(M.___or, [walkitems(item[0])]);
case M.___and:
return Record(M.$or, [walkitems(item[0])]);
case M.$and:
if (item.length !== 1) complain();
return Record(M.___and, [walkitems(item[0])]);
case M.___rec:
return Record(M.$and, [walkitems(item[0])]);
case M.$rec:
if (item.length !== 2) complain();
return Record(M.___rec, [walk(item[0]), walk(item[1])]);
return Record(M.$rec, [walk(item[0]), walk(item[1])]);
default:
complain();
}
} else {
return Record(M.___rec, [Record(M.___lit, [label]), Record(M.___tuple, [item.map(namedwalk)])]);
return Record(M.$rec, [Record(M.$lit, [label]), Record(M.$tuple, [item.map(namedwalk)])]);
}
} else if (Array.isArray(item)) {
if (is(item[item.length - 1], M.DOTDOTDOT)) {
if (item.length < 2) complain();
return Record(M.___tuple_STAR_, [
return Record(M.$tuple_STAR_, [
item.slice(0, item.length - 2).map(namedwalk),
namedwalk(item[item.length - 2]),
]);
} else {
return Record(M.___tuple, [item.map(namedwalk)]);
return Record(M.$tuple, [item.map(namedwalk)]);
}
} else if (Dictionary.isDictionary<Input, never>(item)) {
if (item.size === 2 && item.has(M.DOTDOTDOT)) {
const v = item.clone();
v.delete(M.DOTDOTDOT);
const [[kp, vp]] = v.entries();
return Record(M.___dictof, [walk(kp), walk(vp)]);
return Record(M.$dictof, [walk(kp), walk(vp)]);
} else {
return Record(M.___dict, [item.mapEntries<Pattern, Input, never>(([k, vp]) =>
return Record(M.$dict, [item.mapEntries<Pattern, Input, never>(([k, vp]) =>
[strip(k), walk(vp)])]);
}
} else if (Set.isSet<never>(item)) {
if (item.size !== 1) complain();
const [vp] = item.entries();
return Record(M.___setof, [walk(vp)]);
return Record(M.$setof, [walk(vp)]);
} else {
return Record(M.___lit, [strip(item)]);
return Record(M.$lit, [strip(item)]);
}
}

View File

@ -0,0 +1,236 @@
import * as _ from "@preserves/core";
export const $1 = 1;
export const $Boolean = Symbol.for("Boolean");
export const $ByteString = Symbol.for("ByteString");
export const $Double = Symbol.for("Double");
export const $Float = Symbol.for("Float");
export const $SignedInteger = Symbol.for("SignedInteger");
export const $String = Symbol.for("String");
export const $Symbol = Symbol.for("Symbol");
export const $and = Symbol.for("and");
export const $atom = Symbol.for("atom");
export const $definitions = Symbol.for("definitions");
export const $dict = Symbol.for("dict");
export const $dictof = Symbol.for("dictof");
export const $lit = Symbol.for("lit");
export const $named = Symbol.for("named");
export const $or = Symbol.for("or");
export const $pointer = Symbol.for("pointer");
export const $rec = Symbol.for("rec");
export const $ref = Symbol.for("ref");
export const $schema = Symbol.for("schema");
export const $setof = Symbol.for("setof");
export const $tuple = Symbol.for("tuple");
export const $tuple_STAR_ = Symbol.for("tuple*");
export const $version = Symbol.for("version");
export const Schema = _.Record.makeConstructor<{
"details": (
{
get(k: typeof $version): Version;
get(k: typeof $definitions): _.KeyedDictionary<symbol, Pattern>;
has(k: typeof $version): true;
has(k: typeof $definitions): true;
} & _.Dictionary<_.Value>
)
}>()($schema, ["details"]);
export type Schema = _.Record<
(typeof $schema),
[
(
{
get(k: typeof $version): Version;
get(k: typeof $definitions): _.KeyedDictionary<symbol, Pattern>;
has(k: typeof $version): true;
has(k: typeof $definitions): true;
} & _.Dictionary<_.Value>
)
]
>;
export type Version = (typeof $1);
export type Pattern = (
_.Record<
(typeof $atom),
[
(
(typeof $Boolean) |
(typeof $Float) |
(typeof $Double) |
(typeof $SignedInteger) |
(typeof $String) |
(typeof $ByteString) |
(typeof $Symbol)
)
]
> |
_.Record<(typeof $pointer), []> |
_.Record<(typeof $lit), [_.Value]> |
_.Record<(typeof $ref), [symbol]> |
_.Record<(typeof $or), [Array<Pattern>]> |
_.Record<(typeof $and), [Array<Pattern>]> |
_.Record<(typeof $rec), [Pattern, Pattern]> |
_.Record<(typeof $tuple), [Array<NamedPattern>]> |
_.Record<(typeof $tuple_STAR_), [Array<NamedPattern>, NamedPattern]> |
_.Record<(typeof $setof), [Pattern]> |
_.Record<(typeof $dictof), [Pattern, Pattern]> |
_.Record<(typeof $dict), [_.KeyedDictionary<_.Value, Pattern>]>
);
export type NamedPattern = (_.Record<(typeof $named), [symbol, Pattern]> | Pattern);
export function isSchema(v: any): v is Schema {
let _tmp0, _tmp1: any;
return (
_.Record.isRecord(v) &&
v.label === $schema &&
(
(v.length === 1) &&
(
_.Dictionary.isDictionary(v[0]) &&
((_tmp0 = v[0].get($version)) !== void 0 && isVersion(_tmp0)) &&
(
(_tmp1 = v[0].get($definitions)) !== void 0 && (
_.Dictionary.isDictionary(_tmp1) &&
((() => {
for (const e of _tmp1) {
if (!(typeof e[0] === 'symbol')) return false;
if (!(isPattern(e[1]))) return false;
};
return true;
})())
)
)
)
)
);
}
export function isVersion(v: any): v is Version {return v === $1;}
export function isPattern(v: any): v is Pattern {
return (
(
_.Record.isRecord(v) &&
v.label === $atom &&
(
(v.length === 1) &&
(
v[0] === $Boolean ||
v[0] === $Float ||
v[0] === $Double ||
v[0] === $SignedInteger ||
v[0] === $String ||
v[0] === $ByteString ||
v[0] === $Symbol
)
)
) ||
(_.Record.isRecord(v) && v.label === $pointer && ((v.length === 0))) ||
(_.Record.isRecord(v) && v.label === $lit && ((v.length === 1) && true)) ||
(
_.Record.isRecord(v) &&
v.label === $ref &&
((v.length === 1) && typeof v[0] === 'symbol')
) ||
(
_.Record.isRecord(v) &&
v.label === $or &&
(
(v.length === 1) &&
(
_.Array.isArray(v[0]) &&
!_.Record.isRecord(v[0]) &&
(v[0].length >= 0) &&
v[0].slice(0).every(v => (isPattern(v)))
)
)
) ||
(
_.Record.isRecord(v) &&
v.label === $and &&
(
(v.length === 1) &&
(
_.Array.isArray(v[0]) &&
!_.Record.isRecord(v[0]) &&
(v[0].length >= 0) &&
v[0].slice(0).every(v => (isPattern(v)))
)
)
) ||
(
_.Record.isRecord(v) &&
v.label === $rec &&
((v.length === 2) && isPattern(v[0]) && isPattern(v[1]))
) ||
(
_.Record.isRecord(v) &&
v.label === $tuple &&
(
(v.length === 1) &&
(
_.Array.isArray(v[0]) &&
!_.Record.isRecord(v[0]) &&
(v[0].length >= 0) &&
v[0].slice(0).every(v => (isNamedPattern(v)))
)
)
) ||
(
_.Record.isRecord(v) &&
v.label === $tuple_STAR_ &&
(
(v.length === 2) &&
(
_.Array.isArray(v[0]) &&
!_.Record.isRecord(v[0]) &&
(v[0].length >= 0) &&
v[0].slice(0).every(v => (isNamedPattern(v)))
) &&
isNamedPattern(v[1])
)
) ||
(
_.Record.isRecord(v) &&
v.label === $setof &&
((v.length === 1) && isPattern(v[0]))
) ||
(
_.Record.isRecord(v) &&
v.label === $dictof &&
((v.length === 2) && isPattern(v[0]) && isPattern(v[1]))
) ||
(
_.Record.isRecord(v) &&
v.label === $dict &&
(
(v.length === 1) &&
(
_.Dictionary.isDictionary(v[0]) &&
((() => {
for (const e of v[0]) {if (!(true)) return false; if (!(isPattern(e[1]))) return false;};
return true;
})())
)
)
)
);
}
export function isNamedPattern(v: any): v is NamedPattern {
return (
(
_.Record.isRecord(v) &&
v.label === $named &&
((v.length === 2) && typeof v[0] === 'symbol' && isPattern(v[1]))
) ||
isPattern(v)
);
}