diff --git a/include/scratchcpp/compiler.h b/include/scratchcpp/compiler.h index a8b852bb..05ab0c7c 100644 --- a/include/scratchcpp/compiler.h +++ b/include/scratchcpp/compiler.h @@ -4,6 +4,7 @@ #include #include +#include #include "global.h" #include "spimpl.h" @@ -82,6 +83,8 @@ class LIBSCRATCHCPP_EXPORT Compiler BlockPrototype *procedurePrototype() const; void setProcedurePrototype(BlockPrototype *prototype); + const std::unordered_set &unsupportedBlocks() const; + private: spimpl::unique_impl_ptr impl; }; diff --git a/include/scratchcpp/iengine.h b/include/scratchcpp/iengine.h index 2372d42c..aa5aac94 100644 --- a/include/scratchcpp/iengine.h +++ b/include/scratchcpp/iengine.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "global.h" @@ -390,6 +391,9 @@ class LIBSCRATCHCPP_EXPORT IEngine /*! Sets the user agent of the last person to edit the project. */ virtual void setUserAgent(const std::string &agent) = 0; + + /*! Returns the unsupported block opcodes which were found when compiling. */ + virtual const std::unordered_set &unsupportedBlocks() const = 0; }; } // namespace libscratchcpp diff --git a/src/engine/compiler.cpp b/src/engine/compiler.cpp index 0f549af6..2ff823ba 100644 --- a/src/engine/compiler.cpp +++ b/src/engine/compiler.cpp @@ -66,8 +66,10 @@ void Compiler::compile(std::shared_ptr topLevelBlock) if (impl->block->compileFunction()) impl->block->compile(this); - else + else { std::cout << "warning: unsupported block: " << impl->block->opcode() << std::endl; + impl->unsupportedBlocks.insert(impl->block->opcode()); + } if (substacks != impl->substackTree.size()) continue; @@ -186,6 +188,7 @@ void Compiler::addInput(Input *input) impl->block->compile(this); else { std::cout << "warning: unsupported reporter block: " << impl->block->opcode() << std::endl; + impl->unsupportedBlocks.insert(impl->block->opcode()); addInstruction(OP_NULL); } } else @@ -205,6 +208,7 @@ void Compiler::addInput(Input *input) impl->block->compile(this); else { std::cout << "warning: unsupported reporter block: " << impl->block->opcode() << std::endl; + impl->unsupportedBlocks.insert(impl->block->opcode()); addInstruction(OP_NULL); } } else @@ -356,6 +360,12 @@ void Compiler::setProcedurePrototype(BlockPrototype *prototype) impl->procedurePrototype = prototype; } +/*! Returns unsupported block opcodes which were found when compiling. */ +const std::unordered_set &libscratchcpp::Compiler::unsupportedBlocks() const +{ + return impl->unsupportedBlocks; +} + /*! Returns the list of custom block prototypes. */ const std::vector &Compiler::procedures() const { diff --git a/src/engine/compiler_p.h b/src/engine/compiler_p.h index a310eb47..5a396a7a 100644 --- a/src/engine/compiler_p.h +++ b/src/engine/compiler_p.h @@ -3,6 +3,7 @@ #pragma once #include +#include #include #include @@ -38,6 +39,8 @@ struct CompilerPrivate std::unordered_map> procedureArgs; BlockPrototype *procedurePrototype = nullptr; bool warp = false; + + std::unordered_set unsupportedBlocks; }; } // namespace libscratchcpp diff --git a/src/engine/internal/engine.cpp b/src/engine/internal/engine.cpp index 216dc97b..9f321549 100644 --- a/src/engine/internal/engine.cpp +++ b/src/engine/internal/engine.cpp @@ -95,6 +95,8 @@ void Engine::clear() m_edgeActivatedHatValues.clear(); m_running = false; + + m_unsupportedBlocks.clear(); } // Resolves ID references and sets pointers of entities. @@ -265,7 +267,7 @@ void Engine::compile() Compiler compiler(this, target.get()); const auto &blocks = target->blocks(); for (auto block : blocks) { - if (block->topLevel() && !block->shadow()) { + if (block->topLevel() && !block->isTopLevelReporter() && !block->shadow()) { auto section = blockSection(block->opcode()); if (section) { auto script = std::make_shared