diff --git a/src/dev/blocks/variableblocks.cpp b/src/dev/blocks/variableblocks.cpp index 6d0f464f..177d8dab 100644 --- a/src/dev/blocks/variableblocks.cpp +++ b/src/dev/blocks/variableblocks.cpp @@ -1,5 +1,12 @@ // SPDX-License-Identifier: Apache-2.0 +#include +#include +#include +#include +#include +#include + #include "variableblocks.h" using namespace libscratchcpp; @@ -16,4 +23,45 @@ std::string VariableBlocks::description() const void VariableBlocks::registerBlocks(IEngine *engine) { + engine->addCompileFunction(this, "data_variable", &compileVariable); + engine->addCompileFunction(this, "data_setvariableto", &compileSetVariableTo); + engine->addCompileFunction(this, "data_changevariableby", &compileChangeVariableBy); +} + +CompilerValue *VariableBlocks::compileVariable(Compiler *compiler) +{ + Field *varField = compiler->field("VARIABLE"); + Variable *var = static_cast(varField->valuePtr().get()); + assert(var); + + if (var) + return compiler->addVariableValue(var); + else + return compiler->addConstValue(Value()); +} + +CompilerValue *VariableBlocks::compileSetVariableTo(Compiler *compiler) +{ + Field *varField = compiler->field("VARIABLE"); + Variable *var = static_cast(varField->valuePtr().get()); + assert(var); + + if (var) + compiler->createVariableWrite(var, compiler->addInput("VALUE")); + + return nullptr; +} + +CompilerValue *VariableBlocks::compileChangeVariableBy(Compiler *compiler) +{ + Field *varField = compiler->field("VARIABLE"); + Variable *var = static_cast(varField->valuePtr().get()); + assert(var); + + if (var) { + CompilerValue *value = compiler->createAdd(compiler->addVariableValue(var), compiler->addInput("VALUE")); + compiler->createVariableWrite(var, value); + } + + return nullptr; } diff --git a/src/dev/blocks/variableblocks.h b/src/dev/blocks/variableblocks.h index 6c4144ac..9cb0bcc4 100644 --- a/src/dev/blocks/variableblocks.h +++ b/src/dev/blocks/variableblocks.h @@ -14,6 +14,11 @@ class VariableBlocks : public IExtension std::string description() const override; void registerBlocks(IEngine *engine) override; + + private: + static CompilerValue *compileVariable(Compiler *compiler); + static CompilerValue *compileSetVariableTo(Compiler *compiler); + static CompilerValue *compileChangeVariableBy(Compiler *compiler); }; } // namespace libscratchcpp diff --git a/test/dev/blocks/variable_blocks_test.cpp b/test/dev/blocks/variable_blocks_test.cpp index 0a480f33..2789f289 100644 --- a/test/dev/blocks/variable_blocks_test.cpp +++ b/test/dev/blocks/variable_blocks_test.cpp @@ -1,15 +1,111 @@ +#include +#include +#include +#include +#include +#include #include #include "../common.h" #include "dev/blocks/variableblocks.h" using namespace libscratchcpp; +using namespace libscratchcpp::test; class VariableBlocksTest : public testing::Test { public: - void SetUp() override { m_extension = std::make_unique(); } + void SetUp() override + { + m_extension = std::make_unique(); + m_engine = m_project.engine().get(); + m_extension->registerBlocks(m_engine); + } std::unique_ptr m_extension; + Project m_project; + IEngine *m_engine = nullptr; EngineMock m_engineMock; }; + +TEST_F(VariableBlocksTest, Variable) +{ + auto target = std::make_shared(); + auto var1 = std::make_shared("", "", 835.21); + target->addVariable(var1); + auto var2 = std::make_shared("", "", "Hello world"); + target->addVariable(var2); + ScriptBuilder builder(m_extension.get(), m_engine, target); + + builder.addBlock("data_variable"); + builder.addEntityField("VARIABLE", var1); + builder.captureBlockReturnValue(); + + builder.addBlock("data_variable"); + builder.addEntityField("VARIABLE", var2); + builder.captureBlockReturnValue(); + + builder.build(); + builder.run(); + + List *valueList = builder.capturedValues(); + ValueData *values = valueList->data(); + ASSERT_EQ(valueList->size(), 2); + ASSERT_EQ(Value(values[0]), 835.21); + ASSERT_EQ(Value(values[1]), "Hello world"); +} + +TEST_F(VariableBlocksTest, SetVariableTo) +{ + auto target = std::make_shared(); + auto var1 = std::make_shared("", "", 835.21); + target->addVariable(var1); + auto var2 = std::make_shared("", "", "Hello world"); + target->addVariable(var2); + ScriptBuilder builder(m_extension.get(), m_engine, target); + + builder.addBlock("data_setvariableto"); + builder.addEntityField("VARIABLE", var1); + builder.addValueInput("VALUE", "test"); + + builder.addBlock("data_setvariableto"); + builder.addEntityField("VARIABLE", var2); + builder.addValueInput("VALUE", 123); + + builder.build(); + builder.run(); + ASSERT_EQ(var1->value(), "test"); + ASSERT_EQ(var2->value(), 123); +} + +TEST_F(VariableBlocksTest, ChangeVariableBy) +{ + auto target = std::make_shared(); + auto var1 = std::make_shared("", "", 835.21); + target->addVariable(var1); + auto var2 = std::make_shared("", "", "Hello world"); + target->addVariable(var2); + ScriptBuilder builder(m_extension.get(), m_engine, target); + + builder.addBlock("data_changevariableby"); + builder.addEntityField("VARIABLE", var1); + builder.addValueInput("VALUE", "5.12"); + + builder.addBlock("data_changevariableby"); + builder.addEntityField("VARIABLE", var2); + builder.addValueInput("VALUE", -2.5); + + builder.build(); + + builder.run(); + ASSERT_EQ(var1->value(), 840.33); + ASSERT_EQ(var2->value(), -2.5); + + builder.run(); + ASSERT_EQ(var1->value(), 845.45); + ASSERT_EQ(var2->value(), -5); + + builder.run(); + ASSERT_EQ(var1->value(), 850.57); + ASSERT_EQ(var2->value(), -7.5); +}