Adapt bf and chef to error handling
This commit is contained in:
@ -3,7 +3,6 @@ import {
|
||||
LanguageEngine,
|
||||
StepExecutionResult,
|
||||
} from "../../types";
|
||||
import { UnexpectedError } from "../../errors";
|
||||
import { parseProgram } from "../parser";
|
||||
import * as T from "../types";
|
||||
import InputStream from "./input-stream";
|
||||
@ -62,8 +61,7 @@ export default class ChefLanguageEngine implements LanguageEngine<T.ChefRS> {
|
||||
currFrame.pc += 1;
|
||||
} else if (currFrame.pc === currFrame.recipe.method.length) {
|
||||
// Execution of the "Serves" statement
|
||||
const serves = currFrame.recipe.serves;
|
||||
if (!serves) throw new UnexpectedError();
|
||||
const serves = currFrame.recipe.serves!;
|
||||
output = this.getKitchenOutput(currFrame.kitchen, serves.num);
|
||||
currFrame.pc += 1;
|
||||
} else {
|
||||
@ -157,7 +155,7 @@ export default class ChefLanguageEngine implements LanguageEngine<T.ChefRS> {
|
||||
|
||||
// Check value of loop-opener ingredient
|
||||
const opener = currRecipe.recipe.method[op.opener].op;
|
||||
if (opener.code !== "LOOP-OPEN") throw new UnexpectedError();
|
||||
if (opener.code !== "LOOP-OPEN") throw new Error("Bad jump address");
|
||||
const ing = currRecipe.kitchen.getIngredient(opener.ing, true);
|
||||
if (ing.value === 0) currRecipe.pc += 1;
|
||||
else currRecipe.pc = op.opener;
|
||||
@ -261,7 +259,7 @@ export default class ChefLanguageEngine implements LanguageEngine<T.ChefRS> {
|
||||
|
||||
/** Get topmost frame in call stack. Throws if stack is empty. */
|
||||
private getCurrentFrame(): CallStackItem {
|
||||
if (this._stack.length === 0) throw new UnexpectedError();
|
||||
if (this._stack.length === 0) throw new Error("Call stack is empty");
|
||||
return this._stack[this._stack.length - 1];
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { RuntimeError } from "../../worker-errors";
|
||||
|
||||
/**
|
||||
* A barebones input stream implementation for consuming integers from a string.
|
||||
*/
|
||||
@ -20,10 +22,10 @@ export default class InputStream {
|
||||
getNumber(): number {
|
||||
this.exhaustLeadingWhitespace();
|
||||
// The extra whitespace differentiates whether string is empty or all numbers.
|
||||
if (this._text === "") throw new Error("Unexpected end of input");
|
||||
if (this._text === "") throw new RuntimeError("Unexpected end of input");
|
||||
let posn = this._text.search(/[^0-9]/);
|
||||
if (posn === 0)
|
||||
throw new Error(`Unexpected input character: '${this._text[0]}'`);
|
||||
throw new RuntimeError(`Unexpected input character: '${this._text[0]}'`);
|
||||
if (posn === -1) posn = this._text.length;
|
||||
// Consume and parse numeric part
|
||||
const numStr = this._text.slice(0, posn);
|
||||
|
@ -7,6 +7,7 @@ import {
|
||||
StackItem,
|
||||
} from "../types";
|
||||
import InputStream from "./input-stream";
|
||||
import { RuntimeError } from "../../worker-errors";
|
||||
|
||||
/** Type for a list maintained as an index map */
|
||||
type IndexList<T> = { [k: string]: T };
|
||||
@ -72,9 +73,9 @@ export default class ChefKitchen {
|
||||
|
||||
getIngredient(name: string, assertValue?: boolean): IngredientItem {
|
||||
const item = this._ingredients[name];
|
||||
if (!item) throw new Error(`Ingredient '${name}' does not exist`);
|
||||
if (!item) throw new RuntimeError(`Ingredient '${name}' does not exist`);
|
||||
if (assertValue && item.value == null)
|
||||
throw new Error(`Ingredient '${name}' is undefined`);
|
||||
throw new RuntimeError(`Ingredient '${name}' is undefined`);
|
||||
else return item;
|
||||
}
|
||||
|
||||
@ -113,7 +114,7 @@ export default class ChefKitchen {
|
||||
/** Pop value from a mixing bowl and store into an ingredient */
|
||||
popFromBowl(bowlId: number, ingredient: string): void {
|
||||
const bowl = this.getBowl(bowlId);
|
||||
if (bowl.length === 0) throw new Error(`Bowl ${bowlId} is empty`);
|
||||
if (bowl.length === 0) throw new RuntimeError(`Bowl ${bowlId} is empty`);
|
||||
|
||||
const item = bowl.pop() as StackItem;
|
||||
this.getIngredient(ingredient).type = item.type;
|
||||
@ -126,7 +127,7 @@ export default class ChefKitchen {
|
||||
*/
|
||||
addValue(bowlId: number, ingredient: string): void {
|
||||
const bowl = this.getBowl(bowlId);
|
||||
if (bowl.length === 0) throw new Error(`Bowl ${bowlId} is empty`);
|
||||
if (bowl.length === 0) throw new RuntimeError(`Bowl ${bowlId} is empty`);
|
||||
const bowlValue = bowl.pop()!.value;
|
||||
const ingValue = this.getIngredient(ingredient, true).value as number;
|
||||
bowl.push({ type: "unknown", value: ingValue + bowlValue });
|
||||
@ -138,7 +139,7 @@ export default class ChefKitchen {
|
||||
*/
|
||||
subtractValue(bowlId: number, ingredient: string): void {
|
||||
const bowl = this.getBowl(bowlId);
|
||||
if (bowl.length === 0) throw new Error(`Bowl ${bowlId} is empty`);
|
||||
if (bowl.length === 0) throw new RuntimeError(`Bowl ${bowlId} is empty`);
|
||||
const bowlValue = bowl.pop()!.value;
|
||||
const ingValue = this.getIngredient(ingredient, true).value as number;
|
||||
bowl.push({ type: "unknown", value: bowlValue - ingValue });
|
||||
@ -150,7 +151,7 @@ export default class ChefKitchen {
|
||||
*/
|
||||
multiplyValue(bowlId: number, ingredient: string): void {
|
||||
const bowl = this.getBowl(bowlId);
|
||||
if (bowl.length === 0) throw new Error(`Bowl ${bowlId} is empty`);
|
||||
if (bowl.length === 0) throw new RuntimeError(`Bowl ${bowlId} is empty`);
|
||||
const bowlValue = bowl.pop()!.value;
|
||||
const ingValue = this.getIngredient(ingredient, true).value as number;
|
||||
bowl.push({ type: "unknown", value: ingValue * bowlValue });
|
||||
@ -162,7 +163,7 @@ export default class ChefKitchen {
|
||||
*/
|
||||
divideValue(bowlId: number, ingredient: string): void {
|
||||
const bowl = this.getBowl(bowlId);
|
||||
if (bowl.length === 0) throw new Error(`Bowl ${bowlId} is empty`);
|
||||
if (bowl.length === 0) throw new RuntimeError(`Bowl ${bowlId} is empty`);
|
||||
const bowlValue = bowl.pop()!.value;
|
||||
const ingValue = this.getIngredient(ingredient, true).value as number;
|
||||
bowl.push({ type: "unknown", value: bowlValue / ingValue });
|
||||
@ -173,7 +174,8 @@ export default class ChefKitchen {
|
||||
const totalValue = Object.keys(this._ingredients).reduce((sum, name) => {
|
||||
const ing = this._ingredients[name];
|
||||
if (ing.type !== "dry") return sum;
|
||||
if (ing.value == null) throw new Error(`Ingredient ${name} is undefined`);
|
||||
if (ing.value == null)
|
||||
throw new RuntimeError(`Ingredient ${name} is undefined`);
|
||||
return sum + ing.value;
|
||||
}, 0);
|
||||
this.getBowl(bowlId).push({ type: "dry", value: totalValue });
|
||||
|
Reference in New Issue
Block a user