added better error handling

This commit is contained in:
Aidan K. Ewart 2020-06-02 18:06:32 +01:00
parent 09a704ae7c
commit 2ec9cf6a0c
3 changed files with 48 additions and 17 deletions

View File

@ -13,6 +13,8 @@ code {
<button id="step">step</button> <button id="step">step</button>
<button id="play">play</button> <button id="play">play</button>
<button id="load">load</button> <button id="load">load</button>
<input type="checkbox" id="use-std" name="use-std" checked>
<label for="use-std">use stdlib?</label>
<pre id="insbox"></pre> <pre id="insbox"></pre>
<pre id="outbox"></pre> <pre id="outbox"></pre>
<script src="./main.js" type="module"></script> <script src="./main.js" type="module"></script>

View File

@ -13,6 +13,8 @@ const stepb = document.getElementById("step")
const play = document.getElementById("play") const play = document.getElementById("play")
const load = document.getElementById("load") const load = document.getElementById("load")
const usestd = document.getElementById("use-std")
let state = null; let state = null;
let input = null; let input = null;
@ -36,7 +38,23 @@ const loadState = () => {
} }
insbox.innerHTML = input; insbox.innerHTML = input;
outbox.innerHTML = ""; outbox.innerHTML = "";
state = {scopes:[scope], stacks:[[]], calls:[ast.parsed.arr]}; if (usestd.checked) {
state = {scopes:[scope], stacks:[[]], calls:[ast.parsed.arr]};
} else {
state = {scopes:[{}], stacks:[[]], calls:[ast.parsed.arr]};
}
}
const showIns = (ins) => {
if (ins.val) {
return ins.val;
} else if (ins.ident) {
return ins.ident;
} else if (ins.name) {
return ins.name;
} else {
return 'anon';
}
} }
load.onclick = _ => { load.onclick = _ => {
@ -49,9 +67,12 @@ play.onclick = _ => {
} }
insbox.innerHTML = ""; insbox.innerHTML = "";
while (state.calls[0].length > 0 || state.calls.length > 1) { while (state.calls[0].length > 0 || state.calls.length > 1) {
step(state, customHandler); try {
if (state.stacks.length > 4096) { step(state, customHandler, showIns);
insbox.innerHTML = "max recursion depth exceeded" } catch (err) {
insbox.innerHTML = err;
state = null;
input = null;
return; return;
} }
} }
@ -65,7 +86,15 @@ stepb.onclick = _ => {
return; return;
} }
if (state.calls[0].length > 0 || state.calls.length > 1) { if (state.calls[0].length > 0 || state.calls.length > 1) {
let pos = step(state, customHandler); let pos;
try {
pos = step(state, customHandler, showIns);
} catch (err) {
insbox.innerHTML = err;
state = null;
input = null;
return;
}
if (!(pos.start === 0 && pos.end === 0)) { if (!(pos.start === 0 && pos.end === 0)) {
insbox.innerHTML = highlight(input, pos.start, pos.end, "green"); insbox.innerHTML = highlight(input, pos.start, pos.end, "green");
} }
@ -74,10 +103,6 @@ stepb.onclick = _ => {
} else { } else {
outbox.innerHTML = prettyprint(state.stacks[0]); outbox.innerHTML = prettyprint(state.stacks[0]);
} }
if (state.stacks.length > 4096) {
insbox.innerHTML = "max recursion depth exceeded"
return;
}
} }
} }
@ -85,7 +110,7 @@ const show = (elem) => {
if (elem.type === "pair") { if (elem.type === "pair") {
return "{" + show(elem.val.fst) + ", " + show(elem.val.snd) + "}" return "{" + show(elem.val.fst) + ", " + show(elem.val.snd) + "}"
} else if (elem.type === "closure") { } else if (elem.type === "closure") {
return "(needs: " + elem.val.args.join(", ") + ")" return "(needs " + elem.val.args.length + ")"
} else if (elem.type === "array") { } else if (elem.type === "array") {
return "[" + prettyprint(elem.val) + "]" return "[" + prettyprint(elem.val) + "]"
} else { } else {

View File

@ -121,7 +121,10 @@ const doIns = (ins, state, handler) => {
} }
} }
export const step = (state, handler) => { export const step = (state, handler, showIns, maxdepth) => {
if (state.stacks.length > maxdepth) {
throw 'max recursion depth exceeded'
}
if (state.calls[state.calls.length-1].length === 0) { if (state.calls[state.calls.length-1].length === 0) {
if (state.calls.length === 1) { if (state.calls.length === 1) {
throw 'finished execution' throw 'finished execution'
@ -137,18 +140,19 @@ export const step = (state, handler) => {
} else { } else {
let ins = state.calls[state.calls.length-1][0]; let ins = state.calls[state.calls.length-1][0];
state.calls[state.calls.length-1] = state.calls[state.calls.length-1].slice(1); state.calls[state.calls.length-1] = state.calls[state.calls.length-1].slice(1);
doIns(ins, state, handler); try {
doIns(ins, state, handler);
} catch (error) {
throw error + ' while executing "' + showIns(ins) + '"'
}
return ins.pos; return ins.pos;
} }
} }
export const execRPN = (scope, ins, handler=(x)=>[x]) => { export const execRPN = (scope, ins, handler=(x)=>[x], showIns=(x)=>x.name, maxdepth=16384) => {
let state = {scopes:[scope], stacks:[[]], calls:[ins]}; let state = {scopes:[scope], stacks:[[]], calls:[ins]};
while (state.calls[0].length > 0 || state.calls.length > 1) { while (state.calls[0].length > 0 || state.calls.length > 1) {
step(state, handler); step(state, handler, showIns, maxdepth);
if (state.stacks.length > 4096) {
throw 'max recursion depth exceeded'
}
} }
return state; return state;
} }