File indexing completed on 2024-11-10 03:30:45

0001 #  SPDX-FileCopyrightText: 2005-2009 Cies Breijs
0002 #
0003 #  SPDX-License-Identifier: GPL-2.0-only
0004 
0005 
0006 # In this file commands/instructions/keywords/symbols/etc can easily be added to kturtle.
0007 # Changes can also be made here, but be careful cause the existing code may rely on stuff in here.
0008 # Thanks for looking at the code...
0009 
0010 
0011 # The following variables can be used:
0012 #
0013 # @type,    the internal name of the item
0014 # @look,    the en_US look for the item
0015 # @ali,     the alias (another en_US look)
0016 # @args,    the specification of the arguments (:none, :bool, :number, :string)
0017 #           if omitted no code for argument handling wil be generated (so you gotta DIY)
0018 #               examples:
0019 #                       @args = [:number, :number, :number]
0020 #                       @args = [:none]
0021 #                       @args = [:number, :string]
0022 # @p_def,   method definition for the parser
0023 # @e_def,   method definition for the executer
0024 # @funct,   the functionality the item should be given
0025 # @cat,     the category the item belongs to
0026 # @help,    .docbook formatted text for in a help file
0027 
0028 
0029 # In the @funct variable, one or more categories of the item can be put.
0030 # These are the categories and their descriptions:
0031 #
0032 # statement           the item is a statement and thus will be parsed as such
0033 # constant            the item is a constant so does not need any execution
0034 # auto-Q_EMIT           the Q_EMIT statement will be autogenerated works for many commands
0035 # node                the item can exist in the node tree and
0036 
0037 
0038 new_item()
0039 @type  = "Root"
0040 @funct = "node"
0041 parse_item()
0042 
0043 new_item()
0044 @type  = "Scope"
0045 @cat   = "Scope"
0046 @funct = "node"
0047 @e_def =
0048 <<EOS
0049         // catch loops, they need to be managed...
0050         int parentTokenType = node->parent()->token()->type();
0051         if (parentTokenType == Token::If     ||
0052             parentTokenType == Token::Repeat ||
0053             parentTokenType == Token::While  ||
0054 //          parentTokenType == Token::ForIn  ||
0055             parentTokenType == Token::ForTo) {
0056                 currentNode = node->parent();
0057                 executeCurrent = true;
0058                 return;
0059         }
0060         if(parentTokenType == Token::Learn) {
0061                 //We have the end of a Learn, so we should return
0062                 returning = true;
0063                 returnValue = 0;
0064                 return;
0065         }
0066         newScope = node;
0067 EOS
0068 parse_item()
0069 
0070 new_item()
0071 @type  = "WhiteSpace"
0072 parse_item()
0073 
0074 new_item()
0075 @type  = "EndOfLine"
0076 parse_item()
0077 
0078 new_item()
0079 @type  = "EndOfInput"
0080 parse_item()
0081 
0082 new_item()
0083 @type  = "VariablePrefix"
0084 @look  = "$"
0085 @localize = false
0086 parse_item()
0087 
0088 new_item()
0089 @type  = "Variable"
0090 @cat   = "Variable"
0091 @funct = "statement, node"
0092 @p_def =
0093 <<EOS
0094         // This is called to the variable is the first token on a line.
0095         // There has to be an assignment token right after it...
0096         TreeNode* variableNode = new TreeNode(currentToken);
0097         nextToken();
0098         Token* remeberedToken = new Token(*currentToken);
0099         skipToken(Token::Assign, *variableNode->token());
0100         TreeNode* assignNode = new TreeNode(remeberedToken);
0101         assignNode->appendChild(variableNode);      // the LHV; the symbol
0102         assignNode->appendChild(parseExpression()); // the RHV; the expression
0103         return assignNode;
0104 EOS
0105 @e_def =
0106 <<EOS
0107         bool aValueIsNeeded = true;
0108         // no need to look up when assigning (in a for loop statement)
0109         if ((node->parent()->token()->type() == Token::ForTo) && (node->parent()->child(0)==node))
0110                 return;
0111         // we need to executeVariables in assignments for things like $x=$y to work
0112         if (node->parent()->token()->type() == Token::Assign) {
0113                 // Test if we are in the LHS of the assignment
0114                 if  (node == node->parent()->child(0)) {
0115                         // In this case we do not need to be initialized, we will get a value in executeAssign
0116                         aValueIsNeeded = false;
0117                 }
0118         }
0119         if (!functionStack.isEmpty() && 
0120             functionStack.top().variableTable->contains(node->token()->look())) {
0121                 // //qDebug() << "exists locally";
0122                 node->setValue( (*functionStack.top().variableTable)[node->token()->look()] );
0123         } else if (globalVariableTable.contains(node->token()->look())) {
0124                 // //qDebug() << "exists globally";
0125                 node->setValue(globalVariableTable[node->token()->look()]);
0126         } else if (aValueIsNeeded)
0127         {
0128                 addError(i18n("The variable '%1' was used without first being assigned to a value", node->token()->look()), *node->token(), 0);
0129         }
0130 EOS
0131 parse_item()
0132 
0133 new_item()
0134 @type  = "FunctionCall"
0135 @cat   = "FunctionCall"
0136 @funct = "statement, node"
0137 @p_def =
0138 <<EOS
0139         TreeNode* node = new TreeNode(currentToken);
0140         node->token()->setType(Token::FunctionCall);
0141         nextToken();
0142         appendArguments(node);
0143         return node;
0144 EOS
0145 @e_def =
0146 <<EOS
0147         if (node->parent()->token()->type() == Token::Learn) {  // in case we're defining a function
0148                 currentNode = node->parent();
0149                 executeCurrent = true;
0150                 return;
0151         }
0152 
0153         if (returning) {  // if the function is already executed and returns now
0154                 returnValue = 0;
0155                 returning = false;
0156                 // //qDebug() << "==> functionReturned!";
0157                 return;
0158         }
0159 
0160         if (!functionTable.contains(node->token()->look())) {
0161                 addError(i18n("An unknown function named '%1' was called", node->token()->look()), *node->token(), 0);
0162                 return;
0163         }
0164         
0165         CalledFunction c;
0166         c.function      = node;
0167         c.variableTable = new VariableTable();
0168         functionStack.push(c);
0169         // //qDebug() << "==> functionCalled!";
0170         
0171         TreeNode* learnNode = functionTable[node->token()->look()];
0172 
0173         // if the parameter numbers are not equal...
0174         if (node->childCount() != learnNode->child(1)->childCount()) {
0175                 addError(
0176                         i18n("The function '%1' was called with %2, while it should be called with %3",
0177                                 node->token()->look(),
0178                                 i18ncp("The function '%1' was called with %2, while it should be called with %3", "1 parameter", "%1 parameters", node->childCount()),
0179                                 i18ncp("The function '%1' was called with %2, while it should be called with %3", "1 parameter", "%1 parameters", learnNode->child(1)->childCount())
0180                         ),
0181                         *node->token(), 0);
0182                 return;
0183         }
0184                 
0185         for (uint i = 0; i < node->childCount(); i++) {
0186                 functionStack.top().variableTable->insert(learnNode->child(1)->child(i)->token()->look(), node->child(i)->value());
0187                 // //qDebug() << "inserted variable " << learnNode->child(1)->child(i)->token()->look() << " on function stack";
0188         }
0189         newScope = learnNode->child(2);
0190 EOS
0191 parse_item()
0192 
0193 new_item()
0194 @type  = "String"
0195 @cat   = "String"
0196 @funct = "node, constant"
0197 parse_item()
0198 
0199 new_item()
0200 @type  = "Number"
0201 @cat   = "Number"
0202 @funct = "node, constant"
0203 parse_item()
0204 
0205 
0206 
0207 new_item()
0208 @type  = "True"
0209 @cat   = "TrueFalse"
0210 @look  = "true"
0211 @funct = "node, constant"
0212 parse_item()
0213 
0214 new_item()
0215 @type  = "False"
0216 @cat   = "TrueFalse"
0217 @look  = "false"
0218 @funct = "node, constant"
0219 parse_item()
0220 
0221 
0222 
0223 new_item()
0224 @type  = "Comment"
0225 @cat   = "Comment"
0226 @look  = "#"
0227 @localize = false
0228 parse_item()
0229 
0230 
0231 
0232 new_item()
0233 # shouldnt thisone also be treated as a normal token
0234 # so the code for fetching the whole string has t be in here
0235 @type  = "StringDelimiter"
0236 @cat   = "String"
0237 @look  = "\""
0238 @localize = false
0239 parse_item()
0240 
0241 
0242 
0243 new_item()
0244 @type  = "ScopeOpen"
0245 @cat   = "Scope"
0246 @look  = "{"
0247 @localize = false
0248 @funct = "statement"
0249 @p_def =
0250 <<EOS
0251         TreeNode* scopeNode = new TreeNode(new Token(Token::Scope, "{...}", currentToken->startRow(), currentToken->startCol(), 0, 0));
0252         delete currentToken;
0253         nextToken();
0254         // cannot change the currentScope to this scope cauz we still have to work in the currentScope
0255         // so we set the newScope, which the currentScope will become after parsing the current statement
0256         newScope = scopeNode;
0257         return scopeNode;
0258 EOS
0259 parse_item()
0260 
0261 new_item()
0262 @type  = "ScopeClose"
0263 @cat   = "Scope"
0264 @look  = "}"
0265 @localize = false
0266 @funct = "statement"
0267 @p_def =
0268 <<EOS
0269         TreeNode* node = new TreeNode(currentToken);
0270         int endRow = currentToken->endRow();
0271         int endCol = currentToken->endCol();
0272         nextToken();
0273         while (currentToken->type() == Token::EndOfLine) {  // allow newlines before else
0274                 delete currentToken;
0275                 nextToken();
0276         }
0277         if (currentScope->parent() && 
0278                 currentScope->parent()->token()->type() == Token::If && 
0279                 currentToken->type() == Token::Else) {
0280                 currentScope->parent()->appendChild(parseElse());
0281         }
0282         if (currentScope != rootNode) {
0283                 // find the parent scope of this scope, and make it current
0284                 TreeNode* parentScope = currentScope;
0285                 do {
0286                         parentScope = parentScope->parent();
0287                 } while (parentScope != rootNode && parentScope->token()->type() != Token::Scope);
0288                 currentScope->token()->setEndRow(endRow);
0289                 currentScope->token()->setEndCol(endCol);
0290                 currentScope = parentScope;
0291         }
0292         return node;
0293 EOS
0294 parse_item()
0295 
0296 
0297 
0298 new_item()
0299 @type  = "ParenthesisOpen"
0300 @cat   = "Parenthesis"
0301 @look  = "("
0302 @localize = false
0303 parse_item()
0304 
0305 new_item()
0306 @type  = "ParenthesisClose"
0307 @cat   = "Parenthesis"
0308 @look  = ")"
0309 @localize = false
0310 parse_item()
0311 
0312 
0313 
0314 new_item()
0315 @type  = "ArgumentSeparator"
0316 @cat   = "ArgumentSeparator"
0317 @look  = ","
0318 parse_item()
0319 
0320 
0321 
0322 new_item()
0323 @type  = "DecimalSeparator"
0324 @look  = "."
0325 parse_item()
0326 
0327 
0328 
0329 new_item()
0330 @type  = "Exit"
0331 @cat   = "ControllerCommand"
0332 @look  = "exit"
0333 @funct = "statement, node"
0334 @args  = [:none]
0335 @e_def =
0336 <<EOS
0337         node = node; // stop the warnings
0338         finished = true;
0339 EOS
0340 parse_item()
0341 
0342 new_item()
0343 @type  = "If"
0344 @cat   = "ControllerCommand"
0345 @look  = "if"
0346 @funct = "statement, node"
0347 @p_def =
0348 <<EOS
0349         TreeNode* node = new TreeNode(currentToken);
0350         nextToken();
0351         node->appendChild(parseExpression());
0352         if (currentToken->type() == Token::ScopeOpen) {
0353                 node->appendChild(parseScopeOpen());  // if followed by a scope
0354         }
0355         return node;
0356 EOS
0357 @e_def =
0358 <<EOS
0359         QString id = QString("__%1_%2").arg(node->token()->look()).arg((quintptr)node);
0360         if (currentVariableTable()->contains(id)) {
0361                 currentVariableTable()->remove(id);
0362                 return;
0363         }
0364         
0365         if (node->child(0)->value()->boolean()) {
0366                 // store a empty Value just to know we executed once
0367                 currentVariableTable()->insert(id, Value());
0368                 newScope = node->child(1);
0369         } else {
0370                 if (node->childCount() >= 3) {
0371                         currentVariableTable()->insert(id, Value());
0372                         newScope = node->child(2); // execute the else part
0373                 }
0374         }
0375 EOS
0376 parse_item()
0377 
0378 new_item()
0379 @type  = "Else"
0380 @cat   = "ControllerCommand"
0381 @look  = "else"
0382 @funct = "node"
0383 @p_def =
0384 <<EOS
0385         nextToken();
0386         if (currentToken->type() == Token::ScopeOpen) {
0387                 return parseScopeOpen();  // if followed by a scope
0388         }
0389         return parseStatement();    // if followed by single statement
0390 EOS
0391 @e_def =
0392 <<EOS
0393         execute(node->child(0));  // execute the scope, that's all...
0394 EOS
0395 parse_item()
0396 
0397 
0398 p_def_repeat_while =
0399 <<EOS
0400         TreeNode* node = new TreeNode(currentToken);
0401         nextToken();
0402         node->appendChild(parseExpression());
0403         if (currentToken->type() == Token::ScopeOpen) {
0404                 node->appendChild(parseScopeOpen());  // if followed by a scope
0405         } else {
0406                 node->appendChild(parseStatement());  // if followed by single statement
0407         }
0408         return node;
0409 EOS
0410 
0411 new_item()
0412 @type  = "Repeat"
0413 @cat   = "ControllerCommand"
0414 @look  = "repeat"
0415 @funct = "statement, node"
0416 @p_def = p_def_repeat_while
0417 @e_def =
0418 <<EOS
0419         QString id = QString("__%1_%2").arg(node->token()->look()).arg((quintptr)node);
0420 
0421         if(breaking) {
0422                 breaking = false;
0423                 currentVariableTable()->remove(id);
0424                 return;
0425         }
0426 
0427         // the iteration state is stored on the variable table
0428         if (currentVariableTable()->contains(id)) {
0429                 int currentCount = ROUND2INT((*currentVariableTable())[id].number());
0430                 if (currentCount > 0) {
0431                         (*currentVariableTable())[id].setNumber(currentCount - 1);
0432                 } else {
0433                         currentVariableTable()->remove(id);
0434                         return;
0435                 }
0436         } else {
0437                 if(ROUND2INT(node->child(0)->value()->number())<=0) // handle 'repeat 0'
0438                         return;
0439                 
0440                 currentVariableTable()->insert(id, Value((double)(ROUND2INT(node->child(0)->value()->number()) - 1)));
0441         }
0442         newScope = node->child(1);
0443 EOS
0444 parse_item()
0445 
0446 new_item()
0447 @type  = "While"
0448 @cat   = "ControllerCommand"
0449 @look  = "while"
0450 @funct = "statement, node"
0451 @p_def = p_def_repeat_while
0452 @e_def =
0453 <<EOS
0454         // first time this gets called the expression is already executed
0455         // after one iteration the expression is not automatically re-executed.
0456         // so we do the following on every call to executeWhile:
0457         //     exec scope, exec expression, exec scope, exec expression, ...
0458 
0459         QString id = QString("__%1_%2").arg(node->token()->look()).arg((quintptr)node);
0460 
0461         if (breaking) {
0462                 // We hit a break command while executing the scope
0463                 breaking = false; // Not breaking anymore
0464                 currentVariableTable()->remove(id); // remove the value (cleanup)
0465                 return; // Move to the next sibling
0466         }
0467 
0468         if (currentVariableTable()->contains(id)) {
0469                 newScope = node; // re-execute the expression
0470                 currentVariableTable()->remove(id);
0471                 return;
0472         }
0473         currentVariableTable()->insert(id, Value()); // store a empty Value just to know we executed once
0474 
0475         if (node->child(0)->value()->boolean())
0476                 newScope = node->child(1); // (re-)execute the scope
0477         else
0478                 currentVariableTable()->remove(id); // clean-up, keep currenNode on currentNode so the next sibling we be run next
0479 EOS
0480 parse_item()
0481 
0482 new_item()
0483 @type  = "For"
0484 @cat   = "ControllerCommand"
0485 @look  = "for"
0486 @funct = "statement, node"
0487 @p_def =
0488 <<EOS
0489         TreeNode* node = new TreeNode(currentToken);
0490         nextToken();
0491         Token* firstToken = currentToken;
0492         nextToken();
0493         if (firstToken->type() == Token::Variable && currentToken->type() == Token::Assign) {
0494                 node->token()->setType(Token::ForTo);
0495                 node->appendChild(new TreeNode(firstToken));
0496                 nextToken();
0497                 node->appendChild(parseExpression());
0498                 skipToken(Token::To, *node->token());
0499                 node->appendChild(parseExpression());
0500                 if (currentToken->type() == Token::Step) {
0501                         nextToken();
0502                         node->appendChild(parseExpression());
0503                 } else {
0504                         TreeNode* step = new TreeNode(new Token(Token::Number, "1", 0,0,0,0));
0505                         step->setValue(Value(1.0));
0506                         node->appendChild(step);
0507                 }
0508 //      } else if (currentToken->type() == Token::In) {
0509 //              // @TODO something for a for-in loop
0510         } else {
0511                 addError(i18n("'for' was called wrongly"), *node->token(), 0);
0512                 finished = true;  // abort after this error
0513                 return node;
0514         }
0515 
0516         if (currentToken->type() == Token::ScopeOpen) {
0517                 node->appendChild(parseScopeOpen());  // if followed by a scope
0518         } else {
0519                 node->appendChild(parseStatement());  // if followed by single statement
0520         }
0521 
0522         return node;
0523 EOS
0524 @e_def =
0525 <<EOS
0526         qCritical("Executer::executeFor(): should have been translated to Token::ForTo by the parser");
0527         node = node; // stop the warnings
0528 EOS
0529 parse_item()
0530 
0531 new_item()
0532 @type  = "ForTo"
0533 @cat   = "ControllerCommand"
0534 @funct = "node"
0535 @e_def =
0536 <<EOS
0537         // first time this gets called the expressions are already executed
0538         // after one iteration the expression is not re-executed.
0539         // so we do: exec scope, exec expressions, exec scope, exec expressions, ...
0540 
0541         //TODO: We have the cleanup part twice (after breaking and after the last iteration
0542         // perhaps clean it up by putting it in one place?
0543 
0544         bool firstIteration = false;
0545         if (functionStack.isEmpty() || functionStack.top().function != node) {
0546                 // if this for loop is called for the first time...
0547                 CalledFunction c;
0548                 c.function      = node;
0549                 // TODO: Find a better solution then this for nested for loops
0550                 //c.variableTable = new VariableTable();
0551                 c.variableTable = currentVariableTable();
0552                 functionStack.push(c);
0553 
0554                 currentVariableTable()->insert(node->child(0)->token()->look(), Value(node->child(1)->value()->number()));
0555                 firstIteration = true;
0556         }
0557 
0558         QString id = QString("__%1_%2").arg(node->token()->look()).arg((quintptr)node);
0559 
0560         if(breaking) {
0561                 breaking = false;
0562                 //delete functionStack.top().variableTable;
0563                 functionStack.pop();
0564                 // if we don't delete the functionStack's varibleTable any more
0565                 // do remove the for loops id..
0566                 currentVariableTable()->remove(id);
0567                 return;
0568         }
0569 
0570         if (currentVariableTable()->contains(id)) {
0571                 newScope = node; // re-execute the expressions
0572                 currentVariableTable()->remove(id);
0573                 return;
0574         }
0575         currentVariableTable()->insert(id, Value()); // store a empty Value just to know we executed once
0576 
0577         double currentCount   = (*currentVariableTable())[node->child(0)->token()->look()].number();
0578         double startCondition = node->child(1)->value()->number();
0579         double endCondition   = node->child(2)->value()->number();
0580         double step           = node->child(3)->value()->number();
0581 
0582         if ((startCondition < endCondition && currentCount + step <= endCondition) ||
0583             (startCondition > endCondition && currentCount + step >= endCondition && step<0) ||  //negative loop sanity check, is it implemented?
0584             (startCondition ==endCondition && firstIteration) ) { // for expressions like for $n=1 to 1
0585                 if (!firstIteration)
0586                         (*currentVariableTable())[node->child(0)->token()->look()].setNumber(currentCount + step);
0587                 newScope = node->child(4); // (re-)execute the scope
0588         } else {
0589                 // cleaning up after last iteration...
0590                 //delete functionStack.top().variableTable;
0591                 functionStack.pop();
0592                 // if we don't delete the functionStack's varibleTable any more
0593                 // do remove the for loops id..
0594                 currentVariableTable()->remove(id);
0595         }
0596 EOS
0597 parse_item()
0598 
0599 new_item()
0600 @type  = "To"
0601 @cat   = "ControllerCommand"
0602 @look  = "to"
0603 parse_item()
0604 
0605 # # new_item()
0606 # # @type  = "ForIn"
0607 # # @funct = "node"
0608 # # parse_item()
0609 # #
0610 # # new_item()
0611 # # @type  = "In"
0612 # # @look  = "in"
0613 # # parse_item()
0614 
0615 new_item()
0616 @type  = "Step"
0617 @cat   = "ControllerCommand"
0618 @look  = "step"
0619 parse_item()
0620 
0621 new_item()
0622 @type  = "Break"
0623 @cat   = "ControllerCommand"
0624 @look  = "break"
0625 @funct = "statement, node"
0626 @args  = [:none]
0627 @e_def =
0628 <<EOS
0629         if (!checkParameterQuantity(node, 0, 20000+Token::Break*100+90)) return;
0630 
0631         breaking = true;
0632 
0633         // Check for the first parent which is a repeat, while of for loop.
0634         // If found, switch the newScope to them so they can break.
0635         QList<int> tokenTypes;
0636         tokenTypes.append(Token::Repeat);
0637         tokenTypes.append(Token::While);
0638         tokenTypes.append(Token::ForTo);
0639 
0640         TreeNode* ns = getParentOfTokenTypes(node, &tokenTypes);
0641 
0642         if(ns!=0)
0643                 newScope = ns;
0644         //else
0645                 // We could add an error right HERE
0646         
0647         // At the moment we just ignore a break when we couldn't 
0648         // find a matching parent
0649 EOS
0650 parse_item()
0651 
0652 new_item()
0653 @type  = "Return"
0654 @cat   = "ControllerCommand"
0655 @look  = "return"
0656 @funct = "statement, node"
0657 @p_def =
0658 <<EOS
0659         TreeNode* node = new TreeNode(currentToken);
0660         nextToken();
0661         appendArguments(node);
0662         skipToken(Token::EndOfLine, *node->token());
0663         return node;
0664 EOS
0665 @e_def =
0666 <<EOS
0667         if(node->childCount()>0)
0668                 returnValue = node->child(0)->value();
0669         else
0670                 returnValue = 0;
0671         returning   = true;
0672 EOS
0673 parse_item()
0674 
0675 new_item()
0676 @type  = "Wait"
0677 @cat   = "ControllerCommand"
0678 @look  = "wait"
0679 @funct = "statement, node"
0680 @args  = [:number]
0681 @e_def =
0682 <<EOS
0683         if (!checkParameterQuantity(node, 1, 20000+Token::Wait*100+90)) return;
0684         if (!checkParameterType(node, Value::Number, 20000+Token::Wait*100+91) ) return;
0685         waiting = true;
0686         QTimer::singleShot((int)(1000*node->child(0)->value()->number()), this, SLOT(stopWaiting()));
0687 EOS
0688 parse_item()
0689 
0690 
0691 new_item()
0692 @type  = "Assert"
0693 @cat   = "Command"
0694 @look  = "assert"
0695 @funct = "statement, node"
0696 @args  = [:bool]
0697 @e_def =
0698 <<EOS
0699         if (!checkParameterQuantity(node, 1, 20000+Token::Wait*100+90)) return;
0700         if (!checkParameterType(node, Value::Bool, 20000+Token::Wait*100+91) ) return;
0701         if (!node->child(0)->value()->boolean()) addError(i18n("ASSERT failed"), *node->token(), 0);
0702 EOS
0703 parse_item()
0704 
0705 
0706 new_item()
0707 @type  = "And"
0708 @cat   = "BooleanOperator"
0709 @look  = "and"
0710 @funct = "node"
0711 @e_def =
0712 <<EOS
0713         //Niels: See 'Not'
0714         if(node->childCount()!=2) {
0715                 addError(i18n("'And' needs two variables"), *node->token(), 0);
0716                 return;
0717         }
0718         node->value()->setBool(node->child(0)->value()->boolean() && node->child(1)->value()->boolean());
0719 EOS
0720 parse_item()
0721 
0722 new_item()
0723 @type  = "Or"
0724 @cat   = "BooleanOperator"
0725 @look  = "or"
0726 @funct = "node"
0727 @e_def =
0728 <<EOS
0729         //Niels: See 'Not'
0730         if(node->childCount()!=2) {
0731                 addError(i18n("'Or' needs two variables"), *node->token(), 0);
0732                 return;
0733         }
0734         node->value()->setBool(node->child(0)->value()->boolean() || node->child(1)->value()->boolean());
0735 EOS
0736 parse_item()
0737 
0738 new_item()
0739 @type  = "Not"
0740 @cat   = "BooleanOperator"
0741 @look  = "not"
0742 @funct = "node"
0743 @e_def =
0744 <<EOS
0745         // OLD-TODO: maybe add some error handling here...
0746         //Niels: Ok, now we check if the node has children. Should we also check whether the child value is a boolean?
0747         if(node->childCount()!=1) {
0748                 addError(i18n("I need something to do a not on"), *node->token(), 0);
0749                 return;
0750         }
0751         node->value()->setBool(!node->child(0)->value()->boolean());
0752 EOS
0753 parse_item()
0754 
0755 
0756 
0757 def e_def_expression_creator(look)
0758         # since the looks for expressions are the same in TurtleScript and C++ we can take this shortcut...
0759         # all the logic doing the expressioning is in the Value class
0760         return "\tif(node->childCount()!=2) { \n\t\taddError(i18n(\"I cannot do a '#{look}' without 2 variables\"), *node->token(), 0);\n\t\treturn;\n\t}\n\tnode->value()->setBool(*node->child(0)->value() #{look} node->child(1)->value());\n"
0761 end
0762 
0763 new_item()
0764 @type  = "Equals"
0765 @cat   = "Expression"
0766 @look  = "=="
0767 @localize = false
0768 @funct = "node"
0769 @e_def = e_def_expression_creator(@look)
0770 parse_item()
0771 
0772 new_item()
0773 @type  = "NotEquals"
0774 @cat   = "Expression"
0775 @look  = "!="
0776 @localize = false
0777 @funct = "node"
0778 @e_def = e_def_expression_creator(@look)
0779 parse_item()
0780 
0781 new_item()
0782 @type  = "GreaterThan"
0783 @cat   = "Expression"
0784 @look  = ">"
0785 @localize = false
0786 @funct = "node"
0787 @e_def = e_def_expression_creator(@look)
0788 parse_item()
0789 
0790 new_item()
0791 @type  = "LessThan"
0792 @cat   = "Expression"
0793 @look  = "<"
0794 @localize = false
0795 @funct = "node"
0796 @e_def = e_def_expression_creator(@look)
0797 parse_item()
0798 
0799 new_item()
0800 @type  = "GreaterOrEquals"
0801 @cat   = "Expression"
0802 @look  = ">="
0803 @localize = false
0804 @funct = "node"
0805 @e_def = e_def_expression_creator(@look)
0806 parse_item()
0807 
0808 new_item()
0809 @type  = "LessOrEquals"
0810 @cat   = "Expression"
0811 @look  = "<="
0812 @localize = false
0813 @funct = "node"
0814 @e_def = e_def_expression_creator(@look)
0815 parse_item()
0816 
0817 
0818 
0819 new_item()
0820 @type  = "Addition"
0821 @cat   = "MathOperator"
0822 @look  = "+"
0823 @localize = false
0824 @funct = "node"
0825 @e_def =
0826 <<EOS
0827         if(node->childCount()!=2) {
0828                 addError(i18n("You need two numbers or string to do an addition"), *node->token(), 0);
0829                 return;
0830         }
0831         if (node->child(0)->value()->type() == Value::Number && node->child(1)->value()->type() == Value::Number) {
0832                 node->value()->setNumber(node->child(0)->value()->number() + node->child(1)->value()->number());
0833         } else {
0834                 node->value()->setString(node->child(0)->value()->string().append(node->child(1)->value()->string()));
0835         }
0836 EOS
0837 parse_item()
0838 
0839 new_item()
0840 @type  = "Subtraction"
0841 @cat   = "MathOperator"
0842 @look  = "-"
0843 @localize = false
0844 @funct = "node"
0845 @e_def =
0846 <<EOS
0847         if(node->childCount()!=2) {
0848                 addError(i18n("You need two numbers to subtract"), *node->token(), 0);
0849                 return;
0850         }
0851         if (node->child(0)->value()->type() == Value::Number && node->child(1)->value()->type() == Value::Number) {
0852                 node->value()->setNumber(node->child(0)->value()->number() - node->child(1)->value()->number());
0853         } else {
0854                 if (node->child(0)->value()->type() != Value::Number)
0855                         addError(i18n("You tried to subtract from a non-number, '%1'", node->child(0)->token()->look()), *node->token(), 0);
0856                 if (node->child(1)->value()->type() != Value::Number)
0857                         addError(i18n("You tried to subtract a non-number, '%1'", node->child(1)->token()->look()), *node->token(), 0);
0858         }
0859 EOS
0860 parse_item()
0861 
0862 new_item()
0863 @type  = "Multiplication"
0864 @cat   = "MathOperator"
0865 @look  = "*"
0866 @localize = false
0867 @funct = "node"
0868 @e_def =
0869 <<EOS
0870         if(node->childCount()!=2) {
0871                 addError(i18n("You need two numbers to multiplicate"), *node->token(), 0);
0872                 return;
0873         }
0874         if (node->child(0)->value()->type() == Value::Number && node->child(1)->value()->type() == Value::Number) {
0875                 node->value()->setNumber(node->child(0)->value()->number() * node->child(1)->value()->number());
0876         } else {
0877                 if (node->child(0)->value()->type() != Value::Number)
0878                         addError(i18n("You tried to multiplicate a non-number, '%1'", node->child(0)->token()->look()), *node->token(), 0);
0879                 if (node->child(1)->value()->type() != Value::Number)
0880                         addError(i18n("You tried to multiplicate by a non-number, '%1'", node->child(1)->token()->look()), *node->token(), 0);
0881         }
0882 EOS
0883 parse_item()
0884 
0885 new_item()
0886 @type  = "Division"
0887 @cat   = "MathOperator"
0888 @look  = "/"
0889 @localize = false
0890 @funct = "node"
0891 @e_def =
0892 <<EOS
0893         if(node->childCount()!=2) {
0894                 addError(i18n("You need two numbers to divide"), *node->token(), 0);
0895                 return;
0896         }
0897         if (node->child(0)->value()->type() == Value::Number && node->child(1)->value()->type() == Value::Number) {
0898                 if(node->child(1)->value()->number()==0) {
0899                         addError(i18n("You tried to divide by zero"), *node->token(), 0);
0900                         return;
0901                 }
0902                 node->value()->setNumber(node->child(0)->value()->number() / node->child(1)->value()->number());
0903         } else {
0904                 if (node->child(0)->value()->type() != Value::Number)
0905                         addError(i18n("You tried to divide a non-number, '%1'", node->child(0)->token()->look()), *node->token(), 0);
0906                 if (node->child(1)->value()->type() != Value::Number)
0907                         addError(i18n("You tried to divide by a non-number, '%1'", node->child(1)->token()->look()), *node->token(), 0);
0908         }
0909 EOS
0910 parse_item()
0911 
0912 new_item()
0913 @type  = "Power"
0914 @cat   = "MathOperator"
0915 @look  = "^" # or **
0916 @localize = false
0917 @funct = "node"
0918 @e_def =
0919 <<EOS
0920         if(node->childCount()!=2) {
0921                 addError(i18n("You need two numbers to raise a power"), *node->token(), 0);
0922                 return;
0923         }
0924         if (node->child(0)->value()->type() == Value::Number && node->child(1)->value()->type() == Value::Number) {
0925                 node->value()->setNumber(pow(node->child(0)->value()->number(), node->child(1)->value()->number()));
0926                 
0927                 double result = pow(node->child(0)->value()->number(), node->child(1)->value()->number());
0928 
0929                 int error = errno;
0930                 if(error==ERANGE) {
0931                         node->value()->setNumber(0);
0932                         addError(i18n("The result of an exponentiation was too large"), *node->token(), 0);
0933                 }else{
0934                         node->value()->setNumber(result);
0935                 }
0936         } else {
0937                 if (node->child(0)->value()->type() != Value::Number)
0938                         addError(i18n("You tried to raise a non-number to a power, '%1'", node->child(0)->token()->look()), *node->token(), 0);
0939                 if (node->child(1)->value()->type() != Value::Number)
0940                         addError(i18n("You tried to raise the power of a non-number, '%1'", node->child(1)->token()->look()), *node->token(), 0);
0941         }
0942 EOS
0943 parse_item()
0944 
0945 
0946 
0947 new_item()
0948 @type  = "Assign"
0949 @cat   = "Assignment"
0950 @look  = "="
0951 @localize = false
0952 @funct = "node"
0953 @e_def =
0954 <<EOS
0955         if(node->childCount()!=2) {
0956         addError(i18n("You need one variable and a value or variable to do a '='"), *node->token(), 0);
0957                 return;
0958         }
0959         if (!functionStack.isEmpty() && !globalVariableTable.contains(node->child(0)->token()->look())) // &&functionStack.top().variableTable->contains(node->token()->look())) 
0960         {
0961                 // //qDebug() << "function scope";
0962                 functionStack.top().variableTable->insert(node->child(0)->token()->look(), node->child(1)->value());
0963         } else {
0964                 // inserts unless already exists then replaces
0965                 globalVariableTable.insert(node->child(0)->token()->look(), node->child(1)->value());
0966         }
0967         // //qDebug() << "variableTable updated!";
0968         Q_EMIT variableTableUpdated(node->child(0)->token()->look(), node->child(1)->value());
0969 EOS
0970 parse_item()
0971 
0972 
0973 
0974 new_item()
0975 @type  = "Learn"
0976 @cat   = "LearnCommand"
0977 @look  = "learn"
0978 @funct = "statement, node"
0979 @p_def =
0980 <<EOS
0981         TreeNode* node = new TreeNode(currentToken);
0982         nextToken();
0983         node->appendChild(new TreeNode(new Token(*currentToken)));
0984         skipToken(Token::FunctionCall, *node->token());
0985         
0986         TreeNode* argumentList = new TreeNode(new Token(Token::ArgumentList, "arguments", 0, 0, 0, 0));
0987         while (currentToken->type() == Token::Variable) {
0988                 // cannot just call appendArguments here because we're only appending Token::Variable tokens
0989                 argumentList->appendChild(new TreeNode(currentToken));
0990                 nextToken();
0991                 if (currentToken->type() != Token::ArgumentSeparator) break;
0992                 nextToken();
0993         }
0994         node->appendChild(argumentList);
0995         
0996         //Skip all the following EndOfLine's
0997         while (currentToken->type() == Token::EndOfLine) {
0998                 delete currentToken;
0999                 nextToken();
1000         }
1001 
1002         if (currentToken->type() == Token::ScopeOpen) {
1003                 node->appendChild(parseScopeOpen());  // if followed by a scope
1004         } else {
1005                 addError(i18n("Expected a scope after the 'learn' command"), *node->token(), 0);
1006         }
1007         return node;
1008 EOS
1009 @e_def =
1010 <<EOS
1011         if(functionTable.contains(node->child(0)->token()->look())) {
1012                 addError(i18n("The function '%1' is already defined.", node->child(0)->token()->look()), *node->token(), 0);
1013                 return;
1014         }
1015         functionTable.insert(node->child(0)->token()->look(), node);
1016         // //qDebug() << "functionTable updated!";
1017         QStringList parameters;
1018         for (uint i = 0; i < node->child(1)->childCount(); i++)
1019                 parameters << node->child(1)->child(i)->token()->look();
1020         Q_EMIT functionTableUpdated(node->child(0)->token()->look(), parameters);
1021 EOS
1022 parse_item()
1023 
1024 new_item()
1025 @type  = "ArgumentList"
1026 @funct = "node"
1027 parse_item()
1028 
1029 
1030 
1031 new_item()
1032 @type  = "Reset"
1033 @cat   = "Command"
1034 @look  = "reset"
1035 @funct = "statement, node, auto-Q_EMIT"
1036 @args  = [:none]
1037 parse_item()
1038 
1039 new_item()
1040 @type  = "Clear"
1041 @cat   = "Command"
1042 @look  = "clear"
1043 @ali   = "ccl"
1044 @funct = "statement, node, auto-Q_EMIT"
1045 @args  = [:none]
1046 parse_item()
1047 
1048 new_item()
1049 @type  = "Center"
1050 @cat   = "Command"
1051 @look  = "center"
1052 @funct = "statement, node, auto-Q_EMIT"
1053 @args  = [:none]
1054 parse_item()
1055 
1056 new_item()
1057 @type  = "Go"
1058 @cat   = "Command"
1059 @look  = "go"
1060 @funct = "statement, node, auto-Q_EMIT"
1061 @args  = [:number, :number]
1062 parse_item()
1063 
1064 new_item()
1065 @type  = "GoX"
1066 @cat   = "Command"
1067 @look  = "gox"
1068 @ali   = "gx"
1069 @funct = "statement, node, auto-Q_EMIT"
1070 @args  = [:number]
1071 parse_item()
1072 
1073 new_item()
1074 @type  = "GoY"
1075 @cat   = "Command"
1076 @look  = "goy"
1077 @ali   = "gy"
1078 @funct = "statement, node, auto-Q_EMIT"
1079 @args  = [:number]
1080 parse_item()
1081 
1082 new_item()
1083 @type  = "Forward"
1084 @cat   = "Command"
1085 @look  = "forward"
1086 @ali   = "fw"
1087 @funct = "statement, node, auto-Q_EMIT"
1088 @args  = [:number]
1089 parse_item()
1090 
1091 new_item()
1092 @type  = "Backward"
1093 @cat   = "Command"
1094 @look  = "backward"
1095 @ali   = "bw"
1096 @funct = "statement, node, auto-Q_EMIT"
1097 @args  = [:number]
1098 parse_item()
1099 
1100 new_item()
1101 @type  = "Direction"
1102 @cat   = "Command"
1103 @look  = "direction"
1104 @ali   = "dir"
1105 @funct = "statement, node, auto-Q_EMIT"
1106 @args  = [:number]
1107 parse_item()
1108 
1109 new_item()
1110 @type  = "TurnLeft"
1111 @cat   = "Command"
1112 @look  = "turnleft"
1113 @ali   = "tl"
1114 @funct = "statement, node, auto-Q_EMIT"
1115 @args  = [:number]
1116 parse_item()
1117 
1118 new_item()
1119 @type  = "TurnRight"
1120 @cat   = "Command"
1121 @look  = "turnright"
1122 @ali   = "tr"
1123 @funct = "statement, node, auto-Q_EMIT"
1124 @args  = [:number]
1125 parse_item()
1126 
1127 new_item()
1128 @type  = "PenWidth"
1129 @cat   = "Command"
1130 @look  = "penwidth"
1131 @ali   = "pw"
1132 @funct = "statement, node, auto-Q_EMIT"
1133 @args  = [:number]
1134 parse_item()
1135 
1136 new_item()
1137 @type  = "PenUp"
1138 @cat   = "Command"
1139 @look  = "penup"
1140 @ali   = "pu"
1141 @funct = "statement, node, auto-Q_EMIT"
1142 @args  = [:none]
1143 parse_item()
1144 
1145 new_item()
1146 @type  = "PenDown"
1147 @cat   = "Command"
1148 @look  = "pendown"
1149 @ali   = "pd"
1150 @funct = "statement, node, auto-Q_EMIT"
1151 @args  = [:none]
1152 parse_item()
1153 
1154 new_item()
1155 @type  = "PenColor"
1156 @cat   = "Command"
1157 @look  = "pencolor"
1158 @ali   = "pc"
1159 @funct = "statement, node, auto-Q_EMIT"
1160 @args  = [:number, :number, :number]
1161 parse_item()
1162 
1163 new_item()
1164 @type  = "CanvasColor"
1165 @cat   = "Command"
1166 @look  = "canvascolor"
1167 @ali   = "cc"
1168 @funct = "statement, node, auto-Q_EMIT"
1169 @args  = [:number, :number, :number]
1170 parse_item()
1171 
1172 new_item()
1173 @type  = "CanvasSize"
1174 @cat   = "Command"
1175 @look  = "canvassize"
1176 @ali   = "cs"
1177 @funct = "statement, node, auto-Q_EMIT"
1178 @args  = [:number, :number]
1179 parse_item()
1180 
1181 new_item()
1182 @type  = "SpriteShow"
1183 @cat   = "Command"
1184 @look  = "spriteshow"
1185 @ali   = "ss"
1186 @funct = "statement, node, auto-Q_EMIT"
1187 @args  = [:none]
1188 parse_item()
1189 
1190 new_item()
1191 @type  = "SpriteHide"
1192 @cat   = "Command"
1193 @look  = "spritehide"
1194 @ali   = "sh"
1195 @funct = "statement, node, auto-Q_EMIT"
1196 @args  = [:none]
1197 parse_item()
1198 
1199 new_item()
1200 @type  = "Print"
1201 @cat   = "Command"
1202 @look  = "print"
1203 @funct = "statement, node, auto-Q_EMIT"
1204 @args  = [:string]
1205 @e_def = # define ourself because print handles any argument type
1206 <<EOS
1207         if (!checkParameterQuantity(node, 1, 20000+Token::Print*100+90))
1208                 return;
1209         // //qDebug() << "Printing: '" << node->child(0)->value()->string() << "'";
1210 EOS
1211 parse_item()
1212 
1213 new_item()
1214 @type  = "FontSize"
1215 @cat   = "Command"
1216 @look  = "fontsize"
1217 @funct = "statement, node, auto-Q_EMIT"
1218 @args  = [:number]
1219 parse_item()
1220 
1221 # # new_item()
1222 # # @type  = "WrapOn"
1223 # # @cat   = "Command"
1224 # # @look  = "wrapon"
1225 # # @funct = "statement, node, auto-Q_EMIT"
1226 # # @args  = [:none]
1227 # # parse_item()
1228 # # 
1229 # # new_item()
1230 # # @type  = "WrapOff"
1231 # # @cat   = "Command"
1232 # # @look  = "wrapoff"
1233 # # @funct = "statement, node, auto-Q_EMIT"
1234 # # @args  = [:none]
1235 # # parse_item()
1236 
1237 
1238 new_item()
1239 @type  = "Random"
1240 @cat   = "Command"
1241 @look  = "random"
1242 @ali   = "rnd"
1243 @funct = "statement, node"
1244 @args  = [:number, :number]
1245 @e_def =
1246 <<EOS
1247         if (!checkParameterQuantity(node, 2, 20000+Token::Random*100+90)) return;
1248         TreeNode* nodeX = node->child(0);  // getting
1249         TreeNode* nodeY = node->child(1);
1250         
1251         if (!checkParameterType(node, Value::Number, 20000+Token::Random*100+91)) return;
1252         double x = nodeX->value()->number();
1253         double y = nodeY->value()->number();
1254         double r = (double)(KRandom::random()) / RAND_MAX;
1255         node->value()->setNumber(r * (y - x) + x);
1256 EOS
1257 parse_item()
1258 
1259 new_item()
1260 @type      = "GetX"
1261 @cat       = "Command"
1262 @look      = "getx"
1263 @funct     = "statement, node"
1264 @args      = [:none]
1265 @e_def      =
1266 <<EOS
1267         if (!checkParameterQuantity(node, 0, 20000+Token::GetX*100+90)) return;
1268         double value = 0;
1269         Q_EMIT getX(value);
1270         node->value()->setNumber(value);
1271 EOS
1272 parse_item()
1273 
1274 new_item()
1275 @type      = "GetY"
1276 @cat       = "Command"
1277 @look      = "gety"
1278 @funct     = "statement, node"
1279 @args      = [:none]
1280 @e_def      =
1281 <<EOS
1282         if (!checkParameterQuantity(node, 0, 20000+Token::GetY*100+90)) return;
1283         double value = 0;
1284         Q_EMIT getY(value);
1285         node->value()->setNumber(value);
1286 EOS
1287 parse_item()
1288 
1289 # # new_item()
1290 # # @type  = "Run"
1291 # # @cat   = "Command"
1292 # # @look  = "run"
1293 # # @funct = "statement, node"
1294 # # @args  = [:string]
1295 # # parse_item()
1296 # # 
1297 new_item()
1298 @type  = "Message"
1299 @cat   = "Command"
1300 @look  = "message"
1301 @funct = "statement, node"
1302 @args  = [:string]
1303 @e_def      =
1304 <<EOS
1305         if (!checkParameterQuantity(node, 1, 20000+Token::Message*100+90)) return;
1306         Q_EMIT message(node->child(0)->value()->string());
1307 EOS
1308 parse_item()
1309 
1310 new_item()
1311 @type  = "Ask" # used to be "inputwindow"
1312 @cat   = "Command"
1313 @look  = "ask"
1314 @funct = "statement, node"
1315 @args  = [:string]
1316 @e_def      =
1317 <<EOS
1318         if (!checkParameterQuantity(node, 1, 20000+Token::Ask*100+90)) return;
1319         QString value = node->child(0)->value()->string();
1320         Q_EMIT ask(value);
1321         
1322         bool convertOk;
1323         double d = value.toDouble(&convertOk);
1324         if(convertOk)
1325                 node->value()->setNumber(d);
1326         else
1327                 node->value()->setString(value);
1328 EOS
1329 parse_item()
1330 
1331 new_item()
1332 @type  = "Pi"
1333 @cat   = "Command"
1334 @look  = "pi"
1335 @funct = "statement, node"
1336 @args  = [:none]
1337 @e_def =
1338 <<EOS
1339         node->value()->setNumber(M_PI);
1340 EOS
1341 parse_item()
1342 
1343 new_item()
1344 @type  = "Tan"
1345 @cat   = "Command"
1346 @look  = "tan"
1347 @funct = "statement, node"
1348 @args  = [:number]
1349 @e_def =
1350 <<EOS
1351         if (!checkParameterQuantity(node, 1, 20000+Token::Tan*100+90)) return;
1352         
1353         double deg = node->child(0)->value()->number();
1354         node->value()->setNumber(tan(DEG2RAD(deg)));
1355 EOS
1356 parse_item()
1357 
1358 new_item()
1359 @type  = "Sin"
1360 @cat   = "Command"
1361 @look  = "sin"
1362 @funct = "statement, node"
1363 @args  = [:number]
1364 @e_def =
1365 <<EOS
1366         if (!checkParameterQuantity(node, 1, 20000+Token::Sin*100+90)) return;
1367         
1368         double deg = node->child(0)->value()->number();
1369         node->value()->setNumber(sin(DEG2RAD(deg)));
1370 EOS
1371 parse_item()
1372 
1373 new_item()
1374 @type  = "Cos"
1375 @cat   = "Command"
1376 @look  = "cos"
1377 @funct = "statement, node"
1378 @args  = [:number]
1379 @e_def =
1380 <<EOS
1381         if (!checkParameterQuantity(node, 1, 20000+Token::Cos*100+90)) return;
1382         
1383         double deg = node->child(0)->value()->number();
1384         node->value()->setNumber(cos(DEG2RAD(deg)));
1385 EOS
1386 parse_item()
1387 
1388 new_item()
1389 @type  = "ArcTan"
1390 @cat   = "Command"
1391 @look  = "arctan"
1392 @funct = "statement, node"
1393 @args  = [:number]
1394 @e_def =
1395 <<EOS
1396         if (!checkParameterQuantity(node, 1, 20000+Token::ArcTan*100+90)) return;
1397         
1398         double deg = node->child(0)->value()->number();
1399         node->value()->setNumber(RAD2DEG(atan(deg)));
1400 EOS
1401 parse_item()
1402 
1403 new_item()
1404 @type  = "ArcSin"
1405 @cat   = "Command"
1406 @look  = "arcsin"
1407 @funct = "statement, node"
1408 @args  = [:number]
1409 @e_def =
1410 <<EOS
1411         if (!checkParameterQuantity(node, 1, 20000+Token::ArcSin*100+90)) return;
1412         
1413         double deg = node->child(0)->value()->number();
1414         node->value()->setNumber(RAD2DEG(asin(deg)));
1415 EOS
1416 parse_item()
1417 
1418 new_item()
1419 @type  = "ArcCos"
1420 @cat   = "Command"
1421 @look  = "arccos"
1422 @funct = "statement, node"
1423 @args  = [:number]
1424 @e_def =
1425 <<EOS
1426         if (!checkParameterQuantity(node, 1, 20000+Token::ArcCos*100+90)) return;
1427         
1428         double deg = node->child(0)->value()->number();
1429         node->value()->setNumber(RAD2DEG(acos(deg)));
1430 EOS
1431 parse_item()
1432 
1433 new_item()
1434 @type  = "Sqrt"
1435 @cat   = "Command"
1436 @look  = "sqrt"
1437 @funct = "statement, node"
1438 @args  = [:number]
1439 @e_def =
1440 <<EOS
1441         if (!checkParameterQuantity(node, 1, 20000+Token::Sqrt*100+90)) return;
1442         
1443         double val = node->child(0)->value()->number();
1444         if(val<0) {
1445                 addError(i18n("Can't do a sqrt of a negative number"), *node->child(0)->token(), 0);
1446                 node->value()->setNumber(0);
1447                 return;
1448         }
1449         node->value()->setNumber(sqrt(val));
1450 EOS
1451 parse_item()
1452 
1453 #  i commented this one out because exp will need logarithm and the e number in order to be complete
1454 # new_item()
1455 # @type  = "Exp"
1456 # @cat   = "Command"
1457 # @look  = "exp"
1458 # @funct = "statement, node"
1459 # @args  = [:number]
1460 # @e_def =
1461 # <<EOS
1462 #       if (!checkParameterQuantity(node, 1, 20000+Token::Exp*100+90)) return;
1463 #       
1464 #       double val = node->child(0)->value()->number();
1465 #       node->value()->setNumber(exp(val));
1466 # EOS
1467 # parse_item()
1468 
1469 new_item()
1470 @type  = "Round"
1471 @cat   = "Command"
1472 @look  = "round"
1473 @funct = "statement, node"
1474 @args  = [:number]
1475 @e_def =
1476 <<EOS
1477     if (!checkParameterQuantity(node, 1, 20000+Token::Round*100+90)) return;
1478    
1479     double val = node->child(0)->value()->number();
1480     node->value()->setNumber((double)ROUND2INT(val));
1481 EOS
1482 parse_item()
1483 
1484 new_item()
1485 @type      = "GetDirection"
1486 @cat       = "Command"
1487 @look      = "getdirection"
1488 @funct     = "statement, node"
1489 @args      = [:none]
1490 @e_def      =
1491 <<EOS
1492         if (!checkParameterQuantity(node, 0, 20000+Token::GetDirection*100+90)) return;
1493         double value = 0;
1494         Q_EMIT getDirection(value);
1495         node->value()->setNumber(value);
1496 EOS
1497 parse_item()
1498 
1499 new_item()
1500 @type  = "Mod"
1501 @cat   = "Command"
1502 @look  = "mod"
1503 @funct = "statement, node"
1504 @args  = [:number, :number]
1505 @e_def =
1506 <<EOS
1507         if (!checkParameterQuantity(node, 2, 20000+Token::Mod*100+90)) return;
1508         TreeNode* nodeX = node->child(0);  // getting
1509         TreeNode* nodeY = node->child(1);
1510 
1511         if (!checkParameterType(node, Value::Number, 20000+Token::Mod*100+91)) return;
1512         double x = nodeX->value()->number();
1513         double y = nodeY->value()->number();
1514         double m = (double)(ROUND2INT(x) % ROUND2INT(y));
1515         node->value()->setNumber(m);
1516 EOS
1517 parse_item()