Skip to content

Commit 51e5450

Browse files
committed
Compiler: Add Input method
1 parent f26e8cf commit 51e5450

File tree

3 files changed

+205
-0
lines changed

3 files changed

+205
-0
lines changed

include/scratchcpp/dev/compiler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class LIBSCRATCHCPP_EXPORT Compiler
4343
void moveToLoop(std::shared_ptr<Block> substack);
4444
void warp();
4545

46+
Input *input(const std::string &name) const;
4647
Field *field(const std::string &name) const;
4748

4849
const std::unordered_set<std::string> &unsupportedBlocks() const;

src/dev/engine/compiler.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ void Compiler::warp()
133133
impl->warp = true;
134134
}
135135

136+
/*! Convenience method which returns the field with the given name. */
137+
Input *Compiler::input(const std::string &name) const
138+
{
139+
return impl->block->inputAt(impl->block->findInput(name)).get();
140+
}
141+
136142
/*! Convenience method which returns the field with the given name. */
137143
Field *Compiler::field(const std::string &name) const
138144
{

test/dev/compiler/compiler_test.cpp

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,204 @@ TEST_F(CompilerTest, AddInput)
216216
compile(compiler, block);
217217
}
218218

219+
TEST_F(CompilerTest, MoveToIf)
220+
{
221+
Compiler compiler(&m_engine, &m_target);
222+
EXPECT_CALL(*m_builder, beginElseBranch).Times(0);
223+
224+
auto if1 = std::make_shared<Block>("", "if");
225+
if1->setCompileFunction([](Compiler *compiler) {
226+
EXPECT_CALL(*m_builder, beginIfStatement).Times(0);
227+
EXPECT_CALL(*m_builder, endIf).Times(0);
228+
compiler->moveToIf(nullptr);
229+
});
230+
231+
auto if2 = std::make_shared<Block>("", "if");
232+
if1->setNext(if2);
233+
if2->setParent(if1);
234+
if2->setCompileFunction([](Compiler *compiler) {
235+
EXPECT_CALL(*m_builder, beginIfStatement());
236+
EXPECT_CALL(*m_builder, addConstValue(Value()));
237+
EXPECT_CALL(*m_builder, endIf());
238+
compiler->moveToIf(compiler->input("SUBSTACK")->valueBlock());
239+
});
240+
241+
auto substack1 = std::make_shared<Block>("", "substack");
242+
substack1->setParent(if2);
243+
substack1->setCompileFunction([](Compiler *compiler) { compiler->addConstValue(Value()); });
244+
245+
auto input = std::make_shared<Input>("SUBSTACK", Input::Type::NoShadow);
246+
input->setValueBlock(substack1);
247+
if2->addInput(input);
248+
249+
compile(compiler, if1);
250+
}
251+
252+
TEST_F(CompilerTest, MoveToIfElse)
253+
{
254+
Compiler compiler(&m_engine, &m_target);
255+
256+
auto if1 = std::make_shared<Block>("", "if");
257+
if1->setCompileFunction([](Compiler *compiler) {
258+
EXPECT_CALL(*m_builder, beginIfStatement).Times(0);
259+
EXPECT_CALL(*m_builder, beginElseBranch).Times(0);
260+
EXPECT_CALL(*m_builder, endIf).Times(0);
261+
compiler->moveToIfElse(nullptr, nullptr);
262+
});
263+
264+
auto if2 = std::make_shared<Block>("", "if");
265+
if1->setNext(if2);
266+
if2->setParent(if1);
267+
if2->setCompileFunction([](Compiler *compiler) {
268+
EXPECT_CALL(*m_builder, beginIfStatement());
269+
EXPECT_CALL(*m_builder, addConstValue(Value(1)));
270+
EXPECT_CALL(*m_builder, beginElseBranch());
271+
EXPECT_CALL(*m_builder, addConstValue(Value(2)));
272+
EXPECT_CALL(*m_builder, endIf());
273+
compiler->moveToIfElse(compiler->input("SUBSTACK")->valueBlock(), compiler->input("SUBSTACK2")->valueBlock());
274+
});
275+
276+
auto substack1 = std::make_shared<Block>("", "substack");
277+
substack1->setParent(if2);
278+
substack1->setCompileFunction([](Compiler *compiler) { compiler->addConstValue(1); });
279+
280+
auto substack2 = std::make_shared<Block>("", "substack");
281+
substack2->setParent(if2);
282+
substack2->setCompileFunction([](Compiler *compiler) { compiler->addConstValue(2); });
283+
284+
auto input = std::make_shared<Input>("SUBSTACK", Input::Type::NoShadow);
285+
input->setValueBlock(substack1);
286+
if2->addInput(input);
287+
input = std::make_shared<Input>("SUBSTACK2", Input::Type::NoShadow);
288+
input->setValueBlock(substack2);
289+
if2->addInput(input);
290+
291+
// Nested
292+
auto if3 = std::make_shared<Block>("", "if");
293+
if2->setNext(if3);
294+
if3->setParent(if2);
295+
if3->setCompileFunction([](Compiler *compiler) {
296+
EXPECT_CALL(*m_builder, beginIfStatement()).Times(3);
297+
EXPECT_CALL(*m_builder, beginElseBranch()).Times(3);
298+
EXPECT_CALL(*m_builder, endIf()).Times(3);
299+
EXPECT_CALL(*m_builder, addConstValue(Value(1)));
300+
EXPECT_CALL(*m_builder, addConstValue(Value(2)));
301+
EXPECT_CALL(*m_builder, addConstValue(Value(3)));
302+
EXPECT_CALL(*m_builder, addConstValue(Value(4)));
303+
compiler->moveToIfElse(compiler->input("SUBSTACK")->valueBlock(), compiler->input("SUBSTACK2")->valueBlock());
304+
});
305+
306+
// if
307+
auto ifSubstack1 = std::make_shared<Block>("", "if");
308+
ifSubstack1->setParent(if3);
309+
ifSubstack1->setCompileFunction([](Compiler *compiler) { compiler->moveToIfElse(compiler->input("SUBSTACK")->valueBlock(), compiler->input("SUBSTACK2")->valueBlock()); });
310+
311+
substack1 = std::make_shared<Block>("", "substack");
312+
substack1->setParent(ifSubstack1);
313+
substack1->setCompileFunction([](Compiler *compiler) { compiler->addConstValue(1); });
314+
315+
substack2 = std::make_shared<Block>("", "substack");
316+
substack2->setParent(ifSubstack1);
317+
substack2->setCompileFunction([](Compiler *compiler) { compiler->addConstValue(2); });
318+
319+
input = std::make_shared<Input>("SUBSTACK", Input::Type::NoShadow);
320+
input->setValueBlock(substack1);
321+
ifSubstack1->addInput(input);
322+
input = std::make_shared<Input>("SUBSTACK2", Input::Type::NoShadow);
323+
input->setValueBlock(substack2);
324+
ifSubstack1->addInput(input);
325+
326+
// else
327+
auto ifSubstack2 = std::make_shared<Block>("", "if");
328+
ifSubstack2->setParent(if3);
329+
ifSubstack2->setCompileFunction([](Compiler *compiler) { compiler->moveToIfElse(compiler->input("SUBSTACK")->valueBlock(), compiler->input("SUBSTACK2")->valueBlock()); });
330+
331+
substack1 = std::make_shared<Block>("", "substack");
332+
substack1->setParent(ifSubstack2);
333+
substack1->setCompileFunction([](Compiler *compiler) { compiler->addConstValue(3); });
334+
335+
substack2 = std::make_shared<Block>("", "substack");
336+
substack2->setParent(ifSubstack2);
337+
substack2->setCompileFunction([](Compiler *compiler) { compiler->addConstValue(4); });
338+
339+
input = std::make_shared<Input>("SUBSTACK", Input::Type::NoShadow);
340+
input->setValueBlock(substack1);
341+
ifSubstack2->addInput(input);
342+
input = std::make_shared<Input>("SUBSTACK2", Input::Type::NoShadow);
343+
input->setValueBlock(substack2);
344+
ifSubstack2->addInput(input);
345+
346+
// End if
347+
input = std::make_shared<Input>("SUBSTACK", Input::Type::NoShadow);
348+
input->setValueBlock(ifSubstack1);
349+
if3->addInput(input);
350+
input = std::make_shared<Input>("SUBSTACK2", Input::Type::NoShadow);
351+
input->setValueBlock(ifSubstack2);
352+
if3->addInput(input);
353+
354+
// Empty 'then' branch
355+
auto if4 = std::make_shared<Block>("", "if");
356+
if3->setNext(if4);
357+
if4->setParent(if3);
358+
if4->setCompileFunction([](Compiler *compiler) {
359+
EXPECT_CALL(*m_builder, beginIfStatement());
360+
EXPECT_CALL(*m_builder, beginElseBranch());
361+
EXPECT_CALL(*m_builder, addConstValue(Value(2)));
362+
EXPECT_CALL(*m_builder, endIf());
363+
compiler->moveToIfElse(nullptr, compiler->input("SUBSTACK2")->valueBlock());
364+
});
365+
366+
substack2 = std::make_shared<Block>("", "substack");
367+
substack2->setParent(if4);
368+
substack2->setCompileFunction([](Compiler *compiler) { compiler->addConstValue(2); });
369+
370+
input = std::make_shared<Input>("SUBSTACK2", Input::Type::NoShadow);
371+
input->setValueBlock(substack2);
372+
if4->addInput(input);
373+
374+
// Empty 'else' branch
375+
auto if5 = std::make_shared<Block>("", "if");
376+
if4->setNext(if5);
377+
if5->setParent(if4);
378+
if5->setCompileFunction([](Compiler *compiler) {
379+
EXPECT_CALL(*m_builder, beginIfStatement());
380+
EXPECT_CALL(*m_builder, addConstValue(Value(1)));
381+
EXPECT_CALL(*m_builder, beginElseBranch()).Times(0);
382+
EXPECT_CALL(*m_builder, endIf());
383+
compiler->moveToIfElse(compiler->input("SUBSTACK")->valueBlock(), nullptr);
384+
});
385+
386+
substack1 = std::make_shared<Block>("", "substack");
387+
substack1->setParent(if5);
388+
substack1->setCompileFunction([](Compiler *compiler) { compiler->addConstValue(1); });
389+
390+
input = std::make_shared<Input>("SUBSTACK", Input::Type::NoShadow);
391+
input->setValueBlock(substack1);
392+
if5->addInput(input);
393+
394+
// Code after the if statement
395+
auto block = std::make_shared<Block>("", "");
396+
block->setParent(if5);
397+
if5->setNext(block);
398+
block->setCompileFunction([](Compiler *compiler) { compiler->addConstValue("after"); });
399+
400+
EXPECT_CALL(*m_builder, addConstValue(Value("after")));
401+
compile(compiler, if1);
402+
}
403+
404+
TEST_F(CompilerTest, Input)
405+
{
406+
Compiler compiler(&m_engine, &m_target);
407+
auto block = std::make_shared<Block>("a", "");
408+
block->addInput(std::make_shared<Input>("TEST", Input::Type::Shadow));
409+
block->setCompileFunction([](Compiler *compiler) {
410+
ASSERT_EQ(compiler->input("INVALID"), nullptr);
411+
ASSERT_EQ(compiler->input("TEST"), compiler->block()->inputAt(0).get());
412+
});
413+
414+
compile(compiler, block);
415+
}
416+
219417
TEST_F(CompilerTest, Field)
220418
{
221419
Compiler compiler(&m_engine, &m_target);

0 commit comments

Comments
 (0)