Skip to content

Commit 4903dcb

Browse files
committed
Meter the virtual machine
1 parent 844aeb5 commit 4903dcb

File tree

4 files changed

+62
-6
lines changed

4 files changed

+62
-6
lines changed

document.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export default class Document {
2-
constructor(element, createPage) {
2+
constructor(element, createPage, meterFaultButton) {
33
const self = this;
44
this.document = element.ownerDocument;
55
this.parent = element;
@@ -20,6 +20,8 @@ export default class Document {
2020
self.answer(event.target.number);
2121
};
2222
this.createPage = createPage || this.createPage;
23+
this.meterFaultButton = meterFaultButton;
24+
2325
Object.seal(this);
2426
}
2527

@@ -144,6 +146,12 @@ export default class Document {
144146
}
145147
}
146148

149+
meterFault() {
150+
if (this.meterFaultButton) {
151+
this.body.appendChild(this.meterFaultButton);
152+
}
153+
}
154+
147155
ask(_cue) {}
148156

149157
answer(text) {

engine.js

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ export default class Engine {
3434
this.story = args.story;
3535
this.labels = Object.keys(this.story);
3636
this.handler = args.handler;
37+
this.meter = 0;
38+
this.limit = 1e3;
3739
this.options = [];
3840
this.keywords = {};
3941
this.noOption = null;
@@ -63,11 +65,15 @@ export default class Engine {
6365
this.resume();
6466
}
6567

68+
/**
69+
* Runs the event loop until it yields.
70+
*/
6671
continue() {
67-
let _continue;
68-
do {
72+
this.meter = 0;
73+
for (;;) {
6974
if (this.debug) {
7075
console.log(`${this.label} ${this.instruction.type} ${describe(this.instruction)}`);
76+
console.log(this.top);
7177
}
7278
if (this.instruction == null) {
7379
// TODO user error for non-console interaction.
@@ -79,8 +85,24 @@ export default class Engine {
7985
console.error(`Unexpected instruction type: ${this.instruction.type}`, this.instruction);
8086
this.resume();
8187
}
82-
_continue = this[`$${this.instruction.type}`](this.instruction);
83-
} while (_continue);
88+
const proceed = this[`$${this.instruction.type}`](this.instruction);
89+
if (!proceed) {
90+
return;
91+
}
92+
this.meter += 1;
93+
if (this.meter >= this.limit) {
94+
this.display();
95+
this.dialog.meterFault();
96+
return;
97+
}
98+
}
99+
}
100+
101+
clearMeterFault() {
102+
if (this.meter >= this.limit) {
103+
this.render.clear();
104+
this.continue();
105+
}
84106
}
85107

86108
goto(label) {
@@ -170,6 +192,13 @@ export default class Engine {
170192
}
171193

172194
answer(text) {
195+
if (this.meter >= this.limit) {
196+
// We shouldn’t really arrive here, and can't with the CLI
197+
// implementation, but rigging the web client to be sensitive to the mode
198+
// when dispatching on number keys is more trouble than it's worth.
199+
this.clearMeterFault();
200+
return;
201+
}
173202
if (this.handler && this.handler.answer) {
174203
this.handler.answer(text, this);
175204
}
@@ -256,6 +285,9 @@ export default class Engine {
256285
];
257286
}
258287

288+
/**
289+
* Resumes from a snapshot.
290+
*/
259291
resume(snapshot) {
260292
this.render.clear();
261293
this.flush();

entry.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,13 @@ const handler = {
3838
},
3939
};
4040

41-
const doc = new Document(document.body);
41+
const meterFaultButton = document.createElement('a');
42+
meterFaultButton.innerText = 'Continue…';
43+
meterFaultButton.addEventListener('click', () => {
44+
engine.clearMeterFault();
45+
});
46+
47+
const doc = new Document(document.body, null, meterFaultButton);
4248

4349
const engine = new Engine({
4450
story: story,

readline.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ export default class Readline {
1818
Object.seal(this);
1919
}
2020

21+
meterFault() {
22+
this.readline.question(`Enter any command to continue... `, (answer) => {
23+
if (answer === 'quit') {
24+
this.close();
25+
} else {
26+
this.engine.clearMeterFault();
27+
}
28+
});
29+
}
30+
2131
ask(cue) {
2232
this.readline.question(`${cue || ''}> `, this.boundAnswer);
2333
}

0 commit comments

Comments
 (0)