[flang] Trait-based parse tree traversal.

Add a CLASS_TRAIT macro to idioms.h to define template metaprogramming
based on definable traits of user-defined classes.  Tweak the boilerplate
macros in parse-tree.h to add traits to the empty, wrapper, union, and
tuple classes in the parse tree.  Replace the macros in parse-tree-visitor.h
with trait-driven templates.

Original-commit: flang-compiler/f18@02400146fb
Reviewed-on: https://github.com/flang-compiler/f18/pull/20
Tree-same-pre-rewrite: false
This commit is contained in:
peter klausler 2018-02-28 13:24:01 -08:00
parent 848bf57051
commit 07a028098f
3 changed files with 120 additions and 572 deletions

View file

@ -80,7 +80,29 @@ template<typename A> bool operator!(const std::optional<A> &x) {
// static_assert(BadType<T>::value, "no case for type");
template<typename A> struct BadType : std::false_type {};
// User-defined type traits that default to false:
// Invoke CLASS_TRAIT(traitName) to define a trait, then put
// using traitName = std::true_type; (or false_type)
// into the appropriate class definitions. You can then use
// typename std::enable_if<traitName<...>, ...>::type
// in template specialization definitions.
#define CLASS_TRAIT(T) \
namespace class_trait_ns_##T { \
template<typename A> std::true_type test(typename A::T *); \
template<typename A> std::false_type test(...); \
template<typename A> \
constexpr bool has_trait{decltype(test<A>(nullptr))::value}; \
template<typename A> \
constexpr typename std::enable_if<has_trait<A>, bool>::type \
trait_value() { using U = typename A::T; return U::value; } \
template<typename A> \
constexpr typename std::enable_if<!has_trait<A>, bool>::type \
trait_value() { return false; } \
} \
template<typename A> constexpr bool T{class_trait_ns_##T::trait_value<A>()}
// Formatting
// TODO: remove when unparser is up and running
namespace Fortran {
namespace parser {
template<typename A>
@ -104,21 +126,16 @@ std::ostream &operator<<(std::ostream &o, const std::list<A> &xs) {
return o << ']';
}
template<int J, char C, typename T>
typename std::enable_if<J + 1 == std::tuple_size_v<T>, std::ostream &>::type
formatTuple(std::ostream &o, const T &x) {
return o << C << std::get<J>(x) << '}';
}
template<int J, char C, typename T>
typename std::enable_if<J + 1 != std::tuple_size_v<T>, std::ostream &>::type
formatTuple(std::ostream &o, const T &x) {
return formatTuple<J + 1, ' '>(o << C << std::get<J>(x), x);
template<int J, typename T>
std::ostream &formatTuple(std::ostream &o, const T &x) {
if constexpr (J < std::tuple_size_v<T>) {
return formatTuple<J + 1>(o << std::get<J>(x), x);
}
}
template<typename... As>
std::ostream &operator<<(std::ostream &o, const std::tuple<As...> &xs) {
return formatTuple<0, '{'>(o, xs);
return formatTuple<0>(o << '{', xs) << '}';
}
template<typename... As>

View file

@ -18,26 +18,17 @@
namespace Fortran {
namespace parser {
// Apply func to each member of tuple.
template<size_t I = 0, typename Func, typename... Ts> // clang-format off
typename std::enable_if<I == sizeof...(Ts)>::type
ForEachInTuple(const std::tuple<Ts...> &, Func) {
}
template<size_t I = 0, typename Func, typename... Ts>
typename std::enable_if<I < sizeof...(Ts)>::type
ForEachInTuple(const std::tuple<Ts...> &tuple, Func func) {
func(std::get<I>(tuple));
ForEachInTuple<I + 1>(tuple, func);
} // clang-format on
// Helpers: generic visitor that is called if there is no specific one
// and visitors for std::optional, std::list, and Indirection.
template<typename T, typename V> void Walk(const T &x, V &visitor) {
// Default case for visitation of non-class data members (and strings)
template<typename A, typename V>
typename std::enable_if<!std::is_class_v<A> ||
std::is_same_v<std::string, A>>::type
Walk(const A &x, V &visitor) {
if (visitor.Pre(x)) {
visitor.Post(x);
visitor.Post(x);
}
}
// 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) {
@ -49,6 +40,54 @@ template<typename T, typename V> void Walk(const std::list<T> &x, V &visitor) {
Walk(elem, visitor);
}
}
template<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<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);
}
}
// Trait-determined traversal of empty, tuple, union, and wrapper classes.
template<typename A, typename V>
typename std::enable_if<EmptyTrait<A>>::type
Walk(const A &x, V &visitor) {
if (visitor.Pre(x)) {
visitor.Post(x);
}
}
template<typename A, typename V>
typename std::enable_if<TupleTrait<A>>::type
Walk(const A &x, V &visitor) { Walk(x.t, visitor); }
template<typename A, typename V>
typename std::enable_if<UnionTrait<A>>::type
Walk(const A &x, V &visitor) { Walk(x.u, visitor); }
template<typename A, typename V>
typename std::enable_if<WrapperTrait<A>>::type
Walk(const A &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.v, visitor);
visitor.Post(x);
}
}
template<typename T, typename V>
void Walk(const Indirection<T> &x, V &visitor) {
Walk(*x, visitor);
@ -79,16 +118,6 @@ template<typename T, typename V> void Walk(const Statement<T> &x, V &visitor) {
}
}
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 V> void Walk(const AcSpec &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.type, visitor);
@ -111,6 +140,14 @@ void Walk(const CharSelector::LengthAndKind &x, V &visitor) {
visitor.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 V> void Walk(const CoindexedNamedObject &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.base, visitor);
@ -131,132 +168,6 @@ template<typename V> void Walk(const DeclarationTypeSpec::Type &x, V &visitor) {
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::AND &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicBinary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::Add &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicBinary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::ComplexConstructor &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicBinary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::Concat &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicBinary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::Divide &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicBinary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::EQ &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicBinary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::EQV &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicBinary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::GE &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicBinary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::GT &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicBinary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::LE &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicBinary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::LT &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicBinary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::Multiply &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicBinary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::NE &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicBinary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::NEQV &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicBinary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::NOT &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicUnary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::Negate &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicUnary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::OR &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicBinary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::Parentheses &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicUnary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::Power &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicBinary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::Subtract &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicBinary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Expr::UnaryPlus &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(static_cast<const Expr::IntrinsicUnary &>(x), visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const Fortran::ControlEditDesc &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.kind, visitor);
@ -274,7 +185,14 @@ void Walk(const Fortran::DerivedTypeDataEditDesc &x, V &visitor) {
template<typename V> void Walk(const Fortran::FormatItem &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.repeatCount, visitor);
std::visit([&](const auto &y) { Walk(y, visitor); }, x.u);
Walk(x.u, visitor);
visitor.Post(x);
}
}
template<typename V> void Walk(const FormatSpecification &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.items, visitor);
Walk(x.unlimitedItems, visitor);
visitor.Post(x);
}
}
@ -321,6 +239,15 @@ template<typename V> void Walk(const IntrinsicTypeSpec::Real &x, V &visitor) {
visitor.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 V> void Walk(const PartRef &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.name, visitor);
@ -382,7 +309,7 @@ template<typename V> void Walk(const UseStmt &x, V &visitor) {
if (visitor.Pre(x)) {
Walk(x.nature, visitor);
Walk(x.moduleName, visitor);
std::visit([&](const auto &y) { Walk(y, visitor); }, x.u);
Walk(x.u, visitor);
visitor.Post(x);
}
}
@ -395,412 +322,6 @@ template<typename V> void Walk(const WriteStmt &x, V &visitor) {
visitor.Post(x);
}
}
// Walk a class with a single tuple field 't'.
#define WALK_TUPLE_CLASS(classname) \
template<typename V> void Walk(const classname &x, V &visitor) { \
if (visitor.Pre(x)) { \
ForEachInTuple(x.t, [&](const auto &y) { Walk(y, visitor); }); \
visitor.Post(x); \
} \
}
WALK_TUPLE_CLASS(AcImpliedDo)
WALK_TUPLE_CLASS(AcImpliedDoControl)
WALK_TUPLE_CLASS(AcValue::Triplet)
WALK_TUPLE_CLASS(AccessStmt)
WALK_TUPLE_CLASS(ActualArgSpec)
WALK_TUPLE_CLASS(AllocateCoarraySpec)
WALK_TUPLE_CLASS(AllocateShapeSpec)
WALK_TUPLE_CLASS(AllocateStmt)
WALK_TUPLE_CLASS(Allocation)
WALK_TUPLE_CLASS(ArithmeticIfStmt)
WALK_TUPLE_CLASS(AssignStmt)
WALK_TUPLE_CLASS(AssignedGotoStmt)
WALK_TUPLE_CLASS(AssignmentStmt)
WALK_TUPLE_CLASS(AssociateConstruct)
WALK_TUPLE_CLASS(AssociateStmt)
WALK_TUPLE_CLASS(Association)
WALK_TUPLE_CLASS(AssumedSizeSpec)
WALK_TUPLE_CLASS(BasedPointerStmt)
WALK_TUPLE_CLASS(BindEntity)
WALK_TUPLE_CLASS(BindStmt)
WALK_TUPLE_CLASS(BlockConstruct)
WALK_TUPLE_CLASS(BlockData)
WALK_TUPLE_CLASS(BoundsRemapping)
WALK_TUPLE_CLASS(Call)
WALK_TUPLE_CLASS(CaseConstruct)
WALK_TUPLE_CLASS(CaseConstruct::Case)
WALK_TUPLE_CLASS(CaseStmt)
WALK_TUPLE_CLASS(ChangeTeamConstruct)
WALK_TUPLE_CLASS(ChangeTeamStmt)
WALK_TUPLE_CLASS(CharLiteralConstant)
WALK_TUPLE_CLASS(CharLiteralConstantSubstring)
WALK_TUPLE_CLASS(CoarrayAssociation)
WALK_TUPLE_CLASS(CodimensionDecl)
WALK_TUPLE_CLASS(CommonBlockObject)
WALK_TUPLE_CLASS(CommonStmt)
WALK_TUPLE_CLASS(ComplexLiteralConstant)
WALK_TUPLE_CLASS(ComponentDecl)
WALK_TUPLE_CLASS(ComponentSpec)
WALK_TUPLE_CLASS(ComputedGotoStmt)
WALK_TUPLE_CLASS(ConcurrentControl)
WALK_TUPLE_CLASS(ConcurrentHeader)
WALK_TUPLE_CLASS(ConnectSpec::CharExpr)
WALK_TUPLE_CLASS(CriticalConstruct)
WALK_TUPLE_CLASS(CriticalStmt)
WALK_TUPLE_CLASS(DataComponentDefStmt)
WALK_TUPLE_CLASS(DataImpliedDo)
WALK_TUPLE_CLASS(DataStmtSet)
WALK_TUPLE_CLASS(DataStmtValue)
WALK_TUPLE_CLASS(DeallocateStmt)
WALK_TUPLE_CLASS(DerivedTypeDef)
WALK_TUPLE_CLASS(DerivedTypeSpec)
WALK_TUPLE_CLASS(DerivedTypeStmt)
WALK_TUPLE_CLASS(DimensionStmt::Declaration)
WALK_TUPLE_CLASS(DoConstruct)
WALK_TUPLE_CLASS(ElseIfStmt)
WALK_TUPLE_CLASS(EndChangeTeamStmt)
WALK_TUPLE_CLASS(EntityDecl)
WALK_TUPLE_CLASS(EntryStmt)
WALK_TUPLE_CLASS(EnumDef)
WALK_TUPLE_CLASS(Enumerator)
WALK_TUPLE_CLASS(EventPostStmt)
WALK_TUPLE_CLASS(EventWaitStmt)
WALK_TUPLE_CLASS(ExplicitCoshapeSpec)
WALK_TUPLE_CLASS(ExplicitShapeSpec)
WALK_TUPLE_CLASS(ExponentPart)
WALK_TUPLE_CLASS(Expr::DefinedBinary)
WALK_TUPLE_CLASS(Expr::DefinedUnary)
WALK_TUPLE_CLASS(Expr::IntrinsicBinary)
WALK_TUPLE_CLASS(ForallConstruct)
WALK_TUPLE_CLASS(ForallConstructStmt)
WALK_TUPLE_CLASS(ForallStmt)
WALK_TUPLE_CLASS(FormTeamStmt)
WALK_TUPLE_CLASS(FunctionStmt)
WALK_TUPLE_CLASS(FunctionSubprogram)
WALK_TUPLE_CLASS(GenericStmt)
WALK_TUPLE_CLASS(IfConstruct)
WALK_TUPLE_CLASS(IfConstruct::ElseBlock)
WALK_TUPLE_CLASS(IfConstruct::ElseIfBlock)
WALK_TUPLE_CLASS(IfStmt)
WALK_TUPLE_CLASS(IfThenStmt)
WALK_TUPLE_CLASS(ImageSelector)
WALK_TUPLE_CLASS(ImplicitSpec)
WALK_TUPLE_CLASS(InputImpliedDo)
WALK_TUPLE_CLASS(InquireSpec::CharVar)
WALK_TUPLE_CLASS(InquireSpec::IntVar)
WALK_TUPLE_CLASS(InquireSpec::LogVar)
WALK_TUPLE_CLASS(InquireStmt::Iolength)
WALK_TUPLE_CLASS(IntLiteralConstant)
WALK_TUPLE_CLASS(IntentStmt)
WALK_TUPLE_CLASS(InterfaceBlock)
WALK_TUPLE_CLASS(InterfaceBody::Function)
WALK_TUPLE_CLASS(InterfaceBody::Subroutine)
WALK_TUPLE_CLASS(InternalSubprogramPart)
WALK_TUPLE_CLASS(IoControlSpec::CharExpr)
WALK_TUPLE_CLASS(LabelDoStmt)
WALK_TUPLE_CLASS(LetterSpec)
WALK_TUPLE_CLASS(LockStmt)
WALK_TUPLE_CLASS(LoopControl::Concurrent)
WALK_TUPLE_CLASS(MainProgram)
WALK_TUPLE_CLASS(Map)
WALK_TUPLE_CLASS(MaskedElsewhereStmt)
WALK_TUPLE_CLASS(Module)
WALK_TUPLE_CLASS(ModuleSubprogramPart)
WALK_TUPLE_CLASS(NamedConstantDef)
WALK_TUPLE_CLASS(NamelistStmt::Group)
WALK_TUPLE_CLASS(NonLabelDoStmt)
WALK_TUPLE_CLASS(ObjectDecl)
WALK_TUPLE_CLASS(OutputImpliedDo)
WALK_TUPLE_CLASS(ParentIdentifier)
WALK_TUPLE_CLASS(PointerAssignmentStmt)
WALK_TUPLE_CLASS(PointerDecl)
WALK_TUPLE_CLASS(PrintStmt)
WALK_TUPLE_CLASS(ProcComponentDefStmt)
WALK_TUPLE_CLASS(ProcComponentRef)
WALK_TUPLE_CLASS(ProcDecl)
WALK_TUPLE_CLASS(ProcedureDeclarationStmt)
WALK_TUPLE_CLASS(ProcedureStmt)
WALK_TUPLE_CLASS(RedimensionStmt)
WALK_TUPLE_CLASS(Rename::Names)
WALK_TUPLE_CLASS(Rename::Operators)
WALK_TUPLE_CLASS(SavedEntity)
WALK_TUPLE_CLASS(SelectCaseStmt)
WALK_TUPLE_CLASS(SelectRankCaseStmt)
WALK_TUPLE_CLASS(SelectRankConstruct)
WALK_TUPLE_CLASS(SelectRankConstruct::RankCase)
WALK_TUPLE_CLASS(SelectRankStmt)
WALK_TUPLE_CLASS(SelectTypeConstruct)
WALK_TUPLE_CLASS(SelectTypeConstruct::TypeCase)
WALK_TUPLE_CLASS(SelectTypeStmt)
WALK_TUPLE_CLASS(SeparateModuleSubprogram)
WALK_TUPLE_CLASS(SignedComplexLiteralConstant)
WALK_TUPLE_CLASS(SignedIntLiteralConstant)
WALK_TUPLE_CLASS(SignedRealLiteralConstant)
WALK_TUPLE_CLASS(SpecificationPart)
WALK_TUPLE_CLASS(StmtFunctionStmt)
WALK_TUPLE_CLASS(StopStmt)
WALK_TUPLE_CLASS(StructureConstructor)
WALK_TUPLE_CLASS(StructureDef)
WALK_TUPLE_CLASS(StructureStmt)
WALK_TUPLE_CLASS(Submodule)
WALK_TUPLE_CLASS(SubmoduleStmt)
WALK_TUPLE_CLASS(SubroutineStmt)
WALK_TUPLE_CLASS(SubroutineSubprogram)
WALK_TUPLE_CLASS(SubscriptTriplet)
WALK_TUPLE_CLASS(Substring)
WALK_TUPLE_CLASS(SubstringRange)
WALK_TUPLE_CLASS(SyncImagesStmt)
WALK_TUPLE_CLASS(SyncTeamStmt)
WALK_TUPLE_CLASS(TypeBoundGenericStmt)
WALK_TUPLE_CLASS(TypeBoundProcDecl)
WALK_TUPLE_CLASS(TypeBoundProcedurePart)
WALK_TUPLE_CLASS(TypeDeclarationStmt)
WALK_TUPLE_CLASS(TypeGuardStmt)
WALK_TUPLE_CLASS(TypeParamDecl)
WALK_TUPLE_CLASS(TypeParamDefStmt)
WALK_TUPLE_CLASS(TypeParamSpec)
WALK_TUPLE_CLASS(Union)
WALK_TUPLE_CLASS(UnlockStmt)
WALK_TUPLE_CLASS(WhereConstruct)
WALK_TUPLE_CLASS(WhereConstruct::Elsewhere)
WALK_TUPLE_CLASS(WhereConstruct::MaskedElsewhere)
WALK_TUPLE_CLASS(WhereConstructStmt)
WALK_TUPLE_CLASS(WhereStmt)
#undef WALK_TUPLE_CLASS
// Walk a class with a single variant field 'u'.
#define WALK_UNION_CLASS(classname) \
template<typename V> void Walk(const classname &x, V &visitor) { \
if (visitor.Pre(x)) { \
std::visit([&](const auto &y) { Walk(y, visitor); }, x.u); \
visitor.Post(x); \
} \
}
WALK_UNION_CLASS(AcValue)
WALK_UNION_CLASS(AccessId)
WALK_UNION_CLASS(ActionStmt)
WALK_UNION_CLASS(ActualArg)
WALK_UNION_CLASS(AllocOpt)
WALK_UNION_CLASS(AllocateObject)
WALK_UNION_CLASS(ArraySpec)
WALK_UNION_CLASS(AttrSpec)
WALK_UNION_CLASS(BackspaceStmt)
WALK_UNION_CLASS(BindAttr)
WALK_UNION_CLASS(CaseSelector)
WALK_UNION_CLASS(CaseValueRange)
WALK_UNION_CLASS(CharLength)
WALK_UNION_CLASS(CharSelector)
WALK_UNION_CLASS(CloseStmt::CloseSpec)
WALK_UNION_CLASS(CoarraySpec)
WALK_UNION_CLASS(ComplexPart)
WALK_UNION_CLASS(ComponentArraySpec)
WALK_UNION_CLASS(ComponentAttrSpec)
WALK_UNION_CLASS(ComponentDefStmt)
WALK_UNION_CLASS(ConnectSpec)
WALK_UNION_CLASS(ConstantValue)
WALK_UNION_CLASS(DataIDoObject)
WALK_UNION_CLASS(DataReference)
WALK_UNION_CLASS(DataStmtConstant)
WALK_UNION_CLASS(DataStmtObject)
WALK_UNION_CLASS(DataStmtRepeat)
WALK_UNION_CLASS(DeclarationConstruct)
WALK_UNION_CLASS(DeclarationTypeSpec)
WALK_UNION_CLASS(DefinedOperator)
WALK_UNION_CLASS(Designator)
WALK_UNION_CLASS(DummyArg)
WALK_UNION_CLASS(EndfileStmt)
WALK_UNION_CLASS(EventWaitStmt::EventWaitSpec)
WALK_UNION_CLASS(ExecutableConstruct)
WALK_UNION_CLASS(ExecutionPartConstruct)
WALK_UNION_CLASS(Expr)
WALK_UNION_CLASS(FlushStmt)
WALK_UNION_CLASS(ForallAssignmentStmt)
WALK_UNION_CLASS(ForallBodyConstruct)
WALK_UNION_CLASS(FormTeamStmt::FormTeamSpec)
WALK_UNION_CLASS(Format)
WALK_UNION_CLASS(GenericSpec)
WALK_UNION_CLASS(ImageSelectorSpec)
WALK_UNION_CLASS(ImplicitPartStmt)
WALK_UNION_CLASS(ImplicitStmt)
WALK_UNION_CLASS(Initialization)
WALK_UNION_CLASS(InputItem)
WALK_UNION_CLASS(InquireSpec)
WALK_UNION_CLASS(InquireStmt)
WALK_UNION_CLASS(InterfaceBody)
WALK_UNION_CLASS(InterfaceSpecification)
WALK_UNION_CLASS(InterfaceStmt)
WALK_UNION_CLASS(InternalSubprogram)
WALK_UNION_CLASS(IntrinsicTypeSpec)
WALK_UNION_CLASS(IoControlSpec)
WALK_UNION_CLASS(IoUnit)
WALK_UNION_CLASS(KindParam)
WALK_UNION_CLASS(LengthSelector)
WALK_UNION_CLASS(LiteralConstant)
WALK_UNION_CLASS(LocalitySpec)
WALK_UNION_CLASS(LockStmt::LockStat)
WALK_UNION_CLASS(LoopControl)
WALK_UNION_CLASS(ModuleSubprogram)
WALK_UNION_CLASS(Only)
WALK_UNION_CLASS(OtherSpecificationStmt)
WALK_UNION_CLASS(OutputItem)
WALK_UNION_CLASS(PointerAssignmentStmt::Bounds)
WALK_UNION_CLASS(PointerObject)
WALK_UNION_CLASS(PositionOrFlushSpec)
WALK_UNION_CLASS(PrefixSpec)
WALK_UNION_CLASS(PrivateOrSequence)
WALK_UNION_CLASS(ProcAttrSpec)
WALK_UNION_CLASS(ProcComponentAttrSpec)
WALK_UNION_CLASS(ProcInterface)
WALK_UNION_CLASS(ProcPointerInit)
WALK_UNION_CLASS(ProcedureDesignator)
WALK_UNION_CLASS(ProgramUnit)
WALK_UNION_CLASS(Rename)
WALK_UNION_CLASS(RewindStmt)
WALK_UNION_CLASS(SectionSubscript)
WALK_UNION_CLASS(SelectRankCaseStmt::Rank)
WALK_UNION_CLASS(Selector)
WALK_UNION_CLASS(SpecificationConstruct)
WALK_UNION_CLASS(StatOrErrmsg)
WALK_UNION_CLASS(StopCode)
WALK_UNION_CLASS(StructureField)
WALK_UNION_CLASS(SyncImagesStmt::ImageSet)
WALK_UNION_CLASS(TypeAttrSpec)
WALK_UNION_CLASS(TypeBoundProcBinding)
WALK_UNION_CLASS(TypeBoundProcedureStmt)
WALK_UNION_CLASS(TypeGuardStmt::Guard)
WALK_UNION_CLASS(TypeParamValue)
WALK_UNION_CLASS(TypeSpec)
WALK_UNION_CLASS(Variable)
WALK_UNION_CLASS(WaitSpec)
WALK_UNION_CLASS(WhereBodyConstruct)
#undef WALK_UNION_CLASS
// Walk a class with a single field 'v'.
#define WALK_WRAPPER_CLASS(classname) \
template<typename V> void Walk(const classname &x, V &visitor) { \
if (visitor.Pre(x)) { \
Walk(x.v, visitor); \
visitor.Post(x); \
} \
}
WALK_WRAPPER_CLASS(AccessSpec)
WALK_WRAPPER_CLASS(ActualArg::PercentRef)
WALK_WRAPPER_CLASS(ActualArg::PercentVal)
WALK_WRAPPER_CLASS(AllocOpt::Mold)
WALK_WRAPPER_CLASS(AllocOpt::Source)
WALK_WRAPPER_CLASS(AllocatableStmt)
WALK_WRAPPER_CLASS(AltReturnSpec)
WALK_WRAPPER_CLASS(ArrayConstructor)
WALK_WRAPPER_CLASS(ArraySection)
WALK_WRAPPER_CLASS(AssumedImpliedSpec)
WALK_WRAPPER_CLASS(AssumedShapeSpec)
WALK_WRAPPER_CLASS(AsynchronousStmt)
WALK_WRAPPER_CLASS(BOZLiteralConstant)
WALK_WRAPPER_CLASS(BlockDataStmt)
WALK_WRAPPER_CLASS(BlockSpecificationPart)
WALK_WRAPPER_CLASS(BlockStmt)
WALK_WRAPPER_CLASS(BoundsSpec)
WALK_WRAPPER_CLASS(CallStmt)
WALK_WRAPPER_CLASS(CharVariable)
WALK_WRAPPER_CLASS(CloseStmt)
WALK_WRAPPER_CLASS(CodimensionStmt)
WALK_WRAPPER_CLASS(ComplexPartDesignator)
WALK_WRAPPER_CLASS(ComponentDataSource)
WALK_WRAPPER_CLASS(ConnectSpec::Newunit)
WALK_WRAPPER_CLASS(ConnectSpec::Recl)
WALK_WRAPPER_CLASS(ContiguousStmt)
WALK_WRAPPER_CLASS(CycleStmt)
WALK_WRAPPER_CLASS(DataStmt)
WALK_WRAPPER_CLASS(DeclarationTypeSpec::Record)
WALK_WRAPPER_CLASS(DeferredCoshapeSpecList)
WALK_WRAPPER_CLASS(DeferredShapeSpecList)
WALK_WRAPPER_CLASS(DefinedOpName)
WALK_WRAPPER_CLASS(DimensionStmt)
WALK_WRAPPER_CLASS(ElseStmt)
WALK_WRAPPER_CLASS(ElsewhereStmt)
WALK_WRAPPER_CLASS(EndAssociateStmt)
WALK_WRAPPER_CLASS(EndBlockDataStmt)
WALK_WRAPPER_CLASS(EndBlockStmt)
WALK_WRAPPER_CLASS(EndCriticalStmt)
WALK_WRAPPER_CLASS(EndDoStmt)
WALK_WRAPPER_CLASS(EndForallStmt)
WALK_WRAPPER_CLASS(EndFunctionStmt)
WALK_WRAPPER_CLASS(EndIfStmt)
WALK_WRAPPER_CLASS(EndInterfaceStmt)
WALK_WRAPPER_CLASS(EndLabel)
WALK_WRAPPER_CLASS(EndModuleStmt)
WALK_WRAPPER_CLASS(EndMpSubprogramStmt)
WALK_WRAPPER_CLASS(EndProgramStmt)
WALK_WRAPPER_CLASS(EndSelectStmt)
WALK_WRAPPER_CLASS(EndSubmoduleStmt)
WALK_WRAPPER_CLASS(EndSubroutineStmt)
WALK_WRAPPER_CLASS(EndTypeStmt)
WALK_WRAPPER_CLASS(EndWhereStmt)
WALK_WRAPPER_CLASS(EnumeratorDefStmt)
WALK_WRAPPER_CLASS(EorLabel)
WALK_WRAPPER_CLASS(EquivalenceObject)
WALK_WRAPPER_CLASS(EquivalenceStmt)
WALK_WRAPPER_CLASS(ErrLabel)
WALK_WRAPPER_CLASS(ExitStmt)
WALK_WRAPPER_CLASS(Expr::IntrinsicUnary)
WALK_WRAPPER_CLASS(Expr::PercentLoc)
WALK_WRAPPER_CLASS(ExternalStmt)
WALK_WRAPPER_CLASS(FileUnitNumber)
WALK_WRAPPER_CLASS(FinalProcedureStmt)
WALK_WRAPPER_CLASS(FormatStmt)
WALK_WRAPPER_CLASS(FunctionReference)
WALK_WRAPPER_CLASS(GotoStmt)
WALK_WRAPPER_CLASS(HollerithLiteralConstant)
WALK_WRAPPER_CLASS(IdExpr)
WALK_WRAPPER_CLASS(IdVariable)
WALK_WRAPPER_CLASS(ImageSelectorSpec::Stat)
WALK_WRAPPER_CLASS(ImageSelectorSpec::Team)
WALK_WRAPPER_CLASS(ImageSelectorSpec::Team_Number)
WALK_WRAPPER_CLASS(ImplicitPart)
WALK_WRAPPER_CLASS(ImpliedShapeSpec)
WALK_WRAPPER_CLASS(IntegerTypeSpec)
WALK_WRAPPER_CLASS(IntentSpec)
WALK_WRAPPER_CLASS(IntrinsicStmt)
WALK_WRAPPER_CLASS(IntrinsicTypeSpec::NCharacter)
WALK_WRAPPER_CLASS(IoControlSpec::Asynchronous)
WALK_WRAPPER_CLASS(IoControlSpec::Pos)
WALK_WRAPPER_CLASS(IoControlSpec::Rec)
WALK_WRAPPER_CLASS(IoControlSpec::Size)
WALK_WRAPPER_CLASS(KindSelector)
WALK_WRAPPER_CLASS(LanguageBindingSpec)
WALK_WRAPPER_CLASS(LocalitySpec::Local)
WALK_WRAPPER_CLASS(LocalitySpec::LocalInit)
WALK_WRAPPER_CLASS(LocalitySpec::Shared)
WALK_WRAPPER_CLASS(LogicalLiteralConstant)
WALK_WRAPPER_CLASS(ModuleStmt)
WALK_WRAPPER_CLASS(MpSubprogramStmt)
WALK_WRAPPER_CLASS(MsgVariable)
WALK_WRAPPER_CLASS(NamedConstant)
WALK_WRAPPER_CLASS(NamelistStmt)
WALK_WRAPPER_CLASS(NullifyStmt)
WALK_WRAPPER_CLASS(OpenStmt)
WALK_WRAPPER_CLASS(OptionalStmt)
WALK_WRAPPER_CLASS(ParameterStmt)
WALK_WRAPPER_CLASS(Pass)
WALK_WRAPPER_CLASS(PauseStmt)
WALK_WRAPPER_CLASS(PointerStmt)
WALK_WRAPPER_CLASS(Program)
WALK_WRAPPER_CLASS(ProtectedStmt)
WALK_WRAPPER_CLASS(ReturnStmt)
WALK_WRAPPER_CLASS(SaveStmt)
WALK_WRAPPER_CLASS(SpecificationExpr)
WALK_WRAPPER_CLASS(StatVariable)
WALK_WRAPPER_CLASS(StatusExpr)
WALK_WRAPPER_CLASS(SyncAllStmt)
WALK_WRAPPER_CLASS(SyncMemoryStmt)
WALK_WRAPPER_CLASS(TargetStmt)
WALK_WRAPPER_CLASS(TypeParamInquiry)
WALK_WRAPPER_CLASS(ValueStmt)
WALK_WRAPPER_CLASS(VolatileStmt)
WALK_WRAPPER_CLASS(WaitStmt)
#undef WALK_WRAPPER_CLASS
} // namespace parser
} // namespace Fortran
#endif // FORTRAN_PARSER_PARSE_TREE_VISITOR_H_

View file

@ -34,6 +34,11 @@
// although a C++ compiler wouldn't default them anyway due to the presence
// of move constructors and move assignments.
CLASS_TRAIT(EmptyTrait);
CLASS_TRAIT(WrapperTrait);
CLASS_TRAIT(UnionTrait);
CLASS_TRAIT(TupleTrait);
// Most non-template classes in this file use these default definitions
// for their move constructor and move assignment operator=, and should
// declare an operator<< for formatting.
@ -55,12 +60,14 @@
classname &operator=(const classname &) { return *this; }; \
classname &operator=(classname &&) { return *this; }; \
friend std::ostream &operator<<(std::ostream &, const classname &); \
using EmptyTrait = std::true_type; \
}
// Many classes below simply wrap a std::variant<> discriminated union,
// which is conventionally named "u".
#define UNION_CLASS_BOILERPLATE(classname) \
template<typename A> classname(A &&x) : u(std::move(x)) {} \
using UnionTrait = std::true_type; \
BOILERPLATE(classname)
// Many other classes below simply wrap a std::tuple<> structure, which
@ -68,6 +75,7 @@
#define TUPLE_CLASS_BOILERPLATE(classname) \
template<typename... Ts> \
classname(Ts &&... args) : t(std::forward<Ts>(args)...) {} \
using TupleTrait = std::true_type; \
BOILERPLATE(classname)
// Many other classes below simply wrap a single data member, which is
@ -75,6 +83,7 @@
#define WRAPPER_CLASS_BOILERPLATE(classname, type) \
BOILERPLATE(classname); \
classname(type &&x) : v(std::move(x)) {} \
using WrapperTrait = std::true_type; \
type v
#define WRAPPER_CLASS(classname, type) \
@ -231,6 +240,7 @@ using Keyword = std::string;
// R403 scalar-xyz -> xyz
// These template class wrappers correspond to the Standard's modifiers
// scalar-xyz, constant-xzy, int-xzy, default-char-xyz, & logical-xyz.
// TODO: Implement as wrappers instead, or maybe remove.
template<typename A> struct Scalar {
Scalar(Scalar &&that) = default;
Scalar(A &&that) : thing(std::move(that)) {}