Skip to content

Commit e5757f7

Browse files
committed
add abort function
1 parent c9729d9 commit e5757f7

File tree

4 files changed

+48
-7
lines changed

4 files changed

+48
-7
lines changed

DNCL3.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ export class DNCL3 {
1212
parseTokens(s) {
1313
return this.parser.parseTokens(s);
1414
}
15-
run(maxloop) {
15+
run(maxloop, signal) {
1616
this.runtime = new Runtime(this.ast, this.callbackoutput, this.callbackinput);
17-
return this.runtime.run(maxloop);
17+
return this.runtime.run(maxloop, signal);
1818
}
1919
getVars() {
2020
return this.runtime.getVars();

Runtime.js

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//import { sleep } from "https://js.sabae.cc/sleep.js";
2+
import { sleep } from "./sleep.js";
3+
14
const DEFAULT_MAX_LOOP = 1000;
25

36
const isUpperAlphabet = (c) => "ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(c) >= 0;
@@ -67,6 +70,7 @@ export class Runtime {
6770
this.callbackoutput = callbackoutput;
6871
this.callbackinput = callbackinput;
6972
this.ast = ast;
73+
this.pc = 0;
7074
}
7175
async getArrayIndex(ast, scope) {
7276
const prop = await this.calcExpression(ast, scope);
@@ -80,6 +84,10 @@ export class Runtime {
8084
ast.type == "Program" ? ast.body :
8185
ast.type == "SequenceExpression" ? ast.expressions : [ast];
8286
for (const cmd of body) {
87+
this.checkAbort();
88+
if (this.pc++ % 100 == 0) {
89+
await sleep(1, this.signal);
90+
}
8391
//console.log(cmd)
8492
if (cmd.type == "ExpressionStatement") {
8593
await this.runBlock(cmd.expression, scope);
@@ -221,8 +229,15 @@ export class Runtime {
221229
throw new Error(funcname + "の呼び出し回数が、" + this.maxloop + "回の繰り返し上限に達しました");
222230
}
223231
}
224-
async run(maxloop = DEFAULT_MAX_LOOP) {
232+
checkAbort() {
233+
//console.log(this.signal?.aborted);
234+
if (this.signal?.aborted) {
235+
throw new Error("abort: ", this.signal.reason);
236+
}
237+
}
238+
async run(maxloop = DEFAULT_MAX_LOOP, signal = null) {
225239
this.maxloop = parseInt(maxloop);
240+
this.signal = signal;
226241
if (isNaN(this.maxloop)) throw new Error("maxloopが不正です");
227242
this.callcount = {};
228243
this.scope = new Scope();

index.html

+14-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ <h1>DNCL3実行環境</h1>
66
サンプル <select id=selexamples></select>
77
<label><input type=checkbox id=chkvar checked>変数表示</label>
88
<label><input type=checkbox id=chkmaxloop checked>繰り返し上限 <input id=inmaxloop value=1000></label>
9+
<button id=btnstop>STOP</button>
910
<main>
1011
<div class=diveditor id=divprog></div>
1112
<div class=diveditor id=divrun></div>
@@ -91,10 +92,15 @@ <h1>DNCL3実行環境</h1>
9192
}
9293
};
9394

94-
let bkval = null;
9595
let running = false;
96+
let abortctrl = null;
9697
const onchange = async () => {
97-
if (running) return;
98+
console.log("onchange", performance.now())
99+
if (running) {
100+
//abortctrl.abort();
101+
return;
102+
}
103+
abortctrl = new AbortController();
98104
running = true;
99105
const src = prog.getValue();
100106
run.setValue("");
@@ -104,7 +110,10 @@ <h1>DNCL3実行環境</h1>
104110
run.setValue(run.getValue() + s + "\n");
105111
});
106112
const maxloop = chkmaxloop.checked ? inmaxloop.value : 0;
107-
await dncl.run(maxloop);
113+
btnstop.onclick = () => {
114+
abortctrl.abort();
115+
};
116+
await dncl.run(maxloop, abortctrl.signal);
108117
if (chkvar.checked) {
109118
run.setValue(run.getValue() + "\nvars " + JSON.stringify(dncl.getVars(), null, 2) + "\n");
110119
}
@@ -113,15 +122,16 @@ <h1>DNCL3実行環境</h1>
113122
//ast.setValue(JSON.stringify(e, null, 2));
114123
run.setValue(run.getValue() + e.toString() + "\n");
115124
}
116-
bkval = src;
117125
running = false;
118126
};
119127

120128
//prog.onDidChangeModelContent = onchange; // なぜか初回のみ
129+
let bkval = null;
121130
setInterval(() => {
122131
const txt = prog.getValue();
123132
if (bkval == txt) return;
124133
onchange();
134+
bkval = txt;
125135
}, 500);
126136

127137
const data = await CSV.fetchJSON("examples.csv");

sleep.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export const sleep = (ms, signal) => {
2+
return new Promise((resolve, reject) => {
3+
let abortfunc;
4+
const timer = setTimeout(() => {
5+
resolve();
6+
signal?.removeEventListener("abort", abortfunc);
7+
}, ms);
8+
9+
abortfunc = () => {
10+
clearTimeout(timer);
11+
reject(new Error("sleep aborted"));
12+
signal?.removeEventListener("abort", abortfunc);
13+
};
14+
signal?.addEventListener("abort", abortfunc);
15+
});
16+
};

0 commit comments

Comments
 (0)