Skip to content

Commit 0485474

Browse files
authored
Merge pull request #185 from scratchcpp/compiler_custom_values
Add a way to use custom constant values in Compiler
2 parents a18d5d4 + 67ad176 commit 0485474

File tree

6 files changed

+45
-10
lines changed

6 files changed

+45
-10
lines changed

include/scratchcpp/compiler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class LIBSCRATCHCPP_EXPORT Compiler
5656
void addInstruction(vm::Opcode opcode, const std::initializer_list<unsigned int> &args = {});
5757
void addInput(Input *input);
5858
void addInput(int id);
59+
void addConstValue(const Value &value);
5960
void addFunctionCall(BlockFunc f);
6061
void addProcedureArg(const std::string &procCode, const std::string &argName);
6162
void moveToSubstack(std::shared_ptr<Block> substack1, std::shared_ptr<Block> substack2, SubstackType type);

src/blocks/eventblocks.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,28 @@ void EventBlocks::registerBlocks(IEngine *engine)
3434
void EventBlocks::compileBroadcast(Compiler *compiler)
3535
{
3636
auto input = compiler->input(BROADCAST_INPUT);
37-
compiler->addInput(input);
37+
3838
if (input->type() != Input::Type::ObscuredShadow) {
39-
input->primaryValue()->setValue(compiler->engine()->findBroadcast(input->primaryValue()->value().toString()));
39+
compiler->addConstValue(compiler->engine()->findBroadcast(input->primaryValue()->value().toString()));
4040
compiler->addFunctionCall(&broadcastByIndex);
41-
} else
41+
} else {
42+
compiler->addInput(input);
4243
compiler->addFunctionCall(&broadcast);
44+
}
4345
}
4446

4547
void EventBlocks::compileBroadcastAndWait(Compiler *compiler)
4648
{
4749
auto input = compiler->input(BROADCAST_INPUT);
48-
compiler->addInput(input);
50+
4951
if (input->type() != Input::Type::ObscuredShadow) {
50-
input->primaryValue()->setValue(compiler->engine()->findBroadcast(input->primaryValue()->value().toString()));
52+
int index = compiler->engine()->findBroadcast(input->primaryValue()->value().toString());
53+
compiler->addConstValue(index);
5154
compiler->addFunctionCall(&broadcastByIndexAndWait);
52-
compiler->addInput(input);
55+
compiler->addConstValue(index);
5356
compiler->addFunctionCall(&checkBroadcastByIndex);
5457
} else {
58+
compiler->addInput(input);
5559
compiler->addFunctionCall(&broadcastAndWait);
5660
compiler->addInput(input);
5761
compiler->addFunctionCall(&checkBroadcast);

src/engine/compiler.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#include <scratchcpp/compiler.h>
44
#include <scratchcpp/iengine.h>
55
#include <scratchcpp/input.h>
6-
#include <scratchcpp/inputvalue.h>
76
#include <scratchcpp/block.h>
87
#include <scratchcpp/variable.h>
98
#include <scratchcpp/list.h>
@@ -189,6 +188,14 @@ void Compiler::addInput(int id)
189188
addInput(input(id));
190189
}
191190

191+
/*! Adds a constant value and an instruction to load it. Useful if you don't have an input for the addInput() method. */
192+
void libscratchcpp::Compiler::addConstValue(const Value &value)
193+
{
194+
impl->customConstValues.push_back(std::make_unique<InputValue>());
195+
impl->customConstValues.back()->setValue(value);
196+
addInstruction(OP_CONST, { impl->constIndex(impl->customConstValues.back().get()) });
197+
}
198+
192199
/*! Adds a function call to the bytecode (the OP_EXEC instruction). */
193200
void Compiler::addFunctionCall(BlockFunc f)
194201
{

src/engine/compiler_p.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33
#pragma once
44

55
#include <scratchcpp/compiler.h>
6+
#include <scratchcpp/inputvalue.h>
67

78
namespace libscratchcpp
89
{
910

1011
struct CompilerPrivate
1112
{
1213
CompilerPrivate(IEngine *engine);
14+
CompilerPrivate(const CompilerPrivate &) = delete;
1315

1416
void addInstruction(vm::Opcode opcode, std::initializer_list<unsigned int> args = {});
1517

@@ -25,6 +27,7 @@ struct CompilerPrivate
2527

2628
std::vector<unsigned int> bytecode;
2729
std::vector<InputValue *> constValues;
30+
std::vector<std::unique_ptr<InputValue>> customConstValues;
2831
std::unordered_map<InputValue *, std::pair<bool, std::string>> constValueMenuInfo; // input value, <whether the input points to a dropdown menu, selected menu item>
2932
std::vector<Variable *> variables;
3033
std::vector<List *> lists;

test/blocks/event_blocks_test.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,8 @@ TEST_F(EventBlocksTest, BroadcastAndWait)
180180
ASSERT_EQ(
181181
compiler.bytecode(),
182182
std::vector<unsigned int>(
183-
{ vm::OP_START, vm::OP_CONST, 0, vm::OP_EXEC, 0, vm::OP_CONST, 0, vm::OP_EXEC, 1, vm::OP_NULL, vm::OP_NOT, vm::OP_EXEC, 2, vm::OP_NULL, vm::OP_NOT, vm::OP_EXEC, 3, vm::OP_HALT }));
184-
ASSERT_EQ(compiler.constValues().size(), 1);
185-
ASSERT_EQ(compiler.constValues()[0].toDouble(), 0);
183+
{ vm::OP_START, vm::OP_CONST, 0, vm::OP_EXEC, 0, vm::OP_CONST, 1, vm::OP_EXEC, 1, vm::OP_NULL, vm::OP_NOT, vm::OP_EXEC, 2, vm::OP_NULL, vm::OP_NOT, vm::OP_EXEC, 3, vm::OP_HALT }));
184+
ASSERT_EQ(compiler.constValues(), std::vector<Value>({ 0, 0 }));
186185
ASSERT_TRUE(compiler.variables().empty());
187186
ASSERT_TRUE(compiler.lists().empty());
188187
}

test/compiler/compiler_test.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,27 @@ TEST_F(CompilerTest, ResolveDropdownMenuInput)
365365
ASSERT_EQ(compiler.constValues(), std::vector<Value>({ "test" }));
366366
}
367367

368+
TEST_F(CompilerTest, AddConstValue)
369+
{
370+
INIT_COMPILER(engine, compiler);
371+
compiler.addInstruction(vm::OP_START);
372+
373+
compiler.addConstValue(50);
374+
compiler.addInstruction(vm::OP_PRINT);
375+
compiler.addConstValue(50);
376+
compiler.addInstruction(vm::OP_PRINT);
377+
compiler.addConstValue("hello");
378+
compiler.addInstruction(vm::OP_PRINT);
379+
compiler.addConstValue("world");
380+
compiler.addInstruction(vm::OP_PRINT);
381+
382+
compiler.addInstruction(vm::OP_HALT);
383+
ASSERT_EQ(
384+
compiler.bytecode(),
385+
std::vector<unsigned int>({ vm::OP_START, vm::OP_CONST, 0, vm::OP_PRINT, vm::OP_CONST, 1, vm::OP_PRINT, vm::OP_CONST, 2, vm::OP_PRINT, vm::OP_CONST, 3, vm::OP_PRINT, vm::OP_HALT }));
386+
ASSERT_EQ(compiler.constValues(), std::vector<Value>({ 50, 50, "hello", "world" }));
387+
}
388+
368389
TEST_F(CompilerTest, ResolveField)
369390
{
370391
INIT_COMPILER(engine, compiler);

0 commit comments

Comments
 (0)