Skip to content

Commit 4e53ef6

Browse files
committed
Compiler: Implement repeat until loop
1 parent d19dbfa commit 4e53ef6

File tree

3 files changed

+91
-0
lines changed

3 files changed

+91
-0
lines changed

include/scratchcpp/dev/compiler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class LIBSCRATCHCPP_EXPORT Compiler
4242
void moveToIfElse(std::shared_ptr<Block> substack1, std::shared_ptr<Block> substack2);
4343
void moveToRepeatLoop(std::shared_ptr<Block> substack);
4444
void moveToWhileLoop(std::shared_ptr<Block> substack);
45+
void moveToRepeatUntilLoop(std::shared_ptr<Block> substack);
4546
void beginLoopCondition();
4647
void warp();
4748

src/dev/engine/compiler.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,18 @@ void Compiler::moveToWhileLoop(std::shared_ptr<Block> substack)
153153
impl->substackEnd();
154154
}
155155

156+
/*! Jumps to the given until loop substack. */
157+
void Compiler::moveToRepeatUntilLoop(std::shared_ptr<Block> substack)
158+
{
159+
impl->substackHit = true;
160+
impl->substackTree.push_back({ { impl->block, nullptr }, CompilerPrivate::SubstackType::Loop });
161+
impl->block = substack;
162+
impl->builder->beginRepeatUntilLoop();
163+
164+
if (!impl->block)
165+
impl->substackEnd();
166+
}
167+
156168
/*! Begins a while/until loop condition. */
157169
void Compiler::beginLoopCondition()
158170
{

test/dev/compiler/compiler_test.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,84 @@ TEST_F(CompilerTest, MoveToWhileLoop)
557557
compile(compiler, l1);
558558
}
559559

560+
TEST_F(CompilerTest, MoveToRepeatUntilLoop)
561+
{
562+
Compiler compiler(&m_engine, &m_target);
563+
564+
auto l1 = std::make_shared<Block>("", "loop");
565+
l1->setCompileFunction([](Compiler *compiler) {
566+
EXPECT_CALL(*m_builder, beginRepeatUntilLoop());
567+
EXPECT_CALL(*m_builder, endLoop());
568+
compiler->moveToRepeatUntilLoop(nullptr);
569+
});
570+
571+
auto l2 = std::make_shared<Block>("", "loop");
572+
l1->setNext(l2);
573+
l2->setParent(l1);
574+
l2->setCompileFunction([](Compiler *compiler) {
575+
EXPECT_CALL(*m_builder, beginRepeatUntilLoop());
576+
EXPECT_CALL(*m_builder, addConstValue(Value(2)));
577+
EXPECT_CALL(*m_builder, endLoop());
578+
compiler->moveToRepeatUntilLoop(compiler->input("SUBSTACK")->valueBlock());
579+
});
580+
581+
auto substack = std::make_shared<Block>("", "substack");
582+
substack->setParent(l2);
583+
substack->setCompileFunction([](Compiler *compiler) { compiler->addConstValue(2); });
584+
585+
auto input = std::make_shared<Input>("SUBSTACK", Input::Type::NoShadow);
586+
input->setValueBlock(substack);
587+
l2->addInput(input);
588+
589+
// Nested
590+
auto l3 = std::make_shared<Block>("", "loop");
591+
l2->setNext(l3);
592+
l3->setParent(l2);
593+
l3->setCompileFunction([](Compiler *compiler) {
594+
EXPECT_CALL(*m_builder, beginRepeatUntilLoop()).Times(2);
595+
EXPECT_CALL(*m_builder, endLoop()).Times(2);
596+
EXPECT_CALL(*m_builder, addConstValue(Value(1)));
597+
compiler->moveToRepeatUntilLoop(compiler->input("SUBSTACK")->valueBlock());
598+
});
599+
600+
// Begin loop
601+
auto loopSubstack = std::make_shared<Block>("", "loop");
602+
loopSubstack->setParent(l3);
603+
loopSubstack->setCompileFunction([](Compiler *compiler) { compiler->moveToRepeatUntilLoop(compiler->input("SUBSTACK")->valueBlock()); });
604+
605+
substack = std::make_shared<Block>("", "substack");
606+
substack->setParent(loopSubstack);
607+
substack->setCompileFunction([](Compiler *compiler) { compiler->addConstValue(1); });
608+
609+
input = std::make_shared<Input>("SUBSTACK", Input::Type::NoShadow);
610+
input->setValueBlock(substack);
611+
loopSubstack->addInput(input);
612+
613+
// End loop
614+
input = std::make_shared<Input>("SUBSTACK", Input::Type::NoShadow);
615+
input->setValueBlock(loopSubstack);
616+
l3->addInput(input);
617+
618+
// Empty loop body
619+
auto l4 = std::make_shared<Block>("", "loop");
620+
l3->setNext(l4);
621+
l4->setParent(l3);
622+
l4->setCompileFunction([](Compiler *compiler) {
623+
EXPECT_CALL(*m_builder, beginRepeatUntilLoop());
624+
EXPECT_CALL(*m_builder, endLoop());
625+
compiler->moveToRepeatUntilLoop(nullptr);
626+
});
627+
628+
// Code after the loop
629+
auto block = std::make_shared<Block>("", "");
630+
block->setParent(l4);
631+
l4->setNext(block);
632+
block->setCompileFunction([](Compiler *compiler) { compiler->addConstValue("after"); });
633+
634+
EXPECT_CALL(*m_builder, addConstValue(Value("after")));
635+
compile(compiler, l1);
636+
}
637+
560638
TEST_F(CompilerTest, BeginLoopCondition)
561639
{
562640
Compiler compiler(&m_engine, &m_target);

0 commit comments

Comments
 (0)