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) {
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) {
65 template <
typename T,
typename V>
66 static void Walk(
const std::list<T> &x, V &visitor) {
67 for (
const auto &elem : x) {
71 template <
typename T,
typename M>
72 static void Walk(std::list<T> &x, M &mutator) {
73 for (
auto &elem : x) {
77 template <
typename V>
static void Walk(
const Block &x, V &visitor) {
79 for (
const auto &elem : x) {
85 template <
typename M>
static void Walk(Block &x, M &mutator) {
87 for (
auto &elem : x) {
93 template <
typename T,
typename V>
94 static void Walk(
const std::optional<T> &x, V &visitor) {
99 template <
typename T,
typename M>
100 static void Walk(std::optional<T> &x, M &mutator) {
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);
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); });
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);
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); });
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);
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);
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);
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);
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)) {
174 template <
typename A,
typename M>
175 static std::enable_if_t<EmptyTrait<A>> Walk(A &x, M &mutator) {
176 if (mutator.Pre(x)) {
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)) {
188 template <
typename A,
typename M>
189 static std::enable_if_t<TupleTrait<A>> Walk(A &x, M &mutator) {
190 if (mutator.Pre(x)) {
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)) {
203 template <
typename A,
typename M>
204 static std::enable_if_t<UnionTrait<A>> Walk(A &x, M &mutator) {
205 if (mutator.Pre(x)) {
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)) {
218 template <
typename A,
typename M>
219 static std::enable_if_t<WrapperTrait<A>> Walk(A &x, M &mutator) {
220 if (mutator.Pre(x)) {
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);
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);
241 template <
typename T,
typename V>
243 Walk(x.value(), visitor);
245 template <
typename T,
typename M>
247 Walk(x.value(), mutator);
250 template <
typename T,
typename V>
252 if (visitor.Pre(x)) {
254 Walk(x.source, visitor);
255 Walk(x.statement, visitor);
259 template <
typename T,
typename M>
261 if (mutator.Pre(x)) {
263 Walk(x.source, mutator);
264 Walk(x.statement, mutator);
269 template <
typename T,
typename V>
271 if (visitor.Pre(x)) {
272 Walk(x.source, visitor);
273 Walk(x.statement, visitor);
277 template <
typename T,
typename M>
279 if (mutator.Pre(x)) {
280 Walk(x.source, mutator);
281 Walk(x.statement, mutator);
286 template <
typename V>
static void Walk(
const Name &x, V &visitor) {
287 if (visitor.Pre(x)) {
288 Walk(x.source, visitor);
292 template <
typename M>
static void Walk(
Name &x, M &mutator) {
293 if (mutator.Pre(x)) {
294 Walk(x.source, mutator);
299 template <
typename V>
static void Walk(
const ArrayElement &x, V &visitor) {
300 if (visitor.Pre(x)) {
301 Walk(x.base, visitor);
302 Walk(x.subscripts, visitor);
306 template <
typename M>
static void Walk(
ArrayElement &x, M &mutator) {
307 if (mutator.Pre(x)) {
308 Walk(x.base, mutator);
309 Walk(x.subscripts, mutator);
313 template <
typename V>
315 if (visitor.Pre(x)) {
316 Walk(x.base, visitor);
317 Walk(x.imageSelector, visitor);
322 if (mutator.Pre(x)) {
323 Walk(x.base, mutator);
324 Walk(x.imageSelector, mutator);
328 template <
typename A,
typename B,
typename V>
330 if (visitor.Pre(x)) {
331 Walk(x.name, visitor);
332 Walk(x.lower, visitor);
333 Walk(x.upper, visitor);
334 Walk(x.step, visitor);
338 template <
typename A,
typename B,
typename M>
340 if (mutator.Pre(x)) {
341 Walk(x.name, mutator);
342 Walk(x.lower, mutator);
343 Walk(x.upper, mutator);
344 Walk(x.step, mutator);
360 template <
typename A,
typename V,
typename UNARY,
typename BINARY>
361 static void IterativeWalk(A &start, V &visitor) {
362 struct ExprWorkList {
363 ExprWorkList(A &x) : expr(&x) {}
364 bool doPostExpr{
false}, doPostOpr{
false};
367 std::vector<ExprWorkList> stack;
368 stack.emplace_back(start);
370 A &expr{*stack.back().expr};
371 if (stack.back().doPostOpr) {
372 stack.back().doPostOpr =
false;
373 common::visit([&visitor](
auto &y) { visitor.Post(y); }, expr.u);
374 }
else if (stack.back().doPostExpr) {
377 }
else if (!visitor.Pre(expr)) {
380 stack.back().doPostExpr =
true;
381 Walk(expr.source, visitor);
382 UNARY *unary{
nullptr};
383 BINARY *binary{
nullptr};
385 [&unary, &binary](
auto &y) {
386 if constexpr (std::is_convertible_v<
decltype(&y), UNARY *>) {
388 }
else if constexpr (std::is_convertible_v<
decltype(&y),
394 if (!unary && !binary) {
395 Walk(expr.u, visitor);
396 }
else if (common::visit([&visitor](
auto &y) {
return visitor.Pre(y); },
398 stack.back().doPostOpr =
true;
400 stack.emplace_back(unary->v.value());
402 stack.emplace_back(std::get<1>(binary->t).value());
403 stack.emplace_back(std::get<0>(binary->t).value());
407 }
while (!stack.empty());
409 template <
typename V>
static void Walk(
const Expr &x, V &visitor) {
410 IterativeWalk<
const Expr, V,
const Expr::IntrinsicUnary,
413 template <
typename M>
static void Walk(
Expr &x, M &mutator) {
414 IterativeWalk<Expr, M, Expr::IntrinsicUnary, Expr::IntrinsicBinary>(
418 template <
typename V>
static void Walk(
const Designator &x, V &visitor) {
419 if (visitor.Pre(x)) {
420 Walk(x.source, visitor);
425 template <
typename M>
static void Walk(
Designator &x, M &mutator) {
426 if (mutator.Pre(x)) {
427 Walk(x.source, mutator);
432 template <
typename V>
434 if (visitor.Pre(x)) {
435 Walk(x.source, visitor);
441 if (mutator.Pre(x)) {
442 Walk(x.source, mutator);
447 template <
typename V>
static void Walk(
const CallStmt &x, V &visitor) {
448 if (visitor.Pre(x)) {
449 Walk(x.source, visitor);
450 Walk(x.call, visitor);
451 Walk(x.chevrons, visitor);
455 template <
typename M>
static void Walk(
CallStmt &x, M &mutator) {
456 if (mutator.Pre(x)) {
457 Walk(x.source, mutator);
458 Walk(x.call, mutator);
459 Walk(x.chevrons, mutator);
463 template <
typename V>
static void Walk(
const PartRef &x, V &visitor) {
464 if (visitor.Pre(x)) {
465 Walk(x.name, visitor);
466 Walk(x.subscripts, visitor);
467 Walk(x.imageSelector, visitor);
471 template <
typename M>
static void Walk(
PartRef &x, M &mutator) {
472 if (mutator.Pre(x)) {
473 Walk(x.name, mutator);
474 Walk(x.subscripts, mutator);
475 Walk(x.imageSelector, mutator);
479 template <
typename V>
static void Walk(
const ReadStmt &x, V &visitor) {
480 if (visitor.Pre(x)) {
481 Walk(x.iounit, visitor);
482 Walk(x.format, visitor);
483 Walk(x.controls, visitor);
484 Walk(x.items, visitor);
488 template <
typename M>
static void Walk(
ReadStmt &x, M &mutator) {
489 if (mutator.Pre(x)) {
490 Walk(x.iounit, mutator);
491 Walk(x.format, mutator);
492 Walk(x.controls, mutator);
493 Walk(x.items, mutator);
497 template <
typename V>
499 if (visitor.Pre(x)) {
500 Walk(x.source, visitor);
505 template <
typename M>
507 if (mutator.Pre(x)) {
508 Walk(x.source, mutator);
513 template <
typename V>
515 if (visitor.Pre(x)) {
516 Walk(x.real, visitor);
517 Walk(x.kind, visitor);
522 if (mutator.Pre(x)) {
523 Walk(x.real, mutator);
524 Walk(x.kind, mutator);
528 template <
typename V>
530 if (visitor.Pre(x)) {
531 Walk(x.source, visitor);
535 template <
typename M>
537 if (mutator.Pre(x)) {
538 Walk(x.source, mutator);
542 template <
typename V>
544 if (visitor.Pre(x)) {
545 Walk(x.base, visitor);
546 Walk(x.component, visitor);
551 if (mutator.Pre(x)) {
552 Walk(x.base, mutator);
553 Walk(x.component, mutator);
557 template <
typename V>
static void Walk(
const Suffix &x, V &visitor) {
558 if (visitor.Pre(x)) {
559 Walk(x.binding, visitor);
560 Walk(x.resultName, visitor);
564 template <
typename M>
static void Walk(
Suffix &x, M &mutator) {
565 if (mutator.Pre(x)) {
566 Walk(x.binding, mutator);
567 Walk(x.resultName, mutator);
571 template <
typename V>
573 if (visitor.Pre(x)) {
574 Walk(x.interfaceName, visitor);
575 Walk(x.attributes, visitor);
576 Walk(x.bindingNames, visitor);
580 template <
typename M>
582 if (mutator.Pre(x)) {
583 Walk(x.interfaceName, mutator);
584 Walk(x.attributes, mutator);
585 Walk(x.bindingNames, mutator);
589 template <
typename V>
592 if (visitor.Pre(x)) {
593 Walk(x.attributes, visitor);
594 Walk(x.declarations, visitor);
598 template <
typename M>
600 if (mutator.Pre(x)) {
601 Walk(x.attributes, mutator);
602 Walk(x.declarations, mutator);
606 template <
typename V>
static void Walk(
const UseStmt &x, V &visitor) {
607 if (visitor.Pre(x)) {
608 Walk(x.nature, visitor);
609 Walk(x.moduleName, visitor);
614 template <
typename M>
static void Walk(
UseStmt &x, M &mutator) {
615 if (mutator.Pre(x)) {
616 Walk(x.nature, mutator);
617 Walk(x.moduleName, mutator);
622 template <
typename V>
static void Walk(
const WriteStmt &x, V &visitor) {
623 if (visitor.Pre(x)) {
624 Walk(x.iounit, visitor);
625 Walk(x.format, visitor);
626 Walk(x.controls, visitor);
627 Walk(x.items, visitor);
631 template <
typename M>
static void Walk(
WriteStmt &x, M &mutator) {
632 if (mutator.Pre(x)) {
633 Walk(x.iounit, mutator);
634 Walk(x.format, mutator);
635 Walk(x.controls, mutator);
636 Walk(x.items, mutator);
640 template <
typename V>
642 if (visitor.Pre(x)) {
643 Walk(x.kind, visitor);
647 template <
typename M>
649 if (mutator.Pre(x)) {
650 Walk(x.kind, mutator);
654 template <
typename V>
656 if (visitor.Pre(x)) {
657 Walk(x.type, visitor);
658 Walk(x.parameters, visitor);
662 template <
typename M>
664 if (mutator.Pre(x)) {
665 Walk(x.type, mutator);
666 Walk(x.parameters, mutator);
670 template <
typename V>
672 if (visitor.Pre(x)) {
673 Walk(x.repeatCount, visitor);
679 if (mutator.Pre(x)) {
680 Walk(x.repeatCount, mutator);
685 template <
typename V>
687 if (visitor.Pre(x)) {
688 Walk(x.items, visitor);
689 Walk(x.unlimitedItems, visitor);
693 template <
typename M>
695 if (mutator.Pre(x)) {
696 Walk(x.items, mutator);
697 Walk(x.unlimitedItems, mutator);
701 template <
typename V>
703 if (visitor.Pre(x)) {
704 Walk(x.kind, visitor);
705 Walk(x.width, visitor);
706 Walk(x.digits, visitor);
707 Walk(x.exponentWidth, visitor);
711 template <
typename M>
713 if (mutator.Pre(x)) {
714 Walk(x.kind, mutator);
715 Walk(x.width, mutator);
716 Walk(x.digits, mutator);
717 Walk(x.exponentWidth, mutator);
721 template <
typename V>
723 if (visitor.Pre(x)) {
724 Walk(x.source, visitor);
730 if (mutator.Pre(x)) {
731 Walk(x.source, mutator);
736 template <
typename V>
737 static void Walk(
const CompilerDirective::Unrecognized &x, V &visitor) {
738 if (visitor.Pre(x)) {
742 template <
typename M>
743 static void Walk(CompilerDirective::Unrecognized &x, M &mutator) {
744 if (mutator.Pre(x)) {