Excise old decoder
This commit is contained in:
parent
87dda48083
commit
4ded3a484c
|
@ -3,8 +3,7 @@ import * as M from "./meta";
|
||||||
import { CompilerOptions, ModuleContext } from "./compiler/context";
|
import { CompilerOptions, ModuleContext } from "./compiler/context";
|
||||||
import { block, brackets, Formatter, Item, parens, seq } from "./compiler/block";
|
import { block, brackets, Formatter, Item, parens, seq } from "./compiler/block";
|
||||||
import { typeForDefinition } from "./compiler/gentype";
|
import { typeForDefinition } from "./compiler/gentype";
|
||||||
// import { decoderFor } from "./compiler/decoder";
|
import { converterForDefinition, converterForSimple } from "./compiler/genconverter";
|
||||||
import { converterForDefinition } from "./compiler/genconverter";
|
|
||||||
import { EMPTY_TYPE, renderType } from "./compiler/type";
|
import { EMPTY_TYPE, renderType } from "./compiler/type";
|
||||||
import { genConstructor } from "./compiler/genctor";
|
import { genConstructor } from "./compiler/genctor";
|
||||||
|
|
||||||
|
@ -20,13 +19,13 @@ export function compile(env: M.Environment, schema: M.Schema, options: CompilerO
|
||||||
mod.defineType(`export type _val = _.Value<_ptr>;`);
|
mod.defineType(`export type _val = _.Value<_ptr>;`);
|
||||||
|
|
||||||
mod.defineFunction(ctx =>
|
mod.defineFunction(ctx =>
|
||||||
seq(`export const _decodePtr = `,
|
seq(`export const _toPtr = `,
|
||||||
(pointerName._variant === 'false'
|
(pointerName._variant === 'false'
|
||||||
? '() => { throw new _.DecodeError("Pointers forbidden"); }'
|
? '() => { throw new _.DecodeError("Pointers forbidden"); }'
|
||||||
: seq(`(d: _.TypedDecoder<_ptr>) => `, ctx.block(() => [
|
: seq(`(v: _val) => `, ctx.block(() => [
|
||||||
seq(`let result`),
|
seq(`let result: undefined | _ptr`),
|
||||||
seq(`/* TODO */`),
|
... converterForSimple(
|
||||||
// ... decoderFor(ctx, pointerName, 'result'),
|
ctx, M.SimplePattern.Ref(pointerName.value), 'v', 'result'),
|
||||||
seq(`return result`)]))),
|
seq(`return result`)]))),
|
||||||
`;`));
|
`;`));
|
||||||
|
|
||||||
|
@ -66,14 +65,6 @@ export function compile(env: M.Environment, schema: M.Schema, options: CompilerO
|
||||||
ctx.block(() => [seq(`let result: undefined | `, name.description!),
|
ctx.block(() => [seq(`let result: undefined | `, name.description!),
|
||||||
... converterForDefinition(ctx, def, 'v', 'result'),
|
... converterForDefinition(ctx, def, 'v', 'result'),
|
||||||
seq(`return result`)])));
|
seq(`return result`)])));
|
||||||
|
|
||||||
// mod.defineFunction(ctx =>
|
|
||||||
// seq(`export function decode${name.description!}`,
|
|
||||||
// `(d: _.TypedDecoder<_ptr>): undefined | `, name.description!,
|
|
||||||
// ctx.block(() => [seq(`let result: undefined | `, name.description!),
|
|
||||||
// seq(`/* TODO */`),
|
|
||||||
// // ... decoderFor(ctx, def, 'result'),
|
|
||||||
// seq(`return result`)])));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const f = new Formatter();
|
const f = new Formatter();
|
||||||
|
|
|
@ -173,7 +173,7 @@ function converterFor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function converterForSimple(
|
export function converterForSimple(
|
||||||
ctx: FunctionContext,
|
ctx: FunctionContext,
|
||||||
p: M.SimplePattern,
|
p: M.SimplePattern,
|
||||||
src: string,
|
src: string,
|
||||||
|
@ -202,7 +202,7 @@ function converterForSimple(
|
||||||
(_p) => [`${dest} = to${p.value.name.description!}(${src})`],
|
(_p) => [`${dest} = to${p.value.name.description!}(${src})`],
|
||||||
(modId, modPath,_p) => {
|
(modId, modPath,_p) => {
|
||||||
ctx.mod.imports.add([modId, modPath]);
|
ctx.mod.imports.add([modId, modPath]);
|
||||||
return [`${dest} = ${modId}.decode${p.value.name.description!}(${src})`];
|
return [`${dest} = ${modId}.to${p.value.name.description!}(${src})`];
|
||||||
});
|
});
|
||||||
case 'pointer':
|
case 'pointer':
|
||||||
return [`${dest} = _toPtr(${src})`];
|
return [`${dest} = _toPtr(${src})`];
|
||||||
|
|
|
@ -1,209 +0,0 @@
|
||||||
/*
|
|
||||||
import { FunctionContext } from "./context";
|
|
||||||
import * as M from '../meta';
|
|
||||||
import { anglebrackets, block, brackets, Item, opseq, parens, seq } from "./block";
|
|
||||||
import { typeFor } from './type';
|
|
||||||
import { refPosition } from "../reader";
|
|
||||||
|
|
||||||
function decodeCompound(ctx: FunctionContext,
|
|
||||||
p: M.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: M.Pattern,
|
|
||||||
ps: M.Pattern[],
|
|
||||||
dest: string,
|
|
||||||
recordFields: boolean,
|
|
||||||
variablePattern: M.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 {
|
|
||||||
return [block(
|
|
||||||
seq(`let vN: `, typeFor(ctx.mod, tuplePattern),
|
|
||||||
` | undefined = `, brackets(... temps)),
|
|
||||||
decodeCompound(ctx,
|
|
||||||
variablePattern,
|
|
||||||
() => [`vN = void 0`],
|
|
||||||
(t) => [`vN.push(${t})`]),
|
|
||||||
seq(`${dest} = vN`))];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return recordFields
|
|
||||||
? loop(0)
|
|
||||||
: [seq(`if (d.openSequence()) `, ctx.block(() => loop(0)))];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function decoderFor(ctx: FunctionContext, p: M.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.$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 M.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, M.unname(alt[0])), `) `, ctx.block(() => {
|
|
||||||
const fs = ctx.gentemp();
|
|
||||||
return [...decoderFor(ctx, M.unname(alt[1]), fs, true),
|
|
||||||
seq(`if (${fs} !== void 0) ${dest} = _.Record`,
|
|
||||||
anglebrackets(typeFor(ctx.mod, M.unname(alt[0])),
|
|
||||||
typeFor(ctx.mod, M.unname(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)]))]
|
|
||||||
: [],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
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 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)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case M.$and:
|
|
||||||
switch (p[0].length) {
|
|
||||||
case 0: return [`${dest} = d.next()`];
|
|
||||||
case 1: return decoderFor(ctx, M.unname(p[0][0]), dest);
|
|
||||||
default: {
|
|
||||||
const [pp0, ... ppN] = p[0];
|
|
||||||
return [...decoderFor(ctx, M.unname(pp0), dest),
|
|
||||||
seq(`if (!`, opseq('true', ' && ',
|
|
||||||
... ppN.map(pp =>
|
|
||||||
predicateFor(ctx, dest, M.unname(pp)))),
|
|
||||||
`) ${dest} = void 0`)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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, M.unname(p[0]), label),
|
|
||||||
seq(`if (${label} !== void 0) `, ctx.block(() => {
|
|
||||||
const fs = ctx.gentemp();
|
|
||||||
return [...decoderFor(ctx, M.unname(p[1]), fs, true),
|
|
||||||
seq(`if (${fs} !== void 0) ${dest} = _.Record`,
|
|
||||||
anglebrackets(typeFor(ctx.mod, M.unname(p[0])),
|
|
||||||
typeFor(ctx.mod, M.unname(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(M.unname), dest, recordFields, void 0);
|
|
||||||
case M.$tuple_STAR_:
|
|
||||||
// assume dest is already void 0
|
|
||||||
return decoderForTuple(ctx, p, p[0].map(M.unname), dest, recordFields, M.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()`),
|
|
||||||
decodeCompound(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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
|
@ -106,7 +106,7 @@ export type Ref = {"module": ModulePath, "name": symbol};
|
||||||
export type ModulePath = Array<symbol>;
|
export type ModulePath = Array<symbol>;
|
||||||
|
|
||||||
|
|
||||||
export const _decodePtr = () => { throw new _.DecodeError("Pointers forbidden"); };
|
export const _toPtr = () => { throw new _.DecodeError("Pointers forbidden"); };
|
||||||
|
|
||||||
export function Schema(version: Version, pointer: PointerName, definitions: Definitions): Schema {return {version, pointer, definitions};}
|
export function Schema(version: Version, pointer: PointerName, definitions: Definitions): Schema {return {version, pointer, definitions};}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue