Skip to content

Commit 2266149

Browse files
committed
Implement hat predicates in Compiler
1 parent 66978e0 commit 2266149

File tree

7 files changed

+65
-12
lines changed

7 files changed

+65
-12
lines changed

include/scratchcpp/compiler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class LIBSCRATCHCPP_EXPORT Compiler
4949
Target *target() const;
5050
std::shared_ptr<Block> block() const;
5151

52-
std::shared_ptr<ExecutableCode> compile(std::shared_ptr<Block> startBlock);
52+
std::shared_ptr<ExecutableCode> compile(std::shared_ptr<Block> startBlock, bool isHatPredicate = false);
5353
void preoptimize();
5454

5555
CompilerValue *addFunctionCall(const std::string &functionName, StaticType returnType = StaticType::Void, const ArgTypes &argTypes = {}, const Args &args = {});

src/engine/compiler.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ std::shared_ptr<libscratchcpp::Block> Compiler::block() const
4444
}
4545

4646
/*! Compiles the script starting with the given block. */
47-
std::shared_ptr<ExecutableCode> Compiler::compile(std::shared_ptr<Block> startBlock)
47+
std::shared_ptr<ExecutableCode> Compiler::compile(std::shared_ptr<Block> startBlock, bool isHatPredicate)
4848
{
4949
BlockPrototype *procedurePrototype = nullptr;
5050

@@ -60,13 +60,32 @@ std::shared_ptr<ExecutableCode> Compiler::compile(std::shared_ptr<Block> startBl
6060
}
6161
}
6262

63-
impl->builder = impl->builderFactory->create(impl->ctx, procedurePrototype);
63+
impl->builder = impl->builderFactory->create(impl->ctx, procedurePrototype, isHatPredicate);
6464
impl->substackTree.clear();
6565
impl->substackHit = false;
6666
impl->emptySubstack = false;
6767
impl->warp = false;
6868
impl->block = startBlock;
6969

70+
if (impl->block && isHatPredicate) {
71+
auto f = impl->block->hatPredicateCompileFunction();
72+
73+
if (f) {
74+
CompilerValue *ret = f(this);
75+
assert(ret);
76+
77+
if (!ret)
78+
std::cout << "warning: '" << impl->block->opcode() << "' hat predicate compile function doesn't return a valid value" << std::endl;
79+
} else {
80+
std::cout << "warning: unsupported hat predicate: " << impl->block->opcode() << std::endl;
81+
impl->unsupportedBlocks.insert(impl->block->opcode());
82+
addConstValue(false); // return false if unsupported
83+
}
84+
85+
impl->block = nullptr;
86+
return impl->builder->finalize();
87+
}
88+
7089
while (impl->block) {
7190
if (impl->block->compileFunction()) {
7291
assert(impl->customIfStatementCount == 0);

src/engine/internal/codebuilderfactory.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ std::shared_ptr<CodeBuilderFactory> CodeBuilderFactory::instance()
1313
return m_instance;
1414
}
1515

16-
std::shared_ptr<ICodeBuilder> CodeBuilderFactory::create(CompilerContext *ctx, BlockPrototype *procedurePrototype) const
16+
std::shared_ptr<ICodeBuilder> CodeBuilderFactory::create(CompilerContext *ctx, BlockPrototype *procedurePrototype, bool isPredicate) const
1717
{
1818
assert(dynamic_cast<LLVMCompilerContext *>(ctx));
19-
return std::make_shared<LLVMCodeBuilder>(static_cast<LLVMCompilerContext *>(ctx), procedurePrototype);
19+
return std::make_shared<LLVMCodeBuilder>(static_cast<LLVMCompilerContext *>(ctx), procedurePrototype, isPredicate);
2020
}
2121

2222
std::shared_ptr<CompilerContext> CodeBuilderFactory::createCtx(IEngine *engine, Target *target) const

src/engine/internal/codebuilderfactory.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class CodeBuilderFactory : public ICodeBuilderFactory
1111
{
1212
public:
1313
static std::shared_ptr<CodeBuilderFactory> instance();
14-
std::shared_ptr<ICodeBuilder> create(CompilerContext *ctx, BlockPrototype *procedurePrototype) const override;
14+
std::shared_ptr<ICodeBuilder> create(CompilerContext *ctx, BlockPrototype *procedurePrototype, bool isPredicate) const override;
1515
std::shared_ptr<CompilerContext> createCtx(IEngine *engine, Target *target) const override;
1616

1717
private:

src/engine/internal/icodebuilderfactory.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class ICodeBuilderFactory
1818
public:
1919
virtual ~ICodeBuilderFactory() { }
2020

21-
virtual std::shared_ptr<ICodeBuilder> create(CompilerContext *ctx, BlockPrototype *procedurePrototype = nullptr) const = 0;
21+
virtual std::shared_ptr<ICodeBuilder> create(CompilerContext *ctx, BlockPrototype *procedurePrototype = nullptr, bool isPredicate = false) const = 0;
2222
virtual std::shared_ptr<CompilerContext> createCtx(IEngine *engine, Target *target) const = 0;
2323
};
2424

test/compiler/compiler_test.cpp

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,12 @@ class CompilerTest : public testing::Test
4646
m_testVar.reset();
4747
}
4848

49-
void compile(Compiler *compiler, std::shared_ptr<Block> block, BlockPrototype *procedurePrototype = nullptr)
49+
void compile(Compiler *compiler, std::shared_ptr<Block> block, BlockPrototype *procedurePrototype = nullptr, bool isHatPredicate = false)
5050
{
5151
ASSERT_EQ(compiler->block(), nullptr);
52-
EXPECT_CALL(m_builderFactory, create(m_ctx.get(), procedurePrototype)).WillOnce(Return(m_builder));
52+
EXPECT_CALL(m_builderFactory, create(m_ctx.get(), procedurePrototype, isHatPredicate)).WillOnce(Return(m_builder));
5353
EXPECT_CALL(*m_builder, finalize()).WillOnce(Return(m_code));
54-
ASSERT_EQ(compiler->compile(block), m_code);
54+
ASSERT_EQ(compiler->compile(block, isHatPredicate), m_code);
5555
ASSERT_EQ(compiler->block(), nullptr);
5656
}
5757

@@ -1778,7 +1778,23 @@ TEST_F(CompilerTest, UnsupportedBlocks)
17781778
EXPECT_CALL(*m_builder, addConstValue).WillRepeatedly(Return(nullptr));
17791779
compile(m_compiler.get(), block1);
17801780

1781-
ASSERT_EQ(m_compiler->unsupportedBlocks(), std::unordered_set<std::string>({ "block1", "block2", "value_block1", "value_block3", "value_block5", "block4" }));
1781+
// Hat predicates
1782+
auto block5 = std::make_shared<Block>("b5", "block5");
1783+
compile(m_compiler.get(), block5, nullptr, true);
1784+
1785+
auto block6 = std::make_shared<Block>("b6", "block6");
1786+
block6->setCompileFunction([](Compiler *) -> CompilerValue * { return nullptr; });
1787+
compile(m_compiler.get(), block6, nullptr, true);
1788+
1789+
auto block7 = std::make_shared<Block>("b7", "block7");
1790+
CompilerConstant ret(Compiler::StaticType::Bool, Value(true));
1791+
block7->setCompileFunction([](Compiler *) -> CompilerValue * { return nullptr; });
1792+
block7->setHatPredicateCompileFunction([](Compiler *compiler) -> CompilerValue * { return compiler->addConstValue(true); });
1793+
EXPECT_CALL(*m_builder, addConstValue(Value(true))).WillOnce(Return(&ret));
1794+
compile(m_compiler.get(), block7, nullptr, true);
1795+
1796+
// Check
1797+
ASSERT_EQ(m_compiler->unsupportedBlocks(), std::unordered_set<std::string>({ "block1", "block2", "value_block1", "value_block3", "value_block5", "block4", "block5", "block6" }));
17821798
}
17831799

17841800
TEST_F(CompilerTest, Procedure)
@@ -1818,3 +1834,21 @@ TEST_F(CompilerTest, Preoptimize)
18181834
EXPECT_CALL(*ctx, preoptimize());
18191835
compiler.preoptimize();
18201836
}
1837+
1838+
TEST_F(CompilerTest, HatPredicate)
1839+
{
1840+
auto block = std::make_shared<Block>("", "");
1841+
block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { return compiler->addConstValue(true); });
1842+
block->setHatPredicateCompileFunction([](Compiler *compiler) -> CompilerValue * { return compiler->addConstValue(false); });
1843+
1844+
CompilerConstant ret1(Compiler::StaticType::Bool, Value(true));
1845+
CompilerConstant ret2(Compiler::StaticType::Bool, Value(false));
1846+
1847+
// Script
1848+
EXPECT_CALL(*m_builder, addConstValue(Value(true))).WillOnce(Return(&ret1));
1849+
compile(m_compiler.get(), block, nullptr, false);
1850+
1851+
// Hat predicate
1852+
EXPECT_CALL(*m_builder, addConstValue(Value(false))).WillOnce(Return(&ret2));
1853+
compile(m_compiler.get(), block, nullptr, true);
1854+
}

test/mocks/codebuilderfactorymock.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ using namespace libscratchcpp;
88
class CodeBuilderFactoryMock : public ICodeBuilderFactory
99
{
1010
public:
11-
MOCK_METHOD(std::shared_ptr<ICodeBuilder>, create, (CompilerContext *, BlockPrototype *), (const, override));
11+
MOCK_METHOD(std::shared_ptr<ICodeBuilder>, create, (CompilerContext *, BlockPrototype *, bool), (const, override));
1212
MOCK_METHOD(std::shared_ptr<CompilerContext>, createCtx, (IEngine *, Target *), (const, override));
1313
};

0 commit comments

Comments
 (0)