// Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef FORTRAN_PARSER_PARSE_TREE_VISITOR_H_ #define FORTRAN_PARSER_PARSE_TREE_VISITOR_H_ #include "parse-tree.h" #include #include #include #include #include /// Parse tree visitor /// Call Walk(x, visitor) to visit x and, by default, each node under x. /// If x is non-const, the visitor member functions can modify the tree. /// /// visitor.Pre(x) is called before visiting x and its children are not /// visited if it returns false. /// /// visitor.Post(x) is called after visiting x. namespace Fortran::parser { // Default case for visitation of non-class data members, strings, and // any other non-decomposable values. template std::enable_if_t || std::is_same_v || std::is_same_v> Walk(const A &x, V &visitor) { if (visitor.Pre(x)) { visitor.Post(x); } } template std::enable_if_t || std::is_same_v || std::is_same_v> Walk(A &x, M &mutator) { if (mutator.Pre(x)) { mutator.Post(x); } } template void Walk(const format::ControlEditDesc &, V &); template void Walk(format::ControlEditDesc &, M &); template void Walk(const format::DerivedTypeDataEditDesc &, V &); template void Walk(format::DerivedTypeDataEditDesc &, M &); template void Walk(const format::FormatItem &, V &); template void Walk(format::FormatItem &, M &); template void Walk(const format::FormatSpecification &, V &); template void Walk(format::FormatSpecification &, M &); template void Walk(const format::IntrinsicTypeDataEditDesc &, V &); template void Walk(format::IntrinsicTypeDataEditDesc &, M &); // Traversal of needed STL template classes (optional, list, tuple, variant) template void Walk(const std::optional &x, V &visitor) { if (x.has_value()) { Walk(*x, visitor); } } template void Walk(std::optional &x, M &mutator) { if (x.has_value()) { Walk(*x, mutator); } } // For most lists, just traverse the elements; but when a list constitutes // a Block (i.e., std::list), also invoke the // visitor/mutator on the list itself. template void Walk(const std::list &x, V &visitor) { for (const auto &elem : x) { Walk(elem, visitor); } } template void Walk(std::list &x, M &mutator) { for (auto &elem : x) { Walk(elem, mutator); } } template void Walk(const Block &x, V &visitor) { if (visitor.Pre(x)) { for (const auto &elem : x) { Walk(elem, visitor); } visitor.Post(x); } } template void Walk(Block &x, M &mutator) { if (mutator.Pre(x)) { for (auto &elem : x) { Walk(elem, mutator); } mutator.Post(x); } } template void ForEachInTuple(const T &tuple, Func func) { func(std::get(tuple)); if constexpr (I + 1 < std::tuple_size_v) { ForEachInTuple(tuple, func); } } template void Walk(const std::tuple &x, V &visitor) { if (sizeof...(A) > 0) { if (visitor.Pre(x)) { ForEachInTuple(x, [&](const auto &y) { Walk(y, visitor); }); visitor.Post(x); } } } template void ForEachInTuple(T &tuple, Func func) { func(std::get(tuple)); if constexpr (I + 1 < std::tuple_size_v) { ForEachInTuple(tuple, func); } } template void Walk(std::tuple &x, M &mutator) { if (sizeof...(A) > 0) { if (mutator.Pre(x)) { ForEachInTuple(x, [&](auto &y) { Walk(y, mutator); }); mutator.Post(x); } } } template void Walk(const std::variant &x, V &visitor) { if (visitor.Pre(x)) { std::visit([&](const auto &y) { Walk(y, visitor); }, x); visitor.Post(x); } } template void Walk(std::variant &x, M &mutator) { if (mutator.Pre(x)) { std::visit([&](auto &y) { Walk(y, mutator); }, x); mutator.Post(x); } } template void Walk(const std::pair &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.first, visitor); Walk(x.second, visitor); } } template void Walk(std::pair &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.first, mutator); Walk(x.second, mutator); } } // Trait-determined traversal of empty, tuple, union, wrapper, // and constraint-checking classes. template std::enable_if_t> Walk(const A &x, V &visitor) { if (visitor.Pre(x)) { visitor.Post(x); } } template std::enable_if_t> Walk(A &x, M &mutator) { if (mutator.Pre(x)) { mutator.Post(x); } } template std::enable_if_t> Walk(const A &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.t, visitor); visitor.Post(x); } } template std::enable_if_t> Walk(A &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.t, mutator); mutator.Post(x); } } template std::enable_if_t> Walk(const A &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.u, visitor); visitor.Post(x); } } template std::enable_if_t> Walk(A &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.u, mutator); mutator.Post(x); } } template std::enable_if_t> Walk(const A &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.v, visitor); visitor.Post(x); } } template std::enable_if_t> Walk(A &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.v, mutator); mutator.Post(x); } } template std::enable_if_t> Walk(const A &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.thing, visitor); visitor.Post(x); } } template std::enable_if_t> Walk(A &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.thing, mutator); mutator.Post(x); } } template void Walk(const common::Indirection &x, V &visitor) { Walk(x.value(), visitor); } template void Walk(common::Indirection &x, M &mutator) { Walk(x.value(), mutator); } template void Walk(const Statement &x, V &visitor) { if (visitor.Pre(x)) { // N.B. The label, if any, is not visited. Walk(x.source, visitor); Walk(x.statement, visitor); visitor.Post(x); } } template void Walk(Statement &x, M &mutator) { if (mutator.Pre(x)) { // N.B. The label, if any, is not visited. Walk(x.source, mutator); Walk(x.statement, mutator); mutator.Post(x); } } template void Walk(const UnlabeledStatement &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.source, visitor); Walk(x.statement, visitor); visitor.Post(x); } } template void Walk(UnlabeledStatement &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.source, mutator); Walk(x.statement, mutator); mutator.Post(x); } } template void Walk(const Name &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.source, visitor); visitor.Post(x); } } template void Walk(Name &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.source, mutator); mutator.Post(x); } } template void Walk(const AcSpec &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.type, visitor); Walk(x.values, visitor); visitor.Post(x); } } template void Walk(AcSpec &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.type, mutator); Walk(x.values, mutator); mutator.Post(x); } } template void Walk(const ArrayElement &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.base, visitor); Walk(x.subscripts, visitor); visitor.Post(x); } } template void Walk(ArrayElement &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.base, mutator); Walk(x.subscripts, mutator); mutator.Post(x); } } template void Walk(const CharSelector::LengthAndKind &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.length, visitor); Walk(x.kind, visitor); visitor.Post(x); } } template void Walk(CharSelector::LengthAndKind &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.length, mutator); Walk(x.kind, mutator); mutator.Post(x); } } template void Walk(const CaseValueRange::Range &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.lower, visitor); Walk(x.upper, visitor); visitor.Post(x); } } template void Walk(CaseValueRange::Range &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.lower, mutator); Walk(x.upper, mutator); mutator.Post(x); } } template void Walk(const CoindexedNamedObject &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.base, visitor); Walk(x.imageSelector, visitor); visitor.Post(x); } } template void Walk(CoindexedNamedObject &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.base, mutator); Walk(x.imageSelector, mutator); mutator.Post(x); } } template void Walk(const DeclarationTypeSpec::Class &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.derived, visitor); visitor.Post(x); } } template void Walk(DeclarationTypeSpec::Class &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.derived, mutator); mutator.Post(x); } } template void Walk(const DeclarationTypeSpec::Type &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.derived, visitor); visitor.Post(x); } } template void Walk(DeclarationTypeSpec::Type &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.derived, mutator); mutator.Post(x); } } template void Walk(const ImportStmt &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.names, visitor); visitor.Post(x); } } template void Walk(ImportStmt &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.names, mutator); mutator.Post(x); } } template void Walk(const IntrinsicTypeSpec::Character &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.selector, visitor); visitor.Post(x); } } template void Walk(IntrinsicTypeSpec::Character &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.selector, mutator); mutator.Post(x); } } template void Walk(const IntrinsicTypeSpec::Complex &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.kind, visitor); visitor.Post(x); } } template void Walk(IntrinsicTypeSpec::Complex &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.kind, mutator); mutator.Post(x); } } template void Walk(const IntrinsicTypeSpec::Logical &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.kind, visitor); visitor.Post(x); } } template void Walk(IntrinsicTypeSpec::Logical &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.kind, mutator); mutator.Post(x); } } template void Walk(const IntrinsicTypeSpec::Real &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.kind, visitor); visitor.Post(x); } } template void Walk(IntrinsicTypeSpec::Real &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.kind, mutator); mutator.Post(x); } } template void Walk(const LoopBounds &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.name, visitor); Walk(x.lower, visitor); Walk(x.upper, visitor); Walk(x.step, visitor); visitor.Post(x); } } template void Walk(LoopBounds &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.name, mutator); Walk(x.lower, mutator); Walk(x.upper, mutator); Walk(x.step, mutator); mutator.Post(x); } } template void Walk(const CommonStmt &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.blocks, visitor); visitor.Post(x); } } template void Walk(CommonStmt &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.blocks, mutator); mutator.Post(x); } } template void Walk(const Expr &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.source, visitor); Walk(x.u, visitor); visitor.Post(x); } } template void Walk(Expr &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.source, mutator); Walk(x.u, mutator); mutator.Post(x); } } template void Walk(const Designator &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.source, visitor); Walk(x.u, visitor); visitor.Post(x); } } template void Walk(Designator &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.source, mutator); Walk(x.u, mutator); mutator.Post(x); } } template void Walk(const Call &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.source, visitor); Walk(x.t, visitor); visitor.Post(x); } } template void Walk(Call &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.source, mutator); Walk(x.t, mutator); mutator.Post(x); } } template void Walk(const PartRef &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.name, visitor); Walk(x.subscripts, visitor); Walk(x.imageSelector, visitor); visitor.Post(x); } } template void Walk(PartRef &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.name, mutator); Walk(x.subscripts, mutator); Walk(x.imageSelector, mutator); mutator.Post(x); } } template void Walk(const ReadStmt &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.iounit, visitor); Walk(x.format, visitor); Walk(x.controls, visitor); Walk(x.items, visitor); visitor.Post(x); } } template void Walk(ReadStmt &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.iounit, mutator); Walk(x.format, mutator); Walk(x.controls, mutator); Walk(x.items, mutator); mutator.Post(x); } } template void Walk(const SignedIntLiteralConstant &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.source, visitor); Walk(x.t, visitor); visitor.Post(x); } } template void Walk(SignedIntLiteralConstant &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.source, mutator); Walk(x.t, mutator); mutator.Post(x); } } template void Walk(const RealLiteralConstant &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.real, visitor); Walk(x.kind, visitor); visitor.Post(x); } } template void Walk(RealLiteralConstant &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.real, mutator); Walk(x.kind, mutator); mutator.Post(x); } } template void Walk(const RealLiteralConstant::Real &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.source, visitor); visitor.Post(x); } } template void Walk(RealLiteralConstant::Real &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.source, mutator); mutator.Post(x); } } template void Walk(const StructureComponent &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.base, visitor); Walk(x.component, visitor); visitor.Post(x); } } template void Walk(StructureComponent &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.base, mutator); Walk(x.component, mutator); mutator.Post(x); } } template void Walk(const Suffix &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.binding, visitor); Walk(x.resultName, visitor); visitor.Post(x); } } template void Walk(Suffix &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.binding, mutator); Walk(x.resultName, mutator); mutator.Post(x); } } template void Walk(const TypeBoundProcedureStmt::WithInterface &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.interfaceName, visitor); Walk(x.attributes, visitor); Walk(x.bindingNames, visitor); visitor.Post(x); } } template void Walk(TypeBoundProcedureStmt::WithInterface &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.interfaceName, mutator); Walk(x.attributes, mutator); Walk(x.bindingNames, mutator); mutator.Post(x); } } template void Walk(const TypeBoundProcedureStmt::WithoutInterface &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.attributes, visitor); Walk(x.declarations, visitor); visitor.Post(x); } } template void Walk(TypeBoundProcedureStmt::WithoutInterface &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.attributes, mutator); Walk(x.declarations, mutator); mutator.Post(x); } } template void Walk(const UseStmt &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.nature, visitor); Walk(x.moduleName, visitor); Walk(x.u, visitor); visitor.Post(x); } } template void Walk(UseStmt &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.nature, mutator); Walk(x.moduleName, mutator); Walk(x.u, mutator); mutator.Post(x); } } template void Walk(const WriteStmt &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.iounit, visitor); Walk(x.format, visitor); Walk(x.controls, visitor); Walk(x.items, visitor); visitor.Post(x); } } template void Walk(WriteStmt &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.iounit, mutator); Walk(x.format, mutator); Walk(x.controls, mutator); Walk(x.items, mutator); mutator.Post(x); } } template void Walk(const format::ControlEditDesc &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.kind, visitor); visitor.Post(x); } } template void Walk(format::ControlEditDesc &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.kind, mutator); mutator.Post(x); } } template void Walk(const format::DerivedTypeDataEditDesc &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.type, visitor); Walk(x.parameters, visitor); visitor.Post(x); } } template void Walk(format::DerivedTypeDataEditDesc &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.type, mutator); Walk(x.parameters, mutator); mutator.Post(x); } } template void Walk(const format::FormatItem &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.repeatCount, visitor); Walk(x.u, visitor); visitor.Post(x); } } template void Walk(format::FormatItem &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.repeatCount, mutator); Walk(x.u, mutator); mutator.Post(x); } } template void Walk(const format::FormatSpecification &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.items, visitor); Walk(x.unlimitedItems, visitor); visitor.Post(x); } } template void Walk(format::FormatSpecification &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.items, mutator); Walk(x.unlimitedItems, mutator); mutator.Post(x); } } template void Walk(const format::IntrinsicTypeDataEditDesc &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.kind, visitor); Walk(x.width, visitor); Walk(x.digits, visitor); Walk(x.exponentWidth, visitor); visitor.Post(x); } } template void Walk(format::IntrinsicTypeDataEditDesc &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.kind, mutator); Walk(x.width, mutator); Walk(x.digits, mutator); Walk(x.exponentWidth, mutator); mutator.Post(x); } } template void Walk(const CompilerDirective &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.source, visitor); Walk(x.u, visitor); visitor.Post(x); } } template void Walk(CompilerDirective &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.source, mutator); Walk(x.u, mutator); mutator.Post(x); } } template void Walk(const OmpLinearClause::WithModifier &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.modifier, visitor); Walk(x.names, visitor); Walk(x.step, visitor); visitor.Post(x); } } template void Walk(OmpLinearClause::WithModifier &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.modifier, mutator); Walk(x.names, mutator); Walk(x.step, mutator); mutator.Post(x); } } template void Walk(const OmpLinearClause::WithoutModifier &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.names, visitor); Walk(x.step, visitor); visitor.Post(x); } } template void Walk(OmpLinearClause::WithoutModifier &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.names, mutator); Walk(x.step, mutator); mutator.Post(x); } } template void Walk(const OpenMPDeclareTargetSpecifier::WithClause &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.maptype, visitor); Walk(x.names, visitor); visitor.Post(x); } } template void Walk(OpenMPDeclareTargetSpecifier::WithClause &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.maptype, mutator); Walk(x.names, mutator); mutator.Post(x); } } template void Walk(const OpenMPDeclareTargetSpecifier::WithExtendedList &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.names, visitor); visitor.Post(x); } } template void Walk(OpenMPDeclareTargetSpecifier::WithExtendedList &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.names, mutator); mutator.Post(x); } } } #endif // FORTRAN_PARSER_PARSE_TREE_VISITOR_H_