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 AcSpec &x, V &visitor) {
300 if (visitor.Pre(x)) {
301 Walk(x.type, visitor);
302 Walk(x.values, visitor);
306 template <
typename M>
static void Walk(
AcSpec &x, M &mutator) {
307 if (mutator.Pre(x)) {
308 Walk(x.type, mutator);
309 Walk(x.values, mutator);
313 template <
typename V>
static void Walk(
const ArrayElement &x, V &visitor) {
314 if (visitor.Pre(x)) {
315 Walk(x.base, visitor);
316 Walk(x.subscripts, visitor);
320 template <
typename M>
static void Walk(
ArrayElement &x, M &mutator) {
321 if (mutator.Pre(x)) {
322 Walk(x.base, mutator);
323 Walk(x.subscripts, mutator);
327 template <
typename V>
329 if (visitor.Pre(x)) {
330 Walk(x.length, visitor);
331 Walk(x.kind, visitor);
335 template <
typename M>
337 if (mutator.Pre(x)) {
338 Walk(x.length, mutator);
339 Walk(x.kind, mutator);
343 template <
typename V>
345 if (visitor.Pre(x)) {
346 Walk(x.lower, visitor);
347 Walk(x.upper, visitor);
352 if (mutator.Pre(x)) {
353 Walk(x.lower, mutator);
354 Walk(x.upper, mutator);
358 template <
typename V>
360 if (visitor.Pre(x)) {
361 Walk(x.base, visitor);
362 Walk(x.imageSelector, visitor);
367 if (mutator.Pre(x)) {
368 Walk(x.base, mutator);
369 Walk(x.imageSelector, mutator);
373 template <
typename V>
375 if (visitor.Pre(x)) {
376 Walk(x.derived, visitor);
380 template <
typename M>
382 if (mutator.Pre(x)) {
383 Walk(x.derived, mutator);
387 template <
typename V>
389 if (visitor.Pre(x)) {
390 Walk(x.derived, visitor);
394 template <
typename M>
396 if (mutator.Pre(x)) {
397 Walk(x.derived, mutator);
401 template <
typename V>
static void Walk(
const ImportStmt &x, V &visitor) {
402 if (visitor.Pre(x)) {
403 Walk(x.names, visitor);
407 template <
typename M>
static void Walk(
ImportStmt &x, M &mutator) {
408 if (mutator.Pre(x)) {
409 Walk(x.names, mutator);
413 template <
typename V>
415 if (visitor.Pre(x)) {
416 Walk(x.selector, visitor);
420 template <
typename M>
422 if (mutator.Pre(x)) {
423 Walk(x.selector, mutator);
427 template <
typename V>
429 if (visitor.Pre(x)) {
430 Walk(x.kind, visitor);
434 template <
typename M>
436 if (mutator.Pre(x)) {
437 Walk(x.kind, mutator);
441 template <
typename V>
443 if (visitor.Pre(x)) {
444 Walk(x.kind, visitor);
448 template <
typename M>
450 if (mutator.Pre(x)) {
451 Walk(x.kind, mutator);
455 template <
typename V>
457 if (visitor.Pre(x)) {
458 Walk(x.kind, visitor);
462 template <
typename M>
464 if (mutator.Pre(x)) {
465 Walk(x.kind, mutator);
469 template <
typename A,
typename B,
typename V>
471 if (visitor.Pre(x)) {
472 Walk(x.name, visitor);
473 Walk(x.lower, visitor);
474 Walk(x.upper, visitor);
475 Walk(x.step, visitor);
479 template <
typename A,
typename B,
typename M>
481 if (mutator.Pre(x)) {
482 Walk(x.name, mutator);
483 Walk(x.lower, mutator);
484 Walk(x.upper, mutator);
485 Walk(x.step, mutator);
489 template <
typename V>
static void Walk(
const CommonStmt &x, V &visitor) {
490 if (visitor.Pre(x)) {
491 Walk(x.blocks, visitor);
495 template <
typename M>
static void Walk(
CommonStmt &x, M &mutator) {
496 if (mutator.Pre(x)) {
497 Walk(x.blocks, mutator);
513 template <
typename A,
typename V,
typename UNARY,
typename BINARY>
514 static void IterativeWalk(A &start, V &visitor) {
515 struct ExprWorkList {
516 ExprWorkList(A &x) : expr(&x) {}
517 bool doPostExpr{
false}, doPostOpr{
false};
520 std::vector<ExprWorkList> stack;
521 stack.emplace_back(start);
523 A &expr{*stack.back().expr};
524 if (stack.back().doPostOpr) {
525 stack.back().doPostOpr =
false;
526 common::visit([&visitor](
auto &y) { visitor.Post(y); }, expr.u);
527 }
else if (stack.back().doPostExpr) {
530 }
else if (!visitor.Pre(expr)) {
533 stack.back().doPostExpr =
true;
534 Walk(expr.source, visitor);
535 UNARY *unary{
nullptr};
536 BINARY *binary{
nullptr};
538 [&unary, &binary](
auto &y) {
539 if constexpr (std::is_convertible_v<
decltype(&y), UNARY *>) {
541 }
else if constexpr (std::is_convertible_v<
decltype(&y),
547 if (!unary && !binary) {
548 Walk(expr.u, visitor);
549 }
else if (common::visit([&visitor](
auto &y) {
return visitor.Pre(y); },
551 stack.back().doPostOpr =
true;
553 stack.emplace_back(unary->v.value());
555 stack.emplace_back(std::get<1>(binary->t).value());
556 stack.emplace_back(std::get<0>(binary->t).value());
560 }
while (!stack.empty());
562 template <
typename V>
static void Walk(
const Expr &x, V &visitor) {
563 IterativeWalk<
const Expr, V,
const Expr::IntrinsicUnary,
566 template <
typename M>
static void Walk(
Expr &x, M &mutator) {
567 IterativeWalk<Expr, M, Expr::IntrinsicUnary, Expr::IntrinsicBinary>(
571 template <
typename V>
static void Walk(
const Designator &x, V &visitor) {
572 if (visitor.Pre(x)) {
573 Walk(x.source, visitor);
578 template <
typename M>
static void Walk(
Designator &x, M &mutator) {
579 if (mutator.Pre(x)) {
580 Walk(x.source, mutator);
585 template <
typename V>
587 if (visitor.Pre(x)) {
588 Walk(x.source, visitor);
594 if (mutator.Pre(x)) {
595 Walk(x.source, mutator);
600 template <
typename V>
static void Walk(
const CallStmt &x, V &visitor) {
601 if (visitor.Pre(x)) {
602 Walk(x.source, visitor);
603 Walk(x.call, visitor);
604 Walk(x.chevrons, visitor);
608 template <
typename M>
static void Walk(
CallStmt &x, M &mutator) {
609 if (mutator.Pre(x)) {
610 Walk(x.source, mutator);
611 Walk(x.call, mutator);
612 Walk(x.chevrons, mutator);
616 template <
typename V>
static void Walk(
const PartRef &x, V &visitor) {
617 if (visitor.Pre(x)) {
618 Walk(x.name, visitor);
619 Walk(x.subscripts, visitor);
620 Walk(x.imageSelector, visitor);
624 template <
typename M>
static void Walk(
PartRef &x, M &mutator) {
625 if (mutator.Pre(x)) {
626 Walk(x.name, mutator);
627 Walk(x.subscripts, mutator);
628 Walk(x.imageSelector, mutator);
632 template <
typename V>
static void Walk(
const ReadStmt &x, V &visitor) {
633 if (visitor.Pre(x)) {
634 Walk(x.iounit, visitor);
635 Walk(x.format, visitor);
636 Walk(x.controls, visitor);
637 Walk(x.items, visitor);
641 template <
typename M>
static void Walk(
ReadStmt &x, M &mutator) {
642 if (mutator.Pre(x)) {
643 Walk(x.iounit, mutator);
644 Walk(x.format, mutator);
645 Walk(x.controls, mutator);
646 Walk(x.items, mutator);
650 template <
typename V>
652 if (visitor.Pre(x)) {
653 Walk(x.source, visitor);
658 template <
typename M>
660 if (mutator.Pre(x)) {
661 Walk(x.source, mutator);
666 template <
typename V>
668 if (visitor.Pre(x)) {
669 Walk(x.real, visitor);
670 Walk(x.kind, visitor);
675 if (mutator.Pre(x)) {
676 Walk(x.real, mutator);
677 Walk(x.kind, mutator);
681 template <
typename V>
683 if (visitor.Pre(x)) {
684 Walk(x.source, visitor);
688 template <
typename M>
690 if (mutator.Pre(x)) {
691 Walk(x.source, mutator);
695 template <
typename V>
697 if (visitor.Pre(x)) {
698 Walk(x.base, visitor);
699 Walk(x.component, visitor);
704 if (mutator.Pre(x)) {
705 Walk(x.base, mutator);
706 Walk(x.component, mutator);
710 template <
typename V>
static void Walk(
const Suffix &x, V &visitor) {
711 if (visitor.Pre(x)) {
712 Walk(x.binding, visitor);
713 Walk(x.resultName, visitor);
717 template <
typename M>
static void Walk(
Suffix &x, M &mutator) {
718 if (mutator.Pre(x)) {
719 Walk(x.binding, mutator);
720 Walk(x.resultName, mutator);
724 template <
typename V>
726 if (visitor.Pre(x)) {
727 Walk(x.interfaceName, visitor);
728 Walk(x.attributes, visitor);
729 Walk(x.bindingNames, visitor);
733 template <
typename M>
735 if (mutator.Pre(x)) {
736 Walk(x.interfaceName, mutator);
737 Walk(x.attributes, mutator);
738 Walk(x.bindingNames, mutator);
742 template <
typename V>
745 if (visitor.Pre(x)) {
746 Walk(x.attributes, visitor);
747 Walk(x.declarations, visitor);
751 template <
typename M>
753 if (mutator.Pre(x)) {
754 Walk(x.attributes, mutator);
755 Walk(x.declarations, mutator);
759 template <
typename V>
static void Walk(
const UseStmt &x, V &visitor) {
760 if (visitor.Pre(x)) {
761 Walk(x.nature, visitor);
762 Walk(x.moduleName, visitor);
767 template <
typename M>
static void Walk(
UseStmt &x, M &mutator) {
768 if (mutator.Pre(x)) {
769 Walk(x.nature, mutator);
770 Walk(x.moduleName, mutator);
775 template <
typename V>
static void Walk(
const WriteStmt &x, V &visitor) {
776 if (visitor.Pre(x)) {
777 Walk(x.iounit, visitor);
778 Walk(x.format, visitor);
779 Walk(x.controls, visitor);
780 Walk(x.items, visitor);
784 template <
typename M>
static void Walk(
WriteStmt &x, M &mutator) {
785 if (mutator.Pre(x)) {
786 Walk(x.iounit, mutator);
787 Walk(x.format, mutator);
788 Walk(x.controls, mutator);
789 Walk(x.items, mutator);
793 template <
typename V>
795 if (visitor.Pre(x)) {
796 Walk(x.kind, visitor);
800 template <
typename M>
802 if (mutator.Pre(x)) {
803 Walk(x.kind, mutator);
807 template <
typename V>
809 if (visitor.Pre(x)) {
810 Walk(x.type, visitor);
811 Walk(x.parameters, visitor);
815 template <
typename M>
817 if (mutator.Pre(x)) {
818 Walk(x.type, mutator);
819 Walk(x.parameters, mutator);
823 template <
typename V>
825 if (visitor.Pre(x)) {
826 Walk(x.repeatCount, visitor);
832 if (mutator.Pre(x)) {
833 Walk(x.repeatCount, mutator);
838 template <
typename V>
840 if (visitor.Pre(x)) {
841 Walk(x.items, visitor);
842 Walk(x.unlimitedItems, visitor);
846 template <
typename M>
848 if (mutator.Pre(x)) {
849 Walk(x.items, mutator);
850 Walk(x.unlimitedItems, mutator);
854 template <
typename V>
856 if (visitor.Pre(x)) {
857 Walk(x.kind, visitor);
858 Walk(x.width, visitor);
859 Walk(x.digits, visitor);
860 Walk(x.exponentWidth, visitor);
864 template <
typename M>
866 if (mutator.Pre(x)) {
867 Walk(x.kind, mutator);
868 Walk(x.width, mutator);
869 Walk(x.digits, mutator);
870 Walk(x.exponentWidth, mutator);
874 template <
typename V>
876 if (visitor.Pre(x)) {
877 Walk(x.source, visitor);
883 if (mutator.Pre(x)) {
884 Walk(x.source, mutator);
889 template <
typename V>
890 static void Walk(
const CompilerDirective::Unrecognized &x, V &visitor) {
891 if (visitor.Pre(x)) {
895 template <
typename M>
896 static void Walk(CompilerDirective::Unrecognized &x, M &mutator) {
897 if (mutator.Pre(x)) {