PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, int* errLine, UString* errMsg) { RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), debugger, exec, source, errLine, errMsg); if (!program) return 0; StatementNode* exprStatement = program->singleStatement(); ASSERT(exprStatement); ASSERT(exprStatement->isExprStatement()); if (!exprStatement || !exprStatement->isExprStatement()) return 0; ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr(); ASSERT(funcExpr); ASSERT(funcExpr->isFuncExprNode()); if (!funcExpr || !funcExpr->isFuncExprNode()) return 0; FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body(); ASSERT(body); return FunctionExecutable::create(&exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine()); }
void IdentifierNode::generateILOCCode(Node* context) { if (this->children->size() == 0) { // Variable Symbol* symbol = Scope::getSymbol(this->symbol->getText()); Node* symbolScope = Scope::getScope(this->symbol->getText()); std::string* varAddressRegisterName = ILOC::getRegister(symbol->getText()); std::string registerBaseAddress = (symbolScope->getNodeType() == Common::NT_PROGRAM) ? "bss" : "fp"; std::stringstream symbolOffsetStr; symbolOffsetStr << symbol->getOffset(); ILOC* instruction = new ILOC(Common::ILOC_LOADAI, registerBaseAddress, symbolOffsetStr.str(), *varAddressRegisterName, ""); this->addInstruction(instruction); this->setLastRegister(*varAddressRegisterName); } else { // vector Symbol* symbol = Scope::getSymbol(this->symbol->getText()); Node* symbolScope = Scope::getScope(this->symbol->getText()); std::string* vectorAddressRegisterName = ILOC::getRegister(symbol->getText()); std::string registerBaseAddress = (symbolScope->getNodeType() == Common::NT_PROGRAM) ? "bss" : "fp"; std::stringstream symbolOffsetStr; symbolOffsetStr << symbol->getOffset(); ILOC* instruction = new ILOC(Common::ILOC_ADDI, registerBaseAddress, symbolOffsetStr.str(), *vectorAddressRegisterName, ""); this->addInstruction(instruction); std::string lastBaseRegister = *vectorAddressRegisterName; std::string* indexRegisterName; for (unsigned int i = 0; i < this->children->size(); i++) { ExpressionNode* expression = dynamic_cast<ExpressionNode*>(this->children->at(i)); expression->generateILOCCode(this); std::stringstream indexStream; indexStream << i; std::string* multResultRegisterName = ILOC::getRegister("INST_MULT_VEC_RESULT_" + indexStream.str()); indexRegisterName = ILOC::getRegister("INDEX_REGISTER_NAME_" + indexStream.str()); ILOC* instructionMult = new ILOC(Common::ILOC_MULTI, expression->getLastRegister(), "4", *multResultRegisterName, ""); ILOC* instructionLoadAO = new ILOC(Common::ILOC_LOADA0, lastBaseRegister, *multResultRegisterName, *indexRegisterName, ""); lastBaseRegister = *indexRegisterName; this->addInstruction(instructionMult); this->addInstruction(instructionLoadAO); } this->setLastRegister(*indexRegisterName); } }
ExpressionNode BinaryOperation::simplify(const ExpressionNode& root) const { ExpressionNode* left = root.getFirstChild(); if (left != 0) { if (left->getRight() != 0) { if ((left->getRight())->getRight() != 0) { throw ExpressionNode::WrongArityError("> 2 arguments for BinaryOperation"); } return simplify( *left, *(left->getRight()) ); } else { cerr << left << endl; throw ExpressionNode::WrongArityError("only 1 argument for BinaryOperation"); } } else { throw ExpressionNode::WrongArityError("No arguments for BinaryOperation"); } }
bool ExpressionNode::operator== (const ExpressionNode& other) const { ExpressionNode *selfptr; ExpressionNode *otherptr; if (getType() == other.getType() && getOperation() == other.getOperation() && getVariable() == other.getVariable() && getValue() == other.getValue() ) { selfptr = firstChild; otherptr = other.getFirstChild(); while (selfptr != 0 && otherptr != 0) { if (*selfptr == *otherptr) { selfptr = selfptr->getRight(); otherptr = otherptr->getRight(); } else { return false; } } if (selfptr == 0 && otherptr == 0) { return true; } else { assert(selfptr != otherptr); return false; } } else { return false; } }
bool is_declaration_name() { return op == Lexeme::MUL && value->is_declaration_name(); };
bool is_type_name(Document &document, bool lookup) { return op == Lexeme::MUL && left->is_type_name(document, lookup) && right->is_type_array(); };
bool Addition::isCompatible(const ExpressionNode& term1, const ExpressionNode& term2) const { clog << "checkpoint isAddable(" << term1 << ", " << term2 << ")" << endl; const ExpressionNode * varpart1(0); const ExpressionNode * varpart2(0); const ExpressionNode * left; const ExpressionNode * right; if (term1.getType() == NUMBER) { varpart1 = 0; } else if (term1.getType() == OPERATION) { if (term1.getOperation() == &MULTIPLICATION) { left = term1.getFirstChild(); right = left->getRight(); if (left->getType() == NUMBER) { varpart1 = right; } else if (right->getType() == NUMBER) { varpart1 = left; } else { varpart1 = &term1; } } else { varpart1 = &term1; } } else // VARIABLE { assert(term1.getType() == VARIABLE); varpart1 = &term1; } if (term2.getType() == NUMBER) { varpart2 = 0; } else if (term2.getType() == OPERATION) { if (term2.getOperation() == &MULTIPLICATION) { left = term2.getFirstChild(); right = left->getRight(); if (left->getType() == NUMBER) { varpart2 = right; } else if (right->getType() == NUMBER) { varpart2 = left; } else { varpart2 = &term2; } } else { varpart2 = &term2; } } else // VARIABLE { assert(term2.getType() == VARIABLE); varpart2 = &term2; } if (varpart1 != 0 && varpart2 != 0) { if (*varpart1 == *varpart2) { return true; } else { return false; } } else { if (varpart1 == 0 && varpart2 == 0) { // both numbers return true; } else { return false; } } }
bool is_type_array() { return op == Lexeme::MUL && value->is_type_array(); };
void ExpressionNode::ScopeAndType(ostream &out, int &numErrors) { DeclarationNode *dPtr, *paramPtr, *tempdPtr; ExpressionNode *argPtr; int argCounter; Types lhs_type, rhs_type, lhs_decl, rhs_decl, returnType; bool isUnary, lhs_isArray, rhs_isArray, foundError; lhs_type = rhs_type = lhs_decl = rhs_decl = returnType = Undefined; // initialize types to undefined lhs_isArray = rhs_isArray = foundError = false; // initialize booleans to false isUnary = true; string nameToLookup; switch (subKind) { case AssignK: op = "="; // populate the op for assignments with "=" to make Op logic work properly // intentionally drop through to OpK case... case OpK: if (child[0] != NULL) { child[0]->ScopeAndType(out, numErrors); lhs_type = ((ExpressionNode *)child[0])->type; // grab lhs type lhs_isArray = child[0]->getIsArray(); } if (child[1] != NULL) { isUnary = false; child[1]->ScopeAndType(out, numErrors); rhs_type = ((ExpressionNode *)child[1])->type; // grab lhs type rhs_isArray = child[1]->getIsArray(); } lookupTypes(op, lhs_decl, rhs_decl, returnType); // populate the last three variable from the function //DEBUG /*if (lineNumber == 26) { cerr << "op: " << op << "\nlhs_decl: " << PrintType(lhs_decl) << " lhs_type: " << PrintType(lhs_type) << "\nrhs_decl: " << PrintType(rhs_decl) << " rhs_type: " << PrintType(rhs_type) << "\nlhs_isArray: " << boolalpha << lhs_isArray << "\nrhs_isArray: " << rhs_isArray << noboolalpha << endl; }*/ //DEBUG // unary ops if (isUnary && lhs_type != Error) { //check for arrays if (lhs_isArray) { ++numErrors; foundError = true; // Unary operator array check error PrintError(out, 16, lineNumber, op, "", "", 0, 0); } else if (lhs_type != lhs_decl) { // do type check on unary op ++numErrors; foundError = true; // Unary operator type check error PrintError(out, 17, lineNumber, op, PrintType(lhs_decl), PrintType(lhs_type), 0, 0); } } // binary ops else if (!isUnary) { // check for arrays if (lhs_type != Error && rhs_type != Error && (lhs_isArray || rhs_isArray)) { ++numErrors; foundError = true; // binary operator array check error PrintError(out, 16, lineNumber, op, "", "", 0, 0); } // check for binary ops that can process different types as long as they are the same else if (lhs_type != Error && rhs_type != Error && lhs_decl == Undefined && rhs_decl == Undefined && lhs_type != rhs_type) { ++numErrors; foundError = true; // same type required check error PrintError(out, 1, lineNumber, op, PrintType(lhs_type), PrintType(rhs_type), 0, 0); } // do type check for strict binary operators /*else { if (lhs_type != Error && lhs_decl != Undefined && lhs_decl != lhs_type) { ++numErrors; foundError = true; // binary lhs type check error PrintError(out, 2, lineNumber, op, PrintType(lhs_decl), PrintType(lhs_type), 0, 0); } if (rhs_type != Error && rhs_decl != Undefined && rhs_decl != rhs_type) { ++numErrors; foundError = true; // binary rhs type check error PrintError(out, 3, lineNumber, op, PrintType(rhs_decl), PrintType(rhs_type), 0, 0); } }*/ else if (lhs_type != Error && rhs_type != Error) { if (lhs_decl != Undefined && lhs_decl != lhs_type) { ++numErrors; foundError = true; // binary lhs type check error PrintError(out, 2, lineNumber, op, PrintType(lhs_decl), PrintType(lhs_type), 0, 0); } if (rhs_decl != Undefined && rhs_decl != rhs_type) { ++numErrors; foundError = true; // binary rhs type check error PrintError(out, 3, lineNumber, op, PrintType(rhs_decl), PrintType(rhs_type), 0, 0); } } } // set the type for this node if (foundError || lhs_type == Error || rhs_type == Error) // propagate the error type to avoid cascading errors this->type = Error; else { if (returnType == Undefined) this->type = lhs_type; // if returnType is undefined return the lhs (used for ops that can process multiple types) else this->type = returnType; } break; case IdK: // make sure symbol exists dPtr = (DeclarationNode *)symtab->lookup(name.c_str()); if (dPtr != NULL) { // populate this ID node with the type from the symbol table if (dPtr->subKind == FuncK) { ++numErrors; // Cannot use functions like simple variables PrintError(out, 21, lineNumber, name, "", "", 0, 0); this->type = Error; // don't bother trying to check type if expression } else this->type = dPtr->type; this->dPtr = dPtr; // save this link for later in Code Generation } else if (dPtr == NULL) { ++numErrors; // this symbol has not been declared error PrintError(out, 15, lineNumber, name, "", "", 0, 0); this->type = Error; // set the type to error to avoid cascading errors } if (child[0] != NULL) { // this ID has an indexer child[0]->ScopeAndType(out, numErrors); if (!(dPtr->isArray)) { // if the symbol table record does show this ID as an array ... ++numErrors; // can't index nonarray error PrintError(out, 4, lineNumber, name, "", "", 0, 0); } else if (((ExpressionNode *)child[0])->type != Error && ((ExpressionNode *)child[0])->type != Int) { // index need to be type int ++numErrors; // array index type check error PrintError(out, 10, lineNumber, PrintType(((ExpressionNode *)child[0])->type), "", "", 0, 0); } } break; case CallK: // make sure symbol exists dPtr = (DeclarationNode *)symtab->lookup(name.c_str()); this->dPtr = dPtr; // save this link for later in Code Generation if (dPtr == NULL) { ++numErrors; // this symbol has not been declared PrintError(out, 15, lineNumber, name, "", "", 0, 0); this->type = Error; // set the type to error to avoid cascading errors } else if (dPtr->subKind != FuncK) { ++numErrors; // variables cannot be called like functions PrintError(out, 20, lineNumber, name, "", "", 0, 0); } else { // Process the properly declared functions this->type = dPtr->type; // the type of this node is the return type of the function paramPtr = (DeclarationNode *)dPtr->child[0]; // set the parameter pointer to the function declaration parameters argPtr = (ExpressionNode *)this->child[0]; // set the argument pointer to the call arguments argCounter = 1; // step through the param and argument lists together while (paramPtr != NULL && argPtr != NULL) { argPtr->ScopeAndType(out, numErrors); // process expression in call // do type checks first if (paramPtr->type != Error && argPtr->type != Error && paramPtr->type != argPtr->type) { ++numErrors; // type in param list differs from type in argument list error PrintError(out, 7, lineNumber, PrintType(paramPtr->type), dPtr->name, "", argCounter, dPtr->lineNumber); } // now check to see if array params are handled correctly if (paramPtr->isArray && !(argPtr->getIsArray())) { // expecting an array type in call ++numErrors; // Expecting array in current parameter error PrintError(out, 9, lineNumber, dPtr->name, "", "", argCounter, dPtr->lineNumber); } else if (!paramPtr->isArray && argPtr->getIsArray()) { // not expecting an array type ++numErrors; // Not Expecting array in current parameter error PrintError(out, 13, lineNumber, dPtr->name, "", "", argCounter, dPtr->lineNumber); } // advanced both pointers to next item in list paramPtr = (DeclarationNode *)paramPtr->sibling; argPtr = (ExpressionNode *)argPtr->sibling; ++argCounter; // increment argument counter } // check to make sure that both lists are finished - no more params to process if (paramPtr != NULL || argPtr != NULL) { ++numErrors; // one list was shorter then the other // Wrong number of params error PrintError(out, 18, lineNumber, dPtr->name, "", "", dPtr->lineNumber); } } break; // we already know the type of a constant - handled in Bison code - no need to process here } // now traverse any sibling nodes if (sibling != NULL) sibling->ScopeAndType(out, numErrors); return; }
bool Parser::parse_statement(StatementList *list) { lexer.identify_keywords(); switch(lexeme()) { case Lexeme::KW_IF: parse_if(list); break; case Lexeme::KW_WHILE: parse_while(list); break; case Lexeme::KW_DO: parse_do(list); parse_terminator(); break; case Lexeme::KW_RETURN: parse_return(list); parse_terminator(); break; case Lexeme::KW_BREAK: parse_break(list); parse_terminator(); break; case Lexeme::KW_CONTINUE: parse_continue(list); parse_terminator(); break; case Lexeme::KW_CONST: step(); parse_local(true, parse_expression(), list); parse_terminator(); break; case Lexeme::BRACET_OPEN: list->append(parse_block<true, false>(Scope::EMPTY)); break; case Lexeme::SEMICOLON: step(); break; case Lexeme::END: case Lexeme::BRACET_CLOSE: return false; default: if(is_expression(lexeme())) { ExpressionNode *node = parse_expression(); if(lexeme() == Lexeme::IDENT && node->is_type_name(document, false)) parse_local(false, node, list); else list->append(node); parse_terminator(); } else return false; } return true; }
bool AssignVar(CompileInstance &inst, const mtlChars &name, const mtlChars &expr) { mtlChars base_name = GetBaseName(name); Definition *type = GetType(inst, base_name); if (type == NULL) { AddError(inst, "Undeclared variable", name); return false; } if (type->mut != Mutable) { AddError(inst, "Modifying a constant", name); return false; } ExpressionNode *tree = GenerateTree(expr); if (tree == NULL) { AddError(inst, "Malformed expression", expr); return false; } mtlChars base_mem = GetBaseMembers(name); bool result = true; Parser parser; mtlList<mtlChars> ops; mtlList<mtlChars> m; mtlString order_str; const int num_lanes = (base_mem.GetSize() > 0) ? base_mem.GetSize() : type->type.size; for (int lane = 0; lane < num_lanes; ++lane) { order_str.Free(); const int stack_size = tree->Evaluate(name, order_str, lane, 0); PushStack(inst, stack_size); order_str.SplitByChar(ops, ';'); mtlItem<mtlChars> *op = ops.GetFirst(); while (op != NULL && op->GetItem().GetSize() > 0) { parser.SetBuffer(op->GetItem()); switch (parser.MatchPart("%s+=%s%|%s-=%s%|%s*=%s%|%s/=%s%|%s=%s", m, NULL)) { case 0: EmitInstruction(inst, swsl::FLT_ADD_MM); break; case 1: EmitInstruction(inst, swsl::FLT_SUB_MM); break; case 2: EmitInstruction(inst, swsl::FLT_MUL_MM); break; case 3: EmitInstruction(inst, swsl::FLT_DIV_MM); break; case 4: EmitInstruction(inst, swsl::FLT_SET_MM); break; default: AddError(inst, "Invalid syntax", op->GetItem()); return false; break; } mtlItem<swsl::Instruction> *instr_item = inst.program.GetLast(); const mtlChars dst = m.GetFirst()->GetItem(); const mtlChars src = m.GetFirst()->GetNext()->GetItem(); EmitOperand(inst, dst); if (src.IsFloat()) { *((int*)(&instr_item->GetItem().instr)) += 1; } EmitOperand(inst, src); op = op->GetNext(); } PopStack(inst, stack_size); } delete tree; return result; }
// Evaluates and prints a tree version of the active watch list // The tree will be expanded along the nodes in expansionPath // Optionally the list is filtered to only show differences from pFilterName (the name of a persisted watch list) HRESULT WatchCmd::Print(int expansionIndex, __in_z WCHAR* expansionPath, __in_z WCHAR* pFilterName) { HRESULT Status = S_OK; INIT_API_EE(); INIT_API_DAC(); EnableDMLHolder dmlHolder(TRUE); IfFailRet(InitCorDebugInterface()); PersistList* pFilterList = NULL; if(pFilterName != NULL) { pFilterList = pPersistListHead; while(pFilterList != NULL) { if(_wcscmp(pFilterList->pName, pFilterName)==0) break; pFilterList = pFilterList->pNext; } } PersistWatchExpression* pHeadFilterExpr = (pFilterList != NULL) ? pFilterList->pHeadExpr : NULL; WatchExpression* pExpression = pExpressionListHead; int index = 1; while(pExpression != NULL) { ExpressionNode* pResult = NULL; if(FAILED(Status = ExpressionNode::CreateExpressionNode(pExpression->pExpression, &pResult))) { ExtOut(" %d) Error: HRESULT 0x%x while evaluating expression \'%S\'", index, Status, pExpression->pExpression); } else { //check for matching absolute expression PersistWatchExpression* pCurFilterExpr = pHeadFilterExpr; while(pCurFilterExpr != NULL) { if(_wcscmp(pCurFilterExpr->pExpression, pResult->GetAbsoluteExpression())==0) break; pCurFilterExpr = pCurFilterExpr->pNext; } // check for matching persist evaluation on the matching expression BOOL print = TRUE; if(pCurFilterExpr != NULL) { WCHAR pCurPersistResult[MAX_EXPRESSION]; FormatPersistResult(pCurPersistResult, MAX_EXPRESSION, pResult); if(_wcscmp(pCurPersistResult, pCurFilterExpr->pPersistResult)==0) { print = FALSE; } } //expand and print if(print) { if(index == expansionIndex) pResult->Expand(expansionPath); PrintCallbackData data; data.index = index; WCHAR pCommand[MAX_EXPRESSION]; swprintf_s(pCommand, MAX_EXPRESSION, L"!watch -expand %d", index); data.pCommand = pCommand; pResult->DFSVisit(EvalPrintCallback, (VOID*)&data); } delete pResult; } pExpression = pExpression->pNext; index++; } return Status; }
bool is_declaration_name() { return op == Lexeme::MUL && right->is_declaration_name(); };
bool Multiplication::isCompatible(const ExpressionNode& left, const ExpressionNode& right) { if (left.getType() == NUMBER && right.getType() == NUMBER) { return true; } else if (left.getType() == VARIABLE && right.getType() == VARIABLE) { if (left.getVariable() == right.getVariable()) { return true; } } else if (left.getType() == OPERATION) { if (left.getOperation() == &ADDITION || left.getOperation() == &SUM) { return true; } else if (left.getOperation() == &MULTIPLICATION || left.getOperation() == &PRODUCT) { return true; } } else if (right.getType() == OPERATION) { if (right.getOperation() == &ADDITION || right.getOperation() == &SUM) { return true; } else if (right.getOperation() == &MULTIPLICATION || right.getOperation() == &PRODUCT) { return true; } } return false; }
ExpressionNode ChainOperation::simplify(const ExpressionNode& root) const { ExpressionNode* left = root.getFirstChild(); ExpressionNode* lPtr; ExpressionNode* rPtr; vector<ExpressionNode *> used; ExpressionNode newNode(this); bool ending = false; cout << "ChainOp simplify " << *left << " " <<*left->getRight() << endl; if (left == 0) { return ExpressionNode(root.getOperation()->getIdentity()); } else if (left->getRight() == 0) { return *left; } else { for (lPtr=left; lPtr->getRight()!=0; lPtr=lPtr->getRight()) { if (find(used.begin(), used.end(), lPtr) == used.end() ) //if lPtr not in used { if (lPtr->getOperation() == this || lPtr->getOperation() == pairwiseOp) // if lPtr is itself the same Chain Operation { for (ExpressionNode* i = lPtr->getFirstChild(); i!=0; i=i->getRight()) { newNode.appendChild(*i); } used.push_back(lPtr); } else { for (rPtr = lPtr->getRight(); rPtr!=0; rPtr=rPtr->getRight()) { if (find(used.begin(),used.end(),rPtr)==used.end() && pairwiseOp->isCompatible(*lPtr, *rPtr)) { newNode.appendChild(pairwiseOp->simplify(*lPtr,*rPtr)); used.push_back(lPtr); used.push_back(rPtr); break; } } } } } if (find(used.begin(), used.end(), lPtr) == used.end() ) // check last child for expansion { if (lPtr->getOperation() == this || lPtr->getOperation() == pairwiseOp) { for (ExpressionNode* i = lPtr->getFirstChild(); i!=0; i=i->getRight()) { newNode.appendChild(*i); } used.push_back(lPtr); } } } if (newNode.getFirstChild() == 0) { ending = true; } for (lPtr=left; lPtr!=0; lPtr=lPtr->getRight()) { if (find(used.begin(),used.end(),lPtr) == used.end()) { newNode.appendChild(*lPtr); } } if (ending) { clog << "ending ChainSimplify, root/newNode: " << root << newNode << endl; return newNode; } else { return simplify(newNode); } }
ExpressionNode Addition::simplify(ExpressionNode& left, ExpressionNode& right) const { clog << "checkpoint addsimplify" << endl; //simplest case: at least one side is just 0 if (left.getType() == NUMBER && left.getValue().getInt() == 0) { return right; } else if (right.getType() == NUMBER && right.getValue().getInt() == 0) { return left; } // for each left term: for each right term: try adding stack <ExpressionNode*> leftNodeStack; ExpressionNode * currentLeftNode = &left; bool leftFinished = false; stack <ExpressionNode*> rightNodeStack; vector <ExpressionNode*> rightDeleteList; ExpressionNode * currentRightNode = &right; bool rightFinished = false; ExpressionNode newNode(&ADDITION); while (leftFinished == false) { clog << "looping left" << endl; if (currentLeftNode->getType() == OPERATION && currentLeftNode->getOperation() == &ADDITION) { if (currentLeftNode->getFirstChild() == 0) { throw ExpressionNode::WrongArityError(); } currentLeftNode = currentLeftNode->getFirstChild(); leftNodeStack.push(currentLeftNode); continue; } // leaf term on left tree: traverse right tree rightFinished = false; currentRightNode = &right; while (rightFinished == false) { clog << "looping right" << endl; if (currentRightNode->getType() == OPERATION && currentRightNode->getOperation() == &ADDITION) { if (currentRightNode->getFirstChild() == 0) { throw ExpressionNode::WrongArityError(); } currentRightNode = currentRightNode->getFirstChild(); rightNodeStack.push(currentRightNode); continue; } assert(currentLeftNode != 0); assert(currentRightNode !=0); clog << "checkpoint addsimplify: before isAddable(" << *currentLeftNode << ", " << *currentRightNode << ")"<< endl; // leaf terms on both sides: attempt adding if (isCompatible(*currentLeftNode, *currentRightNode)) { clog << "checkpoint addsimplify: after isAddable; " << endl; clog << *currentLeftNode << " " << *currentRightNode << endl; (*currentLeftNode) = addTerms(*currentLeftNode, *currentRightNode); clog << "checkpoint addsimplify: after addTerms; " << endl; clog << "currentLeftNode: " << *currentLeftNode << " RightNode:" << *currentRightNode << endl; clog << "left " << left << "right " << right << endl; if (currentRightNode == &right) { //entire right tree has been assimilated return left; } // try marking for deletion after right loop instead of removing rightDeleteList.push_back(currentRightNode); } while (true) { clog << "rightNodeStack: " << rightNodeStack.size() << endl; if (rightNodeStack.size() != 0) clog << "rightNodeStack.top(): " << *(rightNodeStack.top()) << endl; if (rightNodeStack.size() == 0) { rightFinished = true; break; } currentRightNode = rightNodeStack.top(); rightNodeStack.pop(); if (currentRightNode->getRight() != 0) { currentRightNode = currentRightNode->getRight(); rightNodeStack.push(currentRightNode); break; } } } // deleting marked rights for (vector<ExpressionNode*>::iterator it = rightDeleteList.begin(); it != rightDeleteList.end(); it++) { right.remove(*it); } rightDeleteList.clear(); clog << "here left: " << left << "right: " << right <<endl; //clog << "leftNodeStack: " << leftNodeStack.size() << endl; //if (leftNodeStack.size() > 0) //{ //clog << "leftNodeStack: " << *(leftNodeStack.top()) << endl; //} while (true) { if (leftNodeStack.size() == 0) { leftFinished = true; break; } currentLeftNode = leftNodeStack.top(); leftNodeStack.pop(); if (currentLeftNode->getRight() != 0) { currentLeftNode = currentLeftNode->getRight(); leftNodeStack.push(currentLeftNode); break; } } } //still some terms left on right newNode.appendChild(left); newNode.appendChild(right); return newNode; }
ExpressionNode Addition::addTerms(const ExpressionNode& term1, const ExpressionNode& term2) const { clog << "checkpoint addTerms" << endl; Number coefficient1; Number coefficient2; const ExpressionNode * varpart1; const ExpressionNode * varpart2; ExpressionNode * left; ExpressionNode * right; ExpressionNode newRight; ExpressionNode newCoef; ExpressionNode newNode; if (term1.getType() == NUMBER) { coefficient1 = term1.getValue(); varpart1 = 0; } else if (term1.getType() == OPERATION) { if (term1.getOperation() == &MULTIPLICATION) { left = term1.getFirstChild(); right = left->getRight(); if (left->getType() == NUMBER) { coefficient1 = left->getValue(); varpart1 = right; } else if (right->getType() == NUMBER) { coefficient1 = right->getValue(); varpart1 = left; } else { coefficient1 = MULTIPLICATION.getIdentity(); varpart1 = &term1; } } else { coefficient1 = MULTIPLICATION.getIdentity(); varpart1 = &term1; } } else // VARIABLE { assert(term1.getType() == VARIABLE); coefficient1 = MULTIPLICATION.getIdentity(); varpart1 = &term1; } if (term2.getType() == NUMBER) { coefficient2 = term2.getValue(); varpart2 = 0; } else if (term2.getType() == OPERATION) { if (term2.getOperation() == &MULTIPLICATION) { left = term2.getFirstChild(); right = left->getRight(); if (left->getType() == NUMBER) { coefficient2 = left->getValue(); varpart2 = right; } else if (right->getType() == NUMBER) { coefficient2 = right->getValue(); varpart2 = left; } else { coefficient2 = MULTIPLICATION.getIdentity(); varpart2 = &term2; } } else { coefficient2 = MULTIPLICATION.getIdentity(); varpart2 = &term2; } } else // VARIABLE { assert(term2.getType() == VARIABLE); coefficient2 = MULTIPLICATION.getIdentity(); varpart2 = &term2; } if (varpart1 != 0 && varpart2 != 0) { if (*varpart1 == *varpart2) { clog << "addTerms simplify like terms" << endl << "coef1: " << coefficient1 << " var1: " << *varpart1 << endl << "coef2: " << coefficient2 << " var2: " << *varpart2 << endl; newCoef = ExpressionNode(coefficient1 + coefficient2); newRight = *varpart1; newNode = ExpressionNode(&MULTIPLICATION); newNode.appendChild(newCoef); newNode.appendChild(newRight); clog << "sum: " << newNode << endl; return newNode; } else { clog << "*varpart1: " << *varpart1 << " *varpart2: " << endl; throw ExpressionNode::GenericError("adding unaddable terms"); } } else { if (varpart1 == 0 && varpart2 == 0) { clog << "sum: " << coefficient1 + coefficient2 << endl; return ExpressionNode(coefficient1 + coefficient2); } else { throw ExpressionNode::GenericError("adding unaddable terms"); } } throw ExpressionNode::GenericError("reached end of addTerms w/o returning."); //if (left.getNodeType() == NUMBER && right.getNodeType() == NUMBER) //{ //ExpressionNode newNode; //newNode.setNodeType(NUMBER); //newNode.setValue(Number(left.getValue().getInt() + right.getValue().getInt())); //return newNode; //} }
bool IsConstant( void ) const { return left->IsConstant() && right->IsConstant(); }
std::ostream& operator<<(std::ostream& out, const ExpressionNode& node) { ExpressionNode * ptr = 0; if (node.getType() == OPERATION) { if (node.getOperation() == 0) { if (node.getFirstChild() != 0) { throw ExpressionNode::GenericError("ERROR: inserting OPERATION parent node w/o operation into ostream"); } else { out << "()"; return out; } } if (node.getOperation()->isFuncFormat() == true) { out << *(node.getOperation()) << "("; ptr = node.getFirstChild(); if (ptr != 0) { out << *ptr; ptr = ptr->getRight(); while (ptr != 0) { out << ", " << *ptr; ptr = ptr->getRight(); } } out << ")"; } else { out << "("; ptr = node.getFirstChild(); if (ptr != 0) { out << *ptr; ptr = ptr->getRight(); while (ptr != 0) { out << *(node.getOperation()) << *ptr; ptr = ptr->getRight(); } } out << ")"; } } else if (node.getType() == VARIABLE) { if (node.getVariable() == 0) { throw ExpressionNode::GenericError("ERROR: inserting VARIABLE node w/o variable into ostream"); } out << *(node.getVariable()); } else { if (node.getType() != NUMBER) { int i = node.getType(); std::clog << std::endl << i << std::endl; } assert(node.getType() == NUMBER); out << node.getValue(); } return out; }
void Expression::ConvertInfixToPostfix() { if (!m_PostfixExpression.empty() || m_InfixExpression.empty()) return; m_Result = true; m_Status = true; std::stack<ExpressionNode> stackOperator; ExpressionNode::ExpressionNodeType lastType = ExpressionNode::Unknown; for (PostfixVector::size_type i = 0; i < m_InfixExpression.size(); ++i) { ExpressionNode expNode; expNode.Initialize(m_InfixExpression[i]); const ExpressionNode::ExpressionNodeType type = expNode.GetType(); if (type == ExpressionNode::Numeric) { // Operand, add to postfix expression m_PostfixExpression.push_back(expNode); while (!stackOperator.empty() && stackOperator.top().IsUnaryOperator()) { m_PostfixExpression.push_back(stackOperator.top()); stackOperator.pop(); } } else if (type == ExpressionNode::LParenthesis) { // Left Parentheses, add to stack stackOperator.push(expNode); } else if (type == ExpressionNode::RParenthesis) { // Right Parentheses, reverse search the Left Parentheses, add all operator of the middle ExpressionNode node; while (!stackOperator.empty()) { node = stackOperator.top(); stackOperator.pop(); if (node.GetType() == ExpressionNode::LParenthesis) { while (!stackOperator.empty() && stackOperator.top().IsUnaryOperator()) { m_PostfixExpression.push_back(stackOperator.top()); stackOperator.pop(); } break; } else m_PostfixExpression.push_back(node); } // The lastest node must be Left Parentheses if (node.GetType() != ExpressionNode::LParenthesis) { m_Status = false; } } else { if (ExpressionNode::IsUnaryNode(type) && (m_PostfixExpression.empty() || (lastType != ExpressionNode::Unknown && lastType != ExpressionNode::RParenthesis && lastType != ExpressionNode::Numeric))) { expNode.SetUnaryOperator(); stackOperator.push(expNode); } else if (stackOperator.empty()) { stackOperator.push(expNode); } else { ExpressionNode beforeExpNode = stackOperator.top(); if (beforeExpNode.GetType() != ExpressionNode::LParenthesis && beforeExpNode.GetPriority() >= expNode.GetPriority()) { m_PostfixExpression.push_back(beforeExpNode); stackOperator.pop(); } stackOperator.push(expNode); } } lastType = type; } while (!stackOperator.empty()) { ExpressionNode beforeExpNode = stackOperator.top(); if (beforeExpNode.GetType() == ExpressionNode::LParenthesis) { m_Status = false; } m_PostfixExpression.push_back(beforeExpNode); stackOperator.pop(); } #ifdef CC_PARSER_TEST wxString infix, postfix; for (InfixVector::size_type i = 0; i < m_InfixExpression.size(); ++i) infix += m_InfixExpression[i] + _T(" "); for (PostfixVector::size_type i = 0; i < m_PostfixExpression.size(); ++i) postfix += m_PostfixExpression[i].GetToken() + _T(" "); TRACE(_T("ConvertInfixToPostfix() : InfixExpression : %s"), infix.wx_str()); TRACE(_T("ConvertInfixToPostfix() : PostfixExpression : %s"), postfix.wx_str()); #endif }
void registerWith(ExpressionNode<T_element>& e) const { e.registerRequiredBy(*this); }
void ExpressionNode::GenCode(CodeEmitter &e, bool travSib, int virtualRegister, int toff) { DeclarationNode *dPtr; ExpressionNode *argPtr; int localToff, boolSkipLoc, currentLoc, currentReg; bool isUnary = true; // Assign virtual register to 'real' register int actualRegister = virtualRegister%MAX_EXP_REGISTERS+FIRST_REG_OFFSET; int nextRegister = (virtualRegister+1)%MAX_EXP_REGISTERS+FIRST_REG_OFFSET; localToff = toff; switch (subKind) { case OpK: // process left child if (child[0] != NULL) child[0]->GenCode(e, true, virtualRegister, toff); // mark location for short circuit jump if (op == "&&" || op == "||") boolSkipLoc = e.emitSkip(1); if (child[1] != NULL) { isUnary = false; // see if all of our registers are full... if (virtualRegister+1 >= MAX_EXP_REGISTERS) { // push value from "next" register e.emitRM("ST", nextRegister, toff--, fp, "dump register"); // push } else e.emitComment("Left side will remain in register"); /* // save left side localToff = toff--; e.emitRM("ST", ac, localToff, fp, "save left side"); */ // process right child child[1]->GenCode(e, true, virtualRegister+1, toff); /* // load left back into the accumulator toff = localToff; e.emitRM("LD", ac1, localToff, fp, "load left into ac1"); */ } // process operators // arithmetic operators if (op == "+") e.emitRO("ADD", actualRegister, actualRegister, nextRegister, "op +"); else if (op == "-" && !isUnary) e.emitRO("SUB", actualRegister, actualRegister, nextRegister, "op -"); else if (op == "*") e.emitRO("MUL", actualRegister, actualRegister, nextRegister, "op *"); else if (op == "/") e.emitRO("DIV", actualRegister, actualRegister, nextRegister, "op /"); else if (op == "%") { e.emitRO("DIV", rt, actualRegister, nextRegister, "begin op %"); e.emitRO("MUL", nextRegister, rt, nextRegister, ""); e.emitRO("SUB", actualRegister, actualRegister, nextRegister, "end op %"); } else if (op == "&&") { /**** Code for the non short circuit case **** e.emitRO("ADD", actualRegister, actualRegister, nextRegister, "prepare for && op"); e.emitRM("LDC", nextRegister, 2, 0, "load constant for &&"); e.emitRO("SUB", actualRegister, nextRegister, actualRegister, "compute value"); e.emitRM("JEQ", actualRegister, 2, pc, "op &&"); e.emitRM("LDC", actualRegister, 0, 0, "load false into ac"); e.emitRM("LDA", pc, 1, pc, "jump past true case"); e.emitRM("LDC", actualRegister, 1, 0, "load true into ac"); **** Code for the non short circuit case *****/ e.emitRM("JGT", nextRegister, 2, pc, "op && (right side)"); // special case: If left side of && is false then whole expression is false currentLoc = e.emitSkip(0); e.emitBackup(boolSkipLoc); e.emitRMAbs("JEQ", actualRegister, currentLoc, "Skip right child of && if left is false"); e.emitRestore(); e.emitRM("LDC", actualRegister, 0, 0, "load false into ac"); e.emitRM("LDA", pc, 1, pc, "jump past true case"); e.emitRM("LDC", actualRegister, 1, 0, "load true into ac"); } else if (op == "||") { /**** Code for the non short circuit case **** e.emitRO("ADD", actualRegister, actualRegister, nextRegister, "prepare for || op"); e.emitRM("JGT", actualRegister, 2, pc, "op ||"); e.emitRM("LDC", actualRegister, 0, 0, "load false into ac"); e.emitRM("LDA", pc, 1, pc, "jump past true case"); e.emitRM("LDC", actualRegister, 1, 0, "load true into ac"); **** Code for the non short circuit case *****/ //e.emitRM("JEQ", nextRegister, 2, pc, "op || (right side)"); /* Since the left side is short circuited the right side alone will determine whether the expression is true or false. Just make sure the RHS is int the right register */ e.emitRM("LDA", actualRegister, 0, nextRegister, "Move RHS to current accumulator"); // special case: If left side of || is true then whole expression is true currentLoc = e.emitSkip(0); e.emitBackup(boolSkipLoc); e.emitRMAbs("JGT", actualRegister, currentLoc, "Skip right child of || if left is true"); e.emitRestore(); //e.emitRM("LDC", actualRegister, 1, 0, "load true into ac"); //e.emitRM("LDA", pc, 1, pc, "jump past false case"); //e.emitRM("LDC", actualRegister, 0, 0, "load false into ac"); } else if (op == "!") { e.emitRM("JEQ", actualRegister, 2, pc, "op !"); e.emitRM("LDC", actualRegister, 0, 0, "load false into ac"); e.emitRM("LDA", pc, 1, pc, "jump past true case"); e.emitRM("LDC", actualRegister, 1, 0, "load true into ac"); } else if (op == "-" and isUnary) { e.emitRM("LDC", rt, 0, 0, "Load zero in rt for unary -"); e.emitRO("SUB", actualRegister, rt, actualRegister, "op unary -"); } else { // comparison operators e.emitRO("SUB", actualRegister, actualRegister, nextRegister, "prepare for comparison op"); if (op == "==") e.emitRM("JEQ", actualRegister, 2, pc, "op =="); else if (op == "!=") e.emitRM("JNE", actualRegister, 2, pc, "op !="); else if (op == "<") e.emitRM("JLT", actualRegister, 2, pc, "op <"); else if (op == "<=") e.emitRM("JLE", actualRegister, 2, pc, "op <="); else if (op == ">") e.emitRM("JGT", actualRegister, 2, pc, "op >"); else if (op == ">=") e.emitRM("JGE", actualRegister, 2, pc, "op >="); e.emitRM("LDC", actualRegister, 0, 0, "load false into ac"); e.emitRM("LDA", pc, 1, pc, "jump past true case"); e.emitRM("LDC", actualRegister, 1, 0, "load true into ac"); } // if we dumped a register earlier we need to restore it here if (virtualRegister+1 >= MAX_EXP_REGISTERS) { // pop value from stack back into next register e.emitRM("LD", nextRegister, ++toff, fp, "restore register"); // pop } break; case AssignK: // process RHS of assignment if (child[1] != NULL) child[1]->GenCode(e, true, virtualRegister, toff); // call function to store in LHS ((ExpressionNode *)child[0])->GenAssignLHS(e, virtualRegister, toff); break; case ConstK: e.emitRM("LDC", actualRegister, val, 0, "load constant"); break; case IdK: if (this->dPtr->isArray) { // is this array indexed? if (child[0] == NULL) { // must be a parameter if (this->dPtr->theScope == TreeNode::Parameter) e.emitRM("LD", actualRegister, this->dPtr->offset, (this->dPtr->theScope == TreeNode::Global)?gp:fp, "Load address of base of array " + this->name); else e.emitRM("LDA", actualRegister, this->dPtr->offset, (this->dPtr->theScope == TreeNode::Global)?gp:fp, "Load address of base of array " + this->name); } else { child[0]->GenCode(e, true, virtualRegister, toff); if (this->dPtr->theScope == TreeNode::Parameter) e.emitRM("LD", rt, this->dPtr->offset, (this->dPtr->theScope == TreeNode::Global)?gp:fp, "Load address of base of array " + this->name); else e.emitRM("LDA", rt, this->dPtr->offset, (this->dPtr->theScope == TreeNode::Global)?gp:fp, "Load address of base of array " + this->name); e.emitRO("SUB", actualRegister, rt, actualRegister, "index off of the base"); e.emitRM("LD", actualRegister, 0, actualRegister, "load the value"); } } else { e.emitRM("LD", actualRegister, this->dPtr->offset, (this->dPtr->theScope == TreeNode::Global)?gp:fp, "load variable " + name); } break; case CallK: // dump any used registers to temps before calling a function currentReg = actualRegister; if (currentReg > FIRST_REG_OFFSET) e.emitComment("Need to dump Registers before call"); while (currentReg > FIRST_REG_OFFSET) e.emitRM("ST", --currentReg, toff--, fp, "Save register to temporaries"); dPtr = (DeclarationNode *)symtab->lookup(name.c_str()); currentLoc = toff--; e.emitRM("ST", fp, currentLoc, fp, "Store old fp in ghost frame"); // leave room for return param --toff; // process function parameters argPtr = (ExpressionNode *)this->child[0]; // set the parameter pointer to the function declaration parameters //localToff = toff; while (argPtr != NULL) { //localToff--; //toff--; argPtr->GenCode(e, false, 0, toff); // store expression result e.emitRM("ST", FIRST_REG_OFFSET, toff-- , fp, "Save parameter"); argPtr = (ExpressionNode *)argPtr->sibling; } // prepare for jump e.emitRM("LDA", fp, currentLoc, fp, "Load address of new frame"); e.emitRM("LDA", FIRST_REG_OFFSET, 1, pc, "Put return address in ac"); e.emitRMAbs("LDA", pc, dPtr->offset, "Call " + dPtr->name); // save return value e.emitRM("LDA", actualRegister, 0, rt, "Save the result in current accumulator"); // restore temps back to registers if (currentReg < actualRegister) e.emitComment("Need to restore registers after call"); toff = currentLoc; while (currentReg < actualRegister) e.emitRM("LD", currentReg++, ++toff, fp, "Load Register from Temporaries"); // restore toff //toff = localToff; break; } if (sibling != NULL && travSib) { e.emitComment(NO_COMMENT); sibling->GenCode(e, true, 0, localToff); } }
void unregisterFrom(ExpressionNode<T_element>& e) const { e.unregisterRequiredBy(*this); }
BuiltinExecutables::BuiltinExecutables(VM& vm) : m_vm(vm) #define INITIALIZE_BUILTIN_SOURCE_MEMBERS(name, functionName, length) , m_##name##Source(makeSource(StringImpl::createFromLiteral(s_##name, length))) JSC_FOREACH_BUILTIN_CODE(INITIALIZE_BUILTIN_SOURCE_MEMBERS) #undef EXPOSE_BUILTIN_STRINGS { } UnlinkedFunctionExecutable* BuiltinExecutables::createDefaultConstructor(ConstructorKind constructorKind, const Identifier& name) { static NeverDestroyed<const String> baseConstructorCode(ASCIILiteral("(function () { })")); static NeverDestroyed<const String> derivedConstructorCode(ASCIILiteral("(function () { super(...arguments); })")); switch (constructorKind) { case ConstructorKind::None: break; case ConstructorKind::Base: return createExecutable(m_vm, makeSource(baseConstructorCode), name, constructorKind, ConstructAbility::CanConstruct); case ConstructorKind::Extends: return createExecutable(m_vm, makeSource(derivedConstructorCode), name, constructorKind, ConstructAbility::CanConstruct); } ASSERT_NOT_REACHED(); return nullptr; } UnlinkedFunctionExecutable* BuiltinExecutables::createBuiltinExecutable(const SourceCode& code, const Identifier& name, ConstructAbility constructAbility) { return createExecutable(m_vm, code, name, ConstructorKind::None, constructAbility); } UnlinkedFunctionExecutable* createBuiltinExecutable(VM& vm, const SourceCode& code, const Identifier& name, ConstructAbility constructAbility) { return BuiltinExecutables::createExecutable(vm, code, name, ConstructorKind::None, constructAbility); } UnlinkedFunctionExecutable* BuiltinExecutables::createExecutable(VM& vm, const SourceCode& source, const Identifier& name, ConstructorKind constructorKind, ConstructAbility constructAbility) { JSTextPosition positionBeforeLastNewline; ParserError error; bool isParsingDefaultConstructor = constructorKind != ConstructorKind::None; JSParserBuiltinMode builtinMode = isParsingDefaultConstructor ? JSParserBuiltinMode::NotBuiltin : JSParserBuiltinMode::Builtin; UnlinkedFunctionKind kind = isParsingDefaultConstructor ? UnlinkedNormalFunction : UnlinkedBuiltinFunction; RefPtr<SourceProvider> sourceOverride = isParsingDefaultConstructor ? source.provider() : nullptr; std::unique_ptr<ProgramNode> program = parse<ProgramNode>( &vm, source, Identifier(), builtinMode, JSParserStrictMode::NotStrict, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, error, &positionBeforeLastNewline, constructorKind); if (!program) { dataLog("Fatal error compiling builtin function '", name.string(), "': ", error.message()); CRASH(); } StatementNode* exprStatement = program->singleStatement(); RELEASE_ASSERT(exprStatement); RELEASE_ASSERT(exprStatement->isExprStatement()); ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr(); RELEASE_ASSERT(funcExpr); RELEASE_ASSERT(funcExpr->isFuncExprNode()); FunctionMetadataNode* metadata = static_cast<FuncExprNode*>(funcExpr)->metadata(); RELEASE_ASSERT(!program->hasCapturedVariables()); metadata->setEndPosition(positionBeforeLastNewline); RELEASE_ASSERT(metadata); RELEASE_ASSERT(metadata->ident().isNull()); // This function assumes an input string that would result in a single anonymous function expression. metadata->setEndPosition(positionBeforeLastNewline); RELEASE_ASSERT(metadata); metadata->overrideName(name); VariableEnvironment dummyTDZVariables; UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, kind, constructAbility, dummyTDZVariables, DerivedContextType::None, WTFMove(sourceOverride)); return functionExecutable; }
ExpressionNode Addition::simplify(ExpressionNode& left, ExpressionNode& right) { std::clog << "checkpoint addsimplify" << std::endl; //simplest case: at least one side is just 0 if (left.getType() == NUMBER && left.getValue().getInt() == 0) { return right; } else if (right.getType() == NUMBER && right.getValue().getInt() == 0) { return left; } // for each left term: for each right term: try adding std::stack <ExpressionNode*> leftNodeStack; ExpressionNode * currentLeftNode = &left; bool leftFinished = false; std::stack <ExpressionNode*> rightNodeStack; ExpressionNode * currentRightNode = &right; bool rightFinished = false; ExpressionNode * tempNodePtr; ExpressionNode newNode; while (leftFinished == false) { std::clog << "looping left" << std::endl; if (currentLeftNode->getType() == OPERATION && currentLeftNode->getOperation() == &ADDITION) { if (currentLeftNode->getFirstChild() == 0) { throw ExpressionNode::WrongArityError(); } currentLeftNode = currentLeftNode->getFirstChild(); leftNodeStack.push(currentLeftNode); continue; } // leaf term on left tree: traverse right tree while (rightFinished == false) { std::clog << "looping right" << std::endl; if (currentRightNode->getType() == OPERATION && currentRightNode->getOperation() == &ADDITION) { if (currentRightNode->getFirstChild() == 0) { throw ExpressionNode::WrongArityError(); } currentRightNode = currentRightNode->getFirstChild(); rightNodeStack.push(currentRightNode); continue; } std::clog << "checkpoint addsimplify: before isAddable; " << std::endl; // leaf terms on both sides: attempt adding if (isAddable(*currentLeftNode, *currentRightNode)) { std::clog << "checkpoint addsimplify: after isAddable; " << std::endl; std::clog << *currentLeftNode << " " << *currentRightNode << std::endl; std::clog << "add testrun: " << addTerms(*currentLeftNode, *currentRightNode); (*currentLeftNode).replace( addTerms(*currentLeftNode, *currentRightNode) ); std::clog << "checkpoint addsimplify: after addTerms; " << std::endl; if (currentRightNode == &right) { //entire right tree has been assimilated return left; } tempNodePtr = currentRightNode; currentRightNode = right.findParentOf(*currentRightNode); right.remove(*tempNodePtr); } while (true) { if (rightNodeStack.size() == 0) { rightFinished = true; break; } currentRightNode = rightNodeStack.top(); rightNodeStack.pop(); if (currentRightNode->getRight() != 0) { currentRightNode = currentRightNode->getRight(); rightNodeStack.push(currentRightNode); break; } } } while (true) { if (leftNodeStack.size() == 0) { leftFinished = true; break; } currentLeftNode = leftNodeStack.top(); leftNodeStack.pop(); if (currentLeftNode->getRight() != 0) { currentLeftNode = currentLeftNode->getRight(); leftNodeStack.push(currentLeftNode); break; } } } //still some terms left on right left.setRight(&right); newNode.init(&ADDITION, &left); return newNode; }