11// SPDX-License-Identifier: Apache-2.0
22
33#include " controlblocks.h"
4+ #include " ../engine/compiler.h"
45
56namespace libscratchcpp
67{
@@ -10,12 +11,17 @@ std::map<std::pair<RunningScript *, Block *>, std::pair<int, int>> ControlBlocks
1011ControlBlocks::ControlBlocks ()
1112{
1213 // Blocks
14+ addCompileFunction (" control_forever" , &ControlBlocks::compileRepeatForever);
15+ addCompileFunction (" control_repeat" , &ControlBlocks::compileRepeat);
16+ addCompileFunction (" control_repeat_until" , &ControlBlocks::compileRepeatUntil);
17+ addCompileFunction (" control_if" , &ControlBlocks::compileIfStatement);
18+ addCompileFunction (" control_if_else" , &ControlBlocks::compileIfElseStatement);
19+ addCompileFunction (" control_stop" , &ControlBlocks::compileStop);
1320 addBlock (" control_forever" , &ControlBlocks::repeatForever);
1421 addBlock (" control_repeat" , &ControlBlocks::repeat);
1522 addBlock (" control_repeat_until" , &ControlBlocks::repeatUntil);
1623 addBlock (" control_if" , &ControlBlocks::ifStatement);
1724 addBlock (" control_if_else" , &ControlBlocks::ifElseStatement);
18- addBlock (" control_stop" , &ControlBlocks::stop);
1925
2026 // Inputs
2127 addInput (" SUBSTACK" , SUBSTACK);
@@ -37,6 +43,104 @@ std::string ControlBlocks::name() const
3743 return " Control" ;
3844}
3945
46+ void ControlBlocks::compileRepeatForever (Compiler *compiler)
47+ {
48+ compiler->addInstruction (vm::OP_FOREVER_LOOP);
49+ compiler->moveToSubstack (compiler->inputBlock (SUBSTACK), Compiler::SubstackType::Loop);
50+ }
51+
52+ void ControlBlocks::compileRepeat (Compiler *compiler)
53+ {
54+ auto substack = compiler->inputBlock (SUBSTACK);
55+ if (substack) {
56+ compiler->addInput (TIMES);
57+ compiler->addInstruction (vm::OP_REPEAT_LOOP);
58+ compiler->moveToSubstack (substack, Compiler::SubstackType::Loop);
59+ }
60+ }
61+
62+ void ControlBlocks::compileRepeatUntil (Compiler *compiler)
63+ {
64+ auto substack = compiler->inputBlock (SUBSTACK);
65+ if (substack) {
66+ compiler->addInstruction (vm::OP_UNTIL_LOOP);
67+ compiler->addInput (CONDITION);
68+ compiler->addInstruction (vm::OP_BEGIN_UNTIL_LOOP);
69+ compiler->moveToSubstack (substack, Compiler::SubstackType::Loop);
70+ }
71+ }
72+
73+ void ControlBlocks::compileRepeatWhile (Compiler *compiler)
74+ {
75+ auto substack = compiler->inputBlock (SUBSTACK);
76+ if (substack) {
77+ compiler->addInstruction (vm::OP_UNTIL_LOOP);
78+ compiler->addInput (CONDITION);
79+ compiler->addInstruction (vm::OP_NOT);
80+ compiler->addInstruction (vm::OP_BEGIN_UNTIL_LOOP);
81+ compiler->moveToSubstack (substack, Compiler::SubstackType::Loop);
82+ }
83+ }
84+
85+ void ControlBlocks::compileIfStatement (Compiler *compiler)
86+ {
87+ auto substack = compiler->inputBlock (SUBSTACK);
88+ if (substack) {
89+ compiler->addInput (CONDITION);
90+ compiler->addInstruction (vm::OP_IF);
91+ compiler->moveToSubstack (substack, Compiler::SubstackType::IfStatement);
92+ }
93+ }
94+
95+ void ControlBlocks::compileIfElseStatement (Compiler *compiler)
96+ {
97+ auto substack1 = compiler->inputBlock (SUBSTACK);
98+ auto substack2 = compiler->inputBlock (SUBSTACK2);
99+ if (substack1 || substack2)
100+ compiler->addInput (CONDITION);
101+ if (substack1 && substack2) {
102+ compiler->addInstruction (vm::OP_IF);
103+ compiler->moveToSubstack (substack1, substack2, Compiler::SubstackType::IfStatement);
104+ } else if (substack1) {
105+ compiler->addInstruction (vm::OP_IF);
106+ compiler->moveToSubstack (substack1, Compiler::SubstackType::IfStatement);
107+ } else if (substack2) {
108+ compiler->addInstruction (vm::OP_NOT);
109+ compiler->addInstruction (vm::OP_IF);
110+ compiler->moveToSubstack (substack2, Compiler::SubstackType::IfStatement);
111+ }
112+ }
113+
114+ void ControlBlocks::compileStop (Compiler *compiler)
115+ {
116+ int option = compiler->field (STOP_OPTION)->specialValueId ();
117+ switch (option) {
118+ case StopAll:
119+ compiler->addFunctionCall (&stopAll);
120+ break ;
121+
122+ case StopThisScript:
123+ compiler->addInstruction (vm::OP_HALT);
124+ break ;
125+
126+ case StopOtherScriptsInSprite:
127+ compiler->addFunctionCall (&stopOtherScriptsInSprite);
128+ break ;
129+ }
130+ }
131+
132+ unsigned int ControlBlocks::stopAll (VirtualMachine *vm)
133+ {
134+ vm->engine ()->stop ();
135+ return 0 ;
136+ }
137+
138+ unsigned int ControlBlocks::stopOtherScriptsInSprite (VirtualMachine *vm)
139+ {
140+ vm->engine ()->stopTarget (vm->target (), vm);
141+ return 0 ;
142+ }
143+
40144Value ControlBlocks::repeatForever (const BlockArgs &args)
41145{
42146 auto script = args.script ();
@@ -138,16 +242,4 @@ Value ControlBlocks::ifElseStatement(const BlockArgs &args)
138242 }
139243}
140244
141- Value ControlBlocks::stop (const BlockArgs &args)
142- {
143- int option = args.field (STOP_OPTION)->specialValueId ();
144- if (option == StopAll)
145- args.engine ()->stop ();
146- else if (option == StopThisScript)
147- args.engine ()->stopScript (args.script ());
148- else if (option == StopOtherScriptsInSprite)
149- args.engine ()->stopTarget (args.target (), args.script ());
150- return Value ();
151- }
152-
153245} // namespace libscratchcpp
0 commit comments