Skip to content

Commit 834b91c

Browse files
committed
Implement control_repeat_until
1 parent 90b566c commit 834b91c

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

src/dev/blocks/controlblocks.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ void ControlBlocks::registerBlocks(IEngine *engine)
3333
engine->addCompileFunction(this, "control_stop", &compileStop);
3434
engine->addCompileFunction(this, "control_wait", &compileWait);
3535
engine->addCompileFunction(this, "control_wait_until", &compileWaitUntil);
36+
engine->addCompileFunction(this, "control_repeat_until", &compileRepeatUntil);
3637
}
3738

3839
CompilerValue *ControlBlocks::compileForever(Compiler *compiler)
@@ -105,6 +106,14 @@ CompilerValue *ControlBlocks::compileWaitUntil(Compiler *compiler)
105106
return nullptr;
106107
}
107108

109+
CompilerValue *ControlBlocks::compileRepeatUntil(Compiler *compiler)
110+
{
111+
auto substack = compiler->input("SUBSTACK");
112+
compiler->beginLoopCondition();
113+
compiler->moveToRepeatUntilLoop(compiler->addInput("CONDITION"), substack ? substack->valueBlock() : nullptr);
114+
return nullptr;
115+
}
116+
108117
extern "C" void control_stop_all(ExecutionContext *ctx)
109118
{
110119
ctx->engine()->stop();

src/dev/blocks/controlblocks.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class ControlBlocks : public IExtension
2323
static CompilerValue *compileStop(Compiler *compiler);
2424
static CompilerValue *compileWait(Compiler *compiler);
2525
static CompilerValue *compileWaitUntil(Compiler *compiler);
26+
static CompilerValue *compileRepeatUntil(Compiler *compiler);
2627
};
2728

2829
} // namespace libscratchcpp

test/dev/blocks/control_blocks_test.cpp

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,3 +472,90 @@ TEST_F(ControlBlocksTest, WaitUntil)
472472
ASSERT_FALSE(m_engine->isRunning());
473473
}
474474
}
475+
476+
TEST_F(ControlBlocksTest, RepeatUntil)
477+
{
478+
auto target = std::make_shared<Sprite>();
479+
480+
{
481+
ScriptBuilder builder(m_extension.get(), m_engine, target);
482+
483+
builder.addBlock("control_repeat_until");
484+
auto substack = std::make_shared<Block>("", "test_print_test");
485+
builder.addObscuredInput("SUBSTACK", substack);
486+
builder.addValueInput("CONDITION", false);
487+
builder.build();
488+
m_engine->start();
489+
490+
for (int i = 0; i < 2; i++) {
491+
testing::internal::CaptureStdout();
492+
m_engine->step();
493+
ASSERT_EQ(testing::internal::GetCapturedStdout().substr(0, 10), "test\ntest\n");
494+
ASSERT_TRUE(m_engine->isRunning());
495+
}
496+
}
497+
498+
m_engine->clear();
499+
target = std::make_shared<Sprite>();
500+
501+
{
502+
ScriptBuilder builder(m_extension.get(), m_engine, target);
503+
504+
builder.addBlock("control_repeat_until");
505+
auto substack = std::make_shared<Block>("", "test_print_test");
506+
builder.addObscuredInput("SUBSTACK", substack);
507+
builder.addValueInput("CONDITION", true);
508+
builder.build();
509+
m_engine->start();
510+
511+
testing::internal::CaptureStdout();
512+
m_engine->step();
513+
m_engine->step();
514+
ASSERT_TRUE(testing::internal::GetCapturedStdout().empty());
515+
ASSERT_FALSE(m_engine->isRunning());
516+
}
517+
518+
m_engine->clear();
519+
target = std::make_shared<Sprite>();
520+
521+
{
522+
ScriptBuilder builder(m_extension.get(), m_engine, target);
523+
524+
builder.addBlock("control_repeat_until");
525+
auto substack = std::make_shared<Block>("", "test_print_test");
526+
builder.addObscuredInput("SUBSTACK", substack);
527+
auto block = std::make_shared<Block>("", "test_condition");
528+
builder.addObscuredInput("CONDITION", block);
529+
builder.build();
530+
531+
conditionReturnValue = false;
532+
m_engine->start();
533+
534+
testing::internal::CaptureStdout();
535+
m_engine->step();
536+
ASSERT_EQ(testing::internal::GetCapturedStdout().substr(0, 10), "test\ntest\n");
537+
ASSERT_TRUE(m_engine->isRunning());
538+
539+
conditionReturnValue = true;
540+
m_engine->step();
541+
m_engine->step();
542+
ASSERT_FALSE(m_engine->isRunning());
543+
}
544+
545+
m_engine->clear();
546+
target = std::make_shared<Sprite>();
547+
548+
{
549+
ScriptBuilder builder(m_extension.get(), m_engine, target);
550+
builder.addBlock("control_repeat_until");
551+
builder.addValueInput("CONDITION", false);
552+
553+
builder.build();
554+
m_engine->start();
555+
556+
for (int i = 0; i < 2; i++) {
557+
m_engine->step();
558+
ASSERT_TRUE(m_engine->isRunning());
559+
}
560+
}
561+
}

0 commit comments

Comments
 (0)