| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright Contributors to the OpenVDB Project | ||
| 2 | // SPDX-License-Identifier: MPL-2.0 | ||
| 3 | |||
| 4 | /// @file ast/Visitor.h | ||
| 5 | /// | ||
| 6 | /// @authors Nick Avramoussis | ||
| 7 | /// | ||
| 8 | /// @brief Contains the AX AST Node Visitor, providing default and | ||
| 9 | /// customizable traversal and visitation methods on a AST hierarchy. | ||
| 10 | /// Using the visitor pattern is the recommended way to implement | ||
| 11 | /// custom operations on AST nodes. | ||
| 12 | /// | ||
| 13 | |||
| 14 | #ifndef OPENVDB_AX_AST_VISITOR_HAS_BEEN_INCLUDED | ||
| 15 | #define OPENVDB_AX_AST_VISITOR_HAS_BEEN_INCLUDED | ||
| 16 | |||
| 17 | #include "AST.h" | ||
| 18 | #include "Tokens.h" | ||
| 19 | |||
| 20 | #include <openvdb/version.h> | ||
| 21 | |||
| 22 | #include <type_traits> | ||
| 23 | |||
| 24 | namespace openvdb { | ||
| 25 | OPENVDB_USE_VERSION_NAMESPACE | ||
| 26 | namespace OPENVDB_VERSION_NAME { | ||
| 27 | |||
| 28 | namespace ax { | ||
| 29 | namespace ast { | ||
| 30 | |||
| 31 | /// @brief The Visitor class uses the Curiously Recursive Template Pattern | ||
| 32 | /// (CRTP) to provide a customizable interface intended to be used by | ||
| 33 | /// clients wishing to perform custom operations over an AX Abstract | ||
| 34 | /// Syntax Tree (AST). By default the Visitor implements simple | ||
| 35 | /// traversal of all nodes, ensuring that each node on a well formed | ||
| 36 | /// AST is visited at least once. By deriving from the Visitor, users | ||
| 37 | /// are able to customize this default behavior and further manually | ||
| 38 | /// override specific node behavior to their needs. The function | ||
| 39 | /// options at the top of visitor can be overridden using CRTP to | ||
| 40 | /// control the prior default behavior, with the ability to override | ||
| 41 | /// the traverse() and visit() methods for the latter more granular | ||
| 42 | /// control. | ||
| 43 | /// | ||
| 44 | /// @details To commence a full visit of an AST, begin by calling traverse() on | ||
| 45 | /// a Node pointer. A visit is defined as one of the visit() methods | ||
| 46 | /// being called and accepting a Node type. Each node is is guaranteed | ||
| 47 | /// to be visited exactly once at its lowest concrete derived type. | ||
| 48 | /// Node inheritance hierarchies can also be visited (disable by | ||
| 49 | /// default, see Visitor::visitNodeHierarchies) The traverse() methods | ||
| 50 | /// define how each AST node accesses its children. The default | ||
| 51 | /// implementation is for each node to traverses its child pointers in | ||
| 52 | /// the order returned by the derived Node::child() method | ||
| 53 | /// (see Visitor::reverseChildVisits). You'll typically only require | ||
| 54 | /// overriding of the visit() methods for achieving most goals, however | ||
| 55 | /// you can utilize the traverse methods if you find that you require | ||
| 56 | /// more control over how the node hierarchy is accessed. The default | ||
| 57 | /// visit order is post order, where by nodes traverse and visit their | ||
| 58 | /// children first (see Visitor::postOrderNodes). Each visit method | ||
| 59 | /// returns a boolean value which, if false, allows for early | ||
| 60 | /// termination of the traversal. In the below example, we show a | ||
| 61 | /// Visitor capable of visiting every Local node type exactly once, | ||
| 62 | /// terminating if the Local variable is called "var". | ||
| 63 | /// | ||
| 64 | /// @par Example: | ||
| 65 | /// @code | ||
| 66 | /// struct LocalVisitor : public Visitor<LocalVisitor> | ||
| 67 | /// { | ||
| 68 | /// // Bring in all base methods to avoid hiding | ||
| 69 | /// using ast::Visitor<LocalVisitor>::traverse; | ||
| 70 | /// using ast::Visitor<LocalVisitor>::visit; | ||
| 71 | /// | ||
| 72 | /// // override the visit for Local AST nodes | ||
| 73 | /// inline bool visit(const Local* node) { | ||
| 74 | /// if (!node) return true; | ||
| 75 | /// if (node->name() == "var") return false; | ||
| 76 | /// return true; | ||
| 77 | /// } | ||
| 78 | /// }; | ||
| 79 | /// | ||
| 80 | /// LocalVisitor visitor; | ||
| 81 | /// visitor.traverse(&tree); | ||
| 82 | /// @endcode | ||
| 83 | /// | ||
| 84 | /// @note The second template argument, ConstVisit, allows you to perform | ||
| 85 | /// non-const traversals over the AST. In this case, the visit and | ||
| 86 | /// traversal function signatures change to non-const pointers. | ||
| 87 | /// @note This design is heavily influenced by Clang's RecursiveVisitor. | ||
| 88 | /// | ||
| 89 | /// @tparam Derived The derived visitor to template on the base visitor, | ||
| 90 | /// using CRTP | ||
| 91 | /// @tparam ConstVisit Whether to visit const or non-const versions of the AST | ||
| 92 | /// nodes. Note that this value changes the class function | ||
| 93 | /// signatures. | ||
| 94 | template <typename Derived, bool ConstVisit=true> | ||
| 95 | struct Visitor | ||
| 96 | { | ||
| 97 | /// @brief Templated conditional which resolves to a const NodeT if | ||
| 98 | /// ConstVisit is true, or a non-const NodeT if ConstVisit is false | ||
| 99 | template <typename NodeT> | ||
| 100 | using NodeType = typename std::conditional<ConstVisit, const NodeT, NodeT>::type; | ||
| 101 | |||
| 102 | /// @brief Accesses the derived class by static casting the current object. | ||
| 103 | /// Assumes use of the Curiously Recursive Template Pattern (CRTP). | ||
| 104 | inline Derived& derived() { | ||
| 105 | return *static_cast<Derived*>(this); | ||
| 106 | } | ||
| 107 | |||
| 108 | /// @name Options | ||
| 109 | /// @{ | ||
| 110 | |||
| 111 | /// @brief Default behavior option. If true, this results in post-order | ||
| 112 | /// traversal, where node children are traversed and visited before | ||
| 113 | /// their parent node. If false, this results in pre-order | ||
| 114 | /// traversal, where by the current node is visited before the | ||
| 115 | /// node's children. | ||
| 116 | /// @details Post-order traversal (for each node): | ||
| 117 | /// 1. Traverse all children. | ||
| 118 | /// 2. Visit the current node. | ||
| 119 | /// Pre-order traversal (for each node): | ||
| 120 | /// 1. Visit the current node. | ||
| 121 | /// 2. Traverse all children. | ||
| 122 | inline bool postOrderNodes() const { return true; } | ||
| 123 | |||
| 124 | /// @brief Default behavior option. Reverses the traversal order of child | ||
| 125 | /// nodes. If true, child nodes are accessed from last to first | ||
| 126 | /// index .i.e. Node::children() -> 0. If false, child nodes are | ||
| 127 | /// accessed from first to last .i.e. 0 -> Node::children() | ||
| 128 | inline bool reverseChildVisits() const { return false; } | ||
| 129 | |||
| 130 | /// @brief Default behavior option. Controls whether nodes visit themselves | ||
| 131 | /// at each stage of their class hierarchy. If true, nodes perform | ||
| 132 | /// multiple visits on their potentially abstract base classes. If | ||
| 133 | /// false, only the concrete derived types are visited. | ||
| 134 | /// @details When disabled, abstract node visitor methods are never accessed | ||
| 135 | /// directly through the default Visitor implementation. These | ||
| 136 | /// types include Node, Statement, Expression, etc AST nodes. | ||
| 137 | /// If true, for each linearly inherited AST node, a visit is | ||
| 138 | /// performed on the entire hierarchy. For example, for a Local AST | ||
| 139 | /// node which derives from Variable -> Expression -> Statement -> | ||
| 140 | /// Node, 5 visits will be performed at each level. | ||
| 141 | inline bool visitNodeHierarchies() const { return false; } | ||
| 142 | |||
| 143 | /// @brief Default behavior option. Reverses the traversal order of node | ||
| 144 | /// hierarchies. If true, hierarchical visits start at the very top | ||
| 145 | /// of their inheritance structure (always a Node AST node) and | ||
| 146 | /// visit downwards until the lowest derived concrete node is | ||
| 147 | /// reached. If false, hierarchical visits start at the lowest | ||
| 148 | /// derived concrete node and visit upwards until the very top of | ||
| 149 | /// their inheritance structure (always a Node AST node) is reached. | ||
| 150 | /// @note Has no effect if visitNodeHierarchies() is false | ||
| 151 | inline bool reverseHierarchyVisits() const { return false; } | ||
| 152 | |||
| 153 | /// @} | ||
| 154 | |||
| 155 | /// @name Traversals | ||
| 156 | /// @{ | ||
| 157 | |||
| 158 | /// @brief Default traversals for a given concrete AST node type | ||
| 159 | /// @return True if traversal should continue, false to terminate | ||
| 160 | |||
| 161 | 78776 | bool traverse(NodeType<ast::Tree>* tree) { | |
| 162 |
2/3✓ Branch 1 taken 2302 times.
✓ Branch 2 taken 290 times.
✗ Branch 3 not taken.
|
81368 | return this->defaultTraversal<ast::Tree>(tree); |
| 163 | } | ||
| 164 | |||
| 165 | 9260 | bool traverse(NodeType<ast::StatementList>* cond) { | |
| 166 | 9260 | return this->defaultTraversal<ast::StatementList>(cond); | |
| 167 | } | ||
| 168 | |||
| 169 | 24986 | bool traverse(NodeType<ast::Block>* block) { | |
| 170 | 70517 | return this->defaultTraversal<ast::Block>(block); | |
| 171 | } | ||
| 172 | |||
| 173 | 7900 | bool traverse(NodeType<ast::CommaOperator>* comma) { | |
| 174 | 7900 | return this->defaultTraversal<ast::CommaOperator>(comma); | |
| 175 | } | ||
| 176 | |||
| 177 | 2440 | bool traverse(NodeType<ast::Loop>* loop) { | |
| 178 | 2440 | return this->defaultTraversal<ast::Loop>(loop); | |
| 179 | } | ||
| 180 | |||
| 181 | 5995 | bool traverse(NodeType<ast::Keyword>* keyw) { | |
| 182 | 5995 | return this->defaultTraversal<ast::Keyword>(keyw); | |
| 183 | } | ||
| 184 | |||
| 185 | 7730 | bool traverse(NodeType<ast::ConditionalStatement>* cond) { | |
| 186 | 7730 | return this->defaultTraversal<ast::ConditionalStatement>(cond); | |
| 187 | } | ||
| 188 | |||
| 189 | 627820 | bool traverse(NodeType<ast::AssignExpression>* asgn) { | |
| 190 | 627820 | return this->defaultTraversal<ast::AssignExpression>(asgn); | |
| 191 | } | ||
| 192 | |||
| 193 | 53458 | bool traverse(NodeType<ast::Crement>* crmt) { | |
| 194 | 53458 | return this->defaultTraversal<ast::Crement>(crmt); | |
| 195 | } | ||
| 196 | |||
| 197 | 215070 | bool traverse(NodeType<ast::UnaryOperator>* unry) { | |
| 198 | 215070 | return this->defaultTraversal<ast::UnaryOperator>(unry); | |
| 199 | } | ||
| 200 | |||
| 201 | 195706 | bool traverse(NodeType<ast::BinaryOperator>* bin) { | |
| 202 | 195706 | return this->defaultTraversal<ast::BinaryOperator>(bin); | |
| 203 | } | ||
| 204 | |||
| 205 | 15502 | bool traverse(NodeType<ast::TernaryOperator>* tern) { | |
| 206 | 15502 | return this->defaultTraversal<ast::TernaryOperator>(tern); | |
| 207 | } | ||
| 208 | |||
| 209 | 3708 | bool traverse(NodeType<ast::Cast>* cast) { | |
| 210 | 3708 | return this->defaultTraversal<ast::Cast>(cast); | |
| 211 | } | ||
| 212 | |||
| 213 | 300955 | bool traverse(NodeType<ast::FunctionCall>* call) { | |
| 214 | 300955 | return this->defaultTraversal<ast::FunctionCall>(call); | |
| 215 | } | ||
| 216 | |||
| 217 | 653056 | bool traverse(NodeType<ast::Attribute>* attr) { | |
| 218 | 671237 | return this->defaultTraversal<ast::Attribute>(attr); | |
| 219 | } | ||
| 220 | |||
| 221 | 1715 | bool traverse(NodeType<ast::ExternalVariable>* ext) { | |
| 222 | 1796 | return this->defaultTraversal<ast::ExternalVariable>(ext); | |
| 223 | } | ||
| 224 | |||
| 225 | 189760 | bool traverse(NodeType<ast::DeclareLocal>* decl) { | |
| 226 | 189760 | return this->defaultTraversal<ast::DeclareLocal>(decl); | |
| 227 | } | ||
| 228 | |||
| 229 | 364757 | bool traverse(NodeType<ast::Local>* loc) { | |
| 230 | 539062 | return this->defaultTraversal<ast::Local>(loc); | |
| 231 | } | ||
| 232 | |||
| 233 | 247239 | bool traverse(NodeType<ast::ArrayPack>* pack) { | |
| 234 | 247239 | return this->defaultTraversal<ast::ArrayPack>(pack); | |
| 235 | } | ||
| 236 | |||
| 237 | 249276 | bool traverse(NodeType<ast::ArrayUnpack>* pack) { | |
| 238 | 249276 | return this->defaultTraversal<ast::ArrayUnpack>(pack); | |
| 239 | } | ||
| 240 | |||
| 241 | 51811 | bool traverse(NodeType<ast::Value<bool>>* val) { | |
| 242 | 51811 | return this->defaultTraversal<ast::Value<bool>>(val); | |
| 243 | } | ||
| 244 | |||
| 245 | ✗ | bool traverse(NodeType<ast::Value<int16_t>>* val) { | |
| 246 | ✗ | return this->defaultTraversal<ast::Value<int16_t>>(val); | |
| 247 | } | ||
| 248 | |||
| 249 | 696881 | bool traverse(NodeType<ast::Value<int32_t>>* val) { | |
| 250 | 696881 | return this->defaultTraversal<ast::Value<int32_t>>(val); | |
| 251 | } | ||
| 252 | |||
| 253 | 21756 | bool traverse(NodeType<ast::Value<int64_t>>* val) { | |
| 254 | 21756 | return this->defaultTraversal<ast::Value<int64_t>>(val); | |
| 255 | } | ||
| 256 | |||
| 257 | 709648 | bool traverse(NodeType<ast::Value<float>>* val) { | |
| 258 | 709648 | return this->defaultTraversal<ast::Value<float>>(val); | |
| 259 | } | ||
| 260 | |||
| 261 | 635285 | bool traverse(NodeType<ast::Value<double>>* val) { | |
| 262 | 676674 | return this->defaultTraversal<ast::Value<double>>(val); | |
| 263 | } | ||
| 264 | |||
| 265 | 13870 | bool traverse(NodeType<ast::Value<std::string>>* val) { | |
| 266 | 20388 | return this->defaultTraversal<ast::Value<std::string>>(val); | |
| 267 | } | ||
| 268 | |||
| 269 | /// @brief The default traversal method which is hit for all child | ||
| 270 | /// traversals. The correct derived traversal scheme is selected by | ||
| 271 | /// using the node enumerated type. | ||
| 272 | /// @note Only handles traversal on concrete node types. | ||
| 273 | 6113120 | bool traverse(NodeType<ast::Node>* node) { | |
| 274 |
2/2✓ Branch 0 taken 2987012 times.
✓ Branch 1 taken 113602 times.
|
6113120 | if (!node) return true; |
| 275 |
26/28✓ Branch 1 taken 39388 times.
✓ Branch 2 taken 4799 times.
✓ Branch 3 taken 12662 times.
✓ Branch 4 taken 4137 times.
✓ Branch 5 taken 7349 times.
✓ Branch 6 taken 3042 times.
✓ Branch 7 taken 4042 times.
✓ Branch 8 taken 319650 times.
✓ Branch 9 taken 27122 times.
✓ Branch 10 taken 109376 times.
✓ Branch 11 taken 99725 times.
✓ Branch 12 taken 7939 times.
✓ Branch 13 taken 1895 times.
✓ Branch 14 taken 356802 times.
✓ Branch 15 taken 152949 times.
✓ Branch 16 taken 977 times.
✓ Branch 17 taken 98475 times.
✓ Branch 18 taken 125592 times.
✓ Branch 19 taken 125902 times.
✓ Branch 20 taken 356381 times.
✓ Branch 21 taken 26239 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 352531 times.
✓ Branch 24 taken 11076 times.
✓ Branch 25 taken 360560 times.
✓ Branch 26 taken 364949 times.
✓ Branch 27 taken 13453 times.
✗ Branch 28 not taken.
|
5888007 | switch (node->nodetype()) { |
| 276 | 78776 | case Node::TreeNode : return this->derived().traverse(static_cast<NodeType<ast::Tree>*>(node)); | |
| 277 | 9270 | case Node::StatementListNode : return this->derived().traverse(static_cast<NodeType<ast::StatementList>*>(node)); | |
| 278 | 24986 | case Node::BlockNode : return this->derived().traverse(static_cast<NodeType<ast::Block>*>(node)); | |
| 279 | 7918 | case Node::CommaOperatorNode : return this->derived().traverse(static_cast<NodeType<ast::CommaOperator>*>(node)); | |
| 280 | 14298 | case Node::LoopNode : return this->derived().traverse(static_cast<NodeType<ast::Loop>*>(node)); | |
| 281 | 5995 | case Node::KeywordNode : return this->derived().traverse(static_cast<NodeType<ast::Keyword>*>(node)); | |
| 282 | 7738 | case Node::ConditionalStatementNode : return this->derived().traverse(static_cast<NodeType<ast::ConditionalStatement>*>(node)); | |
| 283 | 627852 | case Node::AssignExpressionNode : return this->derived().traverse(static_cast<NodeType<ast::AssignExpression>*>(node)); | |
| 284 | 53470 | case Node::CrementNode : return this->derived().traverse(static_cast<NodeType<ast::Crement>*>(node)); | |
| 285 | 215070 | case Node::UnaryOperatorNode : return this->derived().traverse(static_cast<NodeType<ast::UnaryOperator>*>(node)); | |
| 286 | 195762 | case Node::BinaryOperatorNode : return this->derived().traverse(static_cast<NodeType<ast::BinaryOperator>*>(node)); | |
| 287 | 15510 | case Node::TernaryOperatorNode : return this->derived().traverse(static_cast<NodeType<ast::TernaryOperator>*>(node)); | |
| 288 | 3708 | case Node::CastNode : return this->derived().traverse(static_cast<NodeType<ast::Cast>*>(node)); | |
| 289 | 701513 | case Node::AttributeNode : return this->derived().traverse(static_cast<NodeType<ast::Attribute>*>(node)); | |
| 290 | 300955 | case Node::FunctionCallNode : return this->derived().traverse(static_cast<NodeType<ast::FunctionCall>*>(node)); | |
| 291 | 1877 | case Node::ExternalVariableNode : return this->derived().traverse(static_cast<NodeType<ast::ExternalVariable>*>(node)); | |
| 292 | 189776 | case Node::DeclareLocalNode : return this->derived().traverse(static_cast<NodeType<ast::DeclareLocal>*>(node)); | |
| 293 | 247245 | case Node::ArrayPackNode : return this->derived().traverse(static_cast<NodeType<ast::ArrayPack>*>(node)); | |
| 294 | 249294 | case Node::ArrayUnpackNode : return this->derived().traverse(static_cast<NodeType<ast::ArrayUnpack>*>(node)); | |
| 295 | 706199 | case Node::LocalNode : return this->derived().traverse(static_cast<NodeType<ast::Local>*>(node)); | |
| 296 | 51811 | case Node::ValueBoolNode : return this->derived().traverse(static_cast<NodeType<ast::Value<bool>>*>(node)); | |
| 297 | ✗ | case Node::ValueInt16Node : return this->derived().traverse(static_cast<NodeType<ast::Value<int16_t>>*>(node)); | |
| 298 | 696881 | case Node::ValueInt32Node : return this->derived().traverse(static_cast<NodeType<ast::Value<int32_t>>*>(node)); | |
| 299 | 21756 | case Node::ValueInt64Node : return this->derived().traverse(static_cast<NodeType<ast::Value<int64_t>>*>(node)); | |
| 300 | 709648 | case Node::ValueFloatNode : return this->derived().traverse(static_cast<NodeType<ast::Value<float>>*>(node)); | |
| 301 | 718063 | case Node::ValueDoubleNode : return this->derived().traverse(static_cast<NodeType<ast::Value<double>>*>(node)); | |
| 302 | 26301 | case Node::ValueStrNode : return this->derived().traverse(static_cast<NodeType<ast::Value<std::string>>*>(node)); | |
| 303 | default : return true; | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | /// @} | ||
| 308 | |||
| 309 | /// @name Visits | ||
| 310 | /// @{ | ||
| 311 | |||
| 312 | /// @brief Visits for abstract (pure-virtual) Node types. | ||
| 313 | /// @note These are only hit through the default behavior if | ||
| 314 | /// Visitor::visitNodeHierarchies is enabled. | ||
| 315 | /// @return True if traversal should continue, false to terminate | ||
| 316 | inline bool visit(NodeType<ast::Node>*) { return true; } | ||
| 317 | inline bool visit(NodeType<ast::Statement>*) { return true; } | ||
| 318 | inline bool visit(NodeType<ast::Expression>*) { return true; } | ||
| 319 | inline bool visit(NodeType<ast::Variable>*) { return true; } | ||
| 320 | inline bool visit(NodeType<ast::ValueBase>*) { return true; } | ||
| 321 | |||
| 322 | /// @brief Visits for concrete Node types. | ||
| 323 | /// @return True if traversal should continue, false to terminate | ||
| 324 | inline bool visit(NodeType<ast::Tree>*) { return true; } | ||
| 325 | inline bool visit(NodeType<ast::StatementList>*) { return true; } | ||
| 326 | inline bool visit(NodeType<ast::Block>*) { return true; } | ||
| 327 | inline bool visit(NodeType<ast::CommaOperator>*) { return true; } | ||
| 328 | inline bool visit(NodeType<ast::Loop>*) { return true; } | ||
| 329 | inline bool visit(NodeType<ast::Keyword>*) { return true; } | ||
| 330 | inline bool visit(NodeType<ast::ConditionalStatement>*) { return true; } | ||
| 331 | inline bool visit(NodeType<ast::AssignExpression>*) { return true; } | ||
| 332 | inline bool visit(NodeType<ast::Crement>*) { return true; } | ||
| 333 | inline bool visit(NodeType<ast::UnaryOperator>*) { return true; } | ||
| 334 | inline bool visit(NodeType<ast::BinaryOperator>*) { return true; } | ||
| 335 | inline bool visit(NodeType<ast::TernaryOperator>*) { return true; } | ||
| 336 | inline bool visit(NodeType<ast::Cast>*) { return true; } | ||
| 337 | inline bool visit(NodeType<ast::FunctionCall>*) { return true; } | ||
| 338 | inline bool visit(NodeType<ast::Attribute>*) { return true; } | ||
| 339 | inline bool visit(NodeType<ast::ExternalVariable>*) { return true; } | ||
| 340 | inline bool visit(NodeType<ast::DeclareLocal>*) { return true; } | ||
| 341 | inline bool visit(NodeType<ast::Local>*) { return true; } | ||
| 342 | inline bool visit(NodeType<ast::ArrayPack>*) { return true; } | ||
| 343 | inline bool visit(NodeType<ast::ArrayUnpack>*) { return true; } | ||
| 344 | inline bool visit(NodeType<ast::Value<bool>>*) { return true; } | ||
| 345 | inline bool visit(NodeType<ast::Value<int16_t>>*) { return true; } | ||
| 346 | inline bool visit(NodeType<ast::Value<int32_t>>*) { return true; } | ||
| 347 | inline bool visit(NodeType<ast::Value<int64_t>>*) { return true; } | ||
| 348 | inline bool visit(NodeType<ast::Value<float>>*) { return true; } | ||
| 349 | inline bool visit(NodeType<ast::Value<double>>*) { return true; } | ||
| 350 | inline bool visit(NodeType<ast::Value<std::string>>*) { return true; } | ||
| 351 | |||
| 352 | /// @} | ||
| 353 | |||
| 354 | private: | ||
| 355 | /// @brief Enabled for const traversals, where by the node pointer is | ||
| 356 | /// returned | ||
| 357 | /// @param Const reference to an AST node | ||
| 358 | /// @return Const pointer to the node | ||
| 359 | template <bool V, typename NodeT> | ||
| 360 | inline typename std::enable_if<V, const NodeT*>::type | ||
| 361 | strip(const NodeT* node) { | ||
| 362 | return node; | ||
| 363 | } | ||
| 364 | |||
| 365 | /// @brief Enabled for non-const traversals, where by a const stripped node | ||
| 366 | /// pointer is returned | ||
| 367 | /// @param Const reference to an AST node | ||
| 368 | /// @return Non-const pointer to the node | ||
| 369 | template <bool V, typename NodeT> | ||
| 370 | inline typename std::enable_if<!V, typename std::remove_const<NodeT>::type*>::type | ||
| 371 | strip(const NodeT* node) { | ||
| 372 | return const_cast<NodeT*>(node); | ||
| 373 | } | ||
| 374 | |||
| 375 | /// @brief Implements recursive hierarchical visits to a given AST node | ||
| 376 | /// @tparam NodeT The node type | ||
| 377 | /// @param node The node to perform class hierarchy visits on | ||
| 378 | /// @return True if traversal should continue, false to terminate | ||
| 379 | template <typename NodeT> | ||
| 380 |
1/2✓ Branch 0 taken 3048 times.
✗ Branch 1 not taken.
|
6096 | bool hierarchyVisits(NodeT& node) |
| 381 | { | ||
| 382 | if (this->derived().reverseHierarchyVisits()) { | ||
| 383 | if (auto base = node.NodeT::basetype()) { | ||
| 384 | if (!hierarchyVisits(*base)) return false; | ||
| 385 | } | ||
| 386 | if (!this->derived().visit(this->strip<ConstVisit>(&node))) return false; | ||
| 387 | } | ||
| 388 | else { | ||
| 389 |
4/6✓ Branch 0 taken 164070 times.
✓ Branch 1 taken 6651 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 154825 times.
✓ Branch 5 taken 12581 times.
|
338127 | if (!this->derived().visit(this->strip<ConstVisit>(&node))) return false; |
| 390 |
78/358✓ Branch 0 taken 3092 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3102 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3096 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 19 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 585 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 129 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 913 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 117 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 117 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 35 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 243 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 96 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 96 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 6 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 6 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 84 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 84 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 224 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 224 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 14 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 14 times.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✓ Branch 46 taken 170721 times.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✓ Branch 50 taken 167406 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 1 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 1 times.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 108 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✓ Branch 114 taken 1 times.
✗ Branch 115 not taken.
✓ Branch 116 taken 1 times.
✗ Branch 117 not taken.
✓ Branch 118 taken 1 times.
✗ Branch 119 not taken.
✓ Branch 120 taken 1 times.
✗ Branch 121 not taken.
✓ Branch 122 taken 1 times.
✗ Branch 123 not taken.
✓ Branch 124 taken 1 times.
✗ Branch 125 not taken.
✓ Branch 126 taken 2 times.
✗ Branch 127 not taken.
✓ Branch 128 taken 2 times.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 131 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 134 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 137 not taken.
✓ Branch 138 taken 1 times.
✗ Branch 139 not taken.
✓ Branch 140 taken 1 times.
✗ Branch 141 not taken.
✓ Branch 142 taken 1 times.
✗ Branch 143 not taken.
✓ Branch 144 taken 1 times.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
✗ Branch 147 not taken.
✗ Branch 148 not taken.
✗ Branch 149 not taken.
✗ Branch 150 not taken.
✗ Branch 151 not taken.
✓ Branch 152 taken 2 times.
✗ Branch 153 not taken.
✓ Branch 154 taken 2 times.
✗ Branch 155 not taken.
✗ Branch 156 not taken.
✗ Branch 157 not taken.
✗ Branch 158 not taken.
✗ Branch 159 not taken.
✗ Branch 160 not taken.
✗ Branch 161 not taken.
✗ Branch 162 not taken.
✗ Branch 163 not taken.
✗ Branch 164 not taken.
✗ Branch 165 not taken.
✓ Branch 166 taken 3 times.
✗ Branch 167 not taken.
✗ Branch 168 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 171 not taken.
✓ Branch 172 taken 1 times.
✗ Branch 173 not taken.
✓ Branch 174 taken 1 times.
✗ Branch 175 not taken.
✓ Branch 176 taken 1 times.
✗ Branch 177 not taken.
✗ Branch 178 not taken.
✗ Branch 179 not taken.
✗ Branch 180 not taken.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✗ Branch 183 not taken.
✗ Branch 184 not taken.
✗ Branch 185 not taken.
✗ Branch 186 not taken.
✗ Branch 187 not taken.
✓ Branch 188 taken 1 times.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 191 not taken.
✗ Branch 192 not taken.
✗ Branch 193 not taken.
✗ Branch 194 not taken.
✗ Branch 195 not taken.
✗ Branch 196 not taken.
✗ Branch 197 not taken.
✓ Branch 198 taken 1 times.
✗ Branch 199 not taken.
✓ Branch 200 taken 1 times.
✗ Branch 201 not taken.
✓ Branch 202 taken 1 times.
✗ Branch 203 not taken.
✓ Branch 204 taken 1 times.
✗ Branch 205 not taken.
✓ Branch 206 taken 1 times.
✗ Branch 207 not taken.
✓ Branch 208 taken 1 times.
✗ Branch 209 not taken.
✓ Branch 210 taken 1 times.
✗ Branch 211 not taken.
✓ Branch 212 taken 1 times.
✗ Branch 213 not taken.
✓ Branch 214 taken 1 times.
✗ Branch 215 not taken.
✓ Branch 216 taken 1 times.
✗ Branch 217 not taken.
✓ Branch 218 taken 1 times.
✗ Branch 219 not taken.
✓ Branch 220 taken 1 times.
✗ Branch 221 not taken.
✓ Branch 222 taken 2 times.
✗ Branch 223 not taken.
✓ Branch 224 taken 2 times.
✗ Branch 225 not taken.
✓ Branch 226 taken 2 times.
✗ Branch 227 not taken.
✓ Branch 228 taken 2 times.
✗ Branch 229 not taken.
✗ Branch 230 not taken.
✗ Branch 231 not taken.
✗ Branch 232 not taken.
✗ Branch 233 not taken.
✗ Branch 234 not taken.
✗ Branch 235 not taken.
✗ Branch 236 not taken.
✗ Branch 237 not taken.
✗ Branch 238 not taken.
✗ Branch 239 not taken.
✗ Branch 240 not taken.
✗ Branch 241 not taken.
✗ Branch 242 not taken.
✗ Branch 243 not taken.
✗ Branch 244 not taken.
✗ Branch 245 not taken.
✓ Branch 246 taken 1 times.
✗ Branch 247 not taken.
✓ Branch 248 taken 1 times.
✗ Branch 249 not taken.
✓ Branch 250 taken 1 times.
✗ Branch 251 not taken.
✓ Branch 252 taken 1 times.
✗ Branch 253 not taken.
✓ Branch 254 taken 1 times.
✗ Branch 255 not taken.
✓ Branch 256 taken 1 times.
✗ Branch 257 not taken.
✓ Branch 258 taken 1 times.
✗ Branch 259 not taken.
✓ Branch 260 taken 1 times.
✗ Branch 261 not taken.
✓ Branch 262 taken 1 times.
✗ Branch 263 not taken.
✓ Branch 264 taken 1 times.
✗ Branch 265 not taken.
✗ Branch 266 not taken.
✗ Branch 267 not taken.
✗ Branch 268 not taken.
✗ Branch 269 not taken.
✗ Branch 270 not taken.
✗ Branch 271 not taken.
✗ Branch 272 not taken.
✗ Branch 273 not taken.
✗ Branch 274 not taken.
✗ Branch 275 not taken.
✗ Branch 276 not taken.
✗ Branch 277 not taken.
✗ Branch 278 not taken.
✗ Branch 279 not taken.
✗ Branch 280 not taken.
✗ Branch 281 not taken.
✗ Branch 282 not taken.
✗ Branch 283 not taken.
✓ Branch 284 taken 3 times.
✗ Branch 285 not taken.
✓ Branch 286 taken 3 times.
✗ Branch 287 not taken.
✓ Branch 288 taken 3 times.
✗ Branch 289 not taken.
✓ Branch 290 taken 3 times.
✗ Branch 291 not taken.
✗ Branch 292 not taken.
✗ Branch 293 not taken.
✗ Branch 294 not taken.
✗ Branch 295 not taken.
✗ Branch 296 not taken.
✗ Branch 297 not taken.
✗ Branch 298 not taken.
✗ Branch 299 not taken.
✗ Branch 300 not taken.
✗ Branch 301 not taken.
✗ Branch 302 not taken.
✗ Branch 303 not taken.
✗ Branch 304 not taken.
✗ Branch 305 not taken.
✗ Branch 306 not taken.
✗ Branch 307 not taken.
✗ Branch 308 not taken.
✗ Branch 309 not taken.
✗ Branch 310 not taken.
✗ Branch 311 not taken.
✗ Branch 312 not taken.
✗ Branch 313 not taken.
✗ Branch 314 not taken.
✗ Branch 315 not taken.
✗ Branch 316 not taken.
✗ Branch 317 not taken.
✗ Branch 318 not taken.
✗ Branch 319 not taken.
✗ Branch 320 not taken.
✗ Branch 321 not taken.
✓ Branch 322 taken 3 times.
✗ Branch 323 not taken.
✓ Branch 324 taken 3 times.
✗ Branch 325 not taken.
✓ Branch 326 taken 3 times.
✗ Branch 327 not taken.
✗ Branch 328 not taken.
✗ Branch 329 not taken.
✗ Branch 330 not taken.
✗ Branch 331 not taken.
✗ Branch 332 not taken.
✗ Branch 333 not taken.
✗ Branch 334 not taken.
✗ Branch 335 not taken.
✗ Branch 336 not taken.
✗ Branch 337 not taken.
✗ Branch 338 not taken.
✗ Branch 339 not taken.
✗ Branch 340 not taken.
✗ Branch 341 not taken.
✗ Branch 342 not taken.
✗ Branch 343 not taken.
✗ Branch 344 not taken.
✗ Branch 345 not taken.
✗ Branch 346 not taken.
✗ Branch 347 not taken.
✗ Branch 348 not taken.
✗ Branch 349 not taken.
✗ Branch 350 not taken.
✗ Branch 351 not taken.
✗ Branch 352 not taken.
✗ Branch 353 not taken.
✗ Branch 354 not taken.
✗ Branch 355 not taken.
✗ Branch 356 not taken.
✗ Branch 357 not taken.
|
346862 | if (auto base = node.NodeT::basetype()) { |
| 391 | 8735 | return hierarchyVisits(*base); | |
| 392 | } | ||
| 393 | } | ||
| 394 | return true; | ||
| 395 | } | ||
| 396 | |||
| 397 | /// @brief Implements the default behavior for a traversal to a given AST | ||
| 398 | /// node | ||
| 399 | /// @tparam NodeT The node type | ||
| 400 | /// @param node The node to traverse | ||
| 401 | /// @return True if traversal should continue, false to terminate | ||
| 402 | template <typename NodeT> | ||
| 403 | 3023327 | inline bool defaultTraversal(NodeType<NodeT>* node) | |
| 404 | { | ||
| 405 |
1/4✓ Branch 0 taken 1627 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
3023419 | if (!node) return true; |
| 406 | 1846552 | const size_t children = node->children(); | |
| 407 | |||
| 408 | if (this->derived().postOrderNodes()) { | ||
| 409 | if (this->derived().reverseChildVisits()) { | ||
| 410 | 420012 | if (children != 0) { | |
| 411 | 788142 | for (int64_t i = static_cast<int64_t>(children - 1); i >= 0; --i) { | |
| 412 | 539609 | auto child = this->strip<ConstVisit>(node->child(i)); | |
| 413 | 586334 | if (!this->derived().traverse(child)) { | |
| 414 | return false; | ||
| 415 | } | ||
| 416 | } | ||
| 417 | } | ||
| 418 | } | ||
| 419 | else { | ||
| 420 |
2/2✓ Branch 0 taken 1535 times.
✓ Branch 1 taken 1526 times.
|
4711502 | for (size_t i = 0; i < children; ++i) { |
| 421 | ✗ | auto child = this->strip<ConstVisit>(node->child(i)); | |
| 422 | 2338269 | if (!this->derived().traverse(child)) { | |
| 423 | return false; | ||
| 424 | } | ||
| 425 | } | ||
| 426 | } | ||
| 427 | if (this->derived().visitNodeHierarchies()) { | ||
| 428 | 984 | return this->hierarchyVisits(*node); | |
| 429 | } | ||
| 430 | else { | ||
| 431 | 238186 | return this->derived().visit(node); | |
| 432 | } | ||
| 433 | } | ||
| 434 | else { | ||
| 435 | if (this->derived().visitNodeHierarchies()) { | ||
| 436 | if (!this->hierarchyVisits(*node)) return false; | ||
| 437 | } | ||
| 438 | else { | ||
| 439 |
1/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
153 | if (!this->derived().visit(node)) return false; |
| 440 | } | ||
| 441 | if (this->derived().reverseChildVisits()) { | ||
| 442 | if (children != 0) { | ||
| 443 | for (int64_t i = static_cast<int64_t>(children - 1); i >= 0; --i) { | ||
| 444 | auto child = this->strip<ConstVisit>(node->child(i)); | ||
| 445 | if (!this->derived().traverse(child)) { | ||
| 446 | return false; | ||
| 447 | } | ||
| 448 | } | ||
| 449 | } | ||
| 450 | } | ||
| 451 | else { | ||
| 452 | 180 | for (size_t i = 0; i < children; ++i) { | |
| 453 | ✗ | auto child = this->strip<ConstVisit>(node->child(i)); | |
| 454 | 15 | if (!this->derived().traverse(child)) { | |
| 455 | return false; | ||
| 456 | } | ||
| 457 | } | ||
| 458 | } | ||
| 459 | 3 | return true; | |
| 460 | } | ||
| 461 | } | ||
| 462 | }; | ||
| 463 | |||
| 464 | } // namespace ast | ||
| 465 | } // namespace ax | ||
| 466 | |||
| 467 | } // namespace OPENVDB_VERSION_NAME | ||
| 468 | } // namespace openvdb | ||
| 469 | |||
| 470 | #endif // OPENVDB_AX_AST_VISITOR_HAS_BEEN_INCLUDED | ||
| 471 | |||
| 472 |