Skip to content

Commit bf5029f

Browse files
authored
Merge pull request #608 from scratchcpp/llvm_event_blocks
LLVM: Implement event blocks
2 parents 761cbe8 + fb4a422 commit bf5029f

24 files changed

+811
-158
lines changed

include/scratchcpp/dev/executablecode.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace libscratchcpp
1010
{
1111

1212
class ExecutionContext;
13-
class Target;
13+
class Thread;
1414

1515
/*! \brief The ExecutableCode class represents the code of a compiled Scratch script. */
1616
class LIBSCRATCHCPP_EXPORT ExecutableCode
@@ -31,7 +31,7 @@ class LIBSCRATCHCPP_EXPORT ExecutableCode
3131
virtual bool isFinished(ExecutionContext *context) const = 0;
3232

3333
/*! Creates an execution context for the given Target. */
34-
virtual std::shared_ptr<ExecutionContext> createExecutionContext(Target *target) const = 0;
34+
virtual std::shared_ptr<ExecutionContext> createExecutionContext(Thread *thread) const = 0;
3535
};
3636

3737
} // namespace libscratchcpp

include/scratchcpp/dev/executioncontext.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,21 @@
88
namespace libscratchcpp
99
{
1010

11-
class Target;
11+
class Thread;
12+
class IEngine;
1213
class Promise;
1314
class ExecutionContextPrivate;
1415

1516
/*! \brief The ExecutionContext represents the execution context of a target (can be a clone) with variables, lists, etc. */
1617
class LIBSCRATCHCPP_EXPORT ExecutionContext
1718
{
1819
public:
19-
ExecutionContext(Target *target);
20+
ExecutionContext(Thread *thread);
2021
ExecutionContext(const ExecutionContext &) = delete;
2122
virtual ~ExecutionContext() { }
2223

23-
Target *target() const;
24+
Thread *thread() const;
25+
IEngine *engine() const;
2426

2527
std::shared_ptr<Promise> promise() const;
2628
void setPromise(std::shared_ptr<Promise> promise);

include/scratchcpp/dev/test/scriptbuilder.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44

55
#include <vector>
66

7-
#include "../../global.h"
8-
#include "../../spimpl.h"
7+
#include "../../inputvalue.h"
98

109
namespace libscratchcpp
1110
{
@@ -44,13 +43,19 @@ class LIBSCRATCHCPP_EXPORT ScriptBuilder
4443
void addDropdownInput(const std::string &name, const std::string &selectedValue);
4544
void addDropdownField(const std::string &name, const std::string &selectedValue);
4645

46+
void addEntityInput(const std::string &name, const std::string &entityName, InputValue::Type entityType, std::shared_ptr<Entity> entity);
47+
void addEntityField(const std::string &name, std::shared_ptr<Entity> entity);
48+
49+
std::shared_ptr<Block> currentBlock();
50+
4751
void build();
4852
void run();
4953

5054
List *capturedValues() const;
5155

5256
private:
5357
void addBlock(std::shared_ptr<Block> block);
58+
void build(std::shared_ptr<Target> target);
5459

5560
spimpl::unique_impl_ptr<ScriptBuilderPrivate> impl;
5661
};

src/dev/blocks/eventblocks.cpp

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
// SPDX-License-Identifier: Apache-2.0
22

3+
#include <scratchcpp/iengine.h>
4+
#include <scratchcpp/dev/compiler.h>
5+
#include <scratchcpp/block.h>
6+
#include <scratchcpp/field.h>
7+
#include <scratchcpp/broadcast.h>
8+
#include <scratchcpp/dev/executioncontext.h>
9+
#include <scratchcpp/thread.h>
10+
#include <scratchcpp/dev/compilerconstant.h>
11+
312
#include "eventblocks.h"
413

514
using namespace libscratchcpp;
@@ -16,4 +25,105 @@ std::string libscratchcpp::EventBlocks::description() const
1625

1726
void EventBlocks::registerBlocks(IEngine *engine)
1827
{
28+
engine->addCompileFunction(this, "event_whentouchingobject", &compileWhenTouchingObject);
29+
engine->addCompileFunction(this, "event_whenflagclicked", &compileWhenFlagClicked);
30+
engine->addCompileFunction(this, "event_whenthisspriteclicked", &compileWhenThisSpriteClicked);
31+
engine->addCompileFunction(this, "event_whenstageclicked", &compileWhenStageClicked);
32+
engine->addCompileFunction(this, "event_whenbroadcastreceived", &compileWhenBroadcastReceived);
33+
engine->addCompileFunction(this, "event_whenbackdropswitchesto", &compileWhenBackdropSwitchesTo);
34+
engine->addCompileFunction(this, "event_whengreaterthan", &compileWhenGreaterThan);
35+
engine->addCompileFunction(this, "event_broadcast", &compileBroadcast);
36+
engine->addCompileFunction(this, "event_broadcastandwait", &compileBroadcastAndWait);
37+
engine->addCompileFunction(this, "event_whenkeypressed", &compileWhenKeyPressed);
38+
}
39+
40+
CompilerValue *EventBlocks::compileWhenTouchingObject(Compiler *compiler)
41+
{
42+
compiler->engine()->addWhenTouchingObjectScript(compiler->block());
43+
return nullptr;
44+
}
45+
46+
CompilerValue *EventBlocks::compileWhenFlagClicked(Compiler *compiler)
47+
{
48+
compiler->engine()->addGreenFlagScript(compiler->block());
49+
return nullptr;
50+
}
51+
52+
CompilerValue *EventBlocks::compileWhenThisSpriteClicked(Compiler *compiler)
53+
{
54+
compiler->engine()->addTargetClickScript(compiler->block());
55+
return nullptr;
56+
}
57+
58+
CompilerValue *EventBlocks::compileWhenStageClicked(Compiler *compiler)
59+
{
60+
compiler->engine()->addTargetClickScript(compiler->block());
61+
return nullptr;
62+
}
63+
64+
CompilerValue *EventBlocks::compileWhenBroadcastReceived(Compiler *compiler)
65+
{
66+
auto block = compiler->block();
67+
Field *field = compiler->field("BROADCAST_OPTION");
68+
69+
if (field) {
70+
auto broadcast = std::static_pointer_cast<Broadcast>(field->valuePtr());
71+
compiler->engine()->addBroadcastScript(block, field, broadcast.get());
72+
}
73+
74+
return nullptr;
75+
}
76+
77+
CompilerValue *EventBlocks::compileWhenBackdropSwitchesTo(Compiler *compiler)
78+
{
79+
auto block = compiler->block();
80+
Field *field = compiler->field("BACKDROP");
81+
82+
if (field)
83+
compiler->engine()->addBackdropChangeScript(block, field);
84+
85+
return nullptr;
86+
}
87+
88+
CompilerValue *EventBlocks::compileWhenGreaterThan(Compiler *compiler)
89+
{
90+
compiler->engine()->addWhenGreaterThanScript(compiler->block());
91+
return nullptr;
92+
}
93+
94+
CompilerValue *EventBlocks::compileBroadcast(Compiler *compiler)
95+
{
96+
auto input = compiler->addInput("BROADCAST_INPUT");
97+
auto wait = compiler->addConstValue(false);
98+
compiler->addFunctionCallWithCtx("event_broadcast", Compiler::StaticType::Void, { Compiler::StaticType::String, Compiler::StaticType::Bool }, { input, wait });
99+
return nullptr;
100+
}
101+
102+
CompilerValue *EventBlocks::compileBroadcastAndWait(Compiler *compiler)
103+
{
104+
auto input = compiler->addInput("BROADCAST_INPUT");
105+
auto wait = compiler->addConstValue(true);
106+
compiler->addFunctionCallWithCtx("event_broadcast", Compiler::StaticType::Void, { Compiler::StaticType::String, Compiler::StaticType::Bool }, { input, wait });
107+
return nullptr;
108+
}
109+
110+
CompilerValue *EventBlocks::compileWhenKeyPressed(Compiler *compiler)
111+
{
112+
auto block = compiler->block();
113+
Field *field = compiler->field("KEY_OPTION");
114+
115+
if (field)
116+
compiler->engine()->addKeyPressScript(block, field);
117+
118+
return nullptr;
119+
}
120+
121+
extern "C" void event_broadcast(ExecutionContext *ctx, const char *name, bool wait)
122+
{
123+
Thread *thread = ctx->thread();
124+
IEngine *engine = thread->engine();
125+
std::vector<int> broadcasts = engine->findBroadcasts(name);
126+
127+
for (int index : broadcasts)
128+
engine->broadcast(index, thread, wait);
19129
}

src/dev/blocks/eventblocks.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,18 @@ class EventBlocks : public IExtension
1414
std::string description() const override;
1515

1616
void registerBlocks(IEngine *engine) override;
17+
18+
private:
19+
static CompilerValue *compileWhenTouchingObject(Compiler *compiler);
20+
static CompilerValue *compileWhenFlagClicked(Compiler *compiler);
21+
static CompilerValue *compileWhenThisSpriteClicked(Compiler *compiler);
22+
static CompilerValue *compileWhenStageClicked(Compiler *compiler);
23+
static CompilerValue *compileWhenBroadcastReceived(Compiler *compiler);
24+
static CompilerValue *compileWhenBackdropSwitchesTo(Compiler *compiler);
25+
static CompilerValue *compileWhenGreaterThan(Compiler *compiler);
26+
static CompilerValue *compileBroadcast(Compiler *compiler);
27+
static CompilerValue *compileBroadcastAndWait(Compiler *compiler);
28+
static CompilerValue *compileWhenKeyPressed(Compiler *compiler);
1729
};
1830

1931
} // namespace libscratchcpp

src/dev/engine/executioncontext.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,28 @@
11
// SPDX-License-Identifier: Apache-2.0
22

33
#include <scratchcpp/dev/executioncontext.h>
4+
#include <scratchcpp/thread.h>
45

56
#include "executioncontext_p.h"
67

78
using namespace libscratchcpp;
89

910
/*! Constructs ExecutionContext. */
10-
ExecutionContext::ExecutionContext(Target *target) :
11-
impl(spimpl::make_unique_impl<ExecutionContextPrivate>(target))
11+
ExecutionContext::ExecutionContext(Thread *thread) :
12+
impl(spimpl::make_unique_impl<ExecutionContextPrivate>(thread))
1213
{
1314
}
1415

15-
/*! Returns the Target of this context. */
16-
Target *ExecutionContext::target() const
16+
/*! Returns the thread of this context. */
17+
Thread *ExecutionContext::thread() const
1718
{
18-
return impl->target;
19+
return impl->thread;
20+
}
21+
22+
/*! Returns the engine of the project. */
23+
IEngine *ExecutionContext::engine() const
24+
{
25+
return impl->thread->engine();
1926
}
2027

2128
/*! Returns the script promise. */

src/dev/engine/executioncontext_p.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
using namespace libscratchcpp;
66

7-
ExecutionContextPrivate::ExecutionContextPrivate(Target *target) :
8-
target(target)
7+
ExecutionContextPrivate::ExecutionContextPrivate(Thread *thread) :
8+
thread(thread)
99
{
1010
}

src/dev/engine/executioncontext_p.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@
77
namespace libscratchcpp
88
{
99

10+
class Thread;
1011
class Target;
1112
class Promise;
1213

1314
struct ExecutionContextPrivate
1415
{
15-
ExecutionContextPrivate(Target *target);
16+
ExecutionContextPrivate(Thread *thread);
1617

17-
Target *target = nullptr;
18+
Thread *thread = nullptr;
1819
std::shared_ptr<Promise> promise;
1920
};
2021

src/dev/engine/internal/llvm/llvmexecutablecode.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <scratchcpp/stage.h>
66
#include <scratchcpp/iengine.h>
77
#include <scratchcpp/dev/promise.h>
8+
#include <scratchcpp/thread.h>
89
#include <llvm/Support/Error.h>
910
#include <iostream>
1011

@@ -64,7 +65,7 @@ void LLVMExecutableCode::run(ExecutionContext *context)
6465

6566
ctx->setFinished(done);
6667
} else {
67-
Target *target = ctx->target();
68+
Target *target = ctx->thread()->target();
6869
void *handle = m_mainFunction(context, target, target->variableData(), target->listData());
6970

7071
if (!handle)
@@ -95,9 +96,9 @@ bool LLVMExecutableCode::isFinished(ExecutionContext *context) const
9596
return getContext(context)->finished();
9697
}
9798

98-
std::shared_ptr<ExecutionContext> LLVMExecutableCode::createExecutionContext(Target *target) const
99+
std::shared_ptr<ExecutionContext> LLVMExecutableCode::createExecutionContext(Thread *thread) const
99100
{
100-
return std::make_shared<LLVMExecutionContext>(target);
101+
return std::make_shared<LLVMExecutionContext>(thread);
101102
}
102103

103104
uint64_t LLVMExecutableCode::lookupFunction(const std::string &name)

src/dev/engine/internal/llvm/llvmexecutablecode.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class LLVMExecutableCode : public ExecutableCode
2525

2626
bool isFinished(ExecutionContext *context) const override;
2727

28-
std::shared_ptr<ExecutionContext> createExecutionContext(Target *target) const override;
28+
std::shared_ptr<ExecutionContext> createExecutionContext(Thread *thread) const override;
2929

3030
private:
3131
uint64_t lookupFunction(const std::string &name);

0 commit comments

Comments
 (0)