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