Skip to content

Commit 2b11882

Browse files
committed
Use VirtualMachine to run scripts
1 parent b52c713 commit 2b11882

File tree

5 files changed

+49
-73
lines changed

5 files changed

+49
-73
lines changed

src/engine/compiler.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "compiler.h"
44
#include "engine.h"
55
#include <cassert>
6+
#include <iostream>
67

78
using namespace libscratchcpp;
89
using namespace vm;

src/engine/engine.cpp

Lines changed: 28 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,13 @@ void Engine::compile()
8585
variables = compiler.variables();
8686
lists = compiler.lists();
8787
constInputValues = compiler.constInputValues();
88-
auto vm = std::make_shared<VirtualMachine>();
89-
vm->setFunctions(m_functions);
90-
vm->setConstValues(compiler.constValues());
91-
vm->setVariables(compiler.variablePtrs());
92-
vm->setLists(lists);
93-
vm->setBytecode(compiler.bytecode());
94-
m_scripts[block] = vm;
88+
m_scripts[block] = VirtualMachine(target.get(), this);
89+
VirtualMachine &vm = m_scripts[block];
90+
vm.setFunctions(m_functions);
91+
vm.setConstValues(compiler.constValues());
92+
vm.setVariables(compiler.variablePtrs());
93+
vm.setLists(lists);
94+
vm.setBytecode(compiler.bytecode());
9595
} else
9696
std::cout << "warning: unsupported top level block: " << block->opcode() << std::endl;
9797
}
@@ -106,53 +106,24 @@ void Engine::compile()
106106
* \note Nothing will happen until start() is called.
107107
* \param[in] timeLimit The time limit for the frame (for atomic scripts). Set to 0 for no limit.
108108
*/
109-
void Engine::frame(std::chrono::milliseconds timeLimit)
109+
void Engine::frame()
110110
{
111-
auto frameStartTime = std::chrono::steady_clock::now();
112-
std::vector<std::shared_ptr<RunningScript>> scriptsToRemove;
113-
auto scripts = m_runningScripts;
114-
for (auto script : scripts) {
115-
std::shared_ptr<Block> block;
111+
for (VirtualMachine &script : m_runningScripts) {
116112
m_breakFrame = false;
117-
m_atomic = true;
118113

119114
do {
120-
block = script->currentBlock();
121-
if (!script->currentBlock()) {
122-
std::cout << "warning: encountered a null block in one of the scripts" << std::endl;
123-
scriptsToRemove.push_back(script);
124-
continue;
125-
}
126-
127-
// Call the implementation of the block (if it has an implementation)
128-
block->run(script.get());
129-
130-
// Move to next block
131-
if (m_stayOnCurrentBlock) {
132-
m_stayOnCurrentBlock = false;
133-
block = script->currentBlock();
134-
} else {
135-
script->moveToNextBlock();
136-
block = script->currentBlock();
137-
if (!block) {
138-
// There isn't any block to move to
139-
// This means the script has finished
140-
scriptsToRemove.push_back(script);
141-
}
142-
}
143-
144-
if (timeLimit.count() > 0) {
145-
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - frameStartTime);
146-
if (duration > timeLimit)
147-
break;
148-
}
149-
} while (block != nullptr && !m_breakFrame);
115+
script.run(nullptr);
116+
} while (script.atEnd() && !m_breakFrame);
150117
}
151118

152-
for (auto script : scriptsToRemove) {
153-
m_runningScripts.erase(std::remove(m_runningScripts.begin(), m_runningScripts.end(), script), m_runningScripts.end());
119+
for (auto script : m_scriptsToRemove) {
120+
auto it = std::find(m_runningScriptPtrs.begin(), m_runningScriptPtrs.end(), script);
121+
auto index = it - m_runningScriptPtrs.begin();
122+
m_runningScripts.erase(m_runningScripts.begin() + index);
123+
m_runningScriptPtrs.erase(m_runningScriptPtrs.begin() + index);
154124
scriptCount--;
155125
}
126+
m_scriptsToRemove.clear();
156127
}
157128

158129
/*!
@@ -191,40 +162,30 @@ void Engine::startScript(std::shared_ptr<Block> topLevelBlock, std::shared_ptr<T
191162
}
192163

193164
if (topLevelBlock->next()) {
194-
auto script = std::make_shared<RunningScript>(topLevelBlock, target, this);
195-
m_runningScripts.push_back(script);
196-
script->moveToNextBlock();
165+
m_runningScripts.push_back(m_scripts[topLevelBlock]);
166+
m_runningScriptPtrs.push_back(&m_runningScripts.back());
197167
scriptCount++;
198168
}
199169
}
200170

201171
/*! Stops the given script. */
202-
void Engine::stopScript(RunningScript *script)
172+
void Engine::stopScript(VirtualMachine *vm)
203173
{
204-
assert(script);
205-
int i = 0;
206-
for (auto s : m_runningScripts) {
207-
if (s.get() == script) {
208-
m_runningScripts.erase(m_runningScripts.begin() + i);
209-
break;
210-
}
211-
i++;
212-
}
213-
scriptCount--;
174+
assert(vm);
175+
m_scriptsToRemove.push_back(vm);
214176
}
215177

216178
/*!
217179
* Stops all scripts in the given target.
218180
* \param[in] target The Target to stop.
219181
* \param[in] exceptScript Sets this parameter to stop all scripts except the given script.
220182
*/
221-
void Engine::stopTarget(Target *target, RunningScript *exceptScript)
183+
void Engine::stopTarget(Target *target, VirtualMachine *exceptScript)
222184
{
223-
std::vector<RunningScript *> scripts;
224-
for (auto script : m_runningScripts) {
225-
RunningScript *s = script.get();
226-
if ((script->target().get() == target) && (s != exceptScript))
227-
scripts.push_back(s);
185+
std::vector<VirtualMachine *> scripts;
186+
for (VirtualMachine &script : m_runningScripts) {
187+
if ((script.target() == target) && (&script != exceptScript))
188+
scripts.push_back(&script);
228189
}
229190

230191
for (auto script : scripts)
@@ -245,7 +206,7 @@ void Engine::run()
245206
while (true) {
246207
auto lastFrameTime = std::chrono::steady_clock::now();
247208
// Execute the frame
248-
frame(frameDuration);
209+
frame();
249210
if (scriptCount <= 0)
250211
break;
251212

src/engine/engine.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "../scratch/runningscript.h"
88
#include "../scratch/target.h"
99
#include "global.h"
10+
#include "virtualmachine.h"
1011
#include <map>
1112
#include <memory>
1213
#include <chrono>
@@ -31,12 +32,12 @@ class LIBSCRATCHCPP_EXPORT Engine
3132
void clear();
3233
void compile();
3334

34-
void frame(std::chrono::milliseconds timeLimit = std::chrono::milliseconds(0));
35+
void frame();
3536
void start();
3637
void stop();
3738
void startScript(std::shared_ptr<Block> topLevelBlock, std::shared_ptr<Target> target);
38-
void stopScript(RunningScript *script);
39-
void stopTarget(Target *target, RunningScript *exceptScript = nullptr);
39+
void stopScript(VirtualMachine *vm);
40+
void stopTarget(Target *target, VirtualMachine *exceptScript);
4041
void run();
4142

4243
void breakFrame();
@@ -71,8 +72,10 @@ class LIBSCRATCHCPP_EXPORT Engine
7172
std::vector<std::shared_ptr<Target>> m_targets;
7273
std::vector<std::shared_ptr<Broadcast>> m_broadcasts;
7374
std::vector<std::string> m_extensions;
74-
std::vector<std::shared_ptr<RunningScript>> m_runningScripts;
75-
std::unordered_map<std::shared_ptr<Block>, std::shared_ptr<VirtualMachine>> m_scripts;
75+
std::vector<VirtualMachine> m_runningScripts;
76+
std::vector<VirtualMachine *> m_runningScriptPtrs;
77+
std::vector<VirtualMachine *> m_scriptsToRemove;
78+
std::unordered_map<std::shared_ptr<Block>, VirtualMachine> m_scripts;
7679
std::vector<BlockFunc> m_functions;
7780

7881
bool m_breakFrame = false;

src/engine/virtualmachine.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// SPDX-License-Identifier: Apache-2.0
22

33
#include "virtualmachine.h"
4+
#include <iostream>
45

56
#define MAX_REG_COUNT 1024
67

@@ -21,6 +22,13 @@ using namespace vm;
2122

2223
/*! Constructs VirtualMachine. */
2324
VirtualMachine::VirtualMachine()
25+
{
26+
}
27+
28+
/*! \copydoc VirtualMachine() */
29+
VirtualMachine::VirtualMachine(Target *target, Engine *engine) :
30+
m_target(target),
31+
m_engine(engine)
2432
{
2533
m_regs = new Value *[MAX_REG_COUNT];
2634
for (int i = 0; i < MAX_REG_COUNT; i++)

src/engine/virtualmachine.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class LIBSCRATCHCPP_EXPORT VirtualMachine
6060
{
6161
public:
6262
VirtualMachine();
63-
VirtualMachine(const VirtualMachine &) = delete;
63+
VirtualMachine(Target *target, Engine *engine);
6464
~VirtualMachine();
6565

6666
void setFunctions(const std::vector<BlockFunc> &functions);
@@ -69,6 +69,9 @@ class LIBSCRATCHCPP_EXPORT VirtualMachine
6969
void setLists(const std::vector<List *> &lists);
7070
void setBytecode(const std::vector<unsigned int> &code);
7171

72+
Target *target() const { return m_target; };
73+
Engine *engine() const { return m_engine; };
74+
7275
const Value *getInput(unsigned int index, unsigned int argCount) const { return m_regs[m_regCount - argCount + index]; };
7376
unsigned int getFieldIndex(unsigned int index) const { return m_globalPos[index]; };
7477

0 commit comments

Comments
 (0)