45 template <
typename A,
typename V>
46 static std::enable_if_t<!std::is_class_v<A> || common::IsEnumSet<A> ||
47 std::is_same_v<std::string, A> || std::is_same_v<CharBlock, A>>
48 Walk(
const A &x, V &visitor) {
53 template <
typename A,
typename M>
54 static std::enable_if_t<!std::is_class_v<A> ||
55 std::is_same_v<std::string, A> || std::is_same_v<CharBlock, A>>
56 Walk(A &x, M &mutator) {
62 template <
typename A,
typename VM>
63 static void WalkSource(A &x, VM &visitorOrMutator) {
65 Walk(x.source, visitorOrMutator);
73 template <
typename T,
typename V>
74 static void Walk(
const std::list<T> &x, V &visitor) {
75 for (
const auto &elem : x) {
79 template <
typename T,
typename M>
80 static void Walk(std::list<T> &x, M &mutator) {
81 for (
auto &elem : x) {
85 template <
typename V>
static void Walk(
const Block &x, V &visitor) {
87 for (
const auto &elem : x) {
93 template <
typename M>
static void Walk(Block &x, M &mutator) {
95 for (
auto &elem : x) {
101 template <
typename T,
typename V>
102 static void Walk(
const std::optional<T> &x, V &visitor) {
107 template <
typename T,
typename M>
108 static void Walk(std::optional<T> &x, M &mutator) {
113 template <std::
size_t I = 0,
typename Func,
typename T>
114 static void ForEachInTuple(
const T &tuple, Func func) {
115 func(std::get<I>(tuple));
116 if constexpr (I + 1 < std::tuple_size_v<T>) {
117 ForEachInTuple<I + 1>(tuple, func);
120 template <
typename V,
typename... A>
121 static void Walk(
const std::tuple<A...> &x, V &visitor) {
122 if (
sizeof...(A) > 0) {
123 if (visitor.Pre(x)) {
124 ForEachInTuple(x, [&](
const auto &y) { Walk(y, visitor); });
129 template <std::
size_t I = 0,
typename Func,
typename T>
130 static void ForEachInTuple(T &tuple, Func func) {
131 func(std::get<I>(tuple));
132 if constexpr (I + 1 < std::tuple_size_v<T>) {
133 ForEachInTuple<I + 1>(tuple, func);
136 template <
typename M,
typename... A>
137 static void Walk(std::tuple<A...> &x, M &mutator) {
138 if (
sizeof...(A) > 0) {
139 if (mutator.Pre(x)) {
140 ForEachInTuple(x, [&](
auto &y) { Walk(y, mutator); });
145 template <
typename V,
typename... A>
146 static void Walk(
const std::variant<A...> &x, V &visitor) {
147 if (visitor.Pre(x)) {
148 common::visit([&](
const auto &y) { Walk(y, visitor); }, x);
152 template <
typename M,
typename... A>
153 static void Walk(std::variant<A...> &x, M &mutator) {
154 if (mutator.Pre(x)) {
155 common::visit([&](
auto &y) { Walk(y, mutator); }, x);
159 template <
typename A,
typename B,
typename V>
160 static void Walk(
const std::pair<A, B> &x, V &visitor) {
161 if (visitor.Pre(x)) {
162 Walk(x.first, visitor);
163 Walk(x.second, visitor);
166 template <
typename A,
typename B,
typename M>
167 static void Walk(std::pair<A, B> &x, M &mutator) {
168 if (mutator.Pre(x)) {
169 Walk(x.first, mutator);
170 Walk(x.second, mutator);
176 template <
typename A,
typename V>
177 static std::enable_if_t<EmptyTrait<A>> Walk(
const A &x, V &visitor) {
178 if (visitor.Pre(x)) {
179 WalkSource(x, visitor);
183 template <
typename A,
typename M>
184 static std::enable_if_t<EmptyTrait<A>> Walk(A &x, M &mutator) {
185 if (mutator.Pre(x)) {
186 WalkSource(x, mutator);
191 template <
typename A,
typename V>
192 static std::enable_if_t<TupleTrait<A>> Walk(
const A &x, V &visitor) {
193 if (visitor.Pre(x)) {
194 WalkSource(x, visitor);
199 template <
typename A,
typename M>
200 static std::enable_if_t<TupleTrait<A>> Walk(A &x, M &mutator) {
201 if (mutator.Pre(x)) {
202 WalkSource(x, mutator);
208 template <
typename A,
typename V>
209 static std::enable_if_t<UnionTrait<A>> Walk(
const A &x, V &visitor) {
210 if (visitor.Pre(x)) {
211 WalkSource(x, visitor);
216 template <
typename A,
typename M>
217 static std::enable_if_t<UnionTrait<A>> Walk(A &x, M &mutator) {
218 if (mutator.Pre(x)) {
219 WalkSource(x, mutator);
225 template <
typename A,
typename V>
226 static std::enable_if_t<WrapperTrait<A>> Walk(
const A &x, V &visitor) {
227 if (visitor.Pre(x)) {
228 WalkSource(x, visitor);
233 template <
typename A,
typename M>
234 static std::enable_if_t<WrapperTrait<A>> Walk(A &x, M &mutator) {
235 if (mutator.Pre(x)) {
236 WalkSource(x, mutator);
242 template <
typename A,
typename V>
243 static std::enable_if_t<ConstraintTrait<A>> Walk(
const A &x, V &visitor) {
244 if (visitor.Pre(x)) {
245 WalkSource(x, visitor);
246 Walk(x.thing, visitor);
250 template <
typename A,
typename M>
251 static std::enable_if_t<ConstraintTrait<A>> Walk(A &x, M &mutator) {
252 if (mutator.Pre(x)) {
253 WalkSource(x, mutator);
254 Walk(x.thing, mutator);
259 template <
typename T,
typename V>
261 Walk(x.value(), visitor);
263 template <
typename T,
typename M>
265 Walk(x.value(), mutator);
268 template <
typename T,
typename V>
270 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)) {
281 Walk(x.source, mutator);
282 Walk(x.statement, mutator);
287 template <
typename T,
typename V>
289 if (visitor.Pre(x)) {
290 Walk(x.source, visitor);
291 Walk(x.statement, visitor);
295 template <
typename T,
typename M>
297 if (mutator.Pre(x)) {
298 Walk(x.source, mutator);
299 Walk(x.statement, mutator);
304 template <
typename V>
static void Walk(
const Name &x, V &visitor) {
305 if (visitor.Pre(x)) {
306 Walk(x.source, visitor);
310 template <
typename M>
static void Walk(
Name &x, M &mutator) {
311 if (mutator.Pre(x)) {
312 Walk(x.source, mutator);
328 template <
typename A,
typename V,
typename UNARY,
typename BINARY>
329 static void IterativeWalk(A &start, V &visitor) {
330 struct ExprWorkList {
331 ExprWorkList(A &x) : expr(&x) {}
332 bool doPostExpr{
false}, doPostOpr{
false};
335 std::vector<ExprWorkList> stack;
336 stack.emplace_back(start);
338 A &expr{*stack.back().expr};
339 if (stack.back().doPostOpr) {
340 stack.back().doPostOpr =
false;
341 common::visit([&visitor](
auto &y) { visitor.Post(y); }, expr.u);
342 }
else if (stack.back().doPostExpr) {
345 }
else if (!visitor.Pre(expr)) {
348 stack.back().doPostExpr =
true;
349 Walk(expr.source, visitor);
350 UNARY *unary{
nullptr};
351 BINARY *binary{
nullptr};
353 [&unary, &binary](
auto &y) {
354 if constexpr (std::is_convertible_v<
decltype(&y), UNARY *>) {
356 }
else if constexpr (std::is_convertible_v<
decltype(&y),
362 if (!unary && !binary) {
363 Walk(expr.u, visitor);
364 }
else if (common::visit([&visitor](
auto &y) {
return visitor.Pre(y); },
366 stack.back().doPostOpr =
true;
368 stack.emplace_back(unary->v.value());
370 stack.emplace_back(std::get<1>(binary->t).value());
371 stack.emplace_back(std::get<0>(binary->t).value());
375 }
while (!stack.empty());
377 template <
typename V>
static void Walk(
const Expr &x, V &visitor) {
378 IterativeWalk<
const Expr, V,
const Expr::IntrinsicUnary,
381 template <
typename M>
static void Walk(
Expr &x, M &mutator) {
382 IterativeWalk<Expr, M, Expr::IntrinsicUnary, Expr::IntrinsicBinary>(
386 template <
typename V>
static void Walk(
const ReadStmt &x, V &visitor) {
387 if (visitor.Pre(x)) {
388 Walk(x.iounit, visitor);
389 Walk(x.format, visitor);
390 Walk(x.controls, visitor);
391 Walk(x.items, visitor);
395 template <
typename M>
static void Walk(
ReadStmt &x, M &mutator) {
396 if (mutator.Pre(x)) {
397 Walk(x.iounit, mutator);
398 Walk(x.format, mutator);
399 Walk(x.controls, mutator);
400 Walk(x.items, mutator);
404 template <
typename V>
static void Walk(
const UseStmt &x, V &visitor) {
405 if (visitor.Pre(x)) {
406 Walk(x.nature, visitor);
407 Walk(x.moduleName, visitor);
412 template <
typename M>
static void Walk(
UseStmt &x, M &mutator) {
413 if (mutator.Pre(x)) {
414 Walk(x.nature, mutator);
415 Walk(x.moduleName, mutator);
420 template <
typename V>
static void Walk(
const WriteStmt &x, V &visitor) {
421 if (visitor.Pre(x)) {
422 Walk(x.iounit, visitor);
423 Walk(x.format, visitor);
424 Walk(x.controls, visitor);
425 Walk(x.items, visitor);
429 template <
typename M>
static void Walk(
WriteStmt &x, M &mutator) {
430 if (mutator.Pre(x)) {
431 Walk(x.iounit, mutator);
432 Walk(x.format, mutator);
433 Walk(x.controls, mutator);
434 Walk(x.items, mutator);
438 template <
typename V>
440 if (visitor.Pre(x)) {
441 Walk(x.kind, visitor);
445 template <
typename M>
447 if (mutator.Pre(x)) {
448 Walk(x.kind, mutator);
452 template <
typename V>
454 if (visitor.Pre(x)) {
455 Walk(x.type, visitor);
456 Walk(x.parameters, visitor);
460 template <
typename M>
462 if (mutator.Pre(x)) {
463 Walk(x.type, mutator);
464 Walk(x.parameters, mutator);
468 template <
typename V>
470 if (visitor.Pre(x)) {
471 Walk(x.repeatCount, visitor);
477 if (mutator.Pre(x)) {
478 Walk(x.repeatCount, mutator);
483 template <
typename V>
485 if (visitor.Pre(x)) {
486 Walk(x.items, visitor);
487 Walk(x.unlimitedItems, visitor);
491 template <
typename M>
493 if (mutator.Pre(x)) {
494 Walk(x.items, mutator);
495 Walk(x.unlimitedItems, mutator);
499 template <
typename V>
501 if (visitor.Pre(x)) {
502 Walk(x.kind, visitor);
503 Walk(x.width, visitor);
504 Walk(x.digits, visitor);
505 Walk(x.exponentWidth, visitor);
509 template <
typename M>
511 if (mutator.Pre(x)) {
512 Walk(x.kind, mutator);
513 Walk(x.width, mutator);
514 Walk(x.digits, mutator);
515 Walk(x.exponentWidth, mutator);