Skip to content

Commit bf1410d

Browse files
authored
Merge pull request #651 from scratchcpp/llvm_sensing_blocks
Implement sensing blocks
2 parents 35bb084 + 5781a8a commit bf1410d

File tree

15 files changed

+3673
-9
lines changed

15 files changed

+3673
-9
lines changed

include/scratchcpp/iengine.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class Stage;
2424
class Variable;
2525
class List;
2626
class Script;
27+
class StringPtr;
2728
class Thread;
2829
class ITimer;
2930
class KeyEvent;
@@ -182,6 +183,12 @@ class LIBSCRATCHCPP_EXPORT IEngine
182183
/*! Call this when a target is clicked. */
183184
virtual void clickTarget(Target *target) = 0;
184185

186+
/*!
187+
* Returns the answer received from the user.
188+
* \see questionAnswered()
189+
*/
190+
virtual const StringPtr *answer() const = 0;
191+
185192
/*! Returns the stage width. */
186193
virtual unsigned int stageWidth() const = 0;
187194

src/blocks/sensingblocks.cpp

Lines changed: 769 additions & 0 deletions
Large diffs are not rendered by default.

src/blocks/sensingblocks.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,17 @@
33
#pragma once
44

55
#include <scratchcpp/iextension.h>
6+
#include <vector>
7+
#include <memory>
68

79
namespace libscratchcpp
810
{
911

12+
class IAudioInput;
13+
class IClock;
14+
class ExecutionContext;
15+
class Thread;
16+
1017
class SensingBlocks : public IExtension
1118
{
1219
public:
@@ -15,6 +22,55 @@ class SensingBlocks : public IExtension
1522
Rgb color() const override;
1623

1724
void registerBlocks(IEngine *engine) override;
25+
void onInit(IEngine *engine) override;
26+
27+
static void clearQuestions();
28+
static void askQuestion(ExecutionContext *ctx, const StringPtr *question);
29+
30+
static inline IAudioInput *audioInput = nullptr;
31+
static inline IClock *clock = nullptr;
32+
33+
private:
34+
struct Question
35+
{
36+
Question(const std::string &question, Thread *thread, bool wasVisible, bool wasStage) :
37+
question(question),
38+
thread(thread),
39+
wasVisible(wasVisible),
40+
wasStage(wasStage)
41+
{
42+
}
43+
44+
std::string question;
45+
Thread *thread = nullptr;
46+
bool wasVisible = false;
47+
bool wasStage = false;
48+
};
49+
50+
static CompilerValue *compileTouchingObject(Compiler *compiler);
51+
static CompilerValue *compileTouchingColor(Compiler *compiler);
52+
static CompilerValue *compileColorIsTouchingColor(Compiler *compiler);
53+
static CompilerValue *compileDistanceTo(Compiler *compiler);
54+
static CompilerValue *compileAskAndWait(Compiler *compiler);
55+
static CompilerValue *compileAnswer(Compiler *compiler);
56+
static CompilerValue *compileKeyPressed(Compiler *compiler);
57+
static CompilerValue *compileMouseDown(Compiler *compiler);
58+
static CompilerValue *compileMouseX(Compiler *compiler);
59+
static CompilerValue *compileMouseY(Compiler *compiler);
60+
static CompilerValue *compileSetDragMode(Compiler *compiler);
61+
static CompilerValue *compileLoudness(Compiler *compiler);
62+
static CompilerValue *compileLoud(Compiler *compiler);
63+
static CompilerValue *compileTimer(Compiler *compiler);
64+
static CompilerValue *compileResetTimer(Compiler *compiler);
65+
static CompilerValue *compileOf(Compiler *compiler);
66+
static CompilerValue *compileCurrent(Compiler *compiler);
67+
static CompilerValue *compileDaysSince2000(Compiler *compiler);
68+
69+
static void onAnswer(const std::string &answer);
70+
static void enqueueAsk(const std::string &question, Thread *thread);
71+
static void askNextQuestion();
72+
73+
static inline std::vector<std::unique_ptr<Question>> m_questions;
1874
};
1975

2076
} // namespace libscratchcpp

src/engine/internal/engine.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,20 @@ Engine::Engine() :
5050
m_clock(Clock::instance().get()),
5151
m_audioEngine(IAudioEngine::instance())
5252
{
53+
m_answer = string_pool_new();
54+
string_assign_cstring(m_answer, "");
55+
56+
m_questionAnswered.connect([this](const std::string &answer) {
57+
// Update answer
58+
string_assign_cstring(m_answer, answer.c_str());
59+
});
5360
}
5461

5562
Engine::~Engine()
5663
{
5764
m_clones.clear();
5865
m_sortedDrawables.clear();
66+
string_pool_free(m_answer);
5967
}
6068

6169
void Engine::clear()
@@ -848,6 +856,11 @@ void Engine::clickTarget(Target *target)
848856
}
849857
}
850858

859+
const StringPtr *Engine::answer() const
860+
{
861+
return m_answer;
862+
}
863+
851864
unsigned int Engine::stageWidth() const
852865
{
853866
return m_stageWidth;

src/engine/internal/engine.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ class Engine : public IEngine
8484

8585
void clickTarget(Target *target) override;
8686

87+
const StringPtr *answer() const override;
88+
8789
unsigned int stageWidth() const override;
8890
void setStageWidth(unsigned int width) override;
8991

@@ -273,6 +275,7 @@ class Engine : public IEngine
273275
double m_mouseX = 0;
274276
double m_mouseY = 0;
275277
bool m_mousePressed = false;
278+
StringPtr *m_answer = nullptr;
276279
unsigned int m_stageWidth = 480;
277280
unsigned int m_stageHeight = 360;
278281
int m_cloneLimit = 300;

src/engine/internal/llvm/instructions/functions.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,19 @@ LLVMInstruction *Functions::buildFunctionCall(LLVMInstruction *ins)
4646

4747
// Args
4848
for (auto &arg : ins->args) {
49-
types.push_back(m_utils.getType(arg.first));
49+
types.push_back(m_utils.getType(arg.first, false));
5050
args.push_back(m_utils.castValue(arg.second, arg.first));
5151
}
5252

53-
llvm::Type *retType = m_utils.getType(ins->functionReturnReg ? ins->functionReturnReg->type() : Compiler::StaticType::Void);
53+
llvm::Type *retType = m_utils.getType(ins->functionReturnReg ? ins->functionReturnReg->type() : Compiler::StaticType::Void, true);
5454
llvm::Value *ret = m_builder.CreateCall(m_utils.functions().resolveFunction(ins->functionName, llvm::FunctionType::get(retType, types, false)), args);
5555

5656
if (ins->functionReturnReg) {
57-
ins->functionReturnReg->value = ret;
57+
if (ins->functionReturnReg->type() == Compiler::StaticType::Unknown) {
58+
ins->functionReturnReg->value = m_utils.addAlloca(retType);
59+
m_builder.CreateStore(ret, ins->functionReturnReg->value);
60+
} else
61+
ins->functionReturnReg->value = ret;
5862

5963
if (ins->functionReturnReg->type() == Compiler::StaticType::String)
6064
m_utils.freeStringLater(ins->functionReturnReg->value);

src/engine/internal/llvm/llvmbuildutils.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ llvm::Value *LLVMBuildUtils::castValue(LLVMRegister *reg, Compiler::StaticType t
496496
}
497497
}
498498

499-
llvm::Type *LLVMBuildUtils::getType(Compiler::StaticType type)
499+
llvm::Type *LLVMBuildUtils::getType(Compiler::StaticType type, bool isReturnType)
500500
{
501501
switch (type) {
502502
case Compiler::StaticType::Void:
@@ -515,7 +515,10 @@ llvm::Type *LLVMBuildUtils::getType(Compiler::StaticType type)
515515
return m_builder.getVoidTy()->getPointerTo();
516516

517517
case Compiler::StaticType::Unknown:
518-
return m_valueDataType->getPointerTo();
518+
if (isReturnType)
519+
return m_valueDataType;
520+
else
521+
return m_valueDataType->getPointerTo();
519522

520523
default:
521524
assert(false);

src/engine/internal/llvm/llvmbuildutils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ class LLVMBuildUtils
8080

8181
llvm::Value *addAlloca(llvm::Type *type);
8282
llvm::Value *castValue(LLVMRegister *reg, Compiler::StaticType targetType);
83-
llvm::Type *getType(Compiler::StaticType type);
83+
llvm::Type *getType(Compiler::StaticType type, bool isReturnType);
8484
llvm::Value *isNaN(llvm::Value *num);
8585
llvm::Value *removeNaN(llvm::Value *num);
8686

src/engine/internal/llvm/llvmcodebuilder.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,10 @@ CompilerValue *LLVMCodeBuilder::addFunctionCall(const std::string &functionName,
100100

101101
if (returnType != Compiler::StaticType::Void) {
102102
auto reg = std::make_shared<LLVMRegister>(returnType);
103-
reg->isRawValue = true;
103+
104+
if (returnType != Compiler::StaticType::Unknown)
105+
reg->isRawValue = true;
106+
104107
ins->functionReturnReg = reg.get();
105108
return addReg(reg, ins);
106109
}

test/blocks/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ if (LIBSCRATCHCPP_ENABLE_SENSING_BLOCKS)
114114
GTest::gmock_main
115115
scratchcpp
116116
scratchcpp_mocks
117+
block_test_deps
117118
)
118119

119120
gtest_discover_tests(sensing_blocks_test)

0 commit comments

Comments
 (0)