/// Debug routine to print the given node and its immediate children. The node address is the only mandatory /// argument; the other arguments are a textual description, and a start index and a node count. The start index /// tells the subroutine where to start printing (0 means the given node itself, 1 means the first child node, /// n means the n-th child node. The count gives the number of child nodes which should be printed; /// 0 means print only the given node, 1 means print only one child node, etc. void SCoPVisitor::printNode(const NodeAddress &node, std::string descr, unsigned int start, int count) { // determine total number of child nodes, and adjust count accordingly auto children=node.getChildAddresses(); if (count<0) count=children.size(); // if requested (start=0), print the node itself with some debug information if (start==0) { if (!descr.empty()) descr=" ("+descr+")"; std::cout << std::endl << node.getNodeType() << descr << ": " << node << std::endl; start++; } // iterate over the requested children to complete the output for (unsigned int n=start-1; n<start-1+count; n++) std::cout << "\t-" << n << "\t" << children[n].getNodeType() << ": " << *children[n] << std::endl; }
CodeLocation CodeLocation::shift(const NodeAddress& outer, const utils::AnnotationKeyPtr& key) const { // make some assumptions assert_true(outer.hasAnnotation(key)); assert(any(outer.getAnnotation(key)->getChildNodes(), [&](const NodePtr& cur) { return cur == address.getRootNode(); })); // create a copy of this instance CodeLocation res = *this; // update the annotation path res.annotationPath.insert(res.annotationPath.begin(), std::make_pair(key, address)); // update the address res.address = outer; // done return res; }
NodeAddress getRootVariable(NodeAddress var) { // search in declaration in siblings NodeAddress parent = var.getParentAddress(1); return getRootVariable(parent, var); }
NodeAddress getRootVariable(NodeAddress scope, NodeAddress var) { // if the variable is a literal, its a global variable and should therefore be the root if(var.isa<LiteralAddress>()) { //std::cout << "found literal " << *var << std::endl; return var; } // search in declaration in siblings NodeManager& mgr = var.getNodeManager(); icp::TreePattern localOrGlobalVar = pirp::variable() | pirp::literal(pirp::refType(icp::any), icp::any); icp::TreePattern valueCopy = icp::var("val", pirp::variable()) | pirp::callExpr(mgr.getLangBasic().getRefDeref(), icp::var("val", pirp::variable())) | pirp::callExpr(mgr.getLangBasic().getRefNew(), icp::var("val", pirp::variable())) | pirp::callExpr(mgr.getLangBasic().getRefVar(), icp::var("val", pirp::variable())); // icp::TreePattern valueCopyCast = valueCopy | pirp::castExpr(icp::any, valueCopy); // icp::TreePattern assign = pirp::callExpr((mgr.getLangBasic().getRefAssign()), // single(icp::any)); // icp::var("lhs", pirp::variable()) << valueCopyCast); //std::cout << "var: " << *var << std::endl; //std::cout << "\nscope: " << (scope.getChildAddresses().size()) << std::endl; vector<NodeAddress> childAddresses = scope.getChildAddresses(); for(auto I = childAddresses.rbegin(); I != childAddresses.rend(); ++I) { NodeAddress child = *I; //std::cout << "\tTolles I " << child << std::endl; /* will be implplemented when a propper testcase can be found if(CallExprAddress call = dynamic_address_cast<const CallExpr>(child)) { // if there is an assignment, continue with the variable found at the right hand side if(AddressMatchOpt assignment = assign.matchAddress(call)){ std::cout << "assigning " << printer::PrettyPrinter(assignment->getVarBinding("val").getValue()) << std::endl; std::cout << " to " << printer::PrettyPrinter(assignment->getVarBinding("lhs").getValue()) << std::endl; if(assignment->getVarBinding("lhs").getValue() == var) { return getRootVariable(scope, assignment->getVarBinding("val").getValue()); } } } */ if(child.getDepth() > 4) { if(LambdaAddress lambda = child.isa<LambdaAddress>()) { //std::cout << "Lambda: " << lambda << "\n var " << var << std::endl; // if var is a parameter, continue search for declaration of corresponding argument in outer scope // for(int i = 1; i <= 4; ++i) // std::cout << "\nlp: " << utils::whatIs(lambda.getParentNode(i)) << std::endl; CallExprAddress call = lambda.getParentAddress(4).as<CallExprAddress>(); NodeAddress nextScope, nextVar; for_range(make_paired_range(call->getArguments(), lambda->getParameters()->getElements()), [&](const std::pair<const ExpressionAddress, const VariableAddress>& pair) { if(*var == *pair.second) { nextScope = call.getParentAddress(1); nextVar = tryRemoveDeref(pair.first); return; } }); return getRootVariable(nextScope, nextVar); } } if(DeclarationStmtAddress decl = child.isa<DeclarationStmtAddress>()) { if(*(decl->getVariable()) == *var) { // check if init expression is another variable if(icp::AddressMatchOpt valueInit = valueCopy.matchAddress(decl->getInitialization())) { // if so, continue walk with other variable return getRootVariable(scope, valueInit->getVarBinding("val").getValue()); } //std::cout << "found decl of " << *var << std::endl; // if init is no other varable, the root is found return decl->getVariable(); } } if(CallExprAddress call = var.isa<CallExprAddress>()) { //std::cout << "calling " << *call << std::endl; return getRootVariable(scope, extractVariable(call->getArgument(0))); // crossing my fingers that that will work ;) } } //compound expressions may not open a new scope, therefore declaration can be in the parent return getRootVariable(scope.getParentAddress(), var); }
NodeAddress normalize(const NodeAddress& node) { return node.switchRoot(normalize(node.getRootNode())); }
/// Visit all the child nodes of the given node. The given node itself is not taken into account. /// Hence, this subroutine can only be used in the case you want to traverse all children unconditionally. When /// visiting single child nodes, you cannot use this function to do the work. void SCoPVisitor::visitChildren(const NodeAddress &node) { for (auto child: node->getChildList()) visit(child); }