From 7d86ce280d47d3695b801f534138ee26bd631bed Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Fri, 23 Aug 2024 18:27:24 +0200 Subject: [PATCH 1/3] Add API for unsupported blocks to Compiler --- include/scratchcpp/compiler.h | 3 +++ src/engine/compiler.cpp | 12 +++++++++++- src/engine/compiler_p.h | 3 +++ test/compiler/compiler_test.cpp | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) 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/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/test/compiler/compiler_test.cpp b/test/compiler/compiler_test.cpp index e4691a78..e4f3fea5 100644 --- a/test/compiler/compiler_test.cpp +++ b/test/compiler/compiler_test.cpp @@ -300,6 +300,7 @@ TEST_F(CompilerTest, AddObscuredInput) compiler.addInstruction(vm::OP_HALT); ASSERT_EQ(compiler.bytecode(), std::vector({ vm::OP_START, vm::OP_CHECKPOINT, vm::OP_NULL, vm::OP_PRINT, vm::OP_CONST, 0, vm::OP_PRINT, vm::OP_NULL, vm::OP_PRINT, vm::OP_HALT })); + ASSERT_EQ(compiler.unsupportedBlocks(), std::unordered_set({ "test_block2" })); } TEST_F(CompilerTest, AddNoShadowInput) @@ -328,6 +329,14 @@ TEST_F(CompilerTest, AddNoShadowInput) ASSERT_EQ(compiler.bytecode(), std::vector({ vm::OP_START, vm::OP_CHECKPOINT, vm::OP_NULL, vm::OP_PRINT, vm::OP_CONST, 0, vm::OP_NULL, vm::OP_PRINT, vm::OP_HALT })); ASSERT_EQ(compiler.constValues().size(), 1); ASSERT_EQ(compiler.constValues()[0], "test"); + ASSERT_EQ(compiler.unsupportedBlocks(), std::unordered_set({ "test_block2" })); + + Input input4("TEST_INPUT4", Input::Type::NoShadow); + std::shared_ptr block3 = std::make_shared("", "test_block3"); + input4.setValueBlock(block3); + compiler.addInput(&input4); + compiler.addInstruction(vm::OP_PRINT); + ASSERT_EQ(compiler.unsupportedBlocks(), std::unordered_set({ "test_block2", "test_block3" })); } TEST_F(CompilerTest, ResolveInput) @@ -841,3 +850,26 @@ TEST_F(CompilerTest, EdgeActivatedHatPredicate) ASSERT_EQ(compiler.bytecode(), std::vector({ vm::OP_START, vm::OP_CONST, 1, vm::OP_PRINT, vm::OP_HALT })); ASSERT_EQ(compiler.constValues(), std::vector({ true, "test" })); } + +TEST_F(CompilerTest, UnsupportedBlocks) +{ + auto block1 = std::make_shared("b1", "block1"); + + auto block2 = std::make_shared("b2", "block2"); + block2->setParent(block1); + block1->setNext(block2); + + auto block3 = std::make_shared("b3", "block3"); + block3->setCompileFunction([](Compiler *) {}); + block3->setParent(block2); + block2->setNext(block3); + + auto block4 = std::make_shared("b4", "block4"); + block4->setParent(block3); + block3->setNext(block4); + + INIT_COMPILER(engine, compiler); + compiler.compile(block1); + + ASSERT_EQ(compiler.unsupportedBlocks(), std::unordered_set({ "block1", "block2", "block4" })); +} From f3bc87ffa317a870f8b0233a60e7908773d7f5fa Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Fri, 23 Aug 2024 19:09:10 +0200 Subject: [PATCH 2/3] Do not compile top level reporter blocks There's no reason to support this yet --- src/engine/internal/engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/internal/engine.cpp b/src/engine/internal/engine.cpp index 216dc97b..64495178 100644 --- a/src/engine/internal/engine.cpp +++ b/src/engine/internal/engine.cpp @@ -265,7 +265,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