| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright Contributors to the OpenVDB Project | ||
| 2 | // SPDX-License-Identifier: MPL-2.0 | ||
| 3 | |||
| 4 | /// @file ast/Scanners.h | ||
| 5 | /// | ||
| 6 | /// @authors Nick Avramoussis, Richard Jones | ||
| 7 | /// | ||
| 8 | /// @brief Retrieve intrinsic information from AX AST by performing | ||
| 9 | /// various traversal algorithms. | ||
| 10 | /// | ||
| 11 | |||
| 12 | #ifndef OPENVDB_AX_COMPILER_AST_SCANNERS_HAS_BEEN_INCLUDED | ||
| 13 | #define OPENVDB_AX_COMPILER_AST_SCANNERS_HAS_BEEN_INCLUDED | ||
| 14 | |||
| 15 | #include "AST.h" | ||
| 16 | #include "Visitor.h" | ||
| 17 | |||
| 18 | #include <openvdb/version.h> | ||
| 19 | |||
| 20 | #include <string> | ||
| 21 | |||
| 22 | namespace openvdb { | ||
| 23 | OPENVDB_USE_VERSION_NAMESPACE | ||
| 24 | namespace OPENVDB_VERSION_NAME { | ||
| 25 | |||
| 26 | namespace ax { | ||
| 27 | namespace ast { | ||
| 28 | |||
| 29 | /// @brief Returns whether or not a given branch of an AST reads from or writes | ||
| 30 | /// to a given attribute. | ||
| 31 | /// | ||
| 32 | /// @param node The AST to analyze | ||
| 33 | /// @param name the name of the attribute to search for | ||
| 34 | /// @param type the type of the attribute to search for. If UNKNOWN, any | ||
| 35 | /// attribute with the given name is checked. | ||
| 36 | /// | ||
| 37 | OPENVDB_AX_API bool usesAttribute(const ast::Node& node, | ||
| 38 | const std::string& name, | ||
| 39 | const tokens::CoreType type = tokens::UNKNOWN); | ||
| 40 | |||
| 41 | /// @brief Returns whether or not a given branch of an AST writes to a given | ||
| 42 | /// attribute. | ||
| 43 | /// | ||
| 44 | /// @param node The AST to analyze | ||
| 45 | /// @param name the name of the attribute to search for | ||
| 46 | /// @param type the type of the attribute to search for. If UNKNOWN, the first | ||
| 47 | /// attribute encountered with the given name is checked. | ||
| 48 | /// | ||
| 49 | OPENVDB_AX_API bool writesToAttribute(const ast::Node& node, | ||
| 50 | const std::string& name, | ||
| 51 | const tokens::CoreType type = tokens::UNKNOWN); | ||
| 52 | |||
| 53 | /// @brief Returns whether or not a given branch of an AST calls a function | ||
| 54 | /// | ||
| 55 | /// @param node The AST to analyze | ||
| 56 | /// @param name the name of the function to search for | ||
| 57 | /// | ||
| 58 | OPENVDB_AX_API bool callsFunction(const ast::Node& node, const std::string& name); | ||
| 59 | |||
| 60 | /// @brief todo | ||
| 61 | OPENVDB_AX_API void catalogueVariables(const ast::Node& node, | ||
| 62 | std::vector<const ast::Variable*>* readOnly, | ||
| 63 | std::vector<const ast::Variable*>* writeOnly, | ||
| 64 | std::vector<const ast::Variable*>* readWrite, | ||
| 65 | const bool locals = true, | ||
| 66 | const bool attributes = true); | ||
| 67 | |||
| 68 | /// @brief Parse all attributes into three unique vectors which represent how they | ||
| 69 | /// are accessed within the syntax tree. Read only attributes are stored | ||
| 70 | /// within the 'readOnly' container (for example @code int a=@a; @endcode), | ||
| 71 | /// write only attributes in the 'writeOnly' container @code @a=1; @endcode | ||
| 72 | /// and readWrite attributes in the 'readWrite' container @code @a+=1; @endcode | ||
| 73 | /// @note Note that the code generator is able to do this far more efficiently, however | ||
| 74 | /// this provides simple front-end support for detecting these types of operations | ||
| 75 | /// | ||
| 76 | /// @param node The AST to analyze | ||
| 77 | /// @param readOnly The unique list of attributes which are only read from | ||
| 78 | /// @param writeOnly The unique list of attributes which are only written too | ||
| 79 | /// @param readWrite The unique list of attributes which both read from and written too | ||
| 80 | /// | ||
| 81 | OPENVDB_AX_API void catalogueAttributeTokens(const ast::Node& node, | ||
| 82 | std::vector<std::string>* readOnly, | ||
| 83 | std::vector<std::string>* writeOnly, | ||
| 84 | std::vector<std::string>* readWrite); | ||
| 85 | |||
| 86 | /// @brief Populate a list of attribute names which the given attribute depends on | ||
| 87 | OPENVDB_AX_API void attributeDependencyTokens(const ast::Tree& tree, | ||
| 88 | const std::string& name, | ||
| 89 | const tokens::CoreType type, | ||
| 90 | std::vector<std::string>& dependencies); | ||
| 91 | |||
| 92 | /// @brief For an AST node of a given type, search for and call a custom | ||
| 93 | /// const operator() which takes a const reference to every occurrence | ||
| 94 | /// of the specified node type. | ||
| 95 | /// | ||
| 96 | /// @param node The AST to run over | ||
| 97 | /// @param op The operator to call on every found AST node of type NodeT | ||
| 98 | /// | ||
| 99 | template <typename NodeT, typename OpT> | ||
| 100 | inline void visitNodeType(const ast::Node& node, const OpT& op); | ||
| 101 | |||
| 102 | /// @brief Visit all nodes of a given type and store pointers to them in a | ||
| 103 | /// provided compatible container | ||
| 104 | template<typename NodeT, typename ContainerType = std::vector<const NodeT*>> | ||
| 105 | inline void collectNodeType(const ast::Node& node, ContainerType& array); | ||
| 106 | |||
| 107 | /// @brief Visit all nodes of the given types and store pointers to them in a | ||
| 108 | /// container of base ast::Node pointers | ||
| 109 | /// @note NodeTypeList is expected to be a an openvdb::TypeList object with a | ||
| 110 | /// list of node types. For example, to collect all Attribute and | ||
| 111 | /// External Variable ast Nodes: | ||
| 112 | /// | ||
| 113 | /// using ListT = openvdb::TypeList<ast::Attribute, ast::ExternalVariable>; | ||
| 114 | /// std::vector<const ast::Node*> nodes; | ||
| 115 | /// ast::collectNodeTypes<ListT>(tree, nodes); | ||
| 116 | /// | ||
| 117 | template <typename NodeTypeList, typename ContainerType = std::vector<const Node*>> | ||
| 118 | inline void collectNodeTypes(const ast::Node& node, ContainerType& array); | ||
| 119 | |||
| 120 | /// @brief Flatten the provided AST branch into a linear list using post order traversal | ||
| 121 | /// | ||
| 122 | OPENVDB_AX_API void linearize(const ast::Node& node, std::vector<const ast::Node*>& list); | ||
| 123 | |||
| 124 | OPENVDB_AX_API const ast::Variable* firstUse(const ast::Node& node, const std::string& token); | ||
| 125 | OPENVDB_AX_API const ast::Variable* lastUse(const ast::Node& node, const std::string& token); | ||
| 126 | |||
| 127 | |||
| 128 | ////////////////////////////////////////////////////////////////////// | ||
| 129 | ////////////////////////////////////////////////////////////////////// | ||
| 130 | |||
| 131 | /// @cond OPENVDB_DOCS_INTERNAL | ||
| 132 | |||
| 133 | namespace internal { | ||
| 134 | template<typename ContainerType, typename T, typename ...Ts> | ||
| 135 | struct CollectForEach { | ||
| 136 | static void exec(const ast::Node&, ContainerType&) {} | ||
| 137 | }; | ||
| 138 | |||
| 139 | template<typename ContainerType, typename T, typename ...Ts> | ||
| 140 | struct CollectForEach<ContainerType, TypeList<T, Ts...>> { | ||
| 141 | 179932 | static void exec(const ast::Node& node, ContainerType& C) { | |
| 142 | collectNodeType<T, ContainerType>(node, C); | ||
| 143 | 89966 | CollectForEach<ContainerType, TypeList<Ts...>>::exec(node, C); | |
| 144 | 179932 | } | |
| 145 | }; | ||
| 146 | } | ||
| 147 | |||
| 148 | // @endcond | ||
| 149 | |||
| 150 | template<typename NodeT, typename ContainerType> | ||
| 151 | inline void collectNodeType(const ast::Node& node, ContainerType& array) | ||
| 152 | { | ||
| 153 | 44983 | visitNodeType<NodeT>(node, [&](const NodeT& node) -> bool { | |
| 154 | 44577 | array.push_back(&node); | |
| 155 | return true; | ||
| 156 | }); | ||
| 157 | 1537 | } | |
| 158 | |||
| 159 | template <typename NodeTypeList, typename ContainerType> | ||
| 160 | inline void collectNodeTypes(const ast::Node& node, ContainerType& array) | ||
| 161 | { | ||
| 162 |
7/14✓ Branch 1 taken 225 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 108 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 116 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 11793 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 17344 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 8783 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 6614 times.
✗ Branch 20 not taken.
|
44983 | internal::CollectForEach<ContainerType, NodeTypeList>::exec(node, array); |
| 163 | 44983 | } | |
| 164 | |||
| 165 | template <typename NodeT, typename OpT, typename Derived = void> | ||
| 166 | struct VisitNodeType : | ||
| 167 | public ast::Visitor<typename std::conditional< | ||
| 168 | std::is_same<Derived, void>::value, | ||
| 169 | VisitNodeType<NodeT, OpT>, | ||
| 170 | Derived>::type> | ||
| 171 | { | ||
| 172 | using VisitorT = typename std::conditional< | ||
| 173 | std::is_same<Derived, void>::value, | ||
| 174 | VisitNodeType<NodeT, OpT>, | ||
| 175 | Derived>::type; | ||
| 176 | |||
| 177 | using ast::Visitor<VisitorT>::traverse; | ||
| 178 | using ast::Visitor<VisitorT>::visit; | ||
| 179 | |||
| 180 | inline bool visitNodeHierarchies() const { | ||
| 181 | return std::is_abstract<NodeT>::value; | ||
| 182 | } | ||
| 183 | |||
| 184 |
1/2✓ Branch 1 taken 19232 times.
✗ Branch 2 not taken.
|
22327 | VisitNodeType(const OpT& op) : mOp(op) {} |
| 185 | ~VisitNodeType() = default; | ||
| 186 | 17121 | inline bool visit(const NodeT* node) { | |
| 187 |
3/4✓ Branch 21 taken 17121 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 23 times.
✓ Branch 24 taken 17098 times.
|
412047 | if (node) return mOp(*node); |
| 188 | return true; | ||
| 189 | } | ||
| 190 | private: | ||
| 191 | const OpT& mOp; | ||
| 192 | }; | ||
| 193 | |||
| 194 | template <typename NodeT, typename OpT> | ||
| 195 | inline void visitNodeType(const ast::Node& node, const OpT& op) | ||
| 196 | { | ||
| 197 | VisitNodeType<NodeT, OpT> visitOp(op); | ||
| 198 |
18/35✓ Branch 1 taken 1540 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1540 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1537 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 1 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 1 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 1 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 1 times.
✗ Branch 50 not taken.
|
100760 | visitOp.traverse(&node); |
| 199 | } | ||
| 200 | |||
| 201 | } // namespace ast | ||
| 202 | } // namespace ax | ||
| 203 | } // namespace OPENVDB_VERSION_NAME | ||
| 204 | } // namespace openvdb | ||
| 205 | |||
| 206 | #endif // OPENVDB_AX_COMPILER_AST_SCANNERS_HAS_BEEN_INCLUDED | ||
| 207 | |||
| 208 | |||
| 209 |