File indexing completed on 2024-04-14 03:43:53

0001 /*
0002     SPDX-FileCopyrightText: 2003-2006 Cies Breijs <cies AT kde DOT nl>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 
0008 // This file is originally written by Walter Scheppers, but almost
0009 // every aspect of it is slightly changed by Cies Breijs.
0010 
0011 #include "executer.h"
0012 
0013 #include <errno.h>
0014 #include <math.h>
0015 
0016 #include <QRandomGenerator>
0017 #include <QTimer>  // for wait
0018 #include <QDebug>
0019 
0020 #include <KLocalizedString>
0021 #include <QtMath>
0022 
0023 
0024 void Executer::initialize(TreeNode* tree, ErrorList* _errorList)
0025 {
0026     rootNode       = tree;
0027     newScope       = rootNode;
0028     currentNode    = rootNode;
0029     finished       = !currentNode->hasChildren();  // set finished to false unless the tree is empty
0030     errorList      = _errorList;
0031 
0032     breaking       = false;
0033     returning      = false;
0034     waiting        = false;
0035     returnValue    = nullptr;
0036     
0037     executeCurrent = false;
0038 
0039     functionTable.clear();
0040     globalVariableTable.clear();
0041 
0042     while (!functionStack.isEmpty()) {
0043         // In the ForTo loop, we can assign the globalVariableTable to an entry in the functionStack
0044         // we shouldn't delete this variableTable, so check for it.
0045         VariableTable* variableTable = functionStack.pop().variableTable;
0046         if(variableTable!=&globalVariableTable)
0047         delete variableTable;
0048     }
0049 }
0050 
0051 
0052 void Executer::execute()
0053 {
0054     //Do we have to do anything?
0055     if (finished || waiting) return;
0056 
0057     if(executeCurrent) {
0058         // executeCurrent is used to make sure the currentNode will be executed
0059         // this way the tree will not be walked before the execution...
0060         executeCurrent = false;
0061         execute(currentNode);
0062         return;
0063     }
0064 
0065     if(returning) {
0066         //We are returning from a function call
0067 
0068         // Handle returning in the top-level (not inside a function) as
0069         // gracefully as possible.
0070         // See: https://bugs.kde.org/show_bug.cgi?id=300949
0071         if (functionStack.isEmpty()) {
0072             addError(i18n("Cannot return outside a function. "), *(currentNode->token()), 0);
0073             finished = true;
0074             return;
0075         }
0076 
0077         // Take the last called function from the function stack
0078         CalledFunction calledFunction = functionStack.pop();
0079         
0080         // Delete the local variables of the called function
0081         delete calledFunction.variableTable;
0082         currentNode = calledFunction.function;
0083 
0084         if (returnValue == nullptr)
0085             currentNode->setNullValue(); // Handle an empty return value
0086         else
0087             currentNode->setValue(returnValue);
0088 
0089         execute(currentNode);
0090         return;
0091     }
0092 
0093     if (newScope == nullptr) {
0094         TreeNode* currentParent = currentNode->parent();
0095         currentNode = currentNode->nextSibling();
0096         
0097         if(currentNode == nullptr) { //running off sibling list
0098             currentNode = currentParent;
0099             
0100             if(currentNode == rootNode) {
0101                 finished = true;
0102                 return;
0103             }
0104 
0105 //          printExe();  // debugging thing
0106 
0107             execute(currentNode);
0108             return;
0109         }
0110 
0111     }else{
0112         // We're entering a new scope
0113         // skip ahead to frist child (if any) else we will not get into the scope
0114         if(newScope->hasChildren())
0115             currentNode = newScope->firstChild();
0116         else
0117             currentNode = newScope;
0118 
0119         newScope = nullptr;
0120     }
0121 
0122 
0123     while (currentNode->hasChildren() && currentNode->token()->type() != Token::Scope)
0124         currentNode = currentNode->firstChild();
0125     
0126 //  printExe();  // debugging thing
0127 
0128     execute(currentNode);
0129 }
0130 
0131 
0132 void Executer::execute(TreeNode* node)
0133 {
0134     if (finished) return;
0135 
0136     // Q_EMIT a signal for GUI
0137     Token* t = node->token();
0138 //  //qDebug() << "emitting token: '" << t->look() << "' - (" << t->startRow() << "," << t->startCol() << " - " << t->endRow() << "," << t->endCol() << ")";
0139 
0140     // don't report scopes (their are not really executed)
0141     if (t->type() != Token::Scope)
0142         Q_EMIT currentlyExecuting(node);
0143 
0144     // this method executes one node at the time
0145 
0146     // if (currentNode->token()->type() != Token::Scope) //qDebug() << "1234567890!!!!!";
0147 
0148     switch (node->token()->type()) {
0149 
0150 //BEGIN GENERATED executer_switch_cpp CODE
0151 
0152 /* The code between the line that start with "//BEGIN GENERATED" and "//END GENERATED"
0153  * is generated by "generate.rb" according to the definitions specified in
0154  * "definitions.rb". Please make all changes in the "definitions.rb" file, since all
0155  * all change you make here will be overwritten the next time "generate.rb" is run.
0156  * Thanks for looking at the code!
0157  */
0158 
0159         case Token::Root                : executeRoot(node);                break;
0160         case Token::Scope               : executeScope(node);               break;
0161         case Token::Variable            : executeVariable(node);            break;
0162         case Token::FunctionCall        : executeFunctionCall(node);        break;
0163         case Token::String              : /* a constant; do nothing */      break;
0164         case Token::Number              : /* a constant; do nothing */      break;
0165         case Token::True                : /* a constant; do nothing */      break;
0166         case Token::False               : /* a constant; do nothing */      break;
0167         case Token::Exit                : executeExit(node);                break;
0168         case Token::If                  : executeIf(node);                  break;
0169         case Token::Else                : executeElse(node);                break;
0170         case Token::Repeat              : executeRepeat(node);              break;
0171         case Token::While               : executeWhile(node);               break;
0172         case Token::For                 : executeFor(node);                 break;
0173         case Token::ForTo               : executeForTo(node);               break;
0174         case Token::Break               : executeBreak(node);               break;
0175         case Token::Return              : executeReturn(node);              break;
0176         case Token::Wait                : executeWait(node);                break;
0177         case Token::Assert              : executeAssert(node);              break;
0178         case Token::And                 : executeAnd(node);                 break;
0179         case Token::Or                  : executeOr(node);                  break;
0180         case Token::Not                 : executeNot(node);                 break;
0181         case Token::Equals              : executeEquals(node);              break;
0182         case Token::NotEquals           : executeNotEquals(node);           break;
0183         case Token::GreaterThan         : executeGreaterThan(node);         break;
0184         case Token::LessThan            : executeLessThan(node);            break;
0185         case Token::GreaterOrEquals     : executeGreaterOrEquals(node);     break;
0186         case Token::LessOrEquals        : executeLessOrEquals(node);        break;
0187         case Token::Addition            : executeAddition(node);            break;
0188         case Token::Subtraction         : executeSubtraction(node);         break;
0189         case Token::Multiplication      : executeMultiplication(node);      break;
0190         case Token::Division            : executeDivision(node);            break;
0191         case Token::Power               : executePower(node);               break;
0192         case Token::Assign              : executeAssign(node);              break;
0193         case Token::Learn               : executeLearn(node);               break;
0194         case Token::ArgumentList        : executeArgumentList(node);        break;
0195         case Token::Reset               : executeReset(node);               break;
0196         case Token::Clear               : executeClear(node);               break;
0197         case Token::Center              : executeCenter(node);              break;
0198         case Token::Go                  : executeGo(node);                  break;
0199         case Token::GoX                 : executeGoX(node);                 break;
0200         case Token::GoY                 : executeGoY(node);                 break;
0201         case Token::Forward             : executeForward(node);             break;
0202         case Token::Backward            : executeBackward(node);            break;
0203         case Token::Direction           : executeDirection(node);           break;
0204         case Token::TurnLeft            : executeTurnLeft(node);            break;
0205         case Token::TurnRight           : executeTurnRight(node);           break;
0206         case Token::PenWidth            : executePenWidth(node);            break;
0207         case Token::PenUp               : executePenUp(node);               break;
0208         case Token::PenDown             : executePenDown(node);             break;
0209         case Token::PenColor            : executePenColor(node);            break;
0210         case Token::CanvasColor         : executeCanvasColor(node);         break;
0211         case Token::CanvasSize          : executeCanvasSize(node);          break;
0212         case Token::SpriteShow          : executeSpriteShow(node);          break;
0213         case Token::SpriteHide          : executeSpriteHide(node);          break;
0214         case Token::Print               : executePrint(node);               break;
0215         case Token::FontSize            : executeFontSize(node);            break;
0216         case Token::Random              : executeRandom(node);              break;
0217         case Token::GetX                : executeGetX(node);                break;
0218         case Token::GetY                : executeGetY(node);                break;
0219         case Token::Message             : executeMessage(node);             break;
0220         case Token::Ask                 : executeAsk(node);                 break;
0221         case Token::Pi                  : executePi(node);                  break;
0222         case Token::Tan                 : executeTan(node);                 break;
0223         case Token::Sin                 : executeSin(node);                 break;
0224         case Token::Cos                 : executeCos(node);                 break;
0225         case Token::ArcTan              : executeArcTan(node);              break;
0226         case Token::ArcSin              : executeArcSin(node);              break;
0227         case Token::ArcCos              : executeArcCos(node);              break;
0228         case Token::Sqrt                : executeSqrt(node);                break;
0229         case Token::Round               : executeRound(node);               break;
0230         case Token::GetDirection        : executeGetDirection(node);        break;
0231         case Token::Mod                 : executeMod(node);                 break;
0232 
0233 //END GENERATED executer_switch_cpp CODE
0234 
0235         default:
0236             //qDebug() << "Unrecognized Token type (" << node->token()->type() << ", " << node->token()->look() << ") -- THIS SHOULDN'T HAPPEN!";
0237             break;
0238 
0239     }
0240 
0241 }
0242 
0243 
0244 VariableTable* Executer::currentVariableTable()
0245 {
0246     if (functionStack.isEmpty())
0247         return &globalVariableTable;
0248     else
0249         return functionStack.top().variableTable;
0250 }
0251 
0252 
0253 
0254 
0255 bool Executer::checkParameterQuantity(TreeNode* node, uint quantity, int errorCode)
0256 {
0257 //  //qDebug() << "called";
0258     uint nodeSize = node->childCount();
0259 
0260     if (quantity == 0) {
0261         if (nodeSize == 0) return true;  // thats easy!
0262         addError(i18n("The %1 command accepts no parameters.", node->token()->look()), *node->token(), errorCode);
0263         return false;
0264     }
0265     
0266 //  // CHECK THIS OUT LATER
0267 //  if (nodeSize != 0) // when all parameters are forgotten the parser puts a Unknown/tokEOL param, catch this:
0268 //      if (node->firstChild()->getToken().type == tokEOL) nodeSize = 0;
0269     
0270     if (nodeSize != quantity) {
0271         if (nodeSize < quantity) {
0272             addError(i18np("The %2 command was called with %3 but needs 1 parameter.", "The %2 command was called with %3 but needs %1 parameters.", quantity, node->token()->look(), nodeSize), *node->token(), errorCode);
0273         } else {
0274             addError(i18np("The %2 command was called with %3 but only accepts 1 parameter.", "The %2 command was called with %3 but only accepts %1 parameters.", quantity, node->token()->look(), nodeSize), *node->token(), errorCode);
0275         }
0276         return false;
0277     }
0278     return true; // if all tests passed
0279 }
0280 
0281 
0282 bool Executer::checkParameterType(TreeNode* node, int valueType, int errorCode)
0283 {
0284 //  //qDebug() << "called";
0285     uint quantity = node->childCount();
0286     TreeNode* currentChild = node->firstChild();
0287     while (currentChild != nullptr) {
0288         if (currentChild->value()->type() != valueType) {
0289             switch (valueType) {
0290                 case Value::String:
0291                     if (quantity == 1)
0292                         addError(i18n("The %1 command only accepts a string as its parameter.", node->token()->look()), *node->token(), errorCode);
0293                     else
0294                         addError(i18n("The %1 command only accepts strings as its parameters.", node->token()->look()), *node->token(), errorCode);
0295                     break;
0296                 
0297                 case Value::Number:
0298                     if (quantity == 1)
0299                         addError(i18n("The %1 command only accepts a number as its parameter.", node->token()->look()), *node->token(), errorCode);
0300                     else
0301                         addError(i18n("The %1 command only accepts numbers as its parameters.", node->token()->look()), *node->token(), errorCode);
0302                     break;
0303                 
0304                 case Value::Bool:
0305                     if (quantity == 1)
0306                         addError(i18n("The %1 command only accepts an answer as its parameter.", node->token()->look()), *node->token(), errorCode);
0307                     else
0308                         addError(i18n("The %1 command only accepts answers as its parameters.", node->token()->look()), *node->token(), errorCode);
0309                     break;
0310             }
0311             
0312             return false;
0313         }
0314 
0315         currentChild = node->nextChild();
0316     }
0317     return true; // if all tests passed
0318 }
0319 
0320 
0321 void Executer::addError(const QString& s, const Token& t, int code)
0322 {
0323 //  //qDebug() << qPrintable(s) << " (runtime error)";
0324     errorList->addError(s, t, code);
0325 }
0326 
0327 
0328 
0329 //BEGIN GENERATED executer_cpp CODE
0330 
0331 /* The code between the line that start with "//BEGIN GENERATED" and "//END GENERATED"
0332  * is generated by "generate.rb" according to the definitions specified in
0333  * "definitions.rb". Please make all changes in the "definitions.rb" file, since all
0334  * all change you make here will be overwritten the next time "generate.rb" is run.
0335  * Thanks for looking at the code!
0336  */
0337 
0338 void Executer::executeRoot(TreeNode* node) {
0339 //  //qDebug() << "called";
0340     node = node; // stop the warnings // this is a stud
0341 }
0342 void Executer::executeScope(TreeNode* node) {
0343 //  //qDebug() << "called";
0344     // catch loops, they need to be managed...
0345     int parentTokenType = node->parent()->token()->type();
0346     if (parentTokenType == Token::If     ||
0347         parentTokenType == Token::Repeat ||
0348         parentTokenType == Token::While  ||
0349 //      parentTokenType == Token::ForIn  ||
0350         parentTokenType == Token::ForTo) {
0351         currentNode = node->parent();
0352         executeCurrent = true;
0353         return;
0354     }
0355     if(parentTokenType == Token::Learn) {
0356         //We have the end of a Learn, so we should return
0357         returning = true;
0358         returnValue = nullptr;
0359         return;
0360     }
0361     newScope = node;
0362 }
0363 void Executer::executeVariable(TreeNode* node) {
0364 //  //qDebug() << "called";
0365     bool aValueIsNeeded = true;
0366     // no need to look up when assigning (in a for loop statement)
0367     if ((node->parent()->token()->type() == Token::ForTo) && (node->parent()->child(0)==node))
0368         return;
0369     // we need to executeVariables in assignments for things like $x=$y to work
0370     if (node->parent()->token()->type() == Token::Assign) {
0371         // Test if we are in the LHS of the assignment
0372         if  (node == node->parent()->child(0)) {
0373             // In this case we do not need to be initialized, we will get a value in executeAssign
0374             aValueIsNeeded = false;
0375         }
0376     }
0377     if (!functionStack.isEmpty() && 
0378         functionStack.top().variableTable->contains(node->token()->look())) {
0379         // //qDebug() << "exists locally";
0380         node->setValue( (*functionStack.top().variableTable)[node->token()->look()] );
0381     } else if (globalVariableTable.contains(node->token()->look())) {
0382         // //qDebug() << "exists globally";
0383         node->setValue(globalVariableTable[node->token()->look()]);
0384     } else if (aValueIsNeeded)
0385     {
0386         addError(i18n("The variable '%1' was used without first being assigned to a value", node->token()->look()), *node->token(), 0);
0387     }
0388 }
0389 void Executer::executeFunctionCall(TreeNode* node) {
0390 //  //qDebug() << "called";
0391     if (node->parent()->token()->type() == Token::Learn) {  // in case we're defining a function
0392         currentNode = node->parent();
0393         executeCurrent = true;
0394         return;
0395     }
0396 
0397     if (returning) {  // if the function is already executed and returns now
0398         returnValue = nullptr;
0399         returning = false;
0400         // //qDebug() << "==> functionReturned!";
0401         return;
0402     }
0403 
0404     if (!functionTable.contains(node->token()->look())) {
0405         addError(i18n("An unknown function named '%1' was called", node->token()->look()), *node->token(), 0);
0406         return;
0407     }
0408     
0409     CalledFunction c;
0410     c.function      = node;
0411     c.variableTable = new VariableTable();
0412     functionStack.push(c);
0413     // //qDebug() << "==> functionCalled!";
0414     
0415     TreeNode* learnNode = functionTable[node->token()->look()];
0416 
0417     // if the parameter numbers are not equal...
0418     if (node->childCount() != learnNode->child(1)->childCount()) {
0419         addError(
0420             i18n("The function '%1' was called with %2, while it should be called with %3",
0421                 node->token()->look(),
0422                 i18ncp("The function '%1' was called with %2, while it should be called with %3", "1 parameter", "%1 parameters", node->childCount()),
0423                 i18ncp("The function '%1' was called with %2, while it should be called with %3", "1 parameter", "%1 parameters", learnNode->child(1)->childCount())
0424             ),
0425             *node->token(), 0);
0426         return;
0427     }
0428         
0429     for (uint i = 0; i < node->childCount(); i++) {
0430         functionStack.top().variableTable->insert(learnNode->child(1)->child(i)->token()->look(), node->child(i)->value());
0431         // //qDebug() << "inserted variable " << learnNode->child(1)->child(i)->token()->look() << " on function stack";
0432     }
0433     newScope = learnNode->child(2);
0434 }
0435 void Executer::executeExit(TreeNode* node) {
0436 //  //qDebug() << "called";
0437     node = node; // stop the warnings
0438     finished = true;
0439 }
0440 void Executer::executeIf(TreeNode* node) {
0441 //  //qDebug() << "called";
0442     QString id = QStringLiteral("__%1_%2").arg(node->token()->look()).arg(reinterpret_cast<quintptr>(node));
0443     if (currentVariableTable()->contains(id)) {
0444         currentVariableTable()->remove(id);
0445         return;
0446     }
0447     
0448     if (node->child(0)->value()->boolean()) {
0449         // store a empty Value just to know we executed once
0450         currentVariableTable()->insert(id, Value());
0451         newScope = node->child(1);
0452     } else {
0453         if (node->childCount() >= 3) {
0454             currentVariableTable()->insert(id, Value());
0455             newScope = node->child(2); // execute the else part
0456         }
0457     }
0458 }
0459 void Executer::executeElse(TreeNode* node) {
0460 //  //qDebug() << "called";
0461     execute(node->child(0));  // execute the scope, that's all...
0462 }
0463 void Executer::executeRepeat(TreeNode* node) {
0464 //  //qDebug() << "called";
0465     QString id = QStringLiteral("__%1_%2").arg(node->token()->look()).arg(reinterpret_cast<quintptr>(node));
0466 
0467     if(breaking) {
0468         breaking = false;
0469         currentVariableTable()->remove(id);
0470         return;
0471     }
0472 
0473     // the iteration state is stored on the variable table
0474     if (currentVariableTable()->contains(id)) {
0475         int currentCount = static_cast<int>(round((*currentVariableTable())[id].number()));
0476         if (currentCount > 0) {
0477             (*currentVariableTable())[id].setNumber(currentCount - 1);
0478         } else {
0479             currentVariableTable()->remove(id);
0480             return;
0481         }
0482     } else {
0483         if(static_cast<int>(round(node->child(0)->value()->number()))<=0) // handle 'repeat 0'
0484             return;
0485         
0486         currentVariableTable()->insert(id, Value(round(node->child(0)->value()->number()) - 1.0));
0487     }
0488     newScope = node->child(1);
0489 }
0490 void Executer::executeWhile(TreeNode* node) {
0491 //  //qDebug() << "called";
0492     // first time this gets called the expression is already executed
0493     // after one iteration the expression is not automatically re-executed.
0494     // so we do the following on every call to executeWhile:
0495     //     exec scope, exec expression, exec scope, exec expression, ...
0496 
0497     QString id = QStringLiteral("__%1_%2").arg(node->token()->look()).arg(reinterpret_cast<quintptr>(node));
0498 
0499     if (breaking) {
0500         // We hit a break command while executing the scope
0501         breaking = false; // Not breaking anymore
0502         currentVariableTable()->remove(id); // remove the value (cleanup)
0503         return; // Move to the next sibling
0504     }
0505 
0506     if (currentVariableTable()->contains(id)) {
0507         newScope = node; // re-execute the expression
0508         currentVariableTable()->remove(id);
0509         return;
0510     }
0511     currentVariableTable()->insert(id, Value()); // store a empty Value just to know we executed once
0512 
0513     if (node->child(0)->value()->boolean())
0514         newScope = node->child(1); // (re-)execute the scope
0515     else
0516         currentVariableTable()->remove(id); // clean-up, keep currenNode on currentNode so the next sibling we be run next
0517 }
0518 void Executer::executeFor(TreeNode* node) {
0519 //  //qDebug() << "called";
0520     qCritical("Executer::executeFor(): should have been translated to Token::ForTo by the parser");
0521     node = node; // stop the warnings
0522 }
0523 void Executer::executeForTo(TreeNode* node) {
0524 //  //qDebug() << "called";
0525     // first time this gets called the expressions are already executed
0526     // after one iteration the expression is not re-executed.
0527     // so we do: exec scope, exec expressions, exec scope, exec expressions, ...
0528 
0529     //TODO: We have the cleanup part twice (after breaking and after the last iteration
0530     // perhaps clean it up by putting it in one place?
0531 
0532     bool firstIteration = false;
0533     if (functionStack.isEmpty() || functionStack.top().function != node) {
0534         // if this for loop is called for the first time...
0535         CalledFunction c;
0536         c.function      = node;
0537         // TODO: Find a better solution then this for nested for loops
0538         //c.variableTable = new VariableTable();
0539         c.variableTable = currentVariableTable();
0540         functionStack.push(c);
0541 
0542         currentVariableTable()->insert(node->child(0)->token()->look(), Value(node->child(1)->value()->number()));
0543         firstIteration = true;
0544     }
0545 
0546     QString id = QStringLiteral("__%1_%2").arg(node->token()->look()).arg(reinterpret_cast<quintptr>(node));
0547 
0548     if(breaking) {
0549         breaking = false;
0550         //delete functionStack.top().variableTable;
0551         functionStack.pop();
0552         // if we don't delete the functionStack's varibleTable any more
0553         // do remove the for loops id..
0554         currentVariableTable()->remove(id);
0555         return;
0556     }
0557 
0558     if (currentVariableTable()->contains(id)) {
0559         newScope = node; // re-execute the expressions
0560         currentVariableTable()->remove(id);
0561         return;
0562     }
0563     currentVariableTable()->insert(id, Value()); // store a empty Value just to know we executed once
0564 
0565     double currentCount   = (*currentVariableTable())[node->child(0)->token()->look()].number();
0566     double startCondition = node->child(1)->value()->number();
0567     double endCondition   = node->child(2)->value()->number();
0568     double step           = node->child(3)->value()->number();
0569 
0570     if ((startCondition < endCondition && currentCount + step <= endCondition) ||
0571         (startCondition > endCondition && currentCount + step >= endCondition && step<0) ||  //negative loop sanity check, is it implemented?
0572         (startCondition ==endCondition && firstIteration) ) { // for expressions like for $n=1 to 1
0573         if (!firstIteration)
0574             (*currentVariableTable())[node->child(0)->token()->look()].setNumber(currentCount + step);
0575         newScope = node->child(4); // (re-)execute the scope
0576     } else {
0577         // cleaning up after last iteration...
0578         //delete functionStack.top().variableTable;
0579         functionStack.pop();
0580         // if we don't delete the functionStack's varibleTable any more
0581         // do remove the for loops id..
0582         currentVariableTable()->remove(id);
0583     }
0584 }
0585 void Executer::executeBreak(TreeNode* node) {
0586 //  //qDebug() << "called";
0587     if (!checkParameterQuantity(node, 0, 20000+Token::Break*100+90)) return;
0588 
0589     breaking = true;
0590 
0591     // Check for the first parent which is a repeat, while of for loop.
0592     // If found, switch the newScope to them so they can break.
0593     QList<int> tokenTypes;
0594     tokenTypes.append(Token::Repeat);
0595     tokenTypes.append(Token::While);
0596     tokenTypes.append(Token::ForTo);
0597 
0598     TreeNode* ns = getParentOfTokenTypes(node, &tokenTypes);
0599 
0600     if(ns!=nullptr)
0601         newScope = ns;
0602     //else
0603         // We could add an error right HERE
0604     
0605     // At the moment we just ignore a break when we couldn't 
0606     // find a matching parent
0607 }
0608 void Executer::executeReturn(TreeNode* node) {
0609 //  //qDebug() << "called";
0610     if(node->childCount()>0)
0611         returnValue = node->child(0)->value();
0612     else
0613         returnValue = nullptr;
0614     returning   = true;
0615 }
0616 void Executer::executeWait(TreeNode* node) {
0617 //  //qDebug() << "called";
0618     if (!checkParameterQuantity(node, 1, 20000+Token::Wait*100+90)) return;
0619     if (!checkParameterType(node, Value::Number, 20000+Token::Wait*100+91) ) return;
0620     waiting = true;
0621     QTimer::singleShot(static_cast<int>(1000*node->child(0)->value()->number()), this, &Executer::stopWaiting);
0622 }
0623 void Executer::executeAssert(TreeNode* node) {
0624 //  //qDebug() << "called";
0625     if (!checkParameterQuantity(node, 1, 20000+Token::Wait*100+90)) return;
0626     if (!checkParameterType(node, Value::Bool, 20000+Token::Wait*100+91) ) return;
0627     if (!node->child(0)->value()->boolean()) addError(i18n("ASSERT failed"), *node->token(), 0);
0628 }
0629 void Executer::executeAnd(TreeNode* node) {
0630 //  //qDebug() << "called";
0631     //Niels: See 'Not'
0632     if(node->childCount()!=2) {
0633         addError(i18n("'And' needs two variables"), *node->token(), 0);
0634         return;
0635     }
0636     node->value()->setBool(node->child(0)->value()->boolean() && node->child(1)->value()->boolean());
0637 }
0638 void Executer::executeOr(TreeNode* node) {
0639 //  //qDebug() << "called";
0640     //Niels: See 'Not'
0641     if(node->childCount()!=2) {
0642         addError(i18n("'Or' needs two variables"), *node->token(), 0);
0643         return;
0644     }
0645     node->value()->setBool(node->child(0)->value()->boolean() || node->child(1)->value()->boolean());
0646 }
0647 void Executer::executeNot(TreeNode* node) {
0648 //  //qDebug() << "called";
0649     // OLD-TODO: maybe add some error handling here...
0650     //Niels: Ok, now we check if the node has children. Should we also check whether the child value is a boolean?
0651     if(node->childCount()!=1) {
0652         addError(i18n("I need something to do a not on"), *node->token(), 0);
0653         return;
0654     }
0655     node->value()->setBool(!node->child(0)->value()->boolean());
0656 }
0657 void Executer::executeEquals(TreeNode* node) {
0658 //  //qDebug() << "called";
0659     if(node->childCount()!=2) { 
0660         addError(i18n("I cannot do a '==' without 2 variables"), *node->token(), 0);
0661         return;
0662     }
0663     node->value()->setBool(*node->child(0)->value() == node->child(1)->value());
0664 }
0665 void Executer::executeNotEquals(TreeNode* node) {
0666 //  //qDebug() << "called";
0667     if(node->childCount()!=2) { 
0668         addError(i18n("I cannot do a '!=' without 2 variables"), *node->token(), 0);
0669         return;
0670     }
0671     node->value()->setBool(*node->child(0)->value() != node->child(1)->value());
0672 }
0673 void Executer::executeGreaterThan(TreeNode* node) {
0674 //  //qDebug() << "called";
0675     if(node->childCount()!=2) { 
0676         addError(i18n("I cannot do a '>' without 2 variables"), *node->token(), 0);
0677         return;
0678     }
0679     node->value()->setBool(*node->child(0)->value() > node->child(1)->value());
0680 }
0681 void Executer::executeLessThan(TreeNode* node) {
0682 //  //qDebug() << "called";
0683     if(node->childCount()!=2) { 
0684         addError(i18n("I cannot do a '<' without 2 variables"), *node->token(), 0);
0685         return;
0686     }
0687     node->value()->setBool(*node->child(0)->value() < node->child(1)->value());
0688 }
0689 void Executer::executeGreaterOrEquals(TreeNode* node) {
0690 //  //qDebug() << "called";
0691     if(node->childCount()!=2) { 
0692         addError(i18n("I cannot do a '>=' without 2 variables"), *node->token(), 0);
0693         return;
0694     }
0695     node->value()->setBool(*node->child(0)->value() >= node->child(1)->value());
0696 }
0697 void Executer::executeLessOrEquals(TreeNode* node) {
0698 //  //qDebug() << "called";
0699     if(node->childCount()!=2) { 
0700         addError(i18n("I cannot do a '<=' without 2 variables"), *node->token(), 0);
0701         return;
0702     }
0703     node->value()->setBool(*node->child(0)->value() <= node->child(1)->value());
0704 }
0705 void Executer::executeAddition(TreeNode* node) {
0706 //  //qDebug() << "called";
0707     if(node->childCount()!=2) {
0708         addError(i18n("You need two numbers or string to do an addition"), *node->token(), 0);
0709         return;
0710     }
0711     if (node->child(0)->value()->type() == Value::Number && node->child(1)->value()->type() == Value::Number) {
0712         node->value()->setNumber(node->child(0)->value()->number() + node->child(1)->value()->number());
0713     } else {
0714         node->value()->setString(node->child(0)->value()->string().append(node->child(1)->value()->string()));
0715     }
0716 }
0717 void Executer::executeSubtraction(TreeNode* node) {
0718 //  //qDebug() << "called";
0719     if(node->childCount()!=2) {
0720         addError(i18n("You need two numbers to subtract"), *node->token(), 0);
0721         return;
0722     }
0723     if (node->child(0)->value()->type() == Value::Number && node->child(1)->value()->type() == Value::Number) {
0724         node->value()->setNumber(node->child(0)->value()->number() - node->child(1)->value()->number());
0725     } else {
0726         if (node->child(0)->value()->type() != Value::Number)
0727             addError(i18n("You tried to subtract from a non-number, '%1'", node->child(0)->token()->look()), *node->token(), 0);
0728         if (node->child(1)->value()->type() != Value::Number)
0729             addError(i18n("You tried to subtract a non-number, '%1'", node->child(1)->token()->look()), *node->token(), 0);
0730     }
0731 }
0732 void Executer::executeMultiplication(TreeNode* node) {
0733 //  //qDebug() << "called";
0734     if(node->childCount()!=2) {
0735         addError(i18n("You need two numbers to multiplicate"), *node->token(), 0);
0736         return;
0737     }
0738     if (node->child(0)->value()->type() == Value::Number && node->child(1)->value()->type() == Value::Number) {
0739         node->value()->setNumber(node->child(0)->value()->number() * node->child(1)->value()->number());
0740     } else {
0741         if (node->child(0)->value()->type() != Value::Number)
0742             addError(i18n("You tried to multiplicate a non-number, '%1'", node->child(0)->token()->look()), *node->token(), 0);
0743         if (node->child(1)->value()->type() != Value::Number)
0744             addError(i18n("You tried to multiplicate by a non-number, '%1'", node->child(1)->token()->look()), *node->token(), 0);
0745     }
0746 }
0747 void Executer::executeDivision(TreeNode* node) {
0748 //  //qDebug() << "called";
0749     if(node->childCount()!=2) {
0750         addError(i18n("You need two numbers to divide"), *node->token(), 0);
0751         return;
0752     }
0753     if (node->child(0)->value()->type() == Value::Number && node->child(1)->value()->type() == Value::Number) {
0754         if(node->child(1)->value()->number()==0) {
0755             addError(i18n("You tried to divide by zero"), *node->token(), 0);
0756             return;
0757         }
0758         node->value()->setNumber(node->child(0)->value()->number() / node->child(1)->value()->number());
0759     } else {
0760         if (node->child(0)->value()->type() != Value::Number)
0761             addError(i18n("You tried to divide a non-number, '%1'", node->child(0)->token()->look()), *node->token(), 0);
0762         if (node->child(1)->value()->type() != Value::Number)
0763             addError(i18n("You tried to divide by a non-number, '%1'", node->child(1)->token()->look()), *node->token(), 0);
0764     }
0765 }
0766 void Executer::executePower(TreeNode* node) {
0767 //  //qDebug() << "called";
0768     if(node->childCount()!=2) {
0769         addError(i18n("You need two numbers to raise a power"), *node->token(), 0);
0770         return;
0771     }
0772     if (node->child(0)->value()->type() == Value::Number && node->child(1)->value()->type() == Value::Number) {
0773         node->value()->setNumber(pow(node->child(0)->value()->number(), node->child(1)->value()->number()));
0774         
0775         double result = pow(node->child(0)->value()->number(), node->child(1)->value()->number());
0776 
0777         int error = errno;
0778         if(error==ERANGE) {
0779             node->value()->setNumber(0);
0780             addError(i18n("The result of an exponentiation was too large"), *node->token(), 0);
0781         }else{
0782             node->value()->setNumber(result);
0783         }
0784     } else {
0785         if (node->child(0)->value()->type() != Value::Number)
0786             addError(i18n("You tried to raise a non-number to a power, '%1'", node->child(0)->token()->look()), *node->token(), 0);
0787         if (node->child(1)->value()->type() != Value::Number)
0788             addError(i18n("You tried to raise the power of a non-number, '%1'", node->child(1)->token()->look()), *node->token(), 0);
0789     }
0790 }
0791 void Executer::executeAssign(TreeNode* node) {
0792 //  //qDebug() << "called";
0793     if(node->childCount()!=2) {
0794     addError(i18n("You need one variable and a value or variable to do a '='"), *node->token(), 0);
0795         return;
0796     }
0797     if (!functionStack.isEmpty() && !globalVariableTable.contains(node->child(0)->token()->look())) // &&functionStack.top().variableTable->contains(node->token()->look())) 
0798     {
0799         // //qDebug() << "function scope";
0800         functionStack.top().variableTable->insert(node->child(0)->token()->look(), node->child(1)->value());
0801     } else {
0802         // inserts unless already exists then replaces
0803         globalVariableTable.insert(node->child(0)->token()->look(), node->child(1)->value());
0804     }
0805     // //qDebug() << "variableTable updated!";
0806     Q_EMIT variableTableUpdated(node->child(0)->token()->look(), node->child(1)->value());
0807 }
0808 void Executer::executeLearn(TreeNode* node) {
0809 //  //qDebug() << "called";
0810     if(functionTable.contains(node->child(0)->token()->look())) {
0811         addError(i18n("The function '%1' is already defined.", node->child(0)->token()->look()), *node->token(), 0);
0812         return;
0813     }
0814     functionTable.insert(node->child(0)->token()->look(), node);
0815     // //qDebug() << "functionTable updated!";
0816     QStringList parameters;
0817     for (uint i = 0; i < node->child(1)->childCount(); i++)
0818         parameters << node->child(1)->child(i)->token()->look();
0819     Q_EMIT functionTableUpdated(node->child(0)->token()->look(), parameters);
0820 }
0821 void Executer::executeArgumentList(TreeNode* node) {
0822 //  //qDebug() << "called";
0823     node = node; // stop the warnings // this is a stud
0824 }
0825 void Executer::executeReset(TreeNode* node) {
0826 //  //qDebug() << "called";
0827     if (!checkParameterQuantity(node, 0, 20000+Token::Reset*100+90)) return;
0828     Q_EMIT reset();
0829 }
0830 void Executer::executeClear(TreeNode* node) {
0831 //  //qDebug() << "called";
0832     if (!checkParameterQuantity(node, 0, 20000+Token::Clear*100+90)) return;
0833     Q_EMIT clear();
0834 }
0835 void Executer::executeCenter(TreeNode* node) {
0836 //  //qDebug() << "called";
0837     if (!checkParameterQuantity(node, 0, 20000+Token::Center*100+90)) return;
0838     Q_EMIT center();
0839 }
0840 void Executer::executeGo(TreeNode* node) {
0841 //  //qDebug() << "called";
0842     if (!checkParameterQuantity(node, 2, 20000+Token::Go*100+90) ||
0843         !checkParameterType(node, Value::Number, 20000+Token::Go*100+91)) return;
0844     Q_EMIT go(node->child(0)->value()->number(), node->child(1)->value()->number());
0845 }
0846 void Executer::executeGoX(TreeNode* node) {
0847 //  //qDebug() << "called";
0848     if (!checkParameterQuantity(node, 1, 20000+Token::GoX*100+90) ||
0849         !checkParameterType(node, Value::Number, 20000+Token::GoX*100+91)) return;
0850     Q_EMIT goX(node->child(0)->value()->number());
0851 }
0852 void Executer::executeGoY(TreeNode* node) {
0853 //  //qDebug() << "called";
0854     if (!checkParameterQuantity(node, 1, 20000+Token::GoY*100+90) ||
0855         !checkParameterType(node, Value::Number, 20000+Token::GoY*100+91)) return;
0856     Q_EMIT goY(node->child(0)->value()->number());
0857 }
0858 void Executer::executeForward(TreeNode* node) {
0859 //  //qDebug() << "called";
0860     if (!checkParameterQuantity(node, 1, 20000+Token::Forward*100+90) ||
0861         !checkParameterType(node, Value::Number, 20000+Token::Forward*100+91)) return;
0862     Q_EMIT forward(node->child(0)->value()->number());
0863 }
0864 void Executer::executeBackward(TreeNode* node) {
0865 //  //qDebug() << "called";
0866     if (!checkParameterQuantity(node, 1, 20000+Token::Backward*100+90) ||
0867         !checkParameterType(node, Value::Number, 20000+Token::Backward*100+91)) return;
0868     Q_EMIT backward(node->child(0)->value()->number());
0869 }
0870 void Executer::executeDirection(TreeNode* node) {
0871 //  //qDebug() << "called";
0872     if (!checkParameterQuantity(node, 1, 20000+Token::Direction*100+90) ||
0873         !checkParameterType(node, Value::Number, 20000+Token::Direction*100+91)) return;
0874     Q_EMIT direction(node->child(0)->value()->number());
0875 }
0876 void Executer::executeTurnLeft(TreeNode* node) {
0877 //  //qDebug() << "called";
0878     if (!checkParameterQuantity(node, 1, 20000+Token::TurnLeft*100+90) ||
0879         !checkParameterType(node, Value::Number, 20000+Token::TurnLeft*100+91)) return;
0880     Q_EMIT turnLeft(node->child(0)->value()->number());
0881 }
0882 void Executer::executeTurnRight(TreeNode* node) {
0883 //  //qDebug() << "called";
0884     if (!checkParameterQuantity(node, 1, 20000+Token::TurnRight*100+90) ||
0885         !checkParameterType(node, Value::Number, 20000+Token::TurnRight*100+91)) return;
0886     Q_EMIT turnRight(node->child(0)->value()->number());
0887 }
0888 void Executer::executePenWidth(TreeNode* node) {
0889 //  //qDebug() << "called";
0890     if (!checkParameterQuantity(node, 1, 20000+Token::PenWidth*100+90) ||
0891         !checkParameterType(node, Value::Number, 20000+Token::PenWidth*100+91)) return;
0892     Q_EMIT penWidth(node->child(0)->value()->number());
0893 }
0894 void Executer::executePenUp(TreeNode* node) {
0895 //  //qDebug() << "called";
0896     if (!checkParameterQuantity(node, 0, 20000+Token::PenUp*100+90)) return;
0897     Q_EMIT penUp();
0898 }
0899 void Executer::executePenDown(TreeNode* node) {
0900 //  //qDebug() << "called";
0901     if (!checkParameterQuantity(node, 0, 20000+Token::PenDown*100+90)) return;
0902     Q_EMIT penDown();
0903 }
0904 void Executer::executePenColor(TreeNode* node) {
0905 //  //qDebug() << "called";
0906     if (!checkParameterQuantity(node, 3, 20000+Token::PenColor*100+90) ||
0907         !checkParameterType(node, Value::Number, 20000+Token::PenColor*100+91)) return;
0908     Q_EMIT penColor(node->child(0)->value()->number(), node->child(1)->value()->number(), node->child(2)->value()->number());
0909 }
0910 void Executer::executeCanvasColor(TreeNode* node) {
0911 //  //qDebug() << "called";
0912     if (!checkParameterQuantity(node, 3, 20000+Token::CanvasColor*100+90) ||
0913         !checkParameterType(node, Value::Number, 20000+Token::CanvasColor*100+91)) return;
0914     Q_EMIT canvasColor(node->child(0)->value()->number(), node->child(1)->value()->number(), node->child(2)->value()->number());
0915 }
0916 void Executer::executeCanvasSize(TreeNode* node) {
0917 //  //qDebug() << "called";
0918     if (!checkParameterQuantity(node, 2, 20000+Token::CanvasSize*100+90) ||
0919         !checkParameterType(node, Value::Number, 20000+Token::CanvasSize*100+91)) return;
0920     Q_EMIT canvasSize(node->child(0)->value()->number(), node->child(1)->value()->number());
0921 }
0922 void Executer::executeSpriteShow(TreeNode* node) {
0923 //  //qDebug() << "called";
0924     if (!checkParameterQuantity(node, 0, 20000+Token::SpriteShow*100+90)) return;
0925     Q_EMIT spriteShow();
0926 }
0927 void Executer::executeSpriteHide(TreeNode* node) {
0928 //  //qDebug() << "called";
0929     if (!checkParameterQuantity(node, 0, 20000+Token::SpriteHide*100+90)) return;
0930     Q_EMIT spriteHide();
0931 }
0932 void Executer::executePrint(TreeNode* node) {
0933 //  //qDebug() << "called";
0934     if (!checkParameterQuantity(node, 1, 20000+Token::Print*100+90))
0935         return;
0936     // //qDebug() << "Printing: '" << node->child(0)->value()->string() << "'";
0937     Q_EMIT print(node->child(0)->value()->string());
0938 }
0939 void Executer::executeFontSize(TreeNode* node) {
0940 //  //qDebug() << "called";
0941     if (!checkParameterQuantity(node, 1, 20000+Token::FontSize*100+90) ||
0942         !checkParameterType(node, Value::Number, 20000+Token::FontSize*100+91)) return;
0943     Q_EMIT fontSize(node->child(0)->value()->number());
0944 }
0945 void Executer::executeRandom(TreeNode* node) {
0946 //  //qDebug() << "called";
0947     if (!checkParameterQuantity(node, 2, 20000+Token::Random*100+90)) return;
0948     TreeNode* nodeX = node->child(0);  // getting
0949     TreeNode* nodeY = node->child(1);
0950     
0951     if (!checkParameterType(node, Value::Number, 20000+Token::Random*100+91)) return;
0952     double x = nodeX->value()->number();
0953     double y = nodeY->value()->number();
0954     double r = QRandomGenerator::global()->bounded(1.0);
0955     node->value()->setNumber(r * (y - x) + x);
0956 }
0957 void Executer::executeGetX(TreeNode* node) {
0958 //  //qDebug() << "called";
0959     if (!checkParameterQuantity(node, 0, 20000+Token::GetX*100+90)) return;
0960     double value = 0;
0961     Q_EMIT getX(value);
0962     node->value()->setNumber(value);
0963 }
0964 void Executer::executeGetY(TreeNode* node) {
0965 //  //qDebug() << "called";
0966     if (!checkParameterQuantity(node, 0, 20000+Token::GetY*100+90)) return;
0967     double value = 0;
0968     Q_EMIT getY(value);
0969     node->value()->setNumber(value);
0970 }
0971 void Executer::executeMessage(TreeNode* node) {
0972 //  //qDebug() << "called";
0973     if (!checkParameterQuantity(node, 1, 20000+Token::Message*100+90)) return;
0974     Q_EMIT message(node->child(0)->value()->string());
0975 }
0976 void Executer::executeAsk(TreeNode* node) {
0977 //  //qDebug() << "called";
0978     if (!checkParameterQuantity(node, 1, 20000+Token::Ask*100+90)) return;
0979     QString value = node->child(0)->value()->string();
0980     Q_EMIT ask(value);
0981     
0982     bool convertOk;
0983     double d = value.toDouble(&convertOk);
0984     if(convertOk)
0985         node->value()->setNumber(d);
0986     else
0987         node->value()->setString(value);
0988 }
0989 void Executer::executePi(TreeNode* node) {
0990 //  //qDebug() << "called";
0991     node->value()->setNumber(M_PI);
0992 }
0993 void Executer::executeTan(TreeNode* node) {
0994 //  //qDebug() << "called";
0995     if (!checkParameterQuantity(node, 1, 20000+Token::Tan*100+90)) return;
0996     
0997     double deg = node->child(0)->value()->number();
0998     node->value()->setNumber(tan(qDegreesToRadians(deg)));
0999 }
1000 void Executer::executeSin(TreeNode* node) {
1001 //  //qDebug() << "called";
1002     if (!checkParameterQuantity(node, 1, 20000+Token::Sin*100+90)) return;
1003     
1004     double deg = node->child(0)->value()->number();
1005     node->value()->setNumber(sin(qDegreesToRadians(deg)));
1006 }
1007 void Executer::executeCos(TreeNode* node) {
1008 //  //qDebug() << "called";
1009     if (!checkParameterQuantity(node, 1, 20000+Token::Cos*100+90)) return;
1010     
1011     double deg = node->child(0)->value()->number();
1012     node->value()->setNumber(cos(qDegreesToRadians(deg)));
1013 }
1014 void Executer::executeArcTan(TreeNode* node) {
1015 //  //qDebug() << "called";
1016     if (!checkParameterQuantity(node, 1, 20000+Token::ArcTan*100+90)) return;
1017     
1018     double deg = node->child(0)->value()->number();
1019     node->value()->setNumber(qRadiansToDegrees(atan(deg)));
1020 }
1021 void Executer::executeArcSin(TreeNode* node) {
1022 //  //qDebug() << "called";
1023     if (!checkParameterQuantity(node, 1, 20000+Token::ArcSin*100+90)) return;
1024     
1025     double deg = node->child(0)->value()->number();
1026     node->value()->setNumber(qRadiansToDegrees(asin(deg)));
1027 }
1028 void Executer::executeArcCos(TreeNode* node) {
1029 //  //qDebug() << "called";
1030     if (!checkParameterQuantity(node, 1, 20000+Token::ArcCos*100+90)) return;
1031     
1032     double deg = node->child(0)->value()->number();
1033     node->value()->setNumber(qRadiansToDegrees(acos(deg)));
1034 }
1035 void Executer::executeSqrt(TreeNode* node) {
1036 //  //qDebug() << "called";
1037     if (!checkParameterQuantity(node, 1, 20000+Token::Sqrt*100+90)) return;
1038     
1039     double val = node->child(0)->value()->number();
1040     if(val<0) {
1041         addError(i18n("Can't do a sqrt of a negative number"), *node->child(0)->token(), 0);
1042         node->value()->setNumber(0);
1043         return;
1044     }
1045     node->value()->setNumber(sqrt(val));
1046 }
1047 void Executer::executeRound(TreeNode* node) {
1048 //  //qDebug() << "called";
1049     if (!checkParameterQuantity(node, 1, 20000+Token::Round*100+90)) return;
1050    
1051     double val = node->child(0)->value()->number();
1052     node->value()->setNumber(round(val));
1053 }
1054 void Executer::executeGetDirection(TreeNode* node) {
1055 //  //qDebug() << "called";
1056     if (!checkParameterQuantity(node, 0, 20000+Token::GetDirection*100+90)) return;
1057     double value = 0;
1058     Q_EMIT getDirection(value);
1059     node->value()->setNumber(value);
1060 }
1061 void Executer::executeMod(TreeNode* node) {
1062 //  //qDebug() << "called";
1063     if (!checkParameterQuantity(node, 2, 20000+Token::Mod*100+90)) return;
1064     TreeNode* nodeX = node->child(0);  // getting
1065     TreeNode* nodeY = node->child(1);
1066 
1067     if (!checkParameterType(node, Value::Number, 20000+Token::Mod*100+91)) return;
1068     double x = nodeX->value()->number();
1069     double y = nodeY->value()->number();
1070     double m = (static_cast<int>(round(x)) % static_cast<int>(round(y)));
1071     node->value()->setNumber(m);
1072 }
1073 
1074 //END GENERATED executer_cpp CODE
1075 
1076 TreeNode* Executer::getParentOfTokenTypes(TreeNode* child, QList<int>* types) {
1077     for (int type : *types) {
1078         if(child->parent()->token()->type()==type)
1079             return child->parent();
1080         else if(child->parent()->token()->type()==Token::Root)
1081             return nullptr;
1082     }
1083     return getParentOfTokenTypes(child->parent(), types);
1084 }
1085 
1086 void Executer::printExe() {
1087 //  if (currentNode->token()->type() != Token::Scope)
1088 //      //qDebug() << "EXE> " << qPrintable(currentNode->token()->look());
1089 }
1090 
1091 #include "moc_executer.cpp"