Skip to content

Commit dc1bcf7

Browse files
authored
Merge pull request #591 from scratchcpp/llvm_if_and_loops
LLVM: Implement if statements and loops
2 parents a6de26e + 4e53ef6 commit dc1bcf7

File tree

12 files changed

+1246
-16
lines changed

12 files changed

+1246
-16
lines changed

include/scratchcpp/dev/compiler.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,13 @@ class LIBSCRATCHCPP_EXPORT Compiler
4040

4141
void moveToIf(std::shared_ptr<Block> substack);
4242
void moveToIfElse(std::shared_ptr<Block> substack1, std::shared_ptr<Block> substack2);
43-
void moveToLoop(std::shared_ptr<Block> substack);
43+
void moveToRepeatLoop(std::shared_ptr<Block> substack);
44+
void moveToWhileLoop(std::shared_ptr<Block> substack);
45+
void moveToRepeatUntilLoop(std::shared_ptr<Block> substack);
46+
void beginLoopCondition();
4447
void warp();
4548

49+
Input *input(const std::string &name) const;
4650
Field *field(const std::string &name) const;
4751

4852
const std::unordered_set<std::string> &unsupportedBlocks() const;

src/dev/engine/compiler.cpp

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ std::shared_ptr<libscratchcpp::Block> Compiler::block() const
3939
std::shared_ptr<ExecutableCode> Compiler::compile(std::shared_ptr<Block> startBlock)
4040
{
4141
impl->builder = impl->builderFactory->create(startBlock->id());
42+
impl->substackTree.clear();
43+
impl->substackHit = false;
4244
impl->warp = false;
4345
impl->block = startBlock;
4446

@@ -52,10 +54,13 @@ std::shared_ptr<ExecutableCode> Compiler::compile(std::shared_ptr<Block> startBl
5254
impl->unsupportedBlocks.insert(impl->block->opcode());
5355
}
5456

55-
if (substacks != impl->substackTree.size())
57+
if (impl->substackHit) {
58+
impl->substackHit = false;
5659
continue;
60+
}
5761

58-
impl->block = impl->block->next();
62+
if (impl->block)
63+
impl->block = impl->block->next();
5964

6065
if (!impl->block && !impl->substackTree.empty())
6166
impl->substackEnd();
@@ -100,39 +105,84 @@ void Compiler::addInput(const std::string &name)
100105
/*! Jumps to the given if substack. */
101106
void Compiler::moveToIf(std::shared_ptr<Block> substack)
102107
{
108+
if (!substack)
109+
return; // ignore empty if statements
110+
111+
impl->substackHit = true;
103112
impl->substackTree.push_back({ { impl->block, nullptr }, CompilerPrivate::SubstackType::IfStatement });
104113
impl->block = substack;
105-
106-
if (!impl->block)
107-
impl->substackEnd();
114+
impl->builder->beginIfStatement();
108115
}
109116

110117
/*! Jumps to the given if/else substack. The second substack is used for the else branch. */
111118
void Compiler::moveToIfElse(std::shared_ptr<Block> substack1, std::shared_ptr<Block> substack2)
112119
{
120+
if (!substack1 && !substack2)
121+
return; // ignore empty if statements
122+
123+
impl->substackHit = true;
113124
impl->substackTree.push_back({ { impl->block, substack2 }, CompilerPrivate::SubstackType::IfStatement });
114125
impl->block = substack1;
126+
impl->builder->beginIfStatement();
115127

116128
if (!impl->block)
117129
impl->substackEnd();
118130
}
119131

120-
/*! Jumps to the given loop substack. */
121-
void Compiler::moveToLoop(std::shared_ptr<Block> substack)
132+
/*! Jumps to the given repeat loop substack. */
133+
void Compiler::moveToRepeatLoop(std::shared_ptr<Block> substack)
122134
{
135+
impl->substackHit = true;
123136
impl->substackTree.push_back({ { impl->block, nullptr }, CompilerPrivate::SubstackType::Loop });
124137
impl->block = substack;
138+
impl->builder->beginRepeatLoop();
125139

126140
if (!impl->block)
127141
impl->substackEnd();
128142
}
129143

144+
/*! Jumps to the given while loop substack. */
145+
void Compiler::moveToWhileLoop(std::shared_ptr<Block> substack)
146+
{
147+
impl->substackHit = true;
148+
impl->substackTree.push_back({ { impl->block, nullptr }, CompilerPrivate::SubstackType::Loop });
149+
impl->block = substack;
150+
impl->builder->beginWhileLoop();
151+
152+
if (!impl->block)
153+
impl->substackEnd();
154+
}
155+
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+
168+
/*! Begins a while/until loop condition. */
169+
void Compiler::beginLoopCondition()
170+
{
171+
impl->builder->beginLoopCondition();
172+
}
173+
130174
/*! Makes current script run without screen refresh. */
131175
void Compiler::warp()
132176
{
133177
impl->warp = true;
134178
}
135179

180+
/*! Convenience method which returns the field with the given name. */
181+
Input *Compiler::input(const std::string &name) const
182+
{
183+
return impl->block->inputAt(impl->block->findInput(name)).get();
184+
}
185+
136186
/*! Convenience method which returns the field with the given name. */
137187
Field *Compiler::field(const std::string &name) const
138188
{

src/dev/engine/compiler_p.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ CompilerPrivate::CompilerPrivate(IEngine *engine, Target *target) :
1919

2020
void CompilerPrivate::substackEnd()
2121
{
22-
auto parent = substackTree.back();
22+
auto &parent = substackTree.back();
2323

2424
switch (parent.second) {
2525
case SubstackType::Loop:
2626
// Yield at loop end if not running without screen refresh
27-
if (!warp)
28-
builder->yield();
27+
/*if (!warp)
28+
builder->yield();*/
2929

3030
builder->endLoop();
3131
break;

src/dev/engine/compiler_p.h

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

3333
std::shared_ptr<Block> block;
3434
std::vector<std::pair<std::pair<std::shared_ptr<Block>, std::shared_ptr<Block>>, SubstackType>> substackTree;
35+
bool substackHit = false;
3536
bool warp = false;
3637

3738
static inline ICodeBuilderFactory *builderFactory = nullptr;

src/dev/engine/internal/icodebuilder.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ class ICodeBuilder
2929
virtual void beginElseBranch() = 0;
3030
virtual void endIf() = 0;
3131

32-
virtual void beginLoop() = 0;
32+
virtual void beginRepeatLoop() = 0;
33+
virtual void beginWhileLoop() = 0;
34+
virtual void beginRepeatUntilLoop() = 0;
35+
virtual void beginLoopCondition() = 0;
3336
virtual void endLoop() = 0;
3437

3538
virtual void yield() = 0;

0 commit comments

Comments
 (0)