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