diff --git a/implementations/javascript/packages/schema/src/compiler.ts b/implementations/javascript/packages/schema/src/compiler.ts index 818328e..b678c74 100644 --- a/implementations/javascript/packages/schema/src/compiler.ts +++ b/implementations/javascript/packages/schema/src/compiler.ts @@ -15,531 +15,545 @@ function fnblock(... items: Item[]): Item { return seq('((() => ', block(... items), ')())'); } -export function compile(env: Environment, schema: Schema, options: CompilerOptions = {}): string { - const literals = new Dictionary(); - const types: Array = []; - const functions: Array = []; - const imports = new KeyedSet<[string, string]>(); - let temps: Array = []; - let body: Array = []; - let tempCounter = 0; - const pointerName = Schema._._field0(schema).get(M.$pointer); +class ModuleContext { + readonly env: Environment; + readonly schema: Schema; + readonly options: CompilerOptions; - function gentemp(): string { - const varname = '_tmp' + tempCounter++; - temps.push(varname); - return varname; + readonly literals = new Dictionary(); + readonly typedefs: Item[] = []; + readonly functiondefs: Item[] = []; + readonly imports = new KeyedSet<[string, string]>(); + + constructor(env: Environment, schema: Schema, options: CompilerOptions) { + this.env = env; + this.schema = schema; + this.options = options; } - function literal(v: Input): Item { - let varname = literals.get(v); + literal(v: Input): Item { + let varname = this.literals.get(v); if (varname === void 0) { const s = v.asPreservesText() .replace('_', '__') .replace('*', '_STAR_'); - varname = M.isValidToken('_' + s, true) ? '$' + s : '__lit' + literals.size; - literals.set(v, varname); + varname = M.isValidToken('_' + s, true) ? '$' + s : '__lit' + this.literals.size; + this.literals.set(v, varname); } return varname; } - function emit(item: Item): void { - body.push(item); - } - - function collectBody(f: () => void): Item { - const oldTemps = temps; - const oldBody = body; - temps = [] - body = []; - f(); - const ts = temps; - const result = body; - temps = oldTemps; - body = oldBody; - return block( - ... ts.length > 0 ? [seq('let ', commas(... ts), ': any')] : [], - ... result); - } - - function accumulateCompound(p: Pattern, - kFail: () => Item[], - kAcc: (temp: string) => Item[]): Item - { - const t = gentemp(); - return seq(`while (!d.closeCompound()) `, collectBody(() => { - emit(seq(`${t} = void 0`)); - decoderFor(p, t); - emit(seq(`if (${t} === void 0) `, block( - ... kFail(), - seq(`break`)))); - kAcc(t).forEach(emit); - })); - } - - function derefPattern([_name, p]: [symbol, Alternative]): Definition { + derefPattern([_name, p]: [symbol, Alternative]): Definition { if (p.label === M.$ref) { - return lookup(refPosition(p), p, env, + return lookup(refPosition(p), p, this.env, (p) => p, (p) => p, - (_mod, _modPath, pp) => pp ?? p); + (_modId, _modPath, pp) => pp ?? p); } else { return p; } } - function decoderForTuple(tuplePattern: Pattern, - ps: Pattern[], - dest: string, - recordFields: boolean, - variablePattern: Pattern | undefined): void { - const temps = ps.map(gentemp); - function loop(i: number) { - if (i < ps.length) { - decoderFor(ps[i], temps[i]); - emit(seq(`if (${temps[i]} !== void 0) `, - collectBody(() => loop(i + 1)))); + defineType(f: Item): void { + this.typedefs.push(f); + } + + defineFunction(f: (ctx: FunctionContext) => Item): void { + this.functiondefs.push(f(new FunctionContext(this))); + } +} + +class FunctionContext { + readonly mod: ModuleContext; + + tempCounter = 0; + temps: string[] = []; + + constructor(mod: ModuleContext) { + this.mod = mod; + } + + gentemp(): string { + const varname = '_tmp' + this.tempCounter++; + this.temps.push(varname); + return varname; + } + + gentemps(n: number): string[] { + const temps = []; + while (temps.length < n) temps.push(this.gentemp()); + return temps; + } + + block(f: () => Item[]): Item { + const oldTemps = this.temps; + this.temps = []; + const items = f(); + const ts = this.temps; + this.temps = oldTemps; + return block( + ... ts.length > 0 ? [seq(`let `, commas(... ts), ': any')] : [], + ... items); + } +} + +function unname(p: NamedPattern): Pattern { + 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}`; +} + +function accumulateCompound(ctx: FunctionContext, + p: Pattern, + kFail: () => Item[], + kAcc: (temp: string) => Item[]): Item +{ + const t = ctx.gentemp(); + return seq(`while (!d.closeCompound()) `, ctx.block(() => [ + seq(`${t} = void 0`), + ... decoderFor(ctx, p, t), + seq(`if (${t} === void 0) `, block(... kFail(), seq(`break`))), + ... kAcc(t)])); +} + +function decoderForTuple(ctx: FunctionContext, + tuplePattern: Pattern, + ps: Pattern[], + dest: string, + recordFields: boolean, + variablePattern: Pattern | undefined): Item[] +{ + const temps = ctx.gentemps(ps.length); + + function loop(i: number): Item[] { + if (i < ps.length) { + return [... decoderFor(ctx, ps[i], temps[i]), + seq(`if (${temps[i]} !== void 0) `, ctx.block(() => loop(i + 1)))]; + } else { + if (variablePattern === void 0) { + return [seq(`if (d.closeCompound()) ${dest} = `, brackets(... temps), + ` as `, typeFor(ctx.mod, tuplePattern))]; } else { - if (variablePattern === void 0) { - emit(seq(`if (d.closeCompound()) ${dest} = `, brackets(... temps), - ` as `, typeFor(tuplePattern))); - } else { - emit(block( - seq(`let vN: `, typeFor(tuplePattern), - ` | undefined = `, brackets(... temps)), - accumulateCompound(variablePattern, - () => [`vN = void 0`], - (t) => [`vN.push(${t})`]), - seq(`${dest} = vN`))); - } + return [block( + seq(`let vN: `, typeFor(ctx.mod, tuplePattern), + ` | undefined = `, brackets(... temps)), + accumulateCompound(ctx, + variablePattern, + () => [`vN = void 0`], + (t) => [`vN.push(${t})`]), + seq(`${dest} = vN`))]; } } - if (recordFields) { - loop(0); - } else { - emit(seq(`if (d.openSequence()) `, collectBody(() => loop(0)))); - } } - function decoderFor(p: Definition, dest: string, recordFields = false): void { - switch (p.label) { - case M.$atom: - switch (p[0]) { - case M.$Boolean: emit(`${dest} = d.nextBoolean()`); break; - case M.$Float: emit(`${dest} = d.nextFloat()`); break; - case M.$Double: emit(`${dest} = d.nextDouble()`); break; - case M.$SignedInteger: emit(`${dest} = d.nextSignedInteger()`); break; - case M.$String: emit(`${dest} = d.nextString()`); break; - case M.$ByteString: emit(`${dest} = d.nextByteString()`); break; - case M.$Symbol: emit(`${dest} = d.nextSymbol()`); break; - } - break; - case M.$lit: { - let n: string; - switch (typeof p[0]) { - case 'boolean': n = `d.nextBoolean()`; break; - case 'string': n = `d.nextString()`; break; - case 'number': n = `d.nextSignedInteger()`; break; - case 'symbol': n = `d.nextSymbol()`; break; - default: n = `d.next()`; break; - } - emit(`${dest} = _.asLiteral(${n}, ${literal(p[0])})`); - break; + return recordFields + ? loop(0) + : [seq(`if (d.openSequence()) `, ctx.block(() => loop(0)))]; +} + +function decoderFor(ctx: FunctionContext, p: Definition, dest: string, recordFields = false): Item[] +{ + switch (p.label) { + case M.$atom: + switch (p[0]) { + case M.$Boolean: return [`${dest} = d.nextBoolean()`]; + case M.$Float: return [`${dest} = d.nextFloat()`]; + case M.$Double: return [`${dest} = d.nextDouble()`]; + case M.$SignedInteger: return [`${dest} = d.nextSignedInteger()`]; + case M.$String: return [`${dest} = d.nextString()`]; + case M.$ByteString: return [`${dest} = d.nextByteString()`]; + case M.$Symbol: return [`${dest} = d.nextSymbol()`]; } - case M.$ref: - lookup(refPosition(p), p, env, - (_p) => emit(`${dest} = decode${p[1].description!}(d)`), - (p) => decoderFor(p, dest), - (mod, modPath,_p) => { - imports.add([mod, modPath]); - emit(`${dest} = ${mod}.decode${p[1].description!}(d)`); - }); - break; - case M.$or: { - const alts = p[0]; - const recs = alts.map(derefPattern); - if (recs.length > 1 && recs.every(pp => pp.label === M.$rec)) { - // Hoist the record check up. - // This is pretty hacky. If we lift the level of - // discourse a little, we can do this - // automatically and generically... - emit(seq(`if (d.openRecord()) `, collectBody(() => { - const label = gentemp(); - emit(seq(`${label} = d.next()`)); - const mark = gentemp(); - emit(seq(`${mark} = d.mark()`)); - function loop(i: number) { - const alt = recs[i]; - if (alt.label !== M.$rec) return; // avoid a cast - emit(seq(`if (`, predicateFor(label, alt[0]), `) `, collectBody(() => { - const fs = gentemp(); - decoderFor(alt[1], fs, true); - emit(seq(`if (${fs} !== void 0) ${dest} = _.Record`, - anglebrackets(typeFor(alt[0]), typeFor(alt[1])), - parens(seq(label, ` as any`), - seq(fs, ` as any`)))); - }))); - if (i < recs.length - 1) { - emit(seq(`if (${dest} === void 0) `, collectBody(() => { - emit(`d.restoreMark(${mark})`); - loop(i + 1); - }))); - } - } - loop(0); - }))); - } else { - switch (alts.length) { - case 0: break; // assume dest is already void 0 - case 1: decoderFor(alts[0][1], dest); break; - default: { - const mark = gentemp(); - emit(`${mark} = d.mark()`); - function loop(i: number) { - decoderFor(alts[i][1], dest); - if (i < alts.length - 1) { - emit(seq(`if (${dest} === void 0) `, collectBody(() => { - emit(`d.restoreMark(${mark})`); - loop(i + 1); - }))); - } - } - loop(0); - break; - } + case M.$lit: { + let n: string; + switch (typeof p[0]) { + case 'boolean': n = `d.nextBoolean()`; break; + case 'string': n = `d.nextString()`; break; + case 'number': n = `d.nextSignedInteger()`; break; + case 'symbol': n = `d.nextSymbol()`; break; + default: n = `d.next()`; break; + } + return [`${dest} = _.asLiteral(${n}, ${ctx.mod.literal(p[0])})`]; + } + case M.$ref: + return lookup(refPosition(p), p, ctx.mod.env, + (_p) => [`${dest} = decode${p[1].description!}(d)`], + (p) => decoderFor(ctx, p, dest), + (modId, modPath,_p) => { + ctx.mod.imports.add([modId, modPath]); + return [`${dest} = ${modId}.decode${p[1].description!}(d)`]; + }); + case M.$or: { + const alts = p[0]; + const recs = alts.map(p => ctx.mod.derefPattern(p)); + if (recs.length > 1 && recs.every(pp => pp.label === M.$rec)) { + // Hoist the record check up. + // This is pretty hacky. If we lift the level of + // discourse a little, we can do this + // automatically and generically... + return [seq(`if (d.openRecord()) `, ctx.block(() => { + const label = ctx.gentemp(); + const mark = ctx.gentemp(); + function loop(i: number): Item[] { + const alt = recs[i]; + if (alt.label !== M.$rec) throw new Error("Internal error"); // avoid a cast + return [ + seq(`if (`, predicateFor(ctx, label, alt[0]), `) `, ctx.block(() => { + const fs = ctx.gentemp(); + return [... decoderFor(ctx, alt[1], fs, true), + seq(`if (${fs} !== void 0) ${dest} = _.Record`, + anglebrackets(typeFor(ctx.mod, alt[0]), + typeFor(ctx.mod, alt[1])), + parens(seq(label, ` as any`), + seq(fs, ` as any`)))]; + })), + ... (i < recs.length - 1) + ? [seq(`if (${dest} === void 0) `, + ctx.block(() => [`d.restoreMark(${mark})`, ... loop(i + 1)]))] + : [], + ]; } - } - break; - } - case M.$and: - switch (p[0].length) { - case 0: emit(`${dest} = d.next()`); break; - case 1: decoderFor(p[0][0], dest); break; + return [seq(`${label} = d.next()`), + seq(`${mark} = d.mark()`), + ... loop(0)]; + }))]; + } else { + switch (alts.length) { + case 0: return []; // assume dest is already void 0 + case 1: return decoderFor(ctx, alts[0][1], dest); default: { - const [pp0, ... ppN] = p[0]; - decoderFor(pp0, dest); - const otherChecks = - opseq('true', ' && ', ... ppN.map(pp => predicateFor(dest, pp))); - emit(seq(`if (!`, otherChecks, `) ${dest} = void 0`)); - break; + const mark = ctx.gentemp(); + function loop(i: number): Item[] { + return [ + ... decoderFor(ctx, alts[i][1], dest), + ... (i < alts.length - 1) + ? [seq(`if (${dest} === void 0) `, ctx.block(() => + [`d.restoreMark(${mark})`, ... loop(i + 1)]))] + : [], + ]; + } + return [`${mark} = d.mark()`, ... loop(0)]; } } - break; - case M.$pointer: - emit(`${dest} = _decodePtr(d)`); - break; - case M.$rec: - // assume dest is already void 0 - emit(seq(`if (d.openRecord()) `, collectBody(() => { - const label = gentemp(); - decoderFor(p[0], label); - emit(seq(`if (${label} !== void 0) `, - collectBody(() => { - const fs = gentemp(); - decoderFor(p[1], fs, true); - emit(seq( - `if (${fs} !== void 0) ${dest} = _.Record`, - anglebrackets(typeFor(p[0]), typeFor(p[1])), - parens(seq(label, ` as any`), - seq(fs, ` as any`)))); - }))); - }))); - break; - case M.$tuple: - // assume dest is already void 0 - decoderForTuple(p, p[0].map(unname), dest, recordFields, void 0); - break; - case M.$tuple_STAR_: - // assume dest is already void 0 - decoderForTuple(p, p[0].map(unname), dest, recordFields, unname(p[1])); - break; - case M.$setof: - // assume dest is already void 0 - emit(seq(`if (d.openSet()) `, collectBody(() => { - emit(seq(`let r: `, typeFor(p), ` | undefined = new _.KeyedSet()`)); - emit(accumulateCompound(p[0], - () => [`r = void 0`], - (t) => [`r.add(${t})`])); - emit(`${dest} = r`); - }))); - break; - case M.$dictof: - // assume dest is already void 0 - emit(seq(`if (d.openDictionary()) `, collectBody(() => { - emit(seq(`let r: `, typeFor(p), ` | undefined = new _.KeyedDictionary()`)); - emit(seq(`while (!d.closeCompound()) `, collectBody(() => { - emit(seq(`let K: undefined | `, typeFor(p[0]), ` = void 0`)); - decoderFor(p[0], 'K'); - emit(seq(`if (K === void 0) { r = void 0; break; }`)); - emit(seq(`let V: undefined | `, typeFor(p[1]), ` = void 0`)); - decoderFor(p[1], 'V'); - emit(seq(`if (V === void 0) { r = void 0; break; }`)); - emit(seq(`r.set(K, V)`)); - }))); - emit(seq(`${dest} = r`)); - }))); - break; - case M.$dict: - emit(seq(`${dest} = d.next()`)); - emit(seq( - `if (${dest} !== void 0 && !(`, predicateFor(dest, p), `)) ${dest} = void 0`)); - break; - default: - ((_p: never) => {})(p); - throw new Error("Unreachable"); + } } - } - - function typeFor(p: Pattern): Item { - switch (p.label) { - 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.$lit: - return `(typeof ${literal(p[0])})`; - case M.$ref: - return lookup(refPosition(p), p, env, - (_p) => p[1].description!, - (p) => typeForAlternative(p), - (mod, modPath,_p) => { - imports.add([mod, modPath]); - return `${mod}.${p[1].description!}`; - }); - case M.$pointer: - return `_ptr`; - case M.$rec: - return seq('_.Record', anglebrackets(typeFor(p[0]), typeFor(p[1]), '_ptr')); - case M.$tuple: - return brackets(... p[0].map(pp => typeFor(unname(pp)))); - 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: - return seq('_.KeyedSet', anglebrackets(typeFor(p[0]), '_ptr')); - case M.$dictof: - return seq('_.KeyedDictionary', anglebrackets(typeFor(p[0]), typeFor(p[1]), '_ptr')); - case M.$dict: - return parens(seq( - block( - ... Array.from(p[0]).map(([k, vp]) => - seq(`get(k: typeof ${literal(k)}): `, typeFor(unname(vp)))), - ... Array.from(p[0]).map(([k, _vp]) => - seq(`has(k: typeof ${literal(k)}): true`))), - ' & _.Dictionary<_ptr>')); - default: - ((_p: never) => {})(p); - throw new Error("Unreachable"); - } - } - - function typeForDefinition(_name: symbol, d: Definition): Item { - if (d.label === M.$or) { - return opseq('never', ' | ', ... d[0].map(a => typeForAlternative(a[1]))); - } else { - return typeForAlternative(d); - } - } - - function typeForAlternative(a: Alternative): Item { - if (a.label === M.$and) { - return opseq('_val', ' & ', ... a[0].map(p => typeFor(p))); - } else { - return typeFor(a); - } - } - - function predicateFor(v: string, p: Definition, recordOkAsTuple = false): Item { - switch (p.label) { - 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.$lit: - return `_.is(${v}, ${literal(p[0])})`; - case M.$ref: - return lookup(refPosition(p), p, env, - (_p) => `is${Ref._.name(p).description!}(${v})`, - (pp) => predicateFor(v, pp), - (mod, modPath, _p) => { - imports.add([mod, modPath]); - return `${mod}.is${Ref._.name(p).description!}(${v})`; - }); - case M.$or: { - const alts = p[0]; - const recs = alts.map(derefPattern); - if (recs.length > 1 && recs.every(pp => pp.label === M.$rec)) { - return seq( - `_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(${v}) && `, - parens(opseq('false', ' || ', - ... recs.map(r => - (r.label !== M.$rec) ? '' : parens(seq( - predicateFor(`${v}.label`, r[0]), - ' && ', - predicateFor(v, r[1], true))))))); - } else { - return opseq('false', ' || ', ... p[0].map(pp => predicateFor(v, pp[1]))); + case M.$and: + switch (p[0].length) { + case 0: return [`${dest} = d.next()`]; + case 1: return decoderFor(ctx, p[0][0], dest); + default: { + const [pp0, ... ppN] = p[0]; + return [... decoderFor(ctx, pp0, dest), + seq(`if (!`, opseq('true', ' && ', + ... ppN.map(pp => predicateFor(ctx, dest, pp))), + `) ${dest} = void 0`)]; } } - case M.$and: - return opseq('true', ' && ', ... p[0].map(pp => predicateFor(v, pp))); - case M.$pointer: - return `_.isPointer(${v})`; - case M.$rec: - return opseq('true', ' && ', - `_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(${v})`, - predicateFor(`${v}.label`, p[0]), - predicateFor(v, p[1], true)); - case M.$tuple: - return opseq('true', ' && ', - ... (recordOkAsTuple ? [] - : [`_.Array.isArray(${v})`, `!_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(${v})`]), - `(${v}.length === ${p[0].length})`, - ... p[0].map((pp, i) => predicateFor(`${v}[${i}]`, unname(pp)))); - case M.$tuple_STAR_: - return opseq('true', ' && ', - ... (recordOkAsTuple ? [] - : [`_.Array.isArray(${v})`, `!_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(${v})`]), - `(${v}.length >= ${p[0].length})`, - seq(p[0].length > 0 ? `${v}.slice(${p[0].length})` : v, - `.every(v => `, - parens(predicateFor('v', unname(p[1]))), - `)`), - ... p[0].map((pp, i) => predicateFor(`${v}[${i}]`, unname(pp)))); - case M.$setof: - return opseq('true', ' && ', - `_.Set.isSet<_val>(${v})`, - fnblock( - seq(`for (const vv of ${v}) `, block( - seq('if (!(', predicateFor('vv', p[0]), ')) return false'))), - seq('return true'))); - case M.$dictof: - return opseq('true', ' && ', - `_.Dictionary.isDictionary<_ptr>(${v})`, - fnblock( - seq(`for (const e of ${v}) `, block( - seq('if (!(', predicateFor('e[0]', p[0]), ')) return false'), - seq('if (!(', predicateFor('e[1]', p[1]), ')) return false'))), - seq('return true'))); - case M.$dict: - return opseq('true', ' && ', - `_.Dictionary.isDictionary<_ptr>(${v})`, - ... Array.from(p[0]).map(([k, vp]) => { - const tmp = gentemp(); - return parens(seq( - `(${tmp} = ${v}.get(${literal(k)})) !== void 0 && `, - predicateFor(tmp, unname(vp)))); - })); - default: - ((_p: never) => {})(p); - throw new Error("Unreachable"); + case M.$pointer: + return [`${dest} = _decodePtr(d)`]; + case M.$rec: + // assume dest is already void 0 + return [seq(`if (d.openRecord()) `, ctx.block(() => { + const label = ctx.gentemp(); + return [... decoderFor(ctx, p[0], label), + seq(`if (${label} !== void 0) `, ctx.block(() => { + const fs = ctx.gentemp(); + return [... decoderFor(ctx, p[1], fs, true), + seq(`if (${fs} !== void 0) ${dest} = _.Record`, + anglebrackets(typeFor(ctx.mod, p[0]), typeFor(ctx.mod, p[1])), + parens(seq(label, ` as any`), + seq(fs, ` as any`)))]; + }))]; + }))]; + case M.$tuple: + // assume dest is already void 0 + return decoderForTuple(ctx, p, p[0].map(unname), dest, recordFields, void 0); + case M.$tuple_STAR_: + // assume dest is already void 0 + return decoderForTuple(ctx, p, p[0].map(unname), dest, recordFields, unname(p[1])); + case M.$setof: + // assume dest is already void 0 + return [seq(`if (d.openSet()) `, ctx.block(() => [ + seq(`let r: `, typeFor(ctx.mod, p), ` | undefined = new _.KeyedSet()`), + accumulateCompound(ctx, + p[0], + () => [`r = void 0`], + (t) => [`r.add(${t})`]), + `${dest} = r`]))]; + case M.$dictof: + // assume dest is already void 0 + return [seq(`if (d.openDictionary()) `, ctx.block(() => [ + seq(`let r: `, typeFor(ctx.mod, p), ` | undefined = new _.KeyedDictionary()`), + seq(`while (!d.closeCompound()) `, ctx.block(() => [ + seq(`let K: undefined | `, typeFor(ctx.mod, p[0]), ` = void 0`), + ... decoderFor(ctx, p[0], 'K'), + seq(`if (K === void 0) { r = void 0; break; }`), + seq(`let V: undefined | `, typeFor(ctx.mod, p[1]), ` = void 0`), + ... decoderFor(ctx, p[1], 'V'), + seq(`if (V === void 0) { r = void 0; break; }`), + seq(`r.set(K, V)`)])), + seq(`${dest} = r`)]))]; + case M.$dict: + return [seq(`${dest} = d.next()`), + seq(`if (${dest} !== void 0 && !(`, predicateFor(ctx, dest, p), + `)) ${dest} = void 0`)]; + default: + ((_p: never) => {})(p); + throw new Error("Unreachable"); + } +} + +function typeFor(mod: ModuleContext, p: Pattern): Item { + switch (p.label) { + 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.$lit: + return `(typeof ${mod.literal(p[0])})`; + case M.$ref: + return lookup(refPosition(p), p, mod.env, + (_p) => p[1].description!, + (p) => typeForAlternative(mod, p), + (modId, modPath,_p) => { + mod.imports.add([modId, modPath]); + return `${modId}.${p[1].description!}`; + }); + case M.$pointer: + return `_ptr`; + case M.$rec: + return seq('_.Record', anglebrackets(typeFor(mod, p[0]), typeFor(mod, p[1]), '_ptr')); + case M.$tuple: + return brackets(... p[0].map(pp => typeFor(mod, unname(pp)))); + case M.$tuple_STAR_: + if (p[0].length === 0) { + return seq('Array<', typeFor(mod, unname(p[1])), '>'); + } else { + return brackets(... p[0].map(pp => typeFor(mod, unname(pp))), + seq('... Array<', typeFor(mod, unname(p[1])), '>')); + } + case M.$setof: + return seq('_.KeyedSet', anglebrackets(typeFor(mod, p[0]), '_ptr')); + case M.$dictof: + return seq('_.KeyedDictionary', anglebrackets( + typeFor(mod, p[0]), + typeFor(mod, p[1]), + '_ptr')); + case M.$dict: + return parens(seq( + block( + ... Array.from(p[0]).map(([k, vp]) => + seq(`get(k: typeof ${mod.literal(k)}): `, typeFor(mod, unname(vp)))), + ... Array.from(p[0]).map(([k, _vp]) => + seq(`has(k: typeof ${mod.literal(k)}): true`))), + ' & _.Dictionary<_ptr>')); + default: + ((_p: never) => {})(p); + throw new Error("Unreachable"); + } +} + +function typeForDefinition(mod: ModuleContext, _name: symbol, d: Definition): Item { + if (d.label === M.$or) { + return opseq('never', ' | ', ... d[0].map(a => typeForAlternative(mod, a[1]))); + } else { + return typeForAlternative(mod, d); + } +} + +function typeForAlternative(mod: ModuleContext, a: Alternative): Item { + if (a.label === M.$and) { + return opseq('_val', ' & ', ... a[0].map(p => typeFor(mod, p))); + } else { + return typeFor(mod, a); + } +} + +function predicateFor(ctx: FunctionContext, v: string, p: Definition, recordOkAsTuple = false): Item +{ + switch (p.label) { + 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.$lit: + return `_.is(${v}, ${ctx.mod.literal(p[0])})`; + case M.$ref: + return lookup(refPosition(p), p, ctx.mod.env, + (_p) => `is${Ref._.name(p).description!}(${v})`, + (pp) => predicateFor(ctx, v, pp), + (modId, modPath, _p) => { + ctx.mod.imports.add([modId, modPath]); + return `${modId}.is${Ref._.name(p).description!}(${v})`; + }); + case M.$or: { + const alts = p[0]; + const recs = alts.map(p => ctx.mod.derefPattern(p)); + if (recs.length > 1 && recs.every(pp => pp.label === M.$rec)) { + return seq( + `_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(${v}) && `, + parens(opseq('false', ' || ', + ... recs.map(r => + (r.label !== M.$rec) ? '' : parens(seq( + predicateFor(ctx, `${v}.label`, r[0]), + ' && ', + predicateFor(ctx, v, r[1], true))))))); + } else { + return opseq('false', ' || ', ... p[0].map(pp => predicateFor(ctx, v, pp[1]))); + } } + case M.$and: + return opseq('true', ' && ', ... p[0].map(pp => predicateFor(ctx, v, pp))); + case M.$pointer: + return `_.isPointer(${v})`; + case M.$rec: + return opseq('true', ' && ', + `_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(${v})`, + predicateFor(ctx, `${v}.label`, p[0]), + predicateFor(ctx, v, p[1], true)); + case M.$tuple: + return opseq('true', ' && ', + ... (recordOkAsTuple ? [] + : [`_.Array.isArray(${v})`, `!_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(${v})`]), + `(${v}.length === ${p[0].length})`, + ... p[0].map((pp, i) => predicateFor(ctx, `${v}[${i}]`, unname(pp)))); + case M.$tuple_STAR_: + return opseq('true', ' && ', + ... (recordOkAsTuple ? [] + : [`_.Array.isArray(${v})`, `!_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(${v})`]), + `(${v}.length >= ${p[0].length})`, + seq(p[0].length > 0 ? `${v}.slice(${p[0].length})` : v, + `.every(v => `, + parens(predicateFor(ctx, 'v', unname(p[1]))), + `)`), + ... p[0].map((pp, i) => predicateFor(ctx, `${v}[${i}]`, unname(pp)))); + case M.$setof: + return opseq('true', ' && ', + `_.Set.isSet<_val>(${v})`, + fnblock( + seq(`for (const vv of ${v}) `, block( + seq('if (!(', predicateFor(ctx, 'vv', p[0]), ')) return false'))), + seq('return true'))); + case M.$dictof: + return opseq('true', ' && ', + `_.Dictionary.isDictionary<_ptr>(${v})`, + fnblock( + seq(`for (const e of ${v}) `, block( + seq('if (!(', predicateFor(ctx, 'e[0]', p[0]), ')) return false'), + seq('if (!(', predicateFor(ctx, 'e[1]', p[1]), ')) return false'))), + seq('return true'))); + case M.$dict: + return opseq('true', ' && ', + `_.Dictionary.isDictionary<_ptr>(${v})`, + ... Array.from(p[0]).map(([k, vp]) => { + const tmp = ctx.gentemp(); + return parens(seq( + `(${tmp} = ${v}.get(${ctx.mod.literal(k)})) !== void 0 && `, + predicateFor(ctx, tmp, unname(vp)))); + })); + default: + ((_p: never) => {})(p); + throw new Error("Unreachable"); } +} - function unname(p: NamedPattern): Pattern { - 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}`; - } - - function fieldEntry(np: NamedPattern, index: number): Item { - return seq(JSON.stringify(fieldName(np, index)), ': ', typeFor(unname(np))); - } +export function compile(env: Environment, schema: Schema, options: CompilerOptions = {}): string { + const mod = new ModuleContext(env, schema, options); for (const [name0, def] of Schema._._field0(schema).get(M.$definitions)) { const name = name0 as symbol; - temps = []; - const recognizer = predicateFor('v', def); + if (def.label === M.$rec && def[0].label === M.$lit && def[1].label === M.$tuple) { - types.push( + function fieldEntry(np: NamedPattern, index: number): Item { + return seq(JSON.stringify(fieldName(np, index)), ': ', typeFor(mod, unname(np))); + } + mod.defineType( seq(`export const ${name.description!} = _.Record.makeConstructor<`, braces(... def[1][0].map(fieldEntry)), - `, _ptr>()(${literal(def[0][0])}, `, + `, _ptr>()(${mod.literal(def[0][0])}, `, JSON.stringify(def[1][0].map(fieldName)), `);`)); } - types.push( - seq(`export type ${name.description!} = `, typeForDefinition(name, def), `;`)); - functions.push( + + mod.defineType( + seq(`export type ${name.description!} = `, typeForDefinition(mod, name, def), `;`)); + + mod.defineFunction(ctx => seq(`export function is${name.description!}`, '(v: any): v is ', name.description!, ' ', - block( - ... temps.length > 0 ? [seq('let ', commas(... temps), ': any')] : [], - seq('return ', recognizer)))); - functions.push( + ctx.block(() => [seq('return ', predicateFor(ctx, 'v', def))]))); + + mod.defineFunction(ctx => seq(`export function as${name.description!}`, '(v: any): ', name.description!, ' ', - block( + ctx.block(() => [ seq(`if (!is${name.description!}(v)) `, block(`throw new TypeError(\`Invalid ${name.description!}: \${_.stringify(v)}\`)`), ' else ', - block(`return v`))))); + block(`return v`))]))); - functions.push( + mod.defineFunction(ctx => seq(`export function decode${name.description!}`, `(d: _.TypedDecoder<_ptr>): ${name.description!} | undefined `, - collectBody(() => { - emit(seq(`let result`)); - decoderFor(def, 'result'); - emit(seq(`return result`)); - }))); + ctx.block(() => [seq(`let result`), + ... decoderFor(ctx, def, 'result'), + seq(`return result`)]))); } - types.push(seq('export type _ptr = ', pointerName === false ? 'never' : typeFor(pointerName), `;`)); - types.push(`export type _val = _.Value<_ptr>;`); - functions.push(seq(`export const _decodePtr = `, - (pointerName === false - ? '() => { throw new _.DecodeError("Pointers forbidden"); }' - : seq(`(d: _.TypedDecoder<_ptr>) => `, - collectBody(() => { - emit(seq(`let result`)); - decoderFor(pointerName, 'result'); - emit(seq(`return result`)); - }))), + const pointerName = Schema._._field0(schema).get(M.$pointer); + mod.defineType(seq(`export type _ptr = `, + pointerName === false ? 'never' : typeFor(mod, pointerName), `;`)); + mod.defineType(`export type _val = _.Value<_ptr>;`); + + mod.defineFunction(ctx => + seq(`export const _decodePtr = `, + (pointerName === false + ? '() => { throw new _.DecodeError("Pointers forbidden"); }' + : seq(`(d: _.TypedDecoder<_ptr>) => `, ctx.block(() => [ + seq(`let result`), + ... decoderFor(ctx, pointerName, 'result'), + seq(`return result`)]))), + `;`)); const f = new Formatter(); f.write(`import * as _ from ${JSON.stringify(options.preservesModule ?? '@preserves/core')};\n`); - imports.forEach(([identifier, path]) => { + mod.imports.forEach(([identifier, path]) => { f.write(`import * as ${identifier} from ${JSON.stringify(path)};\n`); }); f.newline(); - const sortedLiterals = Array.from(literals); + const sortedLiterals = Array.from(mod.literals); sortedLiterals.sort((a, b) => a[1] < b[1] ? -1 : a[1] === b[1] ? 0 : 1); for (const [lit, varname] of sortedLiterals) { f.write(seq(`export const ${varname} = `, sourceCodeFor(lit), `;\n`)); } f.newline(); - types.forEach(t => { + mod.typedefs.forEach(t => { f.write(t); f.newline(); f.newline(); }); f.newline(); - functions.forEach(p => { + mod.functiondefs.forEach(p => { f.write(p); f.newline(); f.newline(); diff --git a/implementations/javascript/packages/schema/src/gen/schema.ts b/implementations/javascript/packages/schema/src/gen/schema.ts index 3ccc069..e84db5a 100644 --- a/implementations/javascript/packages/schema/src/gen/schema.ts +++ b/implementations/javascript/packages/schema/src/gen/schema.ts @@ -144,20 +144,20 @@ export function asSchema(v: any): Schema { export function decodeSchema(d: _.TypedDecoder<_ptr>): Schema | undefined { let result; if (d.openRecord()) { - let _tmp3: any; - _tmp3 = _.asLiteral(d.nextSymbol(), $schema); - if (_tmp3 !== void 0) { - let _tmp4, _tmp5, _tmp6, _tmp7, _tmp8: any; - _tmp5 = d.next(); - if (_tmp5 !== void 0 && !(( - _.Dictionary.isDictionary<_ptr>(_tmp5) && - ((_tmp6 = _tmp5.get($version)) !== void 0 && isVersion(_tmp6)) && - ((_tmp7 = _tmp5.get($pointer)) !== void 0 && isPointerName(_tmp7)) && + let _tmp0: any; + _tmp0 = _.asLiteral(d.nextSymbol(), $schema); + if (_tmp0 !== void 0) { + let _tmp1, _tmp2, _tmp3, _tmp4, _tmp5: any; + _tmp2 = d.next(); + if (_tmp2 !== void 0 && !(( + _.Dictionary.isDictionary<_ptr>(_tmp2) && + ((_tmp3 = _tmp2.get($version)) !== void 0 && isVersion(_tmp3)) && + ((_tmp4 = _tmp2.get($pointer)) !== void 0 && isPointerName(_tmp4)) && ( - (_tmp8 = _tmp5.get($definitions)) !== void 0 && ( - _.Dictionary.isDictionary<_ptr>(_tmp8) && + (_tmp5 = _tmp2.get($definitions)) !== void 0 && ( + _.Dictionary.isDictionary<_ptr>(_tmp5) && ((() => { - for (const e of _tmp8) { + for (const e of _tmp5) { if (!(typeof e[0] === 'symbol')) return false; if (!(isDefinition(e[1]))) return false; }; @@ -165,9 +165,9 @@ export function decodeSchema(d: _.TypedDecoder<_ptr>): Schema | undefined { })()) ) ) - ))) _tmp5 = void 0; - if (_tmp5 !== void 0) { - if (d.closeCompound()) _tmp4 = [_tmp5] as [ + ))) _tmp2 = void 0; + if (_tmp2 !== void 0) { + if (d.closeCompound()) _tmp1 = [_tmp2] as [ ( { get(k: typeof $version): Version; @@ -180,7 +180,7 @@ export function decodeSchema(d: _.TypedDecoder<_ptr>): Schema | undefined { ) ]; }; - if (_tmp4 !== void 0) result = _.Record< + if (_tmp1 !== void 0) result = _.Record< (typeof $schema), [ ( @@ -194,7 +194,7 @@ export function decodeSchema(d: _.TypedDecoder<_ptr>): Schema | undefined { } & _.Dictionary<_ptr> ) ] - >(_tmp3 as any, _tmp4 as any); + >(_tmp0 as any, _tmp1 as any); }; }; return result; @@ -215,11 +215,11 @@ export function asPointerName(v: any): PointerName { } export function decodePointerName(d: _.TypedDecoder<_ptr>): PointerName | undefined { - let _tmp9: any; + let _tmp0: any; let result; - _tmp9 = d.mark(); + _tmp0 = d.mark(); result = decodeRef(d); - if (result === void 0) {d.restoreMark(_tmp9); result = _.asLiteral(d.nextBoolean(), __lit5);}; + if (result === void 0) {d.restoreMark(_tmp0); result = _.asLiteral(d.nextBoolean(), __lit5);}; return result; } @@ -247,32 +247,32 @@ export function asDefinition(v: any): Definition { } export function decodeDefinition(d: _.TypedDecoder<_ptr>): Definition | undefined { - let _tmp10: any; + let _tmp0: any; let result; - _tmp10 = d.mark(); + _tmp0 = d.mark(); if (d.openRecord()) { - let _tmp11: any; - _tmp11 = _.asLiteral(d.nextSymbol(), $or); - if (_tmp11 !== void 0) { - let _tmp12, _tmp13: any; + let _tmp1: any; + _tmp1 = _.asLiteral(d.nextSymbol(), $or); + if (_tmp1 !== void 0) { + let _tmp2, _tmp3: any; if (d.openSequence()) { - let _tmp14: any; + let _tmp4: any; { let vN: Array | undefined = []; while (!d.closeCompound()) { - _tmp14 = void 0; - _tmp14 = decodeNamedAlternative(d); - if (_tmp14 === void 0) {vN = void 0; break;}; - vN.push(_tmp14); + _tmp4 = void 0; + _tmp4 = decodeNamedAlternative(d); + if (_tmp4 === void 0) {vN = void 0; break;}; + vN.push(_tmp4); }; - _tmp13 = vN; + _tmp3 = vN; }; }; - if (_tmp13 !== void 0) {if (d.closeCompound()) _tmp12 = [_tmp13] as [Array];}; - if (_tmp12 !== void 0) result = _.Record<(typeof $or), [Array]>(_tmp11 as any, _tmp12 as any); + if (_tmp3 !== void 0) {if (d.closeCompound()) _tmp2 = [_tmp3] as [Array];}; + if (_tmp2 !== void 0) result = _.Record<(typeof $or), [Array]>(_tmp1 as any, _tmp2 as any); }; }; - if (result === void 0) {d.restoreMark(_tmp10); result = decodeAlternative(d);}; + if (result === void 0) {d.restoreMark(_tmp0); result = decodeAlternative(d);}; return result; } @@ -291,13 +291,13 @@ export function asNamedAlternative(v: any): NamedAlternative { } export function decodeNamedAlternative(d: _.TypedDecoder<_ptr>): NamedAlternative | undefined { - let _tmp15, _tmp16: any; + let _tmp0, _tmp1: any; let result; if (d.openSequence()) { - _tmp15 = d.nextSymbol(); - if (_tmp15 !== void 0) { - _tmp16 = decodeAlternative(d); - if (_tmp16 !== void 0) {if (d.closeCompound()) result = [_tmp15, _tmp16] as [symbol, Alternative];}; + _tmp0 = d.nextSymbol(); + if (_tmp0 !== void 0) { + _tmp1 = decodeAlternative(d); + if (_tmp1 !== void 0) {if (d.closeCompound()) result = [_tmp0, _tmp1] as [symbol, Alternative];}; }; }; return result; @@ -327,32 +327,32 @@ export function asAlternative(v: any): Alternative { } export function decodeAlternative(d: _.TypedDecoder<_ptr>): Alternative | undefined { - let _tmp17: any; + let _tmp0: any; let result; - _tmp17 = d.mark(); + _tmp0 = d.mark(); if (d.openRecord()) { - let _tmp18: any; - _tmp18 = _.asLiteral(d.nextSymbol(), $and); - if (_tmp18 !== void 0) { - let _tmp19, _tmp20: any; + let _tmp1: any; + _tmp1 = _.asLiteral(d.nextSymbol(), $and); + if (_tmp1 !== void 0) { + let _tmp2, _tmp3: any; if (d.openSequence()) { - let _tmp21: any; + let _tmp4: any; { let vN: Array | undefined = []; while (!d.closeCompound()) { - _tmp21 = void 0; - _tmp21 = decodePattern(d); - if (_tmp21 === void 0) {vN = void 0; break;}; - vN.push(_tmp21); + _tmp4 = void 0; + _tmp4 = decodePattern(d); + if (_tmp4 === void 0) {vN = void 0; break;}; + vN.push(_tmp4); }; - _tmp20 = vN; + _tmp3 = vN; }; }; - if (_tmp20 !== void 0) {if (d.closeCompound()) _tmp19 = [_tmp20] as [Array];}; - if (_tmp19 !== void 0) result = _.Record<(typeof $and), [Array]>(_tmp18 as any, _tmp19 as any); + if (_tmp3 !== void 0) {if (d.closeCompound()) _tmp2 = [_tmp3] as [Array];}; + if (_tmp2 !== void 0) result = _.Record<(typeof $and), [Array]>(_tmp1 as any, _tmp2 as any); }; }; - if (result === void 0) {d.restoreMark(_tmp17); result = decodePattern(d);}; + if (result === void 0) {d.restoreMark(_tmp0); result = decodePattern(d);}; return result; } @@ -363,11 +363,11 @@ export function asPattern(v: any): Pattern { } export function decodePattern(d: _.TypedDecoder<_ptr>): Pattern | undefined { - let _tmp22: any; + let _tmp0: any; let result; - _tmp22 = d.mark(); + _tmp0 = d.mark(); result = decodeSimplePattern(d); - if (result === void 0) {d.restoreMark(_tmp22); result = decodeCompoundPattern(d);}; + if (result === void 0) {d.restoreMark(_tmp0); result = decodeCompoundPattern(d);}; return result; } @@ -391,40 +391,40 @@ export function asSimplePattern(v: any): SimplePattern { export function decodeSimplePattern(d: _.TypedDecoder<_ptr>): SimplePattern | undefined { let result; if (d.openRecord()) { - let _tmp23, _tmp24: any; - _tmp23 = d.next(); - _tmp24 = d.mark(); - if (_.is(_tmp23, $atom)) { - let _tmp25, _tmp26: any; - _tmp26 = decodeAtomKind(d); - if (_tmp26 !== void 0) {if (d.closeCompound()) _tmp25 = [_tmp26] as [AtomKind];}; - if (_tmp25 !== void 0) result = _.Record<(typeof $atom), [AtomKind]>(_tmp23 as any, _tmp25 as any); + let _tmp0, _tmp1: any; + _tmp0 = d.next(); + _tmp1 = d.mark(); + if (_.is(_tmp0, $atom)) { + let _tmp2, _tmp3: any; + _tmp3 = decodeAtomKind(d); + if (_tmp3 !== void 0) {if (d.closeCompound()) _tmp2 = [_tmp3] as [AtomKind];}; + if (_tmp2 !== void 0) result = _.Record<(typeof $atom), [AtomKind]>(_tmp0 as any, _tmp2 as any); }; if (result === void 0) { - d.restoreMark(_tmp24); - if (_.is(_tmp23, $pointer)) { - let _tmp27: any; - if (d.closeCompound()) _tmp27 = [] as []; - if (_tmp27 !== void 0) result = _.Record<(typeof $pointer), []>(_tmp23 as any, _tmp27 as any); + d.restoreMark(_tmp1); + if (_.is(_tmp0, $pointer)) { + let _tmp4: any; + if (d.closeCompound()) _tmp4 = [] as []; + if (_tmp4 !== void 0) result = _.Record<(typeof $pointer), []>(_tmp0 as any, _tmp4 as any); }; if (result === void 0) { - d.restoreMark(_tmp24); - if (_.is(_tmp23, $lit)) { - let _tmp28, _tmp29: any; - _tmp29 = d.next(); - if (_tmp29 !== void 0) {if (d.closeCompound()) _tmp28 = [_tmp29] as [_val];}; - if (_tmp28 !== void 0) result = _.Record<(typeof $lit), [_val]>(_tmp23 as any, _tmp28 as any); + d.restoreMark(_tmp1); + if (_.is(_tmp0, $lit)) { + let _tmp5, _tmp6: any; + _tmp6 = d.next(); + if (_tmp6 !== void 0) {if (d.closeCompound()) _tmp5 = [_tmp6] as [_val];}; + if (_tmp5 !== void 0) result = _.Record<(typeof $lit), [_val]>(_tmp0 as any, _tmp5 as any); }; if (result === void 0) { - d.restoreMark(_tmp24); - if (_.is(_tmp23, $ref)) { - let _tmp30, _tmp31, _tmp32: any; - _tmp31 = decodeModulePath(d); - if (_tmp31 !== void 0) { - _tmp32 = d.nextSymbol(); - if (_tmp32 !== void 0) {if (d.closeCompound()) _tmp30 = [_tmp31, _tmp32] as [ModulePath, symbol];}; + d.restoreMark(_tmp1); + if (_.is(_tmp0, $ref)) { + let _tmp7, _tmp8, _tmp9: any; + _tmp8 = decodeModulePath(d); + if (_tmp8 !== void 0) { + _tmp9 = d.nextSymbol(); + if (_tmp9 !== void 0) {if (d.closeCompound()) _tmp7 = [_tmp8, _tmp9] as [ModulePath, symbol];}; }; - if (_tmp30 !== void 0) result = _.Record<(typeof $ref), [ModulePath, symbol]>(_tmp23 as any, _tmp30 as any); + if (_tmp7 !== void 0) result = _.Record<(typeof $ref), [ModulePath, symbol]>(_tmp0 as any, _tmp7 as any); }; }; }; @@ -478,91 +478,91 @@ export function asCompoundPattern(v: any): CompoundPattern { export function decodeCompoundPattern(d: _.TypedDecoder<_ptr>): CompoundPattern | undefined { let result; if (d.openRecord()) { - let _tmp33, _tmp34: any; - _tmp33 = d.next(); - _tmp34 = d.mark(); - if (_.is(_tmp33, $rec)) { - let _tmp35, _tmp36, _tmp37: any; - _tmp36 = decodePattern(d); - if (_tmp36 !== void 0) { - _tmp37 = decodePattern(d); - if (_tmp37 !== void 0) {if (d.closeCompound()) _tmp35 = [_tmp36, _tmp37] as [Pattern, Pattern];}; + let _tmp0, _tmp1: any; + _tmp0 = d.next(); + _tmp1 = d.mark(); + if (_.is(_tmp0, $rec)) { + let _tmp2, _tmp3, _tmp4: any; + _tmp3 = decodePattern(d); + if (_tmp3 !== void 0) { + _tmp4 = decodePattern(d); + if (_tmp4 !== void 0) {if (d.closeCompound()) _tmp2 = [_tmp3, _tmp4] as [Pattern, Pattern];}; }; - if (_tmp35 !== void 0) result = _.Record<(typeof $rec), [Pattern, Pattern]>(_tmp33 as any, _tmp35 as any); + if (_tmp2 !== void 0) result = _.Record<(typeof $rec), [Pattern, Pattern]>(_tmp0 as any, _tmp2 as any); }; if (result === void 0) { - d.restoreMark(_tmp34); - if (_.is(_tmp33, $tuple)) { - let _tmp38, _tmp39: any; + d.restoreMark(_tmp1); + if (_.is(_tmp0, $tuple)) { + let _tmp5, _tmp6: any; if (d.openSequence()) { - let _tmp40: any; + let _tmp7: any; { let vN: Array | undefined = []; while (!d.closeCompound()) { - _tmp40 = void 0; - _tmp40 = decodeNamedPattern(d); - if (_tmp40 === void 0) {vN = void 0; break;}; - vN.push(_tmp40); + _tmp7 = void 0; + _tmp7 = decodeNamedPattern(d); + if (_tmp7 === void 0) {vN = void 0; break;}; + vN.push(_tmp7); }; - _tmp39 = vN; + _tmp6 = vN; }; }; - if (_tmp39 !== void 0) {if (d.closeCompound()) _tmp38 = [_tmp39] as [Array];}; - if (_tmp38 !== void 0) result = _.Record<(typeof $tuple), [Array]>(_tmp33 as any, _tmp38 as any); + if (_tmp6 !== void 0) {if (d.closeCompound()) _tmp5 = [_tmp6] as [Array];}; + if (_tmp5 !== void 0) result = _.Record<(typeof $tuple), [Array]>(_tmp0 as any, _tmp5 as any); }; if (result === void 0) { - d.restoreMark(_tmp34); - if (_.is(_tmp33, $tuple_STAR_)) { - let _tmp41, _tmp42, _tmp43: any; + d.restoreMark(_tmp1); + if (_.is(_tmp0, $tuple_STAR_)) { + let _tmp8, _tmp9, _tmp10: any; if (d.openSequence()) { - let _tmp44: any; + let _tmp11: any; { let vN: Array | undefined = []; while (!d.closeCompound()) { - _tmp44 = void 0; - _tmp44 = decodeNamedPattern(d); - if (_tmp44 === void 0) {vN = void 0; break;}; - vN.push(_tmp44); + _tmp11 = void 0; + _tmp11 = decodeNamedPattern(d); + if (_tmp11 === void 0) {vN = void 0; break;}; + vN.push(_tmp11); }; - _tmp42 = vN; + _tmp9 = vN; }; }; - if (_tmp42 !== void 0) { - _tmp43 = decodeNamedPattern(d); - if (_tmp43 !== void 0) { - if (d.closeCompound()) _tmp41 = [_tmp42, _tmp43] as [Array, NamedPattern]; + if (_tmp9 !== void 0) { + _tmp10 = decodeNamedPattern(d); + if (_tmp10 !== void 0) { + if (d.closeCompound()) _tmp8 = [_tmp9, _tmp10] as [Array, NamedPattern]; }; }; - if (_tmp41 !== void 0) result = _.Record<(typeof $tuple_STAR_), [Array, NamedPattern]>(_tmp33 as any, _tmp41 as any); + if (_tmp8 !== void 0) result = _.Record<(typeof $tuple_STAR_), [Array, NamedPattern]>(_tmp0 as any, _tmp8 as any); }; if (result === void 0) { - d.restoreMark(_tmp34); - if (_.is(_tmp33, $setof)) { - let _tmp45, _tmp46: any; - _tmp46 = decodeSimplePattern(d); - if (_tmp46 !== void 0) {if (d.closeCompound()) _tmp45 = [_tmp46] as [SimplePattern];}; - if (_tmp45 !== void 0) result = _.Record<(typeof $setof), [SimplePattern]>(_tmp33 as any, _tmp45 as any); + d.restoreMark(_tmp1); + if (_.is(_tmp0, $setof)) { + let _tmp12, _tmp13: any; + _tmp13 = decodeSimplePattern(d); + if (_tmp13 !== void 0) {if (d.closeCompound()) _tmp12 = [_tmp13] as [SimplePattern];}; + if (_tmp12 !== void 0) result = _.Record<(typeof $setof), [SimplePattern]>(_tmp0 as any, _tmp12 as any); }; if (result === void 0) { - d.restoreMark(_tmp34); - if (_.is(_tmp33, $dictof)) { - let _tmp47, _tmp48, _tmp49: any; - _tmp48 = decodeSimplePattern(d); - if (_tmp48 !== void 0) { - _tmp49 = decodeSimplePattern(d); - if (_tmp49 !== void 0) { - if (d.closeCompound()) _tmp47 = [_tmp48, _tmp49] as [SimplePattern, SimplePattern]; + d.restoreMark(_tmp1); + if (_.is(_tmp0, $dictof)) { + let _tmp14, _tmp15, _tmp16: any; + _tmp15 = decodeSimplePattern(d); + if (_tmp15 !== void 0) { + _tmp16 = decodeSimplePattern(d); + if (_tmp16 !== void 0) { + if (d.closeCompound()) _tmp14 = [_tmp15, _tmp16] as [SimplePattern, SimplePattern]; }; }; - if (_tmp47 !== void 0) result = _.Record<(typeof $dictof), [SimplePattern, SimplePattern]>(_tmp33 as any, _tmp47 as any); + if (_tmp14 !== void 0) result = _.Record<(typeof $dictof), [SimplePattern, SimplePattern]>(_tmp0 as any, _tmp14 as any); }; if (result === void 0) { - d.restoreMark(_tmp34); - if (_.is(_tmp33, $dict)) { - let _tmp50, _tmp51: any; - _tmp51 = decodeDictionaryEntries(d); - if (_tmp51 !== void 0) {if (d.closeCompound()) _tmp50 = [_tmp51] as [DictionaryEntries];}; - if (_tmp50 !== void 0) result = _.Record<(typeof $dict), [DictionaryEntries]>(_tmp33 as any, _tmp50 as any); + d.restoreMark(_tmp1); + if (_.is(_tmp0, $dict)) { + let _tmp17, _tmp18: any; + _tmp18 = decodeDictionaryEntries(d); + if (_tmp18 !== void 0) {if (d.closeCompound()) _tmp17 = [_tmp18] as [DictionaryEntries];}; + if (_tmp17 !== void 0) result = _.Record<(typeof $dict), [DictionaryEntries]>(_tmp0 as any, _tmp17 as any); }; }; }; @@ -622,26 +622,26 @@ export function asAtomKind(v: any): AtomKind { } export function decodeAtomKind(d: _.TypedDecoder<_ptr>): AtomKind | undefined { - let _tmp52: any; + let _tmp0: any; let result; - _tmp52 = d.mark(); + _tmp0 = d.mark(); result = _.asLiteral(d.nextSymbol(), $Boolean); if (result === void 0) { - d.restoreMark(_tmp52); + d.restoreMark(_tmp0); result = _.asLiteral(d.nextSymbol(), $Float); if (result === void 0) { - d.restoreMark(_tmp52); + d.restoreMark(_tmp0); result = _.asLiteral(d.nextSymbol(), $Double); if (result === void 0) { - d.restoreMark(_tmp52); + d.restoreMark(_tmp0); result = _.asLiteral(d.nextSymbol(), $SignedInteger); if (result === void 0) { - d.restoreMark(_tmp52); + d.restoreMark(_tmp0); result = _.asLiteral(d.nextSymbol(), $String); if (result === void 0) { - d.restoreMark(_tmp52); + d.restoreMark(_tmp0); result = _.asLiteral(d.nextSymbol(), $ByteString); - if (result === void 0) {d.restoreMark(_tmp52); result = _.asLiteral(d.nextSymbol(), $Symbol);}; + if (result === void 0) {d.restoreMark(_tmp0); result = _.asLiteral(d.nextSymbol(), $Symbol);}; }; }; }; @@ -666,23 +666,23 @@ export function asNamedPattern(v: any): NamedPattern { } export function decodeNamedPattern(d: _.TypedDecoder<_ptr>): NamedPattern | undefined { - let _tmp53: any; + let _tmp0: any; let result; - _tmp53 = d.mark(); + _tmp0 = d.mark(); if (d.openRecord()) { - let _tmp54: any; - _tmp54 = _.asLiteral(d.nextSymbol(), $named); - if (_tmp54 !== void 0) { - let _tmp55, _tmp56, _tmp57: any; - _tmp56 = d.nextSymbol(); - if (_tmp56 !== void 0) { - _tmp57 = decodeSimplePattern(d); - if (_tmp57 !== void 0) {if (d.closeCompound()) _tmp55 = [_tmp56, _tmp57] as [symbol, SimplePattern];}; + let _tmp1: any; + _tmp1 = _.asLiteral(d.nextSymbol(), $named); + if (_tmp1 !== void 0) { + let _tmp2, _tmp3, _tmp4: any; + _tmp3 = d.nextSymbol(); + if (_tmp3 !== void 0) { + _tmp4 = decodeSimplePattern(d); + if (_tmp4 !== void 0) {if (d.closeCompound()) _tmp2 = [_tmp3, _tmp4] as [symbol, SimplePattern];}; }; - if (_tmp55 !== void 0) result = _.Record<(typeof $named), [symbol, SimplePattern]>(_tmp54 as any, _tmp55 as any); + if (_tmp2 !== void 0) result = _.Record<(typeof $named), [symbol, SimplePattern]>(_tmp1 as any, _tmp2 as any); }; }; - if (result === void 0) {d.restoreMark(_tmp53); result = decodePattern(d);}; + if (result === void 0) {d.restoreMark(_tmp0); result = decodePattern(d);}; return result; } @@ -701,16 +701,16 @@ export function asRef(v: any): Ref { export function decodeRef(d: _.TypedDecoder<_ptr>): Ref | undefined { let result; if (d.openRecord()) { - let _tmp58: any; - _tmp58 = _.asLiteral(d.nextSymbol(), $ref); - if (_tmp58 !== void 0) { - let _tmp59, _tmp60, _tmp61: any; - _tmp60 = decodeModulePath(d); - if (_tmp60 !== void 0) { - _tmp61 = d.nextSymbol(); - if (_tmp61 !== void 0) {if (d.closeCompound()) _tmp59 = [_tmp60, _tmp61] as [ModulePath, symbol];}; + let _tmp0: any; + _tmp0 = _.asLiteral(d.nextSymbol(), $ref); + if (_tmp0 !== void 0) { + let _tmp1, _tmp2, _tmp3: any; + _tmp2 = decodeModulePath(d); + if (_tmp2 !== void 0) { + _tmp3 = d.nextSymbol(); + if (_tmp3 !== void 0) {if (d.closeCompound()) _tmp1 = [_tmp2, _tmp3] as [ModulePath, symbol];}; }; - if (_tmp59 !== void 0) result = _.Record<(typeof $ref), [ModulePath, symbol]>(_tmp58 as any, _tmp59 as any); + if (_tmp1 !== void 0) result = _.Record<(typeof $ref), [ModulePath, symbol]>(_tmp0 as any, _tmp1 as any); }; }; return result; @@ -732,14 +732,14 @@ export function asModulePath(v: any): ModulePath { export function decodeModulePath(d: _.TypedDecoder<_ptr>): ModulePath | undefined { let result; if (d.openSequence()) { - let _tmp62: any; + let _tmp0: any; { let vN: Array | undefined = []; while (!d.closeCompound()) { - _tmp62 = void 0; - _tmp62 = d.nextSymbol(); - if (_tmp62 === void 0) {vN = void 0; break;}; - vN.push(_tmp62); + _tmp0 = void 0; + _tmp0 = d.nextSymbol(); + if (_tmp0 === void 0) {vN = void 0; break;}; + vN.push(_tmp0); }; result = vN; }; diff --git a/implementations/javascript/packages/schema/src/meta.ts b/implementations/javascript/packages/schema/src/meta.ts index 99074d0..2b548fc 100644 --- a/implementations/javascript/packages/schema/src/meta.ts +++ b/implementations/javascript/packages/schema/src/meta.ts @@ -43,7 +43,7 @@ export function lookup(namePos: Position | null, env: Environment, kLocal: (p: Definition) => R, kBase: (p: Alternative) => R, - kOther: (mod: string, modPath: string, p: Definition | null) => R): R + kOther: (modId: string, modPath: string, p: Definition | null) => R): R { for (const e of env) { if (is(e.schemaModulePath, Ref._.module(name)) ||