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 |