Program Listing for File astQuery.h#
↰ Return to documentation for file (src/midend/astQuery/astQuery.h)
#ifndef ROSE_AST_QUERY
#define ROSE_AST_QUERY
// tps (01/08/2010) Added sage3basic since this doesnt compile under gcc4.1.2
//#include "sage3basic.h"
//#include "sage3.h"
#include "AstProcessing.h"
#include "rosedll.h"
#include <functional>
#include <type_traits>
// Support for operations like (SgTypeInt | SgTypeFloat)
// note that non-terminals would be expanded into the associated terminals!
// So SgType would generate (SgTypeInt | SgTypeFloat | SgTypeDouble | ... | <last type>)
// typedef class NodeQuery::VariantVector VariantVector;
#include "astQueryInheritedAttribute.h"
class ROSE_DLL_API VariantVector : public std::vector < VariantT >
{
// This class is derived from the STL vector class
public:
VariantVector () {}
VariantVector (const VariantT & X);
VariantVector (const VariantVector & X);
VariantVector operator= (const VariantVector & X);
ROSE_DLL_API friend VariantVector operator+ (VariantT lhs, VariantT rhs);
ROSE_DLL_API friend VariantVector operator+ (VariantT lhs, const VariantVector & rhs);
ROSE_DLL_API friend VariantVector operator+ (const VariantVector & lhs, VariantT rhs);
ROSE_DLL_API friend VariantVector operator+ (const VariantVector & lhs, const VariantVector & rhs);
static void printVariantVector (const VariantVector & X);
};
// DQ (4/23/2006): g++ 4.1.0 requires friend functions to be declared outside the class as well!
ROSE_DLL_API VariantVector operator+ (VariantT lhs, VariantT rhs);
ROSE_DLL_API VariantVector operator+ (VariantT lhs, const VariantVector & rhs);
ROSE_DLL_API VariantVector operator+ (const VariantVector & lhs, VariantT rhs);
ROSE_DLL_API VariantVector operator+ (const VariantVector & lhs, const VariantVector & rhs);
namespace AstQueryNamespace
{
template<typename AstQuerySynthesizedAttributeType>
struct helpFunctionalOneParamater
: public std::function<Rose_STL_Container<AstQuerySynthesizedAttributeType>(SgNode*)>
{
// When elementMatchCount == 1 then a match has been made
typedef Rose_STL_Container<AstQuerySynthesizedAttributeType> (*roseFunctionPointerOneParameter) (SgNode *);
roseFunctionPointerOneParameter queryFunctionOneParameter;
// Constructor
helpFunctionalOneParamater (roseFunctionPointerOneParameter function)
{
queryFunctionOneParameter = function;
}
typename Rose_STL_Container<AstQuerySynthesizedAttributeType> operator()(SgNode* node)
{
return queryFunctionOneParameter(node);
}
};
struct helpF : public std::function<bool(bool, bool)>
{
bool operator()(bool x, bool /*y*/)
{
return x;
}
};
template<typename AstQuerySynthesizedAttributeType, typename ArgumentType>
struct helpFunctionalTwoParamaters
: public std::function<Rose_STL_Container<AstQuerySynthesizedAttributeType>(SgNode*, ArgumentType)>
{
// When elementMatchCount==1 then a match has been made
typedef Rose_STL_Container<AstQuerySynthesizedAttributeType> (*roseFunctionPointerTwoParameters) (SgNode *, ArgumentType);
roseFunctionPointerTwoParameters queryFunctionTwoParameters;
helpFunctionalTwoParamaters(roseFunctionPointerTwoParameters function)
{
queryFunctionTwoParameters = function;
}
Rose_STL_Container<AstQuerySynthesizedAttributeType> operator()(SgNode* node, ArgumentType arg)
{
return queryFunctionTwoParameters(node,arg);
}
};
enum QueryDepth
{
UnknownListElementTypeQueryDepth = 0,
ChildrenOnly = 1,
AllNodes = 2,
// DQ (4/8/2004): Added support for extracting types from tranversed
// nodes (types are not generally traversed).
ExtractTypes = 3,
END_OF_NODE_TYPE_LIST_QUERY_DEPTH
};
// #include "variantVector.h"
// **********************************
// Prototypes for Variable Node Query
// **********************************
// forward declaration
class AstQueryInheritedAttributeType;
ROSE_DLL_API void Merge(Rose_STL_Container<SgNode*>& mergeWith, Rose_STL_Container<SgNode*> mergeTo );
ROSE_DLL_API void Merge(Rose_STL_Container<SgFunctionDeclaration*>& mergeWith, Rose_STL_Container<SgFunctionDeclaration*> mergeTo );
ROSE_DLL_API void Merge(Rose_STL_Container<int> & mergeWith, Rose_STL_Container<int> mergeTo );
ROSE_DLL_API void Merge(Rose_STL_Container<std::string> & mergeWith, Rose_STL_Container<std::string> mergeTo );
// DQ & AS (3/14/2007): Added to support us of astQuery with functions returning void* (not clear why void
// does not work, except that void is not really a return type but instead is a signal that there is no
// return type). This is used in the generation of the list of return types (used for testing in AST
// Consistency tests).
ROSE_DLL_API void Merge(void* mergeWith, void* mergeTo );
template<typename ResultType>
void Merge(std::vector<ResultType> & mergeWith, std::vector<ResultType> & mergeTo )
{
mergeWith.push_back(mergeTo);
}
//typedef std::list<SgNode*> AstQuerySynthesizedAttributeType;
class DefaultNodeFunctional : public std::function<Rose_STL_Container<SgNode*>(SgNode*)>
{
public:
result_type operator()(SgNode* node )
{
result_type returnType;
returnType.push_back(node);
return returnType;
}
};
class AstQuery_DUMMY{};
/*******************************************************
* The class
* class AstQuery
* traverses the memory pool and performs the action
* specified in a functional on every node. The return
* value is a list of SgNode*.
*****************************************************/
template<typename AST_Query_Base = AstQuery_DUMMY, typename NodeFunctional = DefaultNodeFunctional>
class AstQuery : public AST_Query_Base
//public ROSE_VisitTraversal, public AstSimpleProcessing
{
//Instantiate the functional which returns the list of nodes to be processed
NodeFunctional* nodeFunc;
static_assert(std::is_invocable_v<NodeFunctional&, SgNode*>,
"AstQuery requires a callable that accepts SgNode*");
//When a node satisfies a functional it is added to
//this list.
typedef std::invoke_result_t<NodeFunctional&, SgNode*> AstQueryReturnType;
AstQueryReturnType listOfNodes;
public:
AstQuery();
AstQuery(NodeFunctional* funct);
virtual ~AstQuery();
//set the node Functional
void setPredicate (NodeFunctional* funct);
//get the result from the query
AstQueryReturnType get_listOfNodes();
//clear the result list of the query. a new
//query can then be restarted using the same object.
void clear_listOfNodes();
//visitor function will apply the functional to every node
//and add the result to the listOfNodes
void visit(SgNode *node);
};
template<typename AST_Query_Base, typename NodeFunctional>
AstQuery<AST_Query_Base,NodeFunctional>::AstQuery(NodeFunctional* funct)
{
nodeFunc = funct;
}
template<typename AST_Query_Base, typename NodeFunctional>
AstQuery<AST_Query_Base,NodeFunctional>::AstQuery()
{
nodeFunc = new DefaultNodeFunctional();
}
template<typename AST_Query_Base, typename NodeFunctional>
void
AstQuery<AST_Query_Base,NodeFunctional>::setPredicate (NodeFunctional* funct)
{
nodeFunc = funct;
}
template<typename AST_Query_Base, typename NodeFunctional>
AstQuery<AST_Query_Base,NodeFunctional>::~AstQuery(){};
template<typename AST_Query_Base, typename NodeFunctional>
typename AstQuery<AST_Query_Base,NodeFunctional>::AstQueryReturnType
AstQuery<AST_Query_Base,NodeFunctional>::get_listOfNodes(){
return listOfNodes;
};
template<typename AST_Query_Base, typename NodeFunctional>
void
AstQuery<AST_Query_Base,NodeFunctional>::clear_listOfNodes(){
listOfNodes.clear();
};
template<typename AST_Query_Base, typename NodeFunctional>
void
AstQuery<AST_Query_Base,NodeFunctional>::visit(SgNode *node) {
ROSE_ASSERT (node != NULL);
ROSE_ASSERT (nodeFunc != NULL);
#if DEBUG_NODEQUERY
printf ("%%%%% TOP of evaluateSynthesizedAttribute (astNode->sage_class_name() = %s,synthesizedAttributeList.size() = %d) \n",
astNode->sage_class_name(), synthesizedAttributeList.size());
#endif
// This function assemble the elements of the input list (a list of lists) to form the output (a single list)
AstQueryNamespace::Merge(listOfNodes, std::invoke(*nodeFunc, node));
}
/********************************************************************************
* The function
* std::list<ListElement> querySubTree<ListElement>(SgNode* node, Predicate& _pred)
* will query the subtree of the IR node in the first argument for nodes satisfying
* the criteria specified in and returned by the predicate in the second argument.
********************************************************************************/
template<typename NodeFunctional>
std::invoke_result_t<NodeFunctional&, SgNode*>
querySubTree(SgNode* node, NodeFunctional nodeFunc, AstQueryNamespace::QueryDepth defineQueryType = AstQueryNamespace::AllNodes,
t_traverseOrder treeTraversalOrder = preorder)
{
static_assert(std::is_invocable_v<NodeFunctional&, SgNode*>,
"nodeFunc must be callable with SgNode*");
ROSE_ASSERT(node!=NULL);
AstQuery<AstSimpleProcessing,NodeFunctional> astQuery(&nodeFunc);
#if 0
printf ("In AstQueryNamespace::querySubTree() switch \n");
#endif
switch (defineQueryType)
{
case AstQueryNamespace::AllNodes:
{
#if 0
printf ("In AstQueryNamespace::querySubTree() case of AstQueryNamespace::AllNodes \n");
#endif
astQuery.traverse(node,treeTraversalOrder);
break;
}
case AstQueryNamespace::ChildrenOnly:
{
//visit only the nodes which is pointed to by this class
typedef std::vector< SgNode *> DataMemberPointerType;
DataMemberPointerType returnData = node->get_traversalSuccessorContainer ();
// A child of a node is the nodes it points to.
for(DataMemberPointerType::iterator i = returnData.begin(); i != returnData.end(); ++i)
{
// visit the node which is pointed to by this SgNode
if( *i != NULL )
astQuery.visit(*i);
};
break;
}
case AstQueryNamespace::ExtractTypes:
printf ("Sorry, ExtractTypes case not implemented for e_OneParameterFunctionClassification! \n");
ROSE_ABORT();
break;
default:
printf ("default reached in switch (queryType) \n");
ROSE_ABORT();
}
return astQuery.get_listOfNodes();
}
/********************************************************************************
* The function
* _Result querySubTree ( SgNode * subTree,
* _Result (*__x)(SgNode*,_Arg), _Arg x_arg,
* AstQueryNamespace::QueryDepth defineQueryType = AstQueryNamespace::AllNodes )
** will query the subtree of the IR node in the first argument for nodes satisfying
* the criteria specified in and returned by the function pointer in the second argument.
********************************************************************************/
template <class _Arg, class _Result>
_Result querySubTree ( SgNode * subTree,
_Result (*__x)(SgNode*,_Arg), _Arg x_arg,
AstQueryNamespace::QueryDepth defineQueryType = AstQueryNamespace::AllNodes ){
return querySubTree(subTree,std::bind(__x,std::placeholders::_1,x_arg),defineQueryType);
}
/********************************************************************************
* The function
* _Result querySubTree ( SgNode * subTree,
* _Result (*__x)(SgNode*),
* AstQueryNamespace::QueryDepth defineQueryType = AstQueryNamespace::AllNodes )
** will query the subtree of the IR node in the first argument for nodes satisfying
* the criteria specified in and returned by the function pointer in the second argument.
********************************************************************************/
template <class _Result>
_Result querySubTree ( SgNode * subTree,
_Result (*__x)(SgNode*),
AstQueryNamespace::QueryDepth defineQueryType = AstQueryNamespace::AllNodes ){
return querySubTree(subTree,[__x](SgNode* n) { return __x(n); },defineQueryType);
}
/********************************************************************************
* The function
* _Result queryRange(typename _Result::const_iterator& begin, typename _Result::const_iterator& end,
* Predicate _pred)
* will query the iterator _Result::const_iterator from 'begin' to 'end' for IR nodes satisfying
* the criteria specified in and returned by the predicate in the third argument.
********************************************************************************/
template <class Iterator, class NodeFunctional>
std::invoke_result_t<NodeFunctional&, SgNode*>
queryRange(Iterator begin, Iterator end,
NodeFunctional nodeFunc){
static_assert(std::is_invocable_v<NodeFunctional&, SgNode*>,
"nodeFunc must be callable with SgNode*");
AstQuery<AstQuery_DUMMY,NodeFunctional> astQuery(&nodeFunc);
for(; begin!=end; ++begin){
astQuery.visit(*begin);
}
return astQuery.get_listOfNodes();
}
/********************************************************************************
* The function
* _Result queryRange(typename _Result::const_iterator& begin, typename _Result::const_iterator& end,
* _Result (*__x)(SgNode*,_Arg), _Arg x_arg,
* AstQueryNamespace::QueryDepth defineQueryType = AstQueryNamespace::AllNodes )
* will query the iterator _Result::const_iterator from 'begin' to 'end' for IR nodes satisfying
* the criteria specified in and returned by the function pointer in the third argument given the
* fourth argument 'x_arg'.
********************************************************************************/
template <class _Arg, class _Result>
_Result queryRange ( typename _Result::iterator begin, const typename _Result::iterator end,
_Result (*__x)(SgNode*,_Arg), _Arg x_arg){
return queryRange(begin,end,std::bind(__x, std::placeholders::_1,x_arg));
}
/********************************************************************************
* The function
* _Result queryRange(typename _Result::const_iterator& begin, typename _Result::const_iterator& end,
* _Result (*__x)(SgNode*),
* AstQueryNamespace::QueryDepth defineQueryType = AstQueryNamespace::AllNodes )
* will query the iterator _Result::const_iterator from 'begin' to 'end' for IR nodes satisfying
* the criteria specified in and returned by the function pointer in the third argument.
********************************************************************************/
template <class _Result>
_Result queryRange (typename _Result::iterator begin, typename _Result::iterator end,
_Result (*__x)(SgNode*)){
return queryRange(begin,end,[__x](SgNode* n) { return __x(n); });
}
/****************************************************************************
* The function
* void queryMemoryPool(ROSE_VisitTraversal& astQuery, VariantVector* variantsToTraverse);
* traverses the parts of the memory pool which has corresponding variants
* in VariantVector.
***************************************************************************/
template <class FunctionalType>
void queryMemoryPool(AstQuery<ROSE_VisitTraversal,FunctionalType>& astQuery, VariantVector* variantsToTraverse);
/********************************************************************************
* The function
* std::list<ListElement> querySubTree<ListElement>(SgNode* node, Predicate& _pred)
* will query the subtree of the IR node in the first argument for nodes satisfying
* the criteria specified in and returned by the predicate in the second argument.
********************************************************************************/
template<typename NodeFunctional>
std::invoke_result_t<NodeFunctional&, SgNode*>
queryMemoryPool(NodeFunctional nodeFunc , VariantVector* targetVariantVector = NULL)
{
static_assert(std::is_invocable_v<NodeFunctional&, SgNode*>,
"nodeFunc must be callable with SgNode*");
AstQuery<ROSE_VisitTraversal,NodeFunctional> astQuery(&nodeFunc);
if(targetVariantVector == NULL){
//Query the whole memory pool
astQuery.traverseMemoryPool();
}else{
queryMemoryPool<NodeFunctional>(astQuery, targetVariantVector);
}; // end if-else
return astQuery.get_listOfNodes();
}
/********************************************************************************
* The function
* _Result querySubTree ( SgNode * subTree,
* _Result (*__x)(SgNode*,_Arg), _Arg x_arg,
* AstQueryNamespace::QueryDepth defineQueryType = AstQueryNamespace::AllNodes ){
** will query the subtree of the IR node in the first argument for nodes satisfying
* the criteria specified in and returned by the function pointer in the second argument.
********************************************************************************/
template <class _Arg, class _Result>
_Result queryMemoryPool (
_Result (*__x)(SgNode*,_Arg), _Arg x_arg,
VariantVector* targetVariantVector = NULL){
return queryMemoryPool(std::bind(__x,std::placeholders::_1,x_arg),targetVariantVector);
}
/********************************************************************************
* The function
* _Result querySubTree ( SgNode * subTree,
* _Result (*__x)(SgNode*),
* AstQueryNamespace::QueryDepth defineQueryType = AstQueryNamespace::AllNodes ){
** will query the subtree of the IR node in the first argument for nodes satisfying
* the criteria specified in and returned by the function pointer in the second argument.
********************************************************************************/
template <class _Result>
_Result queryMemoryPool (
_Result (*__x)(SgNode*),
VariantVector* targetVariantVector = NULL ){
return queryMemoryPool([__x](SgNode* n) { return __x(n); },targetVariantVector);
}
};// END NAMESPACE ASTQUERY
#include "AstQueryMemoryPool.h"
// endif for ROSE_NAME_QUERY
#endif