Skip to content

Commit 6ea5644

Browse files
committed
Compiler: Add API for custom while/until loops
1 parent 1971123 commit 6ea5644

File tree

4 files changed

+99
-20
lines changed

4 files changed

+99
-20
lines changed

include/scratchcpp/dev/compiler.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,16 @@ class LIBSCRATCHCPP_EXPORT Compiler
103103
void beginElseBranch();
104104
void endIf();
105105

106+
void beginWhileLoop(CompilerValue *cond);
107+
void beginRepeatUntilLoop(CompilerValue *cond);
108+
void beginLoopCondition();
109+
void endLoop();
110+
106111
void moveToIf(CompilerValue *cond, std::shared_ptr<Block> substack);
107112
void moveToIfElse(CompilerValue *cond, std::shared_ptr<Block> substack1, std::shared_ptr<Block> substack2);
108113
void moveToRepeatLoop(CompilerValue *count, std::shared_ptr<Block> substack);
109114
void moveToWhileLoop(CompilerValue *cond, std::shared_ptr<Block> substack);
110115
void moveToRepeatUntilLoop(CompilerValue *cond, std::shared_ptr<Block> substack);
111-
void beginLoopCondition();
112116
void warp();
113117

114118
Input *input(const std::string &name) const;

src/dev/engine/compiler.cpp

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ std::shared_ptr<ExecutableCode> Compiler::compile(std::shared_ptr<Block> startBl
5454
std::cerr << "error: if statement created by block '" << impl->block->opcode() << "' not terminated" << std::endl;
5555
assert(false);
5656
}
57+
58+
if (impl->customLoopCount > 0) {
59+
std::cerr << "error: loop created by block '" << impl->block->opcode() << "' not terminated" << std::endl;
60+
assert(false);
61+
}
5762
} else {
5863
std::cout << "warning: unsupported block: " << impl->block->opcode() << std::endl;
5964
impl->unsupportedBlocks.insert(impl->block->opcode());
@@ -382,6 +387,45 @@ void Compiler::endIf()
382387
impl->customIfStatementCount--;
383388
}
384389

390+
/*!
391+
* Begins a custom while loop.
392+
* \note The loop must be terminated with endLoop() after compiling your block.
393+
*/
394+
void Compiler::beginWhileLoop(CompilerValue *cond)
395+
{
396+
impl->builder->beginWhileLoop(cond);
397+
impl->customLoopCount++;
398+
}
399+
400+
/*!
401+
* Begins a custom repeat until loop.
402+
* \note The loop must be terminated with endLoop() after compiling your block.
403+
*/
404+
void Compiler::beginRepeatUntilLoop(CompilerValue *cond)
405+
{
406+
impl->builder->beginRepeatUntilLoop(cond);
407+
impl->customLoopCount++;
408+
}
409+
410+
/*! Begins a while/until loop condition. */
411+
void Compiler::beginLoopCondition()
412+
{
413+
impl->builder->beginLoopCondition();
414+
}
415+
416+
/*! Ends custom loop. */
417+
void Compiler::endLoop()
418+
{
419+
if (impl->customLoopCount == 0) {
420+
std::cerr << "error: called Compiler::endLoop() without a loop";
421+
assert(false);
422+
return;
423+
}
424+
425+
impl->builder->endLoop();
426+
impl->customLoopCount--;
427+
}
428+
385429
/*! Jumps to the given if substack. */
386430
void Compiler::moveToIf(CompilerValue *cond, std::shared_ptr<Block> substack)
387431
{
@@ -445,12 +489,6 @@ void Compiler::moveToRepeatUntilLoop(CompilerValue *cond, std::shared_ptr<Block>
445489
impl->substackEnd();
446490
}
447491

448-
/*! Begins a while/until loop condition. */
449-
void Compiler::beginLoopCondition()
450-
{
451-
impl->builder->beginLoopCondition();
452-
}
453-
454492
/*! Makes current script run without screen refresh. */
455493
void Compiler::warp()
456494
{

src/dev/engine/compiler_p.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ struct CompilerPrivate
3333

3434
std::shared_ptr<Block> block;
3535
int customIfStatementCount = 0;
36+
int customLoopCount = 0;
3637
std::vector<std::pair<std::pair<std::shared_ptr<Block>, std::shared_ptr<Block>>, SubstackType>> substackTree;
3738
bool substackHit = false;
3839
bool warp = false;

test/dev/compiler/compiler_test.cpp

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,55 @@ TEST_F(CompilerTest, CustomIfStatement)
892892
compile(compiler, block);
893893
}
894894

895+
TEST_F(CompilerTest, CustomWhileLoop)
896+
{
897+
Compiler compiler(&m_engine, &m_target);
898+
auto block = std::make_shared<Block>("", "");
899+
900+
block->setCompileFunction([](Compiler *compiler) -> CompilerValue * {
901+
CompilerValue arg(Compiler::StaticType::Unknown);
902+
EXPECT_CALL(*m_builder, beginWhileLoop(&arg));
903+
compiler->beginWhileLoop(&arg);
904+
EXPECT_CALL(*m_builder, endLoop());
905+
compiler->endLoop();
906+
907+
return nullptr;
908+
});
909+
910+
compile(compiler, block);
911+
}
912+
913+
TEST_F(CompilerTest, CustomRepeatUntilLoop)
914+
{
915+
Compiler compiler(&m_engine, &m_target);
916+
auto block = std::make_shared<Block>("", "");
917+
918+
block->setCompileFunction([](Compiler *compiler) -> CompilerValue * {
919+
CompilerValue arg(Compiler::StaticType::Unknown);
920+
EXPECT_CALL(*m_builder, beginRepeatUntilLoop(&arg));
921+
compiler->beginRepeatUntilLoop(&arg);
922+
EXPECT_CALL(*m_builder, endLoop());
923+
compiler->endLoop();
924+
925+
return nullptr;
926+
});
927+
928+
compile(compiler, block);
929+
}
930+
931+
TEST_F(CompilerTest, BeginLoopCondition)
932+
{
933+
Compiler compiler(&m_engine, &m_target);
934+
auto block = std::make_shared<Block>("a", "");
935+
block->setCompileFunction([](Compiler *compiler) -> CompilerValue * {
936+
EXPECT_CALL(*m_builder, beginLoopCondition());
937+
compiler->beginLoopCondition();
938+
return nullptr;
939+
});
940+
941+
compile(compiler, block);
942+
}
943+
895944
TEST_F(CompilerTest, MoveToIf)
896945
{
897946
Compiler compiler(&m_engine, &m_target);
@@ -1369,19 +1418,6 @@ TEST_F(CompilerTest, MoveToRepeatUntilLoop)
13691418
compile(compiler, l1);
13701419
}
13711420

1372-
TEST_F(CompilerTest, BeginLoopCondition)
1373-
{
1374-
Compiler compiler(&m_engine, &m_target);
1375-
auto block = std::make_shared<Block>("a", "");
1376-
block->setCompileFunction([](Compiler *compiler) -> CompilerValue * {
1377-
EXPECT_CALL(*m_builder, beginLoopCondition());
1378-
compiler->beginLoopCondition();
1379-
return nullptr;
1380-
});
1381-
1382-
compile(compiler, block);
1383-
}
1384-
13851421
TEST_F(CompilerTest, Input)
13861422
{
13871423
Compiler compiler(&m_engine, &m_target);

0 commit comments

Comments
 (0)