/* Given a node in the AST, it replaces all function calls with the corresponding expression from the fct2Var mapping. Since we traverse in order of function evaluation, all nodes that are lower in the subtree are supposed to have been mapped, since they have already appeared in the list. Also, we only replace the shallowest level of function calls in the surrent subtree, since we assume that replaceFunctionCallsInExpression has already been called for each of the subtrees rooted at the shallowest function calls lower than the current node: E.g.: f(g(h(i))) + 5 has the AST: + / \ fc1 5 / \ f fc2 / \ g fc3 / \ h i where fc? represents an SgFunctionCallExpression. Order of function evaluation is h(i), g(_), f(_). Calling 'replaceFunctionCallsInExpression' on '+' will generate temp_var + 5 but calling the same function on 'fc2' will generate f(temp_var) + 5 */ void FunctionCallNormalization::replaceFunctionCallsInExpression( SgNode *root, map<SgFunctionCallExp *, SgExpression *> fct2Var ) { if ( !root ) return; if ( NodeQuery::querySubTree( root, V_SgFunctionCallExp ).size() > 0 ) { list<SgNode *> toVisit; toVisit.push_back( root ); while ( !toVisit.empty() ) { SgNode *crt = toVisit.front(); // will visit every node above an function call exp, but not below // also, we will replace function call expressions found if ( !isSgFunctionCallExp( crt ) ) { vector<SgNode *> succ = ( crt )->get_traversalSuccessorContainer(); for ( vector<SgNode *>::iterator succIt = succ.begin(); succIt != succ.end(); succIt++ ) if ( isSgNode ( *succIt ) ) toVisit.push_back( *succIt ); } else { SgFunctionCallExp *call = isSgFunctionCallExp( crt ); ROSE_ASSERT ( call ); map<SgFunctionCallExp *, SgExpression *>::iterator mapIter; mapIter = fct2Var.find( call ); if ( mapIter == fct2Var.end() ) cout << "NOT FOUND " << call->unparseToString() << "\t" << call << "\n"; // a mapping for function call exps in the subtree must already exist ( postorder traversal ) ROSE_ASSERT ( mapIter != fct2Var.end() && mapIter->second ); // duplicate the variable SgTreeCopy treeCopy; SgExpression *scnd = mapIter->second; ROSE_ASSERT ( isSgExpression( scnd ) ); SgExpression *newVar = isSgExpression( scnd->copy( treeCopy ) ); ROSE_ASSERT ( newVar ); SgExpression *parent = isSgExpression( call->get_parent() ); ROSE_ASSERT ( parent ); // replace the node in the AST newVar->set_parent( parent ); int k = parent->replace_expression( call, newVar ); ROSE_ASSERT ( k == 1 ); delete call; } toVisit.pop_front(); } } }