Skip to content

Commit e37c9fd

Browse files
committed
Implement data_showvariable block
1 parent 989b8d0 commit e37c9fd

File tree

3 files changed

+161
-0
lines changed

3 files changed

+161
-0
lines changed

src/blocks/variableblocks.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include <scratchcpp/field.h>
66
#include <scratchcpp/block.h>
77
#include <scratchcpp/variable.h>
8+
#include <scratchcpp/stage.h>
9+
#include <scratchcpp/monitor.h>
810

911
#include "variableblocks.h"
1012

@@ -21,6 +23,7 @@ void VariableBlocks::registerBlocks(IEngine *engine)
2123
engine->addCompileFunction(this, "data_variable", &compileVariable);
2224
engine->addCompileFunction(this, "data_setvariableto", &compileSetVariable);
2325
engine->addCompileFunction(this, "data_changevariableby", &compileChangeVariableBy);
26+
engine->addCompileFunction(this, "data_showvariable", &compileShowVariable);
2427

2528
// Monitor names
2629
engine->addMonitorNameFunction(this, "data_variable", &variableMonitorName);
@@ -53,6 +56,49 @@ void VariableBlocks::compileChangeVariableBy(Compiler *compiler)
5356
compiler->addInstruction(vm::OP_CHANGE_VAR, { compiler->variableIndex(compiler->field(VARIABLE)->valuePtr()) });
5457
}
5558

59+
void VariableBlocks::compileShowVariable(Compiler *compiler)
60+
{
61+
Field *field = compiler->field(VARIABLE);
62+
assert(field);
63+
Variable *var = static_cast<Variable *>(field->valuePtr().get());
64+
assert(var);
65+
66+
compiler->addConstValue(var->id());
67+
68+
if (var->target() == static_cast<Target *>(compiler->engine()->stage()))
69+
compiler->addFunctionCall(&showGlobalVariable);
70+
else
71+
compiler->addFunctionCall(&showVariable);
72+
}
73+
74+
void VariableBlocks::setVarVisible(std::shared_ptr<Variable> var, bool visible)
75+
{
76+
if (var) {
77+
assert(var->monitor());
78+
var->monitor()->setVisible(visible);
79+
}
80+
}
81+
82+
unsigned int VariableBlocks::showGlobalVariable(VirtualMachine *vm)
83+
{
84+
if (Stage *target = vm->engine()->stage()) {
85+
int index = target->findVariableById(vm->getInput(0, 1)->toString());
86+
setVarVisible(target->variableAt(index), true);
87+
}
88+
89+
return 1;
90+
}
91+
92+
unsigned int VariableBlocks::showVariable(VirtualMachine *vm)
93+
{
94+
if (Target *target = vm->target()) {
95+
int index = target->findVariableById(vm->getInput(0, 1)->toString());
96+
setVarVisible(target->variableAt(index), true);
97+
}
98+
99+
return 1;
100+
}
101+
56102
const std::string &VariableBlocks::variableMonitorName(Block *block)
57103
{
58104
Variable *var = dynamic_cast<Variable *>(block->findFieldById(VARIABLE)->valuePtr().get());

src/blocks/variableblocks.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace libscratchcpp
88
{
99

1010
class Compiler;
11+
class Variable;
1112

1213
/*! \brief The VariableBlocks class contains the implementation of variable blocks. */
1314
class VariableBlocks : public IBlockSection
@@ -30,6 +31,12 @@ class VariableBlocks : public IBlockSection
3031
static void compileVariable(Compiler *compiler);
3132
static void compileSetVariable(Compiler *compiler);
3233
static void compileChangeVariableBy(Compiler *compiler);
34+
static void compileShowVariable(Compiler *compiler);
35+
36+
static void setVarVisible(std::shared_ptr<Variable> var, bool visible);
37+
38+
static unsigned int showGlobalVariable(VirtualMachine *vm);
39+
static unsigned int showVariable(VirtualMachine *vm);
3340

3441
static const std::string &variableMonitorName(Block *block);
3542
static void changeVariableMonitorValue(Block *block, const Value &newValue);

test/blocks/variable_blocks_test.cpp

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include <scratchcpp/input.h>
44
#include <scratchcpp/field.h>
55
#include <scratchcpp/variable.h>
6+
#include <scratchcpp/stage.h>
7+
#include <scratchcpp/monitor.h>
68
#include <enginemock.h>
79

810
#include "../common.h"
@@ -11,6 +13,8 @@
1113

1214
using namespace libscratchcpp;
1315

16+
using ::testing::Return;
17+
1418
class VariableBlocksTest : public testing::Test
1519
{
1620
public:
@@ -70,6 +74,7 @@ TEST_F(VariableBlocksTest, RegisterBlocks)
7074
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "data_variable", &VariableBlocks::compileVariable)).Times(1);
7175
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "data_setvariableto", &VariableBlocks::compileSetVariable)).Times(1);
7276
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "data_changevariableby", &VariableBlocks::compileChangeVariableBy)).Times(1);
77+
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "data_showvariable", &VariableBlocks::compileShowVariable)).Times(1);
7378

7479
// Monitor names
7580
EXPECT_CALL(m_engineMock, addMonitorNameFunction(m_section.get(), "data_variable", &VariableBlocks::variableMonitorName));
@@ -208,3 +213,106 @@ TEST_F(VariableBlocksTest, ChangeVariableBy)
208213
}));
209214
ASSERT_TRUE(compiler.lists().empty());
210215
}
216+
217+
TEST_F(VariableBlocksTest, ShowVariable)
218+
{
219+
Compiler compiler(&m_engineMock);
220+
Stage stage;
221+
Target target;
222+
223+
// show variable [var1]
224+
auto var1 = std::make_shared<Variable>("b", "var1");
225+
var1->setTarget(&stage);
226+
auto block1 = createVariableBlock("a", "data_showvariable", var1);
227+
228+
// show variable [var2]
229+
auto var2 = std::make_shared<Variable>("d", "var2");
230+
var2->setTarget(&target);
231+
auto block2 = createVariableBlock("c", "data_showvariable", var2);
232+
233+
EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
234+
EXPECT_CALL(m_engineMock, functionIndex(&VariableBlocks::showGlobalVariable)).WillOnce(Return(0));
235+
compiler.init();
236+
compiler.setBlock(block1);
237+
VariableBlocks::compileShowVariable(&compiler);
238+
239+
EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
240+
EXPECT_CALL(m_engineMock, functionIndex(&VariableBlocks::showVariable)).WillOnce(Return(1));
241+
compiler.setBlock(block2);
242+
VariableBlocks::compileShowVariable(&compiler);
243+
compiler.end();
244+
245+
ASSERT_EQ(compiler.bytecode(), std::vector<unsigned int>({ vm::OP_START, vm::OP_CONST, 0, vm::OP_EXEC, 0, vm::OP_CONST, 1, vm::OP_EXEC, 1, vm::OP_HALT }));
246+
ASSERT_EQ(compiler.constValues(), std::vector<Value>({ "b", "d" }));
247+
ASSERT_TRUE(compiler.variables().empty());
248+
ASSERT_TRUE(compiler.lists().empty());
249+
}
250+
251+
TEST_F(VariableBlocksTest, ShowVariableImpl)
252+
{
253+
static unsigned int bytecode1[] = { vm::OP_START, vm::OP_CONST, 0, vm::OP_EXEC, 0, vm::OP_HALT };
254+
static unsigned int bytecode2[] = { vm::OP_START, vm::OP_CONST, 1, vm::OP_EXEC, 0, vm::OP_HALT };
255+
static unsigned int bytecode3[] = { vm::OP_START, vm::OP_CONST, 2, vm::OP_EXEC, 1, vm::OP_HALT };
256+
static unsigned int bytecode4[] = { vm::OP_START, vm::OP_CONST, 3, vm::OP_EXEC, 1, vm::OP_HALT };
257+
static BlockFunc functions[] = { &VariableBlocks::showGlobalVariable, &VariableBlocks::showVariable };
258+
static Value constValues[] = { "a", "b", "c", "d" };
259+
260+
auto var1 = std::make_shared<Variable>("b", "");
261+
Monitor monitor1("b", "");
262+
monitor1.setVisible(false);
263+
var1->setMonitor(&monitor1);
264+
265+
auto var2 = std::make_shared<Variable>("d", "");
266+
Monitor monitor2("d", "");
267+
monitor2.setVisible(false);
268+
var2->setMonitor(&monitor2);
269+
270+
Stage stage;
271+
stage.addVariable(var1);
272+
273+
Target target;
274+
target.addVariable(var2);
275+
276+
// Global
277+
VirtualMachine vm1(&stage, &m_engineMock, nullptr);
278+
vm1.setBytecode(bytecode1);
279+
vm1.setFunctions(functions);
280+
vm1.setConstValues(constValues);
281+
282+
EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
283+
vm1.run();
284+
285+
ASSERT_EQ(vm1.registerCount(), 0);
286+
ASSERT_FALSE(monitor1.visible());
287+
ASSERT_FALSE(monitor2.visible());
288+
289+
EXPECT_CALL(m_engineMock, stage()).WillOnce(Return(&stage));
290+
vm1.reset();
291+
vm1.setBytecode(bytecode2);
292+
vm1.run();
293+
294+
ASSERT_EQ(vm1.registerCount(), 0);
295+
ASSERT_TRUE(monitor1.visible());
296+
ASSERT_FALSE(monitor2.visible());
297+
298+
monitor1.setVisible(false);
299+
300+
// Local
301+
VirtualMachine vm2(&target, &m_engineMock, nullptr);
302+
vm2.setBytecode(bytecode3);
303+
vm2.setFunctions(functions);
304+
vm2.setConstValues(constValues);
305+
vm2.run();
306+
307+
ASSERT_EQ(vm2.registerCount(), 0);
308+
ASSERT_FALSE(monitor1.visible());
309+
ASSERT_FALSE(monitor2.visible());
310+
311+
vm2.reset();
312+
vm2.setBytecode(bytecode4);
313+
vm2.run();
314+
315+
ASSERT_EQ(vm2.registerCount(), 0);
316+
ASSERT_FALSE(monitor1.visible());
317+
ASSERT_TRUE(monitor2.visible());
318+
}

0 commit comments

Comments
 (0)