Skip to content

Commit d010bf7

Browse files
committed
Compiler: Add support for procedure arguments
1 parent 560ff9f commit d010bf7

File tree

2 files changed

+57
-9
lines changed

2 files changed

+57
-9
lines changed

src/engine/compiler.cpp

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ Compiler::Compiler(Engine *engine) :
1919
void Compiler::compile(std::shared_ptr<Block> topLevelBlock)
2020
{
2121
m_bytecode.clear();
22+
m_procedurePrototype = nullptr;
23+
2224
// Add start instruction
2325
addInstruction(OP_START);
2426

@@ -95,22 +97,21 @@ void Compiler::addInstruction(Opcode opcode, std::initializer_list<unsigned int>
9597
m_bytecode.push_back(arg);
9698
}
9799

98-
/*! Compiles the given input (resolved by ID) and adds it to the bytecode. */
99-
void Compiler::addInput(int id)
100+
/*! Compiles the given input and adds it to the bytecode. */
101+
void Compiler::addInput(Input *input)
100102
{
101-
auto in = input(id);
102-
if (!in) {
103+
if (!input) {
103104
addInstruction(OP_NULL);
104105
return;
105106
}
106-
switch (in->type()) {
107+
switch (input->type()) {
107108
case Input::Type::Shadow:
108-
addInstruction(OP_CONST, { constIndex(in->primaryValue()) });
109+
addInstruction(OP_CONST, { constIndex(input->primaryValue()) });
109110
break;
110111

111112
case Input::Type::NoShadow: {
112113
auto previousBlock = m_block;
113-
m_block = in->valueBlock();
114+
m_block = input->valueBlock();
114115
assert(m_block);
115116
if (m_block->compileFunction())
116117
m_block->compile(this);
@@ -124,7 +125,7 @@ void Compiler::addInput(int id)
124125

125126
case Input::Type::ObscuredShadow: {
126127
auto previousBlock = m_block;
127-
m_block = in->valueBlock();
128+
m_block = input->valueBlock();
128129
if (m_block) {
129130
if (m_block->compileFunction())
130131
m_block->compile(this);
@@ -133,19 +134,31 @@ void Compiler::addInput(int id)
133134
addInstruction(OP_NULL);
134135
}
135136
} else
136-
in->primaryValue()->compile(this);
137+
input->primaryValue()->compile(this);
137138
m_block = previousBlock;
138139
break;
139140
}
140141
}
141142
}
142143

144+
/*! Compiles the given input (resolved by ID) and adds it to the bytecode. */
145+
void Compiler::addInput(int id)
146+
{
147+
addInput(input(id));
148+
}
149+
143150
/*! Adds a function call to the bytecode (the OP_EXEC instruction). */
144151
void Compiler::addFunctionCall(BlockFunc f)
145152
{
146153
addInstruction(OP_EXEC, { m_engine->functionIndex(f) });
147154
}
148155

156+
/*! Adds an argument to a procedure (custom block). */
157+
void Compiler::addProcedureArg(std::string procCode, std::string argName)
158+
{
159+
m_procedureArgs[procCode].push_back(argName);
160+
}
161+
149162
/*! Jumps to the given substack. The second substack is used for example for the if/else block. */
150163
void Compiler::moveToSubstack(std::shared_ptr<Block> substack1, std::shared_ptr<Block> substack2, SubstackType type)
151164
{
@@ -221,6 +234,21 @@ unsigned int Compiler::procedureIndex(std::string proc)
221234
return m_procedures.size() - 1;
222235
}
223236

237+
/*! Returns the index of the argument of the given procedure (custom block). */
238+
long Compiler::procedureArgIndex(std::string procCode, std::string argName)
239+
{
240+
if (m_procedureArgs.count(procCode) == 0) {
241+
std::cout << "warning: could not find custom block '" << procCode << "'" << std::endl;
242+
return -1;
243+
}
244+
const std::vector<std::string> args = m_procedureArgs[procCode];
245+
auto it = std::find(args.begin(), args.end(), argName);
246+
if (it != args.end())
247+
return it - args.begin();
248+
std::cout << "warning: could not find argument '" << argName << "' in custom block '" << procCode << "'" << std::endl;
249+
return -1;
250+
}
251+
224252
void Compiler::substackEnd()
225253
{
226254
auto parent = m_substackTree.back();
@@ -244,6 +272,18 @@ void Compiler::substackEnd()
244272
substackEnd();
245273
}
246274

275+
/*! Returns the prototype of the current custom block. */
276+
BlockPrototype *Compiler::procedurePrototype() const
277+
{
278+
return m_procedurePrototype;
279+
}
280+
281+
/*! Sets the prototype of the current custom block. */
282+
void Compiler::setProcedurePrototype(BlockPrototype *prototype)
283+
{
284+
m_procedurePrototype = prototype;
285+
}
286+
247287
/*! Returns the list of custom block prototypes. */
248288
const std::vector<std::string> &Compiler::procedures() const
249289
{

src/engine/compiler.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ class LIBSCRATCHCPP_EXPORT Compiler
3434
const std::vector<List *> &lists() const;
3535

3636
void addInstruction(vm::Opcode opcode, std::initializer_list<unsigned int> args = {});
37+
void addInput(Input *input);
3738
void addInput(int id);
3839
void addFunctionCall(BlockFunc f);
40+
void addProcedureArg(std::string procCode, std::string argName);
3941
void moveToSubstack(std::shared_ptr<Block> substack1, std::shared_ptr<Block> substack2, SubstackType type);
4042
void moveToSubstack(std::shared_ptr<Block> substack, SubstackType type);
4143

@@ -46,11 +48,15 @@ class LIBSCRATCHCPP_EXPORT Compiler
4648
unsigned int listIndex(std::shared_ptr<IEntity> listEntity);
4749
unsigned int constIndex(InputValue *value);
4850
unsigned int procedureIndex(std::string proc);
51+
long procedureArgIndex(std::string procCode, std::string argName);
4952

5053
const std::vector<std::string> &procedures() const;
5154

5255
const std::shared_ptr<Block> &block() const;
5356

57+
BlockPrototype *procedurePrototype() const;
58+
void setProcedurePrototype(BlockPrototype *prototype);
59+
5460
private:
5561
void substackEnd();
5662

@@ -63,6 +69,8 @@ class LIBSCRATCHCPP_EXPORT Compiler
6369
std::vector<Variable *> m_variables;
6470
std::vector<List *> m_lists;
6571
std::vector<std::string> m_procedures;
72+
std::unordered_map<std::string, std::vector<std::string>> m_procedureArgs;
73+
BlockPrototype *m_procedurePrototype = nullptr;
6674
};
6775

6876
} // namespace libscratchcpp

0 commit comments

Comments
 (0)