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