Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion include/scratchcpp/dev/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,13 @@ class LIBSCRATCHCPP_EXPORT Compiler

void moveToIf(std::shared_ptr<Block> substack);
void moveToIfElse(std::shared_ptr<Block> substack1, std::shared_ptr<Block> substack2);
void moveToLoop(std::shared_ptr<Block> substack);
void moveToRepeatLoop(std::shared_ptr<Block> substack);
void moveToWhileLoop(std::shared_ptr<Block> substack);
void moveToRepeatUntilLoop(std::shared_ptr<Block> substack);
void beginLoopCondition();
void warp();

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

const std::unordered_set<std::string> &unsupportedBlocks() const;
Expand Down
64 changes: 57 additions & 7 deletions src/dev/engine/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ std::shared_ptr<libscratchcpp::Block> Compiler::block() const
std::shared_ptr<ExecutableCode> Compiler::compile(std::shared_ptr<Block> startBlock)
{
impl->builder = impl->builderFactory->create(startBlock->id());
impl->substackTree.clear();
impl->substackHit = false;
impl->warp = false;
impl->block = startBlock;

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

if (substacks != impl->substackTree.size())
if (impl->substackHit) {
impl->substackHit = false;
continue;
}

impl->block = impl->block->next();
if (impl->block)
impl->block = impl->block->next();

if (!impl->block && !impl->substackTree.empty())
impl->substackEnd();
Expand Down Expand Up @@ -100,39 +105,84 @@ void Compiler::addInput(const std::string &name)
/*! Jumps to the given if substack. */
void Compiler::moveToIf(std::shared_ptr<Block> substack)
{
if (!substack)
return; // ignore empty if statements

impl->substackHit = true;
impl->substackTree.push_back({ { impl->block, nullptr }, CompilerPrivate::SubstackType::IfStatement });
impl->block = substack;

if (!impl->block)
impl->substackEnd();
impl->builder->beginIfStatement();
}

/*! Jumps to the given if/else substack. The second substack is used for the else branch. */
void Compiler::moveToIfElse(std::shared_ptr<Block> substack1, std::shared_ptr<Block> substack2)
{
if (!substack1 && !substack2)
return; // ignore empty if statements

impl->substackHit = true;
impl->substackTree.push_back({ { impl->block, substack2 }, CompilerPrivate::SubstackType::IfStatement });
impl->block = substack1;
impl->builder->beginIfStatement();

if (!impl->block)
impl->substackEnd();
}

/*! Jumps to the given loop substack. */
void Compiler::moveToLoop(std::shared_ptr<Block> substack)
/*! Jumps to the given repeat loop substack. */
void Compiler::moveToRepeatLoop(std::shared_ptr<Block> substack)
{
impl->substackHit = true;
impl->substackTree.push_back({ { impl->block, nullptr }, CompilerPrivate::SubstackType::Loop });
impl->block = substack;
impl->builder->beginRepeatLoop();

if (!impl->block)
impl->substackEnd();
}

/*! Jumps to the given while loop substack. */
void Compiler::moveToWhileLoop(std::shared_ptr<Block> substack)
{
impl->substackHit = true;
impl->substackTree.push_back({ { impl->block, nullptr }, CompilerPrivate::SubstackType::Loop });
impl->block = substack;
impl->builder->beginWhileLoop();

if (!impl->block)
impl->substackEnd();
}

/*! Jumps to the given until loop substack. */
void Compiler::moveToRepeatUntilLoop(std::shared_ptr<Block> substack)
{
impl->substackHit = true;
impl->substackTree.push_back({ { impl->block, nullptr }, CompilerPrivate::SubstackType::Loop });
impl->block = substack;
impl->builder->beginRepeatUntilLoop();

if (!impl->block)
impl->substackEnd();
}

/*! Begins a while/until loop condition. */
void Compiler::beginLoopCondition()
{
impl->builder->beginLoopCondition();
}

/*! Makes current script run without screen refresh. */
void Compiler::warp()
{
impl->warp = true;
}

/*! Convenience method which returns the field with the given name. */
Input *Compiler::input(const std::string &name) const
{
return impl->block->inputAt(impl->block->findInput(name)).get();
}

/*! Convenience method which returns the field with the given name. */
Field *Compiler::field(const std::string &name) const
{
Expand Down
6 changes: 3 additions & 3 deletions src/dev/engine/compiler_p.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ CompilerPrivate::CompilerPrivate(IEngine *engine, Target *target) :

void CompilerPrivate::substackEnd()
{
auto parent = substackTree.back();
auto &parent = substackTree.back();

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

builder->endLoop();
break;
Expand Down
1 change: 1 addition & 0 deletions src/dev/engine/compiler_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct CompilerPrivate

std::shared_ptr<Block> block;
std::vector<std::pair<std::pair<std::shared_ptr<Block>, std::shared_ptr<Block>>, SubstackType>> substackTree;
bool substackHit = false;
bool warp = false;

static inline ICodeBuilderFactory *builderFactory = nullptr;
Expand Down
5 changes: 4 additions & 1 deletion src/dev/engine/internal/icodebuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ class ICodeBuilder
virtual void beginElseBranch() = 0;
virtual void endIf() = 0;

virtual void beginLoop() = 0;
virtual void beginRepeatLoop() = 0;
virtual void beginWhileLoop() = 0;
virtual void beginRepeatUntilLoop() = 0;
virtual void beginLoopCondition() = 0;
virtual void endLoop() = 0;

virtual void yield() = 0;
Expand Down
Loading
Loading