Skip to content

Commit e9f0a36

Browse files
committed
Implement LOOP blocks in interpreter
1 parent 87119ea commit e9f0a36

File tree

4 files changed

+39
-5
lines changed

4 files changed

+39
-5
lines changed

src/engine/execute.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const handleReport = function (resolvedValue, sequencer, thread, blockCached, la
5555
const opcode = blockCached.opcode;
5656
const isHat = blockCached._isHat;
5757
const isConditional = blockCached._isConditional;
58+
const isLoop = blockCached._isLoop;
5859

5960
thread.pushReportedValue(resolvedValue);
6061
if (isHat) {
@@ -87,6 +88,8 @@ const handleReport = function (resolvedValue, sequencer, thread, blockCached, la
8788
} else if (isConditional) {
8889
const branch = Math.round(resolvedValue);
8990
sequencer.stepToBranch(thread, branch, false);
91+
} else if (isLoop && cast.toBoolean(resolvedValue)) {
92+
sequencer.stepToBranch(thread, 1, true);
9093
} else {
9194
// In a non-hat, report the value visually if necessary if
9295
// at the top of the thread stack.
@@ -298,6 +301,7 @@ class BlockCached {
298301

299302
const flowing = runtime._flowing[opcode];
300303
this._isConditional = !!(flowing && flowing.conditional);
304+
this._isLoop = !!(flowing && flowing.loop);
301305

302306
// Store the current shadow value if there is a shadow value.
303307
const fieldKeys = Object.keys(fields);

src/engine/runtime.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,10 +1127,15 @@ class Runtime extends EventEmitter {
11271127
edgeActivated: blockInfo.isEdgeActivated,
11281128
restartExistingThreads: blockInfo.shouldRestartExistingThreads
11291129
};
1130-
}
1131-
if (blockInfo.blockType === BlockType.CONDITIONAL) {
1130+
} else if (blockInfo.blockType === BlockType.CONDITIONAL) {
1131+
this._flowing[opcode] = {
1132+
conditional: true,
1133+
loop: false
1134+
};
1135+
} else if (blockInfo.blockType === BlockType.LOOP) {
11321136
this._flowing[opcode] = {
1133-
conditional: true
1137+
conditional: false,
1138+
loop: true
11341139
};
11351140
}
11361141
}

test/fixtures/tw-loop.sb3

2.7 KB
Binary file not shown.

test/integration/tw_conditional_and_loop.js

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,20 +89,45 @@ compilerAndInterpreter('CONDITIONAL', (t, co) => {
8989
const vm = new VirtualMachine();
9090
vm.setCompilerOptions(co);
9191
vm.extensionManager.addBuiltinExtension('loopsAndThings', LoopsAndThings);
92+
vm.runtime.on('COMPILE_ERROR', () => {
93+
t.fail('Compile error');
94+
});
9295

9396
vm.loadProject(fs.readFileSync(path.join(__dirname, '../fixtures/tw-conditional.sb3'))).then(() => {
9497
let okayCount = 0;
9598
vm.runtime.on('SAY', (target, type, text) => {
9699
if (text === 'OK!') {
97100
okayCount++;
98101
} else if (text === 'end') {
102+
vm.stop();
99103
t.equal(okayCount, 5);
100-
vm.runtime.stop();
101104
t.end();
102105
}
103106
});
104107

105108
vm.greenFlag();
106-
vm.runtime.start();
109+
vm.start();
110+
});
111+
});
112+
113+
compilerAndInterpreter('LOOP', (t, co) => {
114+
t.plan(1);
115+
116+
const vm = new VirtualMachine();
117+
vm.setCompilerOptions(co);
118+
vm.extensionManager.addBuiltinExtension('loopsAndThings', LoopsAndThings);
119+
vm.runtime.on('COMPILE_ERROR', () => {
120+
t.fail('Compile error');
121+
});
122+
123+
vm.loadProject(fs.readFileSync(path.join(__dirname, '../fixtures/tw-loop.sb3'))).then(() => {
124+
vm.runtime.on('SAY', (target, type, text) => {
125+
vm.stop();
126+
t.equal(text, 'a 5 b 50 c 200');
127+
t.end();
128+
});
129+
130+
vm.greenFlag();
131+
vm.start();
107132
});
108133
});

0 commit comments

Comments
 (0)