Warning: This file is not a C or C++ file. It does not have highlighting.
1 | //===-- include/flang/Parser/parse-tree-visitor.h ---------------*- C++ -*-===// |
---|---|
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef FORTRAN_PARSER_PARSE_TREE_VISITOR_H_ |
10 | #define FORTRAN_PARSER_PARSE_TREE_VISITOR_H_ |
11 | |
12 | #include "parse-tree.h" |
13 | #include "flang/Common/visit.h" |
14 | #include <cstddef> |
15 | #include <optional> |
16 | #include <tuple> |
17 | #include <utility> |
18 | #include <variant> |
19 | #include <vector> |
20 | |
21 | /// Parse tree visitor |
22 | /// Call Walk(x, visitor) to visit x and, by default, each node under x. |
23 | /// If x is non-const, the visitor member functions can modify the tree. |
24 | /// |
25 | /// visitor.Pre(x) is called before visiting x and its children are not |
26 | /// visited if it returns false. |
27 | /// |
28 | /// visitor.Post(x) is called after visiting x. |
29 | |
30 | namespace Fortran::parser { |
31 | |
32 | // Default case for visitation of non-class data members, strings, and |
33 | // any other non-decomposable values. |
34 | template <typename A, typename V> |
35 | std::enable_if_t<!std::is_class_v<A> || std::is_same_v<std::string, A> || |
36 | std::is_same_v<CharBlock, A>> |
37 | Walk(const A &x, V &visitor) { |
38 | if (visitor.Pre(x)) { |
39 | visitor.Post(x); |
40 | } |
41 | } |
42 | template <typename A, typename M> |
43 | std::enable_if_t<!std::is_class_v<A> || std::is_same_v<std::string, A> || |
44 | std::is_same_v<CharBlock, A>> |
45 | Walk(A &x, M &mutator) { |
46 | if (mutator.Pre(x)) { |
47 | mutator.Post(x); |
48 | } |
49 | } |
50 | |
51 | template <typename V> void Walk(const format::ControlEditDesc &, V &); |
52 | template <typename M> void Walk(format::ControlEditDesc &, M &); |
53 | template <typename V> void Walk(const format::DerivedTypeDataEditDesc &, V &); |
54 | template <typename M> void Walk(format::DerivedTypeDataEditDesc &, M &); |
55 | template <typename V> void Walk(const format::FormatItem &, V &); |
56 | template <typename M> void Walk(format::FormatItem &, M &); |
57 | template <typename V> void Walk(const format::FormatSpecification &, V &); |
58 | template <typename M> void Walk(format::FormatSpecification &, M &); |
59 | template <typename V> void Walk(const format::IntrinsicTypeDataEditDesc &, V &); |
60 | template <typename M> void Walk(format::IntrinsicTypeDataEditDesc &, M &); |
61 | |
62 | // Traversal of needed STL template classes (optional, list, tuple, variant) |
63 | // For most lists, just traverse the elements; but when a list constitutes |
64 | // a Block (i.e., std::list<ExecutionPartConstruct>), also invoke the |
65 | // visitor/mutator on the list itself. |
66 | template <typename T, typename V> void Walk(const std::list<T> &x, V &visitor) { |
67 | for (const auto &elem : x) { |
68 | Walk(elem, visitor); |
69 | } |
70 | } |
71 | template <typename T, typename M> void Walk(std::list<T> &x, M &mutator) { |
72 | for (auto &elem : x) { |
73 | Walk(elem, mutator); |
74 | } |
75 | } |
76 | template <typename V> void Walk(const Block &x, V &visitor) { |
77 | if (visitor.Pre(x)) { |
78 | for (const auto &elem : x) { |
79 | Walk(elem, visitor); |
80 | } |
81 | visitor.Post(x); |
82 | } |
83 | } |
84 | template <typename M> void Walk(Block &x, M &mutator) { |
85 | if (mutator.Pre(x)) { |
86 | for (auto &elem : x) { |
87 | Walk(elem, mutator); |
88 | } |
89 | mutator.Post(x); |
90 | } |
91 | } |
92 | template <typename T, typename V> |
93 | void Walk(const std::optional<T> &x, V &visitor) { |
94 | if (x) { |
95 | Walk(*x, visitor); |
96 | } |
97 | } |
98 | template <typename T, typename M> void Walk(std::optional<T> &x, M &mutator) { |
99 | if (x) { |
100 | Walk(*x, mutator); |
101 | } |
102 | } |
103 | template <std::size_t I = 0, typename Func, typename T> |
104 | void ForEachInTuple(const T &tuple, Func func) { |
105 | func(std::get<I>(tuple)); |
106 | if constexpr (I + 1 < std::tuple_size_v<T>) { |
107 | ForEachInTuple<I + 1>(tuple, func); |
108 | } |
109 | } |
110 | template <typename V, typename... A> |
111 | void Walk(const std::tuple<A...> &x, V &visitor) { |
112 | if (sizeof...(A) > 0) { |
113 | if (visitor.Pre(x)) { |
114 | ForEachInTuple(x, [&](const auto &y) { Walk(y, visitor); }); |
115 | visitor.Post(x); |
116 | } |
117 | } |
118 | } |
119 | template <std::size_t I = 0, typename Func, typename T> |
120 | void ForEachInTuple(T &tuple, Func func) { |
121 | func(std::get<I>(tuple)); |
122 | if constexpr (I + 1 < std::tuple_size_v<T>) { |
123 | ForEachInTuple<I + 1>(tuple, func); |
124 | } |
125 | } |
126 | template <typename M, typename... A> |
127 | void Walk(std::tuple<A...> &x, M &mutator) { |
128 | if (sizeof...(A) > 0) { |
129 | if (mutator.Pre(x)) { |
130 | ForEachInTuple(x, [&](auto &y) { Walk(y, mutator); }); |
131 | mutator.Post(x); |
132 | } |
133 | } |
134 | } |
135 | template <typename V, typename... A> |
136 | void Walk(const std::variant<A...> &x, V &visitor) { |
137 | if (visitor.Pre(x)) { |
138 | common::visit([&](const auto &y) { Walk(y, visitor); }, x); |
139 | visitor.Post(x); |
140 | } |
141 | } |
142 | template <typename M, typename... A> |
143 | void Walk(std::variant<A...> &x, M &mutator) { |
144 | if (mutator.Pre(x)) { |
145 | common::visit([&](auto &y) { Walk(y, mutator); }, x); |
146 | mutator.Post(x); |
147 | } |
148 | } |
149 | template <typename A, typename B, typename V> |
150 | void Walk(const std::pair<A, B> &x, V &visitor) { |
151 | if (visitor.Pre(x)) { |
152 | Walk(x.first, visitor); |
153 | Walk(x.second, visitor); |
154 | } |
155 | } |
156 | template <typename A, typename B, typename M> |
157 | void Walk(std::pair<A, B> &x, M &mutator) { |
158 | if (mutator.Pre(x)) { |
159 | Walk(x.first, mutator); |
160 | Walk(x.second, mutator); |
161 | } |
162 | } |
163 | |
164 | // Trait-determined traversal of empty, tuple, union, wrapper, |
165 | // and constraint-checking classes. |
166 | template <typename A, typename V> |
167 | std::enable_if_t<EmptyTrait<A>> Walk(const A &x, V &visitor) { |
168 | if (visitor.Pre(x)) { |
169 | visitor.Post(x); |
170 | } |
171 | } |
172 | template <typename A, typename M> |
173 | std::enable_if_t<EmptyTrait<A>> Walk(A &x, M &mutator) { |
174 | if (mutator.Pre(x)) { |
175 | mutator.Post(x); |
176 | } |
177 | } |
178 | |
179 | template <typename A, typename V> |
180 | std::enable_if_t<TupleTrait<A>> Walk(const A &x, V &visitor) { |
181 | if (visitor.Pre(x)) { |
182 | Walk(x.t, visitor); |
183 | visitor.Post(x); |
184 | } |
185 | } |
186 | template <typename A, typename M> |
187 | std::enable_if_t<TupleTrait<A>> Walk(A &x, M &mutator) { |
188 | if (mutator.Pre(x)) { |
189 | Walk(x.t, mutator); |
190 | mutator.Post(x); |
191 | } |
192 | } |
193 | |
194 | template <typename A, typename V> |
195 | std::enable_if_t<UnionTrait<A>> Walk(const A &x, V &visitor) { |
196 | if (visitor.Pre(x)) { |
197 | Walk(x.u, visitor); |
198 | visitor.Post(x); |
199 | } |
200 | } |
201 | template <typename A, typename M> |
202 | std::enable_if_t<UnionTrait<A>> Walk(A &x, M &mutator) { |
203 | if (mutator.Pre(x)) { |
204 | Walk(x.u, mutator); |
205 | mutator.Post(x); |
206 | } |
207 | } |
208 | |
209 | template <typename A, typename V> |
210 | std::enable_if_t<WrapperTrait<A>> Walk(const A &x, V &visitor) { |
211 | if (visitor.Pre(x)) { |
212 | Walk(x.v, visitor); |
213 | visitor.Post(x); |
214 | } |
215 | } |
216 | template <typename A, typename M> |
217 | std::enable_if_t<WrapperTrait<A>> Walk(A &x, M &mutator) { |
218 | if (mutator.Pre(x)) { |
219 | Walk(x.v, mutator); |
220 | mutator.Post(x); |
221 | } |
222 | } |
223 | |
224 | template <typename A, typename V> |
225 | std::enable_if_t<ConstraintTrait<A>> Walk(const A &x, V &visitor) { |
226 | if (visitor.Pre(x)) { |
227 | Walk(x.thing, visitor); |
228 | visitor.Post(x); |
229 | } |
230 | } |
231 | template <typename A, typename M> |
232 | std::enable_if_t<ConstraintTrait<A>> Walk(A &x, M &mutator) { |
233 | if (mutator.Pre(x)) { |
234 | Walk(x.thing, mutator); |
235 | mutator.Post(x); |
236 | } |
237 | } |
238 | |
239 | template <typename T, typename V> |
240 | void Walk(const common::Indirection<T> &x, V &visitor) { |
241 | Walk(x.value(), visitor); |
242 | } |
243 | template <typename T, typename M> |
244 | void Walk(common::Indirection<T> &x, M &mutator) { |
245 | Walk(x.value(), mutator); |
246 | } |
247 | |
248 | template <typename T, typename V> void Walk(const Statement<T> &x, V &visitor) { |
249 | if (visitor.Pre(x)) { |
250 | // N.B. The label, if any, is not visited. |
251 | Walk(x.source, visitor); |
252 | Walk(x.statement, visitor); |
253 | visitor.Post(x); |
254 | } |
255 | } |
256 | template <typename T, typename M> void Walk(Statement<T> &x, M &mutator) { |
257 | if (mutator.Pre(x)) { |
258 | // N.B. The label, if any, is not visited. |
259 | Walk(x.source, mutator); |
260 | Walk(x.statement, mutator); |
261 | mutator.Post(x); |
262 | } |
263 | } |
264 | |
265 | template <typename T, typename V> |
266 | void Walk(const UnlabeledStatement<T> &x, V &visitor) { |
267 | if (visitor.Pre(x)) { |
268 | Walk(x.source, visitor); |
269 | Walk(x.statement, visitor); |
270 | visitor.Post(x); |
271 | } |
272 | } |
273 | template <typename T, typename M> |
274 | void Walk(UnlabeledStatement<T> &x, M &mutator) { |
275 | if (mutator.Pre(x)) { |
276 | Walk(x.source, mutator); |
277 | Walk(x.statement, mutator); |
278 | mutator.Post(x); |
279 | } |
280 | } |
281 | |
282 | template <typename V> void Walk(const Name &x, V &visitor) { |
283 | if (visitor.Pre(x)) { |
284 | Walk(x.source, visitor); |
285 | visitor.Post(x); |
286 | } |
287 | } |
288 | template <typename M> void Walk(Name &x, M &mutator) { |
289 | if (mutator.Pre(x)) { |
290 | Walk(x.source, mutator); |
291 | mutator.Post(x); |
292 | } |
293 | } |
294 | |
295 | template <typename V> void Walk(const AcSpec &x, V &visitor) { |
296 | if (visitor.Pre(x)) { |
297 | Walk(x.type, visitor); |
298 | Walk(x.values, visitor); |
299 | visitor.Post(x); |
300 | } |
301 | } |
302 | template <typename M> void Walk(AcSpec &x, M &mutator) { |
303 | if (mutator.Pre(x)) { |
304 | Walk(x.type, mutator); |
305 | Walk(x.values, mutator); |
306 | mutator.Post(x); |
307 | } |
308 | } |
309 | template <typename V> void Walk(const ArrayElement &x, V &visitor) { |
310 | if (visitor.Pre(x)) { |
311 | Walk(x.base, visitor); |
312 | Walk(x.subscripts, visitor); |
313 | visitor.Post(x); |
314 | } |
315 | } |
316 | template <typename M> void Walk(ArrayElement &x, M &mutator) { |
317 | if (mutator.Pre(x)) { |
318 | Walk(x.base, mutator); |
319 | Walk(x.subscripts, mutator); |
320 | mutator.Post(x); |
321 | } |
322 | } |
323 | template <typename V> |
324 | void Walk(const CharSelector::LengthAndKind &x, V &visitor) { |
325 | if (visitor.Pre(x)) { |
326 | Walk(x.length, visitor); |
327 | Walk(x.kind, visitor); |
328 | visitor.Post(x); |
329 | } |
330 | } |
331 | template <typename M> void Walk(CharSelector::LengthAndKind &x, M &mutator) { |
332 | if (mutator.Pre(x)) { |
333 | Walk(x.length, mutator); |
334 | Walk(x.kind, mutator); |
335 | mutator.Post(x); |
336 | } |
337 | } |
338 | template <typename V> void Walk(const CaseValueRange::Range &x, V &visitor) { |
339 | if (visitor.Pre(x)) { |
340 | Walk(x.lower, visitor); |
341 | Walk(x.upper, visitor); |
342 | visitor.Post(x); |
343 | } |
344 | } |
345 | template <typename M> void Walk(CaseValueRange::Range &x, M &mutator) { |
346 | if (mutator.Pre(x)) { |
347 | Walk(x.lower, mutator); |
348 | Walk(x.upper, mutator); |
349 | mutator.Post(x); |
350 | } |
351 | } |
352 | template <typename V> void Walk(const CoindexedNamedObject &x, V &visitor) { |
353 | if (visitor.Pre(x)) { |
354 | Walk(x.base, visitor); |
355 | Walk(x.imageSelector, visitor); |
356 | visitor.Post(x); |
357 | } |
358 | } |
359 | template <typename M> void Walk(CoindexedNamedObject &x, M &mutator) { |
360 | if (mutator.Pre(x)) { |
361 | Walk(x.base, mutator); |
362 | Walk(x.imageSelector, mutator); |
363 | mutator.Post(x); |
364 | } |
365 | } |
366 | template <typename V> |
367 | void Walk(const DeclarationTypeSpec::Class &x, V &visitor) { |
368 | if (visitor.Pre(x)) { |
369 | Walk(x.derived, visitor); |
370 | visitor.Post(x); |
371 | } |
372 | } |
373 | template <typename M> void Walk(DeclarationTypeSpec::Class &x, M &mutator) { |
374 | if (mutator.Pre(x)) { |
375 | Walk(x.derived, mutator); |
376 | mutator.Post(x); |
377 | } |
378 | } |
379 | template <typename V> |
380 | void Walk(const DeclarationTypeSpec::Type &x, V &visitor) { |
381 | if (visitor.Pre(x)) { |
382 | Walk(x.derived, visitor); |
383 | visitor.Post(x); |
384 | } |
385 | } |
386 | template <typename M> void Walk(DeclarationTypeSpec::Type &x, M &mutator) { |
387 | if (mutator.Pre(x)) { |
388 | Walk(x.derived, mutator); |
389 | mutator.Post(x); |
390 | } |
391 | } |
392 | template <typename V> void Walk(const ImportStmt &x, V &visitor) { |
393 | if (visitor.Pre(x)) { |
394 | Walk(x.names, visitor); |
395 | visitor.Post(x); |
396 | } |
397 | } |
398 | template <typename M> void Walk(ImportStmt &x, M &mutator) { |
399 | if (mutator.Pre(x)) { |
400 | Walk(x.names, mutator); |
401 | mutator.Post(x); |
402 | } |
403 | } |
404 | template <typename V> |
405 | void Walk(const IntrinsicTypeSpec::Character &x, V &visitor) { |
406 | if (visitor.Pre(x)) { |
407 | Walk(x.selector, visitor); |
408 | visitor.Post(x); |
409 | } |
410 | } |
411 | template <typename M> void Walk(IntrinsicTypeSpec::Character &x, M &mutator) { |
412 | if (mutator.Pre(x)) { |
413 | Walk(x.selector, mutator); |
414 | mutator.Post(x); |
415 | } |
416 | } |
417 | template <typename V> |
418 | void Walk(const IntrinsicTypeSpec::Complex &x, V &visitor) { |
419 | if (visitor.Pre(x)) { |
420 | Walk(x.kind, visitor); |
421 | visitor.Post(x); |
422 | } |
423 | } |
424 | template <typename M> void Walk(IntrinsicTypeSpec::Complex &x, M &mutator) { |
425 | if (mutator.Pre(x)) { |
426 | Walk(x.kind, mutator); |
427 | mutator.Post(x); |
428 | } |
429 | } |
430 | template <typename V> |
431 | void Walk(const IntrinsicTypeSpec::Logical &x, V &visitor) { |
432 | if (visitor.Pre(x)) { |
433 | Walk(x.kind, visitor); |
434 | visitor.Post(x); |
435 | } |
436 | } |
437 | template <typename M> void Walk(IntrinsicTypeSpec::Logical &x, M &mutator) { |
438 | if (mutator.Pre(x)) { |
439 | Walk(x.kind, mutator); |
440 | mutator.Post(x); |
441 | } |
442 | } |
443 | template <typename V> void Walk(const IntrinsicTypeSpec::Real &x, V &visitor) { |
444 | if (visitor.Pre(x)) { |
445 | Walk(x.kind, visitor); |
446 | visitor.Post(x); |
447 | } |
448 | } |
449 | template <typename M> void Walk(IntrinsicTypeSpec::Real &x, M &mutator) { |
450 | if (mutator.Pre(x)) { |
451 | Walk(x.kind, mutator); |
452 | mutator.Post(x); |
453 | } |
454 | } |
455 | template <typename A, typename B, typename V> |
456 | void Walk(const LoopBounds<A, B> &x, V &visitor) { |
457 | if (visitor.Pre(x)) { |
458 | Walk(x.name, visitor); |
459 | Walk(x.lower, visitor); |
460 | Walk(x.upper, visitor); |
461 | Walk(x.step, visitor); |
462 | visitor.Post(x); |
463 | } |
464 | } |
465 | template <typename A, typename B, typename M> |
466 | void Walk(LoopBounds<A, B> &x, M &mutator) { |
467 | if (mutator.Pre(x)) { |
468 | Walk(x.name, mutator); |
469 | Walk(x.lower, mutator); |
470 | Walk(x.upper, mutator); |
471 | Walk(x.step, mutator); |
472 | mutator.Post(x); |
473 | } |
474 | } |
475 | template <typename V> void Walk(const CommonStmt &x, V &visitor) { |
476 | if (visitor.Pre(x)) { |
477 | Walk(x.blocks, visitor); |
478 | visitor.Post(x); |
479 | } |
480 | } |
481 | template <typename M> void Walk(CommonStmt &x, M &mutator) { |
482 | if (mutator.Pre(x)) { |
483 | Walk(x.blocks, mutator); |
484 | mutator.Post(x); |
485 | } |
486 | } |
487 | |
488 | // Expr traversal uses iteration rather than recursion to avoid |
489 | // blowing out the stack on very deep expression parse trees. |
490 | // It replaces implementations that looked like: |
491 | // template <typename V> void Walk(const Expr &x, V visitor) { |
492 | // if (visitor.Pre(x)) { // Pre on the Expr |
493 | // Walk(x.source, visitor); |
494 | // // Pre on the operator, walk the operands, Post on operator |
495 | // Walk(x.u, visitor); |
496 | // visitor.Post(x); // Post on the Expr |
497 | // } |
498 | // } |
499 | template <typename A, typename V, typename UNARY, typename BINARY> |
500 | static void IterativeWalk(A &start, V &visitor) { |
501 | struct ExprWorkList { |
502 | ExprWorkList(A &x) : expr(&x) {} |
503 | bool doPostExpr{false}, doPostOpr{false}; |
504 | A *expr; |
505 | }; |
506 | std::vector<ExprWorkList> stack; |
507 | stack.emplace_back(start); |
508 | do { |
509 | A &expr{*stack.back().expr}; |
510 | if (stack.back().doPostOpr) { |
511 | stack.back().doPostOpr = false; |
512 | common::visit([&visitor](auto &y) { visitor.Post(y); }, expr.u); |
513 | } else if (stack.back().doPostExpr) { |
514 | visitor.Post(expr); |
515 | stack.pop_back(); |
516 | } else if (!visitor.Pre(expr)) { |
517 | stack.pop_back(); |
518 | } else { |
519 | stack.back().doPostExpr = true; |
520 | Walk(expr.source, visitor); |
521 | UNARY *unary{nullptr}; |
522 | BINARY *binary{nullptr}; |
523 | common::visit( |
524 | [&unary, &binary](auto &y) { |
525 | if constexpr (std::is_convertible_v<decltype(&y), UNARY *>) { |
526 | unary = &y; |
527 | } else if constexpr (std::is_convertible_v<decltype(&y), |
528 | BINARY *>) { |
529 | binary = &y; |
530 | } |
531 | }, |
532 | expr.u); |
533 | if (!unary && !binary) { |
534 | Walk(expr.u, visitor); |
535 | } else if (common::visit( |
536 | [&visitor](auto &y) { return visitor.Pre(y); }, expr.u)) { |
537 | stack.back().doPostOpr = true; |
538 | if (unary) { |
539 | stack.emplace_back(unary->v.value()); |
540 | } else { |
541 | stack.emplace_back(std::get<1>(binary->t).value()); |
542 | stack.emplace_back(std::get<0>(binary->t).value()); |
543 | } |
544 | } |
545 | } |
546 | } while (!stack.empty()); |
547 | } |
548 | template <typename V> void Walk(const Expr &x, V &visitor) { |
549 | IterativeWalk<const Expr, V, const Expr::IntrinsicUnary, |
550 | const Expr::IntrinsicBinary>(x, visitor); |
551 | } |
552 | template <typename M> void Walk(Expr &x, M &mutator) { |
553 | IterativeWalk<Expr, M, Expr::IntrinsicUnary, Expr::IntrinsicBinary>( |
554 | x, mutator); |
555 | } |
556 | |
557 | template <typename V> void Walk(const Designator &x, V &visitor) { |
558 | if (visitor.Pre(x)) { |
559 | Walk(x.source, visitor); |
560 | Walk(x.u, visitor); |
561 | visitor.Post(x); |
562 | } |
563 | } |
564 | template <typename M> void Walk(Designator &x, M &mutator) { |
565 | if (mutator.Pre(x)) { |
566 | Walk(x.source, mutator); |
567 | Walk(x.u, mutator); |
568 | mutator.Post(x); |
569 | } |
570 | } |
571 | template <typename V> void Walk(const FunctionReference &x, V &visitor) { |
572 | if (visitor.Pre(x)) { |
573 | Walk(x.source, visitor); |
574 | Walk(x.v, visitor); |
575 | visitor.Post(x); |
576 | } |
577 | } |
578 | template <typename M> void Walk(FunctionReference &x, M &mutator) { |
579 | if (mutator.Pre(x)) { |
580 | Walk(x.source, mutator); |
581 | Walk(x.v, mutator); |
582 | mutator.Post(x); |
583 | } |
584 | } |
585 | template <typename V> void Walk(const CallStmt &x, V &visitor) { |
586 | if (visitor.Pre(x)) { |
587 | Walk(x.source, visitor); |
588 | Walk(x.call, visitor); |
589 | Walk(x.chevrons, visitor); |
590 | visitor.Post(x); |
591 | } |
592 | } |
593 | template <typename M> void Walk(CallStmt &x, M &mutator) { |
594 | if (mutator.Pre(x)) { |
595 | Walk(x.source, mutator); |
596 | Walk(x.call, mutator); |
597 | Walk(x.chevrons, mutator); |
598 | mutator.Post(x); |
599 | } |
600 | } |
601 | template <typename V> void Walk(const PartRef &x, V &visitor) { |
602 | if (visitor.Pre(x)) { |
603 | Walk(x.name, visitor); |
604 | Walk(x.subscripts, visitor); |
605 | Walk(x.imageSelector, visitor); |
606 | visitor.Post(x); |
607 | } |
608 | } |
609 | template <typename M> void Walk(PartRef &x, M &mutator) { |
610 | if (mutator.Pre(x)) { |
611 | Walk(x.name, mutator); |
612 | Walk(x.subscripts, mutator); |
613 | Walk(x.imageSelector, mutator); |
614 | mutator.Post(x); |
615 | } |
616 | } |
617 | template <typename V> void Walk(const ReadStmt &x, V &visitor) { |
618 | if (visitor.Pre(x)) { |
619 | Walk(x.iounit, visitor); |
620 | Walk(x.format, visitor); |
621 | Walk(x.controls, visitor); |
622 | Walk(x.items, visitor); |
623 | visitor.Post(x); |
624 | } |
625 | } |
626 | template <typename M> void Walk(ReadStmt &x, M &mutator) { |
627 | if (mutator.Pre(x)) { |
628 | Walk(x.iounit, mutator); |
629 | Walk(x.format, mutator); |
630 | Walk(x.controls, mutator); |
631 | Walk(x.items, mutator); |
632 | mutator.Post(x); |
633 | } |
634 | } |
635 | template <typename V> void Walk(const SignedIntLiteralConstant &x, V &visitor) { |
636 | if (visitor.Pre(x)) { |
637 | Walk(x.source, visitor); |
638 | Walk(x.t, visitor); |
639 | visitor.Post(x); |
640 | } |
641 | } |
642 | template <typename M> void Walk(SignedIntLiteralConstant &x, M &mutator) { |
643 | if (mutator.Pre(x)) { |
644 | Walk(x.source, mutator); |
645 | Walk(x.t, mutator); |
646 | mutator.Post(x); |
647 | } |
648 | } |
649 | template <typename V> void Walk(const RealLiteralConstant &x, V &visitor) { |
650 | if (visitor.Pre(x)) { |
651 | Walk(x.real, visitor); |
652 | Walk(x.kind, visitor); |
653 | visitor.Post(x); |
654 | } |
655 | } |
656 | template <typename M> void Walk(RealLiteralConstant &x, M &mutator) { |
657 | if (mutator.Pre(x)) { |
658 | Walk(x.real, mutator); |
659 | Walk(x.kind, mutator); |
660 | mutator.Post(x); |
661 | } |
662 | } |
663 | template <typename V> |
664 | void Walk(const RealLiteralConstant::Real &x, V &visitor) { |
665 | if (visitor.Pre(x)) { |
666 | Walk(x.source, visitor); |
667 | visitor.Post(x); |
668 | } |
669 | } |
670 | template <typename M> void Walk(RealLiteralConstant::Real &x, M &mutator) { |
671 | if (mutator.Pre(x)) { |
672 | Walk(x.source, mutator); |
673 | mutator.Post(x); |
674 | } |
675 | } |
676 | template <typename V> void Walk(const StructureComponent &x, V &visitor) { |
677 | if (visitor.Pre(x)) { |
678 | Walk(x.base, visitor); |
679 | Walk(x.component, visitor); |
680 | visitor.Post(x); |
681 | } |
682 | } |
683 | template <typename M> void Walk(StructureComponent &x, M &mutator) { |
684 | if (mutator.Pre(x)) { |
685 | Walk(x.base, mutator); |
686 | Walk(x.component, mutator); |
687 | mutator.Post(x); |
688 | } |
689 | } |
690 | template <typename V> void Walk(const Suffix &x, V &visitor) { |
691 | if (visitor.Pre(x)) { |
692 | Walk(x.binding, visitor); |
693 | Walk(x.resultName, visitor); |
694 | visitor.Post(x); |
695 | } |
696 | } |
697 | template <typename M> void Walk(Suffix &x, M &mutator) { |
698 | if (mutator.Pre(x)) { |
699 | Walk(x.binding, mutator); |
700 | Walk(x.resultName, mutator); |
701 | mutator.Post(x); |
702 | } |
703 | } |
704 | template <typename V> |
705 | void Walk(const TypeBoundProcedureStmt::WithInterface &x, V &visitor) { |
706 | if (visitor.Pre(x)) { |
707 | Walk(x.interfaceName, visitor); |
708 | Walk(x.attributes, visitor); |
709 | Walk(x.bindingNames, visitor); |
710 | visitor.Post(x); |
711 | } |
712 | } |
713 | template <typename M> |
714 | void Walk(TypeBoundProcedureStmt::WithInterface &x, M &mutator) { |
715 | if (mutator.Pre(x)) { |
716 | Walk(x.interfaceName, mutator); |
717 | Walk(x.attributes, mutator); |
718 | Walk(x.bindingNames, mutator); |
719 | mutator.Post(x); |
720 | } |
721 | } |
722 | template <typename V> |
723 | void Walk(const TypeBoundProcedureStmt::WithoutInterface &x, V &visitor) { |
724 | if (visitor.Pre(x)) { |
725 | Walk(x.attributes, visitor); |
726 | Walk(x.declarations, visitor); |
727 | visitor.Post(x); |
728 | } |
729 | } |
730 | template <typename M> |
731 | void Walk(TypeBoundProcedureStmt::WithoutInterface &x, M &mutator) { |
732 | if (mutator.Pre(x)) { |
733 | Walk(x.attributes, mutator); |
734 | Walk(x.declarations, mutator); |
735 | mutator.Post(x); |
736 | } |
737 | } |
738 | template <typename V> void Walk(const UseStmt &x, V &visitor) { |
739 | if (visitor.Pre(x)) { |
740 | Walk(x.nature, visitor); |
741 | Walk(x.moduleName, visitor); |
742 | Walk(x.u, visitor); |
743 | visitor.Post(x); |
744 | } |
745 | } |
746 | template <typename M> void Walk(UseStmt &x, M &mutator) { |
747 | if (mutator.Pre(x)) { |
748 | Walk(x.nature, mutator); |
749 | Walk(x.moduleName, mutator); |
750 | Walk(x.u, mutator); |
751 | mutator.Post(x); |
752 | } |
753 | } |
754 | template <typename V> void Walk(const WriteStmt &x, V &visitor) { |
755 | if (visitor.Pre(x)) { |
756 | Walk(x.iounit, visitor); |
757 | Walk(x.format, visitor); |
758 | Walk(x.controls, visitor); |
759 | Walk(x.items, visitor); |
760 | visitor.Post(x); |
761 | } |
762 | } |
763 | template <typename M> void Walk(WriteStmt &x, M &mutator) { |
764 | if (mutator.Pre(x)) { |
765 | Walk(x.iounit, mutator); |
766 | Walk(x.format, mutator); |
767 | Walk(x.controls, mutator); |
768 | Walk(x.items, mutator); |
769 | mutator.Post(x); |
770 | } |
771 | } |
772 | template <typename V> void Walk(const format::ControlEditDesc &x, V &visitor) { |
773 | if (visitor.Pre(x)) { |
774 | Walk(x.kind, visitor); |
775 | visitor.Post(x); |
776 | } |
777 | } |
778 | template <typename M> void Walk(format::ControlEditDesc &x, M &mutator) { |
779 | if (mutator.Pre(x)) { |
780 | Walk(x.kind, mutator); |
781 | mutator.Post(x); |
782 | } |
783 | } |
784 | template <typename V> |
785 | void Walk(const format::DerivedTypeDataEditDesc &x, V &visitor) { |
786 | if (visitor.Pre(x)) { |
787 | Walk(x.type, visitor); |
788 | Walk(x.parameters, visitor); |
789 | visitor.Post(x); |
790 | } |
791 | } |
792 | template <typename M> |
793 | void Walk(format::DerivedTypeDataEditDesc &x, M &mutator) { |
794 | if (mutator.Pre(x)) { |
795 | Walk(x.type, mutator); |
796 | Walk(x.parameters, mutator); |
797 | mutator.Post(x); |
798 | } |
799 | } |
800 | template <typename V> void Walk(const format::FormatItem &x, V &visitor) { |
801 | if (visitor.Pre(x)) { |
802 | Walk(x.repeatCount, visitor); |
803 | Walk(x.u, visitor); |
804 | visitor.Post(x); |
805 | } |
806 | } |
807 | template <typename M> void Walk(format::FormatItem &x, M &mutator) { |
808 | if (mutator.Pre(x)) { |
809 | Walk(x.repeatCount, mutator); |
810 | Walk(x.u, mutator); |
811 | mutator.Post(x); |
812 | } |
813 | } |
814 | template <typename V> |
815 | void Walk(const format::FormatSpecification &x, V &visitor) { |
816 | if (visitor.Pre(x)) { |
817 | Walk(x.items, visitor); |
818 | Walk(x.unlimitedItems, visitor); |
819 | visitor.Post(x); |
820 | } |
821 | } |
822 | template <typename M> void Walk(format::FormatSpecification &x, M &mutator) { |
823 | if (mutator.Pre(x)) { |
824 | Walk(x.items, mutator); |
825 | Walk(x.unlimitedItems, mutator); |
826 | mutator.Post(x); |
827 | } |
828 | } |
829 | template <typename V> |
830 | void Walk(const format::IntrinsicTypeDataEditDesc &x, V &visitor) { |
831 | if (visitor.Pre(x)) { |
832 | Walk(x.kind, visitor); |
833 | Walk(x.width, visitor); |
834 | Walk(x.digits, visitor); |
835 | Walk(x.exponentWidth, visitor); |
836 | visitor.Post(x); |
837 | } |
838 | } |
839 | template <typename M> |
840 | void Walk(format::IntrinsicTypeDataEditDesc &x, M &mutator) { |
841 | if (mutator.Pre(x)) { |
842 | Walk(x.kind, mutator); |
843 | Walk(x.width, mutator); |
844 | Walk(x.digits, mutator); |
845 | Walk(x.exponentWidth, mutator); |
846 | mutator.Post(x); |
847 | } |
848 | } |
849 | template <typename V> void Walk(const CompilerDirective &x, V &visitor) { |
850 | if (visitor.Pre(x)) { |
851 | Walk(x.source, visitor); |
852 | Walk(x.u, visitor); |
853 | visitor.Post(x); |
854 | } |
855 | } |
856 | template <typename M> void Walk(CompilerDirective &x, M &mutator) { |
857 | if (mutator.Pre(x)) { |
858 | Walk(x.source, mutator); |
859 | Walk(x.u, mutator); |
860 | mutator.Post(x); |
861 | } |
862 | } |
863 | template <typename V> |
864 | void Walk(const CompilerDirective::Unrecognized &x, V &visitor) { |
865 | if (visitor.Pre(x)) { |
866 | visitor.Post(x); |
867 | } |
868 | } |
869 | template <typename M> |
870 | void Walk(CompilerDirective::Unrecognized &x, M &mutator) { |
871 | if (mutator.Pre(x)) { |
872 | mutator.Post(x); |
873 | } |
874 | } |
875 | template <typename V> |
876 | void Walk(const OmpLinearClause::WithModifier &x, V &visitor) { |
877 | if (visitor.Pre(x)) { |
878 | Walk(x.modifier, visitor); |
879 | Walk(x.names, visitor); |
880 | Walk(x.step, visitor); |
881 | visitor.Post(x); |
882 | } |
883 | } |
884 | template <typename M> void Walk(OmpLinearClause::WithModifier &x, M &mutator) { |
885 | if (mutator.Pre(x)) { |
886 | Walk(x.modifier, mutator); |
887 | Walk(x.names, mutator); |
888 | Walk(x.step, mutator); |
889 | mutator.Post(x); |
890 | } |
891 | } |
892 | template <typename V> |
893 | void Walk(const OmpLinearClause::WithoutModifier &x, V &visitor) { |
894 | if (visitor.Pre(x)) { |
895 | Walk(x.names, visitor); |
896 | Walk(x.step, visitor); |
897 | visitor.Post(x); |
898 | } |
899 | } |
900 | template <typename M> |
901 | void Walk(OmpLinearClause::WithoutModifier &x, M &mutator) { |
902 | if (mutator.Pre(x)) { |
903 | Walk(x.names, mutator); |
904 | Walk(x.step, mutator); |
905 | mutator.Post(x); |
906 | } |
907 | } |
908 | } // namespace Fortran::parser |
909 | #endif // FORTRAN_PARSER_PARSE_TREE_VISITOR_H_ |
910 |
Warning: This file is not a C or C++ file. It does not have highlighting.