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