Skip to content

Commit d932257

Browse files
committed
Implement control_forever
1 parent bf5029f commit d932257

File tree

6 files changed

+130
-1
lines changed

6 files changed

+130
-1
lines changed

src/dev/blocks/controlblocks.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
// SPDX-License-Identifier: Apache-2.0
22

3+
#include <scratchcpp/iengine.h>
4+
#include <scratchcpp/dev/compiler.h>
5+
#include <scratchcpp/dev/compilerconstant.h>
6+
#include <scratchcpp/value.h>
7+
#include <scratchcpp/input.h>
8+
39
#include "controlblocks.h"
410

511
using namespace libscratchcpp;
@@ -16,4 +22,13 @@ std::string ControlBlocks::description() const
1622

1723
void ControlBlocks::registerBlocks(IEngine *engine)
1824
{
25+
engine->addCompileFunction(this, "control_forever", &compileForever);
26+
}
27+
28+
CompilerValue *ControlBlocks::compileForever(Compiler *compiler)
29+
{
30+
auto substack = compiler->input("SUBSTACK");
31+
compiler->beginLoopCondition();
32+
compiler->moveToWhileLoop(compiler->addConstValue(true), substack ? substack->valueBlock() : nullptr);
33+
return nullptr;
1934
}

src/dev/blocks/controlblocks.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ class ControlBlocks : public IExtension
1414
std::string description() const override;
1515

1616
void registerBlocks(IEngine *engine) override;
17+
18+
private:
19+
static CompilerValue *compileForever(Compiler *compiler);
1720
};
1821

1922
} // namespace libscratchcpp

test/dev/blocks/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
add_library(
2+
block_test_deps SHARED
3+
util.cpp
4+
util.h
5+
)
6+
7+
target_link_libraries(
8+
block_test_deps
9+
GTest::gtest_main
10+
scratchcpp
11+
)
12+
113
# motion_blocks_test
214
if (LIBSCRATCHCPP_ENABLE_MOTION_BLOCKS)
315
add_executable(
@@ -83,6 +95,7 @@ if (LIBSCRATCHCPP_ENABLE_CONTROL_BLOCKS)
8395
GTest::gmock_main
8496
scratchcpp
8597
scratchcpp_mocks
98+
block_test_deps
8699
)
87100

88101
gtest_discover_tests(control_blocks_test)
Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,70 @@
1+
#include <scratchcpp/project.h>
2+
#include <scratchcpp/dev/compiler.h>
3+
#include <scratchcpp/dev/test/scriptbuilder.h>
4+
#include <scratchcpp/sprite.h>
5+
#include <scratchcpp/block.h>
6+
#include <scratchcpp/input.h>
17
#include <enginemock.h>
28

39
#include "../common.h"
410
#include "dev/blocks/controlblocks.h"
11+
#include "util.h"
512

613
using namespace libscratchcpp;
14+
using namespace libscratchcpp::test;
715

816
class ControlBlocksTest : public testing::Test
917
{
1018
public:
11-
void SetUp() override { m_extension = std::make_unique<ControlBlocks>(); }
19+
void SetUp() override
20+
{
21+
m_extension = std::make_unique<ControlBlocks>();
22+
m_engine = m_project.engine().get();
23+
m_extension->registerBlocks(m_engine);
24+
registerBlocks(m_engine, m_extension.get());
25+
}
1226

1327
std::unique_ptr<IExtension> m_extension;
28+
Project m_project;
29+
IEngine *m_engine = nullptr;
1430
EngineMock m_engineMock;
1531
};
32+
33+
TEST_F(ControlBlocksTest, Forever)
34+
{
35+
auto target = std::make_shared<Sprite>();
36+
37+
{
38+
ScriptBuilder builder(m_extension.get(), m_engine, target);
39+
40+
builder.addBlock("control_forever");
41+
auto substack = std::make_shared<Block>("", "test_print_test");
42+
builder.addObscuredInput("SUBSTACK", substack);
43+
44+
builder.build();
45+
m_engine->start();
46+
47+
for (int i = 0; i < 2; i++) {
48+
testing::internal::CaptureStdout();
49+
m_engine->step();
50+
ASSERT_EQ(testing::internal::GetCapturedStdout().substr(0, 10), "test\ntest\n");
51+
ASSERT_TRUE(m_engine->isRunning());
52+
}
53+
}
54+
55+
m_engine->clear();
56+
target = std::make_shared<Sprite>();
57+
58+
{
59+
ScriptBuilder builder(m_extension.get(), m_engine, target);
60+
builder.addBlock("control_forever");
61+
62+
builder.build();
63+
m_engine->start();
64+
65+
for (int i = 0; i < 2; i++) {
66+
m_engine->step();
67+
ASSERT_TRUE(m_engine->isRunning());
68+
}
69+
}
70+
}

test/dev/blocks/util.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include <scratchcpp/iengine.h>
2+
#include <scratchcpp/dev/compiler.h>
3+
#include <scratchcpp/dev/compilerconstant.h>
4+
#include <scratchcpp/value.h>
5+
#include <iostream>
6+
7+
#include "util.h"
8+
9+
namespace libscratchcpp
10+
{
11+
12+
void registerBlocks(IEngine *engine, IExtension *extension)
13+
{
14+
engine->addCompileFunction(extension, "test_print", [](Compiler *compiler) -> CompilerValue * {
15+
auto input = compiler->addInput("STRING");
16+
compiler->addFunctionCall("test_print", Compiler::StaticType::Void, { Compiler::StaticType::String }, { input });
17+
return nullptr;
18+
});
19+
20+
engine->addCompileFunction(extension, "test_print_test", [](Compiler *compiler) -> CompilerValue * {
21+
auto input = compiler->addConstValue("test");
22+
compiler->addFunctionCall("test_print", Compiler::StaticType::Void, { Compiler::StaticType::String }, { input });
23+
return nullptr;
24+
});
25+
}
26+
27+
extern "C" void test_print(const char *str)
28+
{
29+
std::cout << str << std::endl;
30+
}
31+
32+
} // namespace libscratchcpp

test/dev/blocks/util.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#pragma once
2+
3+
namespace libscratchcpp
4+
{
5+
6+
class IEngine;
7+
class IExtension;
8+
9+
void registerBlocks(IEngine *engine, IExtension *extension);
10+
11+
} // namespace libscratchcpp

0 commit comments

Comments
 (0)