Skip to content

Commit

Permalink
feat(Value): return Errors as CoreValues
Browse files Browse the repository at this point in the history
BREAKING CHANGE
  • Loading branch information
Sheyne committed Feb 27, 2017
1 parent 3475d69 commit 25fb4b0
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 22 deletions.
12 changes: 8 additions & 4 deletions sinap-includes/plugin-program.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
export type Error = { error: string };
export type Error = {
kind: "sinap-error",
message: string,
stack?: string,
};
export type Result = { states: any[], result: any };

export interface PluginProgram {
run(a: any): Result | Error;
run(a: any): Result;
validate(): string[];
}

export function isError(e: { states: any[], result: any } | { error: any } | null): e is Error {
return e != null && (e as any).error !== undefined;
export function isError(e: any): e is Error {
return e != null && typeof (e.message) === "string" && (e.stack === undefined || typeof (e.stack) === "string") && e.kind === "sinap-error";
}
10 changes: 6 additions & 4 deletions sinap-includes/plugin-stub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,15 @@ export class Program implements PluginProgram {
// TODO: improve if plugin defines a validate function
const res = this.run([]);
if (isError(res)) {
return [res.error];
return [res.message];
}
return [];
}

run(input: any[]) {
const states: plugin.State[] = [];
try {
let current = (plugin as any).start(this.graph, ...input);
const states: plugin.State[] = [];
while (current instanceof plugin.State) {
states.push(current);
current = plugin.step(current);
Expand All @@ -117,14 +117,16 @@ export class Program implements PluginProgram {
result: current,
};
} catch (e) {
const message = e instanceof Error ? e.message : e;
const stack = e instanceof Error ? e.stack : undefined;
return {
error: e
result: { message: e.message, stack: stack, kind: "sinap-error" },
states: states,
};
}
}
}


export class File {
constructor(public name: string) { }
}
Expand Down
25 changes: 19 additions & 6 deletions src/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,28 @@ export class Program {
runArguments: Type[][];
run(a: CoreValue[]): { states: CoreValue[], result: CoreValue } {
const output = this.program.run(a.map(v => v.value));
if (isError(output)) {
throw output.error;
}
const stateType = this.plugin.typeEnvironment.lookupPluginType("State");
const errorType = this.plugin.typeEnvironment.lookupGlobalType("Error");

let result: CoreValue;

if (isError(output.result)) {
const err = new Error(output.result.message);
err.stack = output.result.stack;
result = new CoreValue(
errorType,
err,
);
} else {
result = new CoreValue(
pickReturnType(a.map(v => v.type), this.plugin.typeEnvironment.startTypes, stateType, this.plugin.typeEnvironment),
output.result
);
}

return {
states: output.states.map(s => new CoreValue(stateType, s)),
result: new CoreValue(
pickReturnType(a.map(v => v.type), this.plugin.typeEnvironment.startTypes, stateType, this.plugin.typeEnvironment),
output.result),
result: result,
};
}
}
31 changes: 24 additions & 7 deletions test/test-interpreters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,10 @@ describe("various interpreters", () => {
const pluginProg = new context.global["plugin-stub"].Program(JSON.parse(serialGraph));
const prog = new Program(pluginProg, dfa);
const stringType = dfa.typeEnvironment.getStringType();
const errorType = dfa.typeEnvironment.lookupGlobalType("Error");

assert.throws(() => prog.run([new CoreValue(stringType, "11")]), "allows multiple start states");
assert.equal(errorType, prog.run([new CoreValue(stringType, "11")]).result.type);
assert.equal("Only one start state allowed", prog.run([new CoreValue(stringType, "11")]).result.value.message);
});
it("checks for 0 start states", () => {
const model = new CoreModel(dfa, {
Expand Down Expand Up @@ -363,7 +365,10 @@ describe("various interpreters", () => {
const prog = new Program(pluginProg, dfa);
const stringType = dfa.typeEnvironment.getStringType();

assert.throws(() => prog.run([new CoreValue(stringType, "11")]), "allows zero start states");
const errorType = dfa.typeEnvironment.lookupGlobalType("Error");

assert.equal(errorType, prog.run([new CoreValue(stringType, "11")]).result.type);
assert.equal("Must have one start state", prog.run([new CoreValue(stringType, "11")]).result.value.message);
});
it("checks for empty transitions", () => {
const model = new CoreModel(dfa, {
Expand Down Expand Up @@ -466,7 +471,10 @@ describe("various interpreters", () => {
const prog = new Program(pluginProg, dfa);
const stringType = dfa.typeEnvironment.getStringType();

assert.throws(() => prog.run([new CoreValue(stringType, "11")]), "allows empty transitions");
const errorType = dfa.typeEnvironment.lookupGlobalType("Error");

assert.equal(errorType, prog.run([new CoreValue(stringType, "11")]).result.type);
assert.equal("Lambda transition from q0 to q0 is not allowed", prog.run([new CoreValue(stringType, "11")]).result.value.message);
});
it("checks for two character transitions", () => {
const model = new CoreModel(dfa, {
Expand Down Expand Up @@ -569,7 +577,10 @@ describe("various interpreters", () => {
const prog = new Program(pluginProg, dfa);
const stringType = dfa.typeEnvironment.getStringType();

assert.throws(() => prog.run([new CoreValue(stringType, "11")]), "allows two character transitions");
const errorType = dfa.typeEnvironment.lookupGlobalType("Error");

assert.equal(errorType, prog.run([new CoreValue(stringType, "11")]).result.type);
assert.equal("Edge 23 must be one symbol", prog.run([new CoreValue(stringType, "11")]).result.value.message);
});
});
describe("nfa", () => {
Expand Down Expand Up @@ -809,8 +820,10 @@ describe("various interpreters", () => {
const pluginProg = new context.global["plugin-stub"].Program(JSON.parse(serialGraph));
const prog = new Program(pluginProg, nfa);
const stringType = nfa.typeEnvironment.getStringType();
const errorType = nfa.typeEnvironment.lookupGlobalType("Error");

assert.throws(() => prog.run([new CoreValue(stringType, "11")]), "allows multiple start states");
assert.equal(errorType, prog.run([new CoreValue(stringType, "11")]).result.type, "allows multiple start states");
assert.equal("Only one start state allowed", prog.run([new CoreValue(stringType, "11")]).result.value.message, "allows multiple start states");
});
it("checks for 0 start states", () => {
const model = new CoreModel(nfa, {
Expand Down Expand Up @@ -912,8 +925,10 @@ describe("various interpreters", () => {
const pluginProg = new context.global["plugin-stub"].Program(JSON.parse(serialGraph));
const prog = new Program(pluginProg, nfa);
const stringType = nfa.typeEnvironment.getStringType();
const errorType = nfa.typeEnvironment.lookupGlobalType("Error");

assert.throws(() => prog.run([new CoreValue(stringType, "11")]), "allows zero start states");
assert.equal(errorType, prog.run([new CoreValue(stringType, "11")]).result.type, "allows zero start states");
assert.equal("Must have one start state", prog.run([new CoreValue(stringType, "11")]).result.value.message, "allows zero start states");
});
it("allows empty transitions", () => {
const model = new CoreModel(nfa, {
Expand Down Expand Up @@ -1118,8 +1133,10 @@ describe("various interpreters", () => {
const pluginProg = new context.global["plugin-stub"].Program(JSON.parse(serialGraph));
const prog = new Program(pluginProg, nfa);
const stringType = nfa.typeEnvironment.getStringType();
const errorType = nfa.typeEnvironment.lookupGlobalType("Error");

assert.throws(() => prog.run([new CoreValue(stringType, "11")]), "allows two character transitions");
assert.equal(errorType, prog.run([new CoreValue(stringType, "11")]).result.type);
assert.equal("Edge 23 must be one symbol", prog.run([new CoreValue(stringType, "11")]).result.value.message);
});
it("supports non-determinism", () => {
const model = new CoreModel(nfa, {
Expand Down
4 changes: 3 additions & 1 deletion test/test-stub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,10 @@ describe("plugin stub", () => {
const pluginProg = new (context as any).global["plugin-stub"].Program({ elements: [] });
const prog = new Program(pluginProg, plugin);
const numberType = plugin.typeEnvironment.getStringType();
const errorType = plugin.typeEnvironment.lookupGlobalType("Error");

assert.throws(() => prog.run([new CoreValue(numberType, 456)]));
assert.equal(errorType, prog.run([new CoreValue(numberType, 456)]).result.type);
assert.equal("Cannot read property 'parents' of undefined", prog.run([new CoreValue(numberType, 456)]).result.value.message);
});

it("has sinap types", () => {
Expand Down

0 comments on commit 25fb4b0

Please sign in to comment.