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