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 |