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