//===-- include/flang/Parser/tools.h ----------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef FORTRAN_PARSER_TOOLS_H_ #define FORTRAN_PARSER_TOOLS_H_ #include "parse-tree.h" namespace Fortran::parser { // GetLastName() isolates and returns a reference to the rightmost Name // in a variable (i.e., the Name whose symbol's type determines the type // of the variable or expression). const Name &GetLastName(const Name &); const Name &GetLastName(const StructureComponent &); const Name &GetLastName(const DataRef &); const Name &GetLastName(const Substring &); const Name &GetLastName(const Designator &); const Name &GetLastName(const ProcComponentRef &); const Name &GetLastName(const ProcedureDesignator &); const Name &GetLastName(const Call &); const Name &GetLastName(const FunctionReference &); const Name &GetLastName(const Variable &); const Name &GetLastName(const AllocateObject &); // GetFirstName() isolates and returns a reference to the leftmost Name // in a variable or entity declaration. const Name &GetFirstName(const Name &); const Name &GetFirstName(const StructureComponent &); const Name &GetFirstName(const DataRef &); const Name &GetFirstName(const Substring &); const Name &GetFirstName(const Designator &); const Name &GetFirstName(const ProcComponentRef &); const Name &GetFirstName(const ProcedureDesignator &); const Name &GetFirstName(const Call &); const Name &GetFirstName(const FunctionReference &); const Name &GetFirstName(const Variable &); // When a parse tree node is an instance of a specific type wrapped in // layers of packaging, return a pointer to that object. // Implemented with mutually recursive template functions that are // wrapped in a struct to avoid prototypes. struct UnwrapperHelper { template static const A *Unwrap(B *p) { if (p) { return Unwrap(*p); } else { return nullptr; } } template static const A *Unwrap(const common::Indirection &x) { return Unwrap(x.value()); } template static const A *Unwrap(const std::variant &x) { return common::visit([](const auto &y) { return Unwrap(y); }, x); } template static const A *Unwrap(const std::tuple &x) { if constexpr (J < sizeof...(Bs)) { if (auto result{Unwrap(std::get(x))}) { return result; } return Unwrap(x); } else { return nullptr; } } template static const A *Unwrap(const std::optional &o) { if (o) { return Unwrap(*o); } else { return nullptr; } } template static const A *Unwrap(const UnlabeledStatement &x) { return Unwrap(x.statement); } template static const A *Unwrap(const Statement &x) { return Unwrap(x.statement); } template static const A *Unwrap(B &x) { if constexpr (std::is_same_v, std::decay_t>) { return &x; } else if constexpr (ConstraintTrait) { return Unwrap(x.thing); } else if constexpr (WrapperTrait) { return Unwrap(x.v); } else if constexpr (UnionTrait) { return Unwrap(x.u); } else { return nullptr; } } }; template const A *Unwrap(const B &x) { return UnwrapperHelper::Unwrap(x); } template A *Unwrap(B &x) { return const_cast(Unwrap(const_cast(x))); } // Get the CoindexedNamedObject if the entity is a coindexed object. const CoindexedNamedObject *GetCoindexedNamedObject(const AllocateObject &); const CoindexedNamedObject *GetCoindexedNamedObject(const DataRef &); const CoindexedNamedObject *GetCoindexedNamedObject(const Designator &); const CoindexedNamedObject *GetCoindexedNamedObject(const Variable &); // Detects parse tree nodes with "source" members. template struct HasSource : std::false_type {}; template struct HasSource(A::source), 0)> : std::true_type {}; // Detects parse tree nodes with "typedExpr" members. template struct HasTypedExpr : std::false_type {}; template struct HasTypedExpr(A::typedExpr), 0)> : std::true_type {}; // GetSource() template struct GetSourceHelper { using Result = std::optional; template static Result GetSource(A *p) { if (p) { return GetSource(*p); } else { return std::nullopt; } } template static Result GetSource(const common::Indirection &x) { return GetSource(x.value()); } template static Result GetSource(const common::Indirection &x) { return GetSource(x.value()); } template static Result GetSource(const std::variant &x) { return common::visit([](const auto &y) { return GetSource(y); }, x); } template static Result GetSource(const std::tuple &x) { if constexpr (J < sizeof...(As)) { constexpr std::size_t index{GET_FIRST ? J : sizeof...(As) - J - 1}; if (auto result{GetSource(std::get(x))}) { return result; } return GetSource<(J + 1)>(x); } else { return {}; } } template static Result GetSource(const std::optional &o) { if (o) { return GetSource(*o); } else { return {}; } } template static Result GetSource(const std::list &x) { if constexpr (GET_FIRST) { for (const A &y : x) { if (auto result{GetSource(y)}) { return result; } } } else { for (auto iter{x.rbegin()}; iter != x.rend(); ++iter) { if (auto result{GetSource(*iter)}) { return result; } } } return {}; } template static Result GetSource(const std::vector &x) { if constexpr (GET_FIRST) { for (const A &y : x) { if (auto result{GetSource(y)}) { return result; } } } else { for (auto iter{x.rbegin()}; iter != x.rend(); ++iter) { if (auto result{GetSource(*iter)}) { return result; } } } return {}; } template static Result GetSource(A &x) { if constexpr (HasSource::value) { return x.source; } else if constexpr (ConstraintTrait) { return GetSource(x.thing); } else if constexpr (WrapperTrait) { return GetSource(x.v); } else if constexpr (UnionTrait) { return GetSource(x.u); } else if constexpr (TupleTrait) { return GetSource(x.t); } else { return {}; } } }; template std::optional GetSource(const A &x) { return GetSourceHelper::GetSource(x); } template std::optional GetSource(A &x) { return GetSourceHelper::GetSource(const_cast(x)); } template std::optional GetLastSource(const A &x) { return GetSourceHelper::GetSource(x); } template std::optional GetLastSource(A &x) { return GetSourceHelper::GetSource(const_cast(x)); } } // namespace Fortran::parser #endif // FORTRAN_PARSER_TOOLS_H_