@@ -24,11 +24,21 @@ void Compiler::compile()
2424
2525 m_block = m_block->next ();
2626 while (m_block) {
27+ size_t substacks = m_substackTree.size ();
28+
2729 if (m_block->compileFunction ())
2830 m_block->compile (this );
2931 else
3032 std::cout << " warning: unsupported block: " << m_block->opcode () << std::endl;
31- m_block = m_block->next ();
33+
34+ if (substacks != m_substackTree.size ())
35+ continue ;
36+
37+ if (m_block)
38+ m_block = m_block->next ();
39+
40+ if (!m_block && !m_substackTree.empty ())
41+ substackEnd ();
3242 }
3343
3444 // Add end instruction (halt)
@@ -107,6 +117,10 @@ void Compiler::addInstruction(Opcode opcode, std::initializer_list<unsigned int>
107117void Compiler::addInput (int id)
108118{
109119 auto in = input (id);
120+ if (!in) {
121+ addInstruction (OP_NULL);
122+ return ;
123+ }
110124 switch (in->type ()) {
111125 case Input::Type::Shadow:
112126 addInstruction (OP_CONST, { constIndex (in->primaryValue ()) });
@@ -128,6 +142,21 @@ void Compiler::addFunctionCall(BlockFunc f)
128142 addInstruction (OP_EXEC, { m_engine->functionIndex (f) });
129143}
130144
145+ /* ! Jumps to the given substack. The second substack is used for example for the if/else block. */
146+ void Compiler::moveToSubstack (std::shared_ptr<Block> substack1, std::shared_ptr<Block> substack2, SubstackType type)
147+ {
148+ m_substackTree.push_back ({ { m_block, substack2 }, type });
149+ m_block = substack1;
150+ if (!m_block)
151+ substackEnd ();
152+ }
153+
154+ /* ! Jumps to the given substack. */
155+ void Compiler::moveToSubstack (std::shared_ptr<Block> substack, SubstackType type)
156+ {
157+ moveToSubstack (substack, nullptr , type);
158+ }
159+
131160/* ! Returns the input with the given ID. */
132161Input *Compiler::input (int id) const
133162{
@@ -140,6 +169,13 @@ Field *Compiler::field(int id) const
140169 return m_block->findFieldById (id);
141170}
142171
172+ /* ! Returns the block in the given input. Same as input(id)->valueBlock(), but with a null pointer check. */
173+ std::shared_ptr<Block> Compiler::inputBlock (int id) const
174+ {
175+ auto in = input (id);
176+ return in ? in->valueBlock () : nullptr ;
177+ }
178+
143179/* ! Returns the index of the given variable. */
144180unsigned int Compiler::variableIndex (std::shared_ptr<IEntity> varEntity)
145181{
@@ -170,3 +206,26 @@ unsigned int Compiler::constIndex(InputValue *value)
170206 m_constValues.push_back (value);
171207 return m_constValues.size () - 1 ;
172208}
209+
210+ void Compiler::substackEnd ()
211+ {
212+ auto parent = m_substackTree.back ();
213+ switch (parent.second ) {
214+ case SubstackType::Loop:
215+ addInstruction (OP_LOOP_END);
216+ break ;
217+ case SubstackType::IfStatement:
218+ if (parent.first .second ) {
219+ addInstruction (OP_ELSE);
220+ m_block = parent.first .second ;
221+ m_substackTree[m_substackTree.size () - 1 ].first .second = nullptr ;
222+ return ;
223+ } else
224+ addInstruction (OP_ENDIF);
225+ break ;
226+ }
227+ m_block = parent.first .first ->next ();
228+ m_substackTree.pop_back ();
229+ if (!m_block && !m_substackTree.empty ())
230+ substackEnd ();
231+ }
0 commit comments