Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/scratchcpp/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class LIBSCRATCHCPP_EXPORT Compiler
void addInstruction(vm::Opcode opcode, const std::initializer_list<unsigned int> &args = {});
void addInput(Input *input);
void addInput(int id);
void addConstValue(const Value &value);
void addFunctionCall(BlockFunc f);
void addProcedureArg(const std::string &procCode, const std::string &argName);
void moveToSubstack(std::shared_ptr<Block> substack1, std::shared_ptr<Block> substack2, SubstackType type);
Expand Down
16 changes: 10 additions & 6 deletions src/blocks/eventblocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,28 @@ void EventBlocks::registerBlocks(IEngine *engine)
void EventBlocks::compileBroadcast(Compiler *compiler)
{
auto input = compiler->input(BROADCAST_INPUT);
compiler->addInput(input);

if (input->type() != Input::Type::ObscuredShadow) {
input->primaryValue()->setValue(compiler->engine()->findBroadcast(input->primaryValue()->value().toString()));
compiler->addConstValue(compiler->engine()->findBroadcast(input->primaryValue()->value().toString()));
compiler->addFunctionCall(&broadcastByIndex);
} else
} else {
compiler->addInput(input);
compiler->addFunctionCall(&broadcast);
}
}

void EventBlocks::compileBroadcastAndWait(Compiler *compiler)
{
auto input = compiler->input(BROADCAST_INPUT);
compiler->addInput(input);

if (input->type() != Input::Type::ObscuredShadow) {
input->primaryValue()->setValue(compiler->engine()->findBroadcast(input->primaryValue()->value().toString()));
int index = compiler->engine()->findBroadcast(input->primaryValue()->value().toString());
compiler->addConstValue(index);
compiler->addFunctionCall(&broadcastByIndexAndWait);
compiler->addInput(input);
compiler->addConstValue(index);
compiler->addFunctionCall(&checkBroadcastByIndex);
} else {
compiler->addInput(input);
compiler->addFunctionCall(&broadcastAndWait);
compiler->addInput(input);
compiler->addFunctionCall(&checkBroadcast);
Expand Down
9 changes: 8 additions & 1 deletion src/engine/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include <scratchcpp/compiler.h>
#include <scratchcpp/iengine.h>
#include <scratchcpp/input.h>
#include <scratchcpp/inputvalue.h>
#include <scratchcpp/block.h>
#include <scratchcpp/variable.h>
#include <scratchcpp/list.h>
Expand Down Expand Up @@ -189,6 +188,14 @@ void Compiler::addInput(int id)
addInput(input(id));
}

/*! Adds a constant value and an instruction to load it. Useful if you don't have an input for the addInput() method. */
void libscratchcpp::Compiler::addConstValue(const Value &value)
{
impl->customConstValues.push_back(std::make_unique<InputValue>());
impl->customConstValues.back()->setValue(value);
addInstruction(OP_CONST, { impl->constIndex(impl->customConstValues.back().get()) });
}

/*! Adds a function call to the bytecode (the OP_EXEC instruction). */
void Compiler::addFunctionCall(BlockFunc f)
{
Expand Down
3 changes: 3 additions & 0 deletions src/engine/compiler_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
#pragma once

#include <scratchcpp/compiler.h>
#include <scratchcpp/inputvalue.h>

namespace libscratchcpp
{

struct CompilerPrivate
{
CompilerPrivate(IEngine *engine);
CompilerPrivate(const CompilerPrivate &) = delete;

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

Expand All @@ -25,6 +27,7 @@ struct CompilerPrivate

std::vector<unsigned int> bytecode;
std::vector<InputValue *> constValues;
std::vector<std::unique_ptr<InputValue>> customConstValues;
std::unordered_map<InputValue *, std::pair<bool, std::string>> constValueMenuInfo; // input value, <whether the input points to a dropdown menu, selected menu item>
std::vector<Variable *> variables;
std::vector<List *> lists;
Expand Down
5 changes: 2 additions & 3 deletions test/blocks/event_blocks_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,8 @@ TEST_F(EventBlocksTest, BroadcastAndWait)
ASSERT_EQ(
compiler.bytecode(),
std::vector<unsigned int>(
{ 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 }));
ASSERT_EQ(compiler.constValues().size(), 1);
ASSERT_EQ(compiler.constValues()[0].toDouble(), 0);
{ 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 }));
ASSERT_EQ(compiler.constValues(), std::vector<Value>({ 0, 0 }));
ASSERT_TRUE(compiler.variables().empty());
ASSERT_TRUE(compiler.lists().empty());
}
Expand Down
21 changes: 21 additions & 0 deletions test/compiler/compiler_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,27 @@ TEST_F(CompilerTest, ResolveDropdownMenuInput)
ASSERT_EQ(compiler.constValues(), std::vector<Value>({ "test" }));
}

TEST_F(CompilerTest, AddConstValue)
{
INIT_COMPILER(engine, compiler);
compiler.addInstruction(vm::OP_START);

compiler.addConstValue(50);
compiler.addInstruction(vm::OP_PRINT);
compiler.addConstValue(50);
compiler.addInstruction(vm::OP_PRINT);
compiler.addConstValue("hello");
compiler.addInstruction(vm::OP_PRINT);
compiler.addConstValue("world");
compiler.addInstruction(vm::OP_PRINT);

compiler.addInstruction(vm::OP_HALT);
ASSERT_EQ(
compiler.bytecode(),
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 }));
ASSERT_EQ(compiler.constValues(), std::vector<Value>({ 50, 50, "hello", "world" }));
}

TEST_F(CompilerTest, ResolveField)
{
INIT_COMPILER(engine, compiler);
Expand Down