llvm/flang/lib/parser/parse-tree-visitor.h
peter klausler be3b765e2a [flang] basic skeleton of assignment analyzer
remove needless template<> on some function overloads

dodge bogus compiler warning from gcc 8.1.0 only

stricter typing of expressions in symbols

adjust modfile12.f90 expected test results

add Unwrap, massage folding a bit

Use Unwrap to simplify folding

Move KindSelector analysis into expression semantics

fix crash

checkpoint

updates to TypeParamInquiry

support of %KIND type parameter inquiry

equality testing for expressions

checkpoint during PDT implementation

reformat

checkpoint derived type instantiation

checkpoint

resolve merge

debugging failed tests

fix failing resolve37.f90 test

all existing tests pass

clean up all build warnings

fix bug

update copyright dates

fix copyright dates

address review comments

review comment

merge with master after peeling off changes

bugfixing new feature

fix warning from old g++s

tweaks after merging with latest head

more bugfixing

making modfile17.f90 test work

Make kinds into expressions in symbol table types

big refactor for deferring kinds in intrinsic types

modfile17.f90 test passes

clean up TODOs

Simplify types as stored in scopes

Test KIND parameter default init expressions, debug them

Update copyright dates

address comments

remove dead line

address comments

Original-commit: flang-compiler/f18@1f43d0a048
Reviewed-on: https://github.com/flang-compiler/f18/pull/260
Tree-same-pre-rewrite: false
2019-01-17 10:41:08 -08:00

839 lines
22 KiB
C++

// 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 <cstddef>
#include <optional>
#include <tuple>
#include <utility>
#include <variant>
/// 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<typename A, typename V>
std::enable_if_t<!std::is_class_v<A> || std::is_same_v<std::string, A> ||
std::is_same_v<CharBlock, A>>
Walk(const A &x, V &visitor) {
if (visitor.Pre(x)) {
visitor.Post(x);
}
}
template<typename A, typename M>
std::enable_if_t<!std::is_class_v<A> || std::is_same_v<std::string, A> ||
std::is_same_v<CharBlock, A>>
Walk(A &x, M &mutator) {
if (mutator.Pre(x)) {
mutator.Post(x);
}
}
template<typename V> void Walk(const format::ControlEditDesc &, V &);
template<typename M> void Walk(format::ControlEditDesc &, M &);
template<typename V> void Walk(const format::DerivedTypeDataEditDesc &, V &);
template<typename M> void Walk(format::DerivedTypeDataEditDesc &, M &);
template<typename V> void Walk(const format::FormatItem &, V &);
template<typename M> void Walk(format::FormatItem &, M &);
template<typename V> void Walk(const format::FormatSpecification &, V &);
template<typename M> void Walk(format::FormatSpecification &, M &);
template<typename V> void Walk(const format::IntrinsicTypeDataEditDesc &, V &);
template<typename M> void Walk(format::IntrinsicTypeDataEditDesc &, M &);
// Traversal of needed STL template classes (optional, list, tuple, variant)
template<typename T, typename V>
void Walk(const std::optional<T> &x, V &visitor) {
if (x.has_value()) {
Walk(*x, visitor);
}
}
template<typename T, typename M> void Walk(std::optional<T> &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<ExecutionPartConstruct>), also invoke the
// visitor/mutator on the list itself.
template<typename T, typename V> void Walk(const std::list<T> &x, V &visitor) {
for (const auto &elem : x) {
Walk(elem, visitor);
}
}
template<typename T, typename M> void Walk(std::list<T> &x, M &mutator) {
for (auto &elem : x) {
Walk(elem, mutator);
}
}
template<typename V> void Walk(const Block &x, V &visitor) {
if (visitor.Pre(x)) {
for (const auto &elem : x) {
Walk(elem, visitor);
}
visitor.Post(x);
}
}
template<typename M> void Walk(Block &x, M &mutator) {
if (mutator.Pre(x)) {
for (auto &elem : x) {
Walk(elem, mutator);
}
mutator.Post(x);
}
}
template<std::size_t I = 0, typename Func, typename T>
void ForEachInTuple(const T &tuple, Func func) {
if constexpr (I < std::tuple_size_v<T>) {
func(std::get<I>(tuple));
ForEachInTuple<I + 1>(tuple, func);
}
}
template<typename V, typename... A>
void Walk(const std::tuple<A...> &x, V &visitor) {
if (visitor.Pre(x)) {
ForEachInTuple(x, [&](const auto &y) { Walk(y, visitor); });
visitor.Post(x);
}
}
template<std::size_t I = 0, typename Func, typename T>
void ForEachInTuple(T &tuple, Func func) {
if constexpr (I < std::tuple_size_v<T>) {
func(std::get<I>(tuple));
ForEachInTuple<I + 1>(tuple, func);
}
}
template<typename M, typename... A> void Walk(std::tuple<A...> &x, M &mutator) {
if (mutator.Pre(x)) {
ForEachInTuple(x, [&](auto &y) { Walk(y, mutator); });
mutator.Post(x);
}
}
template<typename V, typename... A>
void Walk(const std::variant<A...> &x, V &visitor) {
if (visitor.Pre(x)) {
std::visit([&](const auto &y) { Walk(y, visitor); }, x);
visitor.Post(x);
}
}
template<typename M, typename... A>
void Walk(std::variant<A...> &x, M &mutator) {
if (mutator.Pre(x)) {
std::visit([&](auto &y) { Walk(y, mutator); }, x);
mutator.Post(x);
}
}
template<typename A, typename B, typename V>
void Walk(const std::pair<A, B> &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.first, visitor);
Walk(x.second, visitor);
}
}
template<typename A, typename B, typename M>
void Walk(std::pair<A, B> &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.first, mutator);
Walk(x.second, mutator);
}
}
// Trait-determined traversal of empty, tuple, union, and wrapper classes.
template<typename A, typename V>
std::enable_if_t<EmptyTrait<A>> Walk(const A &x, V &visitor) {
if (visitor.Pre(x)) {
visitor.Post(x);
}
}
template<typename A, typename M>
std::enable_if_t<EmptyTrait<A>> Walk(A &x, M &mutator) {
if (mutator.Pre(x)) {
mutator.Post(x);
}
}
template<typename A, typename V>
std::enable_if_t<TupleTrait<A>> Walk(const A &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.t, visitor);
visitor.Post(x);
}
}
template<typename A, typename M>
std::enable_if_t<TupleTrait<A>> Walk(A &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.t, mutator);
mutator.Post(x);
}
}
template<typename A, typename V>
std::enable_if_t<UnionTrait<A>> Walk(const A &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.u, visitor);
visitor.Post(x);
}
}
template<typename A, typename M>
std::enable_if_t<UnionTrait<A>> Walk(A &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.u, mutator);
mutator.Post(x);
}
}
template<typename A, typename V>
std::enable_if_t<WrapperTrait<A>> Walk(const A &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.v, visitor);
visitor.Post(x);
}
}
template<typename A, typename M>
std::enable_if_t<WrapperTrait<A>> Walk(A &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.v, mutator);
mutator.Post(x);
}
}
template<typename T, typename V>
void Walk(const common::Indirection<T> &x, V &visitor) {
Walk(*x, visitor);
}
template<typename T, typename M>
void Walk(common::Indirection<T> &x, M &mutator) {
Walk(*x, mutator);
}
// Walk a class with a single field 'thing'.
template<typename T, typename V> void Walk(const Scalar<T> &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.thing, visitor);
visitor.Post(x);
}
}
template<typename T, typename M> void Walk(Scalar<T> &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.thing, mutator);
mutator.Post(x);
}
}
template<typename T, typename V> void Walk(const Constant<T> &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.thing, visitor);
visitor.Post(x);
}
}
template<typename T, typename M> void Walk(Constant<T> &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.thing, mutator);
mutator.Post(x);
}
}
template<typename T, typename V> void Walk(const Integer<T> &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.thing, visitor);
visitor.Post(x);
}
}
template<typename T, typename M> void Walk(Integer<T> &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.thing, mutator);
mutator.Post(x);
}
}
template<typename T, typename V> void Walk(const Logical<T> &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.thing, visitor);
visitor.Post(x);
}
}
template<typename T, typename M> void Walk(Logical<T> &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.thing, mutator);
mutator.Post(x);
}
}
template<typename T, typename V>
void Walk(const DefaultChar<T> &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.thing, visitor);
visitor.Post(x);
}
}
template<typename T, typename M> void Walk(DefaultChar<T> &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.thing, mutator);
mutator.Post(x);
}
}
template<typename T, typename V> void Walk(const Statement<T> &x, V &visitor) {
if (visitor.Pre(x)) {
// N.B. the label is not traversed
Walk(x.source, visitor);
Walk(x.statement, visitor);
visitor.Post(x);
}
}
template<typename T, typename M> void Walk(Statement<T> &x, M &mutator) {
if (mutator.Pre(x)) {
// N.B. the label is not traversed
Walk(x.source, mutator);
Walk(x.statement, mutator);
mutator.Post(x);
}
}
template<typename V> void Walk(const Name &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.source, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(Name &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.source, mutator);
mutator.Post(x);
}
}
template<typename V> void Walk(const AcSpec &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.type, visitor);
Walk(x.values, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(AcSpec &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.type, mutator);
Walk(x.values, mutator);
mutator.Post(x);
}
}
template<typename V> void Walk(const ArrayElement &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.base, visitor);
Walk(x.subscripts, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(ArrayElement &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.base, mutator);
Walk(x.subscripts, mutator);
mutator.Post(x);
}
}
template<typename V>
void Walk(const CharSelector::LengthAndKind &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.length, visitor);
Walk(x.kind, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(CharSelector::LengthAndKind &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.length, mutator);
Walk(x.kind, mutator);
mutator.Post(x);
}
}
template<typename V> void Walk(const CaseValueRange::Range &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.lower, visitor);
Walk(x.upper, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(CaseValueRange::Range &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.lower, mutator);
Walk(x.upper, mutator);
mutator.Post(x);
}
}
template<typename V> void Walk(const CoindexedNamedObject &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.base, visitor);
Walk(x.imageSelector, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(CoindexedNamedObject &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.base, mutator);
Walk(x.imageSelector, mutator);
mutator.Post(x);
}
}
template<typename V>
void Walk(const DeclarationTypeSpec::Class &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.derived, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(DeclarationTypeSpec::Class &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.derived, mutator);
mutator.Post(x);
}
}
template<typename V> void Walk(const DeclarationTypeSpec::Type &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.derived, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(DeclarationTypeSpec::Type &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.derived, mutator);
mutator.Post(x);
}
}
template<typename V> void Walk(const ImportStmt &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.names, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(ImportStmt &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.names, mutator);
mutator.Post(x);
}
}
template<typename V>
void Walk(const IntrinsicTypeSpec::Character &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.selector, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(IntrinsicTypeSpec::Character &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.selector, mutator);
mutator.Post(x);
}
}
template<typename V>
void Walk(const IntrinsicTypeSpec::Complex &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.kind, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(IntrinsicTypeSpec::Complex &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.kind, mutator);
mutator.Post(x);
}
}
template<typename V>
void Walk(const IntrinsicTypeSpec::Logical &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.kind, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(IntrinsicTypeSpec::Logical &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.kind, mutator);
mutator.Post(x);
}
}
template<typename V> void Walk(const IntrinsicTypeSpec::Real &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.kind, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(IntrinsicTypeSpec::Real &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.kind, mutator);
mutator.Post(x);
}
}
template<typename T, typename V> void Walk(const LoopBounds<T> &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<typename T, typename M> void Walk(LoopBounds<T> &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<typename V> void Walk(const Expr &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.source, visitor);
Walk(x.u, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(Expr &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.source, mutator);
Walk(x.u, mutator);
mutator.Post(x);
}
}
template<typename V> 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<typename M> 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<typename V> 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<typename M> 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<typename V> void Walk(const SignedIntLiteralConstant &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.source, visitor);
Walk(x.t, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(SignedIntLiteralConstant &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.source, mutator);
Walk(x.t, mutator);
mutator.Post(x);
}
}
template<typename V> void Walk(const RealLiteralConstant &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.real, visitor);
Walk(x.kind, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(RealLiteralConstant &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.real, mutator);
Walk(x.kind, mutator);
mutator.Post(x);
}
}
template<typename V> void Walk(const RealLiteralConstant::Real &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.source, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(RealLiteralConstant::Real &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.source, mutator);
mutator.Post(x);
}
}
template<typename V> void Walk(const StructureComponent &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.base, visitor);
Walk(x.component, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(StructureComponent &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.base, mutator);
Walk(x.component, mutator);
mutator.Post(x);
}
}
template<typename V> void Walk(const Suffix &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.binding, visitor);
Walk(x.resultName, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(Suffix &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.binding, mutator);
Walk(x.resultName, mutator);
mutator.Post(x);
}
}
template<typename V>
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<typename M>
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<typename V>
void Walk(const TypeBoundProcedureStmt::WithoutInterface &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.attributes, visitor);
Walk(x.declarations, visitor);
visitor.Post(x);
}
}
template<typename M>
void Walk(TypeBoundProcedureStmt::WithoutInterface &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.attributes, mutator);
Walk(x.declarations, mutator);
mutator.Post(x);
}
}
template<typename V> 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<typename M> 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<typename V> 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<typename M> 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<typename V> void Walk(const format::ControlEditDesc &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.kind, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(format::ControlEditDesc &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.kind, mutator);
mutator.Post(x);
}
}
template<typename V>
void Walk(const format::DerivedTypeDataEditDesc &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.type, visitor);
Walk(x.parameters, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(format::DerivedTypeDataEditDesc &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.type, mutator);
Walk(x.parameters, mutator);
mutator.Post(x);
}
}
template<typename V> void Walk(const format::FormatItem &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.repeatCount, visitor);
Walk(x.u, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(format::FormatItem &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.repeatCount, mutator);
Walk(x.u, mutator);
mutator.Post(x);
}
}
template<typename V>
void Walk(const format::FormatSpecification &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.items, visitor);
Walk(x.unlimitedItems, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(format::FormatSpecification &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.items, mutator);
Walk(x.unlimitedItems, mutator);
mutator.Post(x);
}
}
template<typename V>
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<typename M>
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<typename V> void Walk(const CompilerDirective &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.source, visitor);
Walk(x.u, visitor);
visitor.Post(x);
}
}
template<typename M> void Walk(CompilerDirective &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.source, mutator);
Walk(x.u, mutator);
mutator.Post(x);
}
}
template<typename V>
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<typename M> 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<typename V>
void Walk(const OmpLinearClause::WithoutModifier &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.names, visitor);
Walk(x.step, visitor);
visitor.Post(x);
}
}
template<typename M>
void Walk(OmpLinearClause::WithoutModifier &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.names, mutator);
Walk(x.step, mutator);
mutator.Post(x);
}
}
template<typename V>
void Walk(const OpenMPDeclareTargetConstruct::WithClause &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.maptype, visitor);
Walk(x.names, visitor);
visitor.Post(x);
}
}
template<typename M>
void Walk(OpenMPDeclareTargetConstruct::WithClause &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.maptype, mutator);
Walk(x.names, mutator);
mutator.Post(x);
}
}
template<typename V>
void Walk(const OpenMPDeclareTargetConstruct::WithExtendedList &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.names, visitor);
visitor.Post(x);
}
}
template<typename M>
void Walk(OpenMPDeclareTargetConstruct::WithExtendedList &x, M &mutator) {
if (mutator.Pre(x)) {
Walk(x.names, mutator);
mutator.Post(x);
}
}
}
#endif // FORTRAN_PARSER_PARSE_TREE_VISITOR_H_