Skip to content

Commit 2886f2e

Browse files
committed
Compile monitor blocks
1 parent 332dbaa commit 2886f2e

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

src/engine/internal/engine.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ void Engine::resolveIds()
134134
for (auto monitor : m_monitors) {
135135
auto block = monitor->block();
136136
auto container = blockSectionContainer(block->opcode());
137+
138+
if (container)
139+
block->setCompileFunction(container->resolveBlockCompileFunc(block->opcode()));
140+
137141
const auto &fields = block->fields();
138142
Target *target;
139143

@@ -211,6 +215,37 @@ void Engine::compile()
211215
}
212216
}
213217
}
218+
219+
// Compile monitor blocks to bytecode
220+
std::cout << "Compiling stage monitors..." << std::endl;
221+
222+
for (auto monitor : m_monitors) {
223+
Target *target = monitor->sprite() ? dynamic_cast<Target *>(monitor->sprite()) : stage();
224+
Compiler compiler(this, target);
225+
auto block = monitor->block();
226+
auto section = blockSection(block->opcode());
227+
228+
if (section) {
229+
auto script = std::make_shared<Script>(target, block, this);
230+
monitor->setScript(script);
231+
compiler.init();
232+
compiler.setBlock(block);
233+
234+
if (block->compileFunction())
235+
block->compile(&compiler);
236+
else
237+
std::cout << "warning: monitor block doesn't have a compile function: " << block->opcode() << std::endl;
238+
239+
compiler.end();
240+
241+
script->setBytecode(compiler.bytecode());
242+
script->setFunctions(m_functions);
243+
script->setConstValues(compiler.constValues());
244+
script->setVariables(compiler.variables());
245+
script->setLists(compiler.lists());
246+
} else
247+
std::cout << "warning: unsupported monitor block: " << block->opcode() << std::endl;
248+
}
214249
}
215250

216251
void Engine::start()

test/engine/engine_test.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
#include <scratchcpp/keyevent.h>
99
#include <scratchcpp/monitor.h>
1010
#include <scratchcpp/field.h>
11+
#include <scratchcpp/compiler.h>
12+
#include <scratchcpp/script.h>
13+
#include <scratchcpp/virtualmachine.h>
1114
#include <scratch/sound_p.h>
1215
#include <timermock.h>
1316
#include <clockmock.h>
@@ -99,6 +102,37 @@ TEST(EngineTest, Clear)
99102
ASSERT_TRUE(engine.monitors().empty());
100103
}
101104

105+
TEST(EngineTest, CompileMonitors)
106+
{
107+
Engine engine;
108+
auto stage = std::make_shared<Stage>();
109+
auto sprite = std::make_shared<Sprite>();
110+
engine.setTargets({ stage, sprite });
111+
112+
auto m1 = std::make_shared<Monitor>("a", "monitor_test1");
113+
auto m2 = std::make_shared<Monitor>("b", "monitor_test2");
114+
m2->setSprite(sprite.get());
115+
engine.setMonitors({ m1, m2 });
116+
117+
auto section = std::make_shared<TestSection>();
118+
engine.registerSection(section);
119+
engine.addCompileFunction(section.get(), m1->opcode(), [](Compiler *compiler) { compiler->addConstValue(5.4); });
120+
engine.addCompileFunction(section.get(), m2->opcode(), [](Compiler *compiler) { compiler->addConstValue("test"); });
121+
122+
engine.compile();
123+
auto script1 = m1->script();
124+
auto script2 = m2->script();
125+
ASSERT_TRUE(script1 && script2);
126+
127+
ASSERT_EQ(script1->bytecodeVector(), std::vector<unsigned int>({ vm::OP_START, vm::OP_CONST, 0, vm::OP_HALT }));
128+
ASSERT_EQ(script1->target(), stage.get());
129+
ASSERT_EQ(script1->topBlock(), m1->block());
130+
131+
ASSERT_EQ(script2->bytecodeVector(), std::vector<unsigned int>({ vm::OP_START, vm::OP_CONST, 0, vm::OP_HALT }));
132+
ASSERT_EQ(script2->target(), sprite.get());
133+
ASSERT_EQ(script2->topBlock(), m2->block());
134+
}
135+
102136
TEST(EngineTest, IsRunning)
103137
{
104138
Engine engine;

0 commit comments

Comments
 (0)