1 //===-- include/flang/Parser/tools.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_TOOLS_H_
10 #define FORTRAN_PARSER_TOOLS_H_
11 
12 #include "parse-tree.h"
13 
14 namespace Fortran::parser {
15 
16 // GetLastName() isolates and returns a reference to the rightmost Name
17 // in a variable (i.e., the Name whose symbol's type determines the type
18 // of the variable or expression).
19 const Name &GetLastName(const Name &);
20 const Name &GetLastName(const StructureComponent &);
21 const Name &GetLastName(const DataRef &);
22 const Name &GetLastName(const Substring &);
23 const Name &GetLastName(const Designator &);
24 const Name &GetLastName(const ProcComponentRef &);
25 const Name &GetLastName(const ProcedureDesignator &);
26 const Name &GetLastName(const Call &);
27 const Name &GetLastName(const FunctionReference &);
28 const Name &GetLastName(const Variable &);
29 const Name &GetLastName(const AllocateObject &);
30 
31 // GetFirstName() isolates and returns a reference to the leftmost Name
32 // in a variable.
33 const Name &GetFirstName(const Name &);
34 const Name &GetFirstName(const StructureComponent &);
35 const Name &GetFirstName(const DataRef &);
36 const Name &GetFirstName(const Substring &);
37 const Name &GetFirstName(const Designator &);
38 const Name &GetFirstName(const ProcComponentRef &);
39 const Name &GetFirstName(const ProcedureDesignator &);
40 const Name &GetFirstName(const Call &);
41 const Name &GetFirstName(const FunctionReference &);
42 const Name &GetFirstName(const Variable &);
43 
44 // When a parse tree node is an instance of a specific type wrapped in
45 // layers of packaging, return a pointer to that object.
46 // Implemented with mutually recursive template functions that are
47 // wrapped in a struct to avoid prototypes.
48 struct UnwrapperHelper {
49 
UnwrapUnwrapperHelper50   template <typename A, typename B> static const A *Unwrap(B *p) {
51     if (p) {
52       return Unwrap<A>(*p);
53     } else {
54       return nullptr;
55     }
56   }
57 
58   template <typename A, typename B, bool COPY>
UnwrapUnwrapperHelper59   static const A *Unwrap(const common::Indirection<B, COPY> &x) {
60     return Unwrap<A>(x.value());
61   }
62 
63   template <typename A, typename... Bs>
UnwrapUnwrapperHelper64   static const A *Unwrap(const std::variant<Bs...> &x) {
65     return std::visit([](const auto &y) { return Unwrap<A>(y); }, x);
66   }
67 
68   template <typename A, typename B>
UnwrapUnwrapperHelper69   static const A *Unwrap(const std::optional<B> &o) {
70     if (o) {
71       return Unwrap<A>(*o);
72     } else {
73       return nullptr;
74     }
75   }
76 
77   template <typename A, typename B>
UnwrapUnwrapperHelper78   static const A *Unwrap(const UnlabeledStatement<B> &x) {
79     return Unwrap<A>(x.statement);
80   }
81   template <typename A, typename B>
UnwrapUnwrapperHelper82   static const A *Unwrap(const Statement<B> &x) {
83     return Unwrap<A>(x.statement);
84   }
85 
UnwrapUnwrapperHelper86   template <typename A, typename B> static const A *Unwrap(B &x) {
87     if constexpr (std::is_same_v<std::decay_t<A>, std::decay_t<B>>) {
88       return &x;
89     } else if constexpr (ConstraintTrait<B>) {
90       return Unwrap<A>(x.thing);
91     } else if constexpr (WrapperTrait<B>) {
92       return Unwrap<A>(x.v);
93     } else if constexpr (UnionTrait<B>) {
94       return Unwrap<A>(x.u);
95     } else {
96       return nullptr;
97     }
98   }
99 };
100 
Unwrap(const B & x)101 template <typename A, typename B> const A *Unwrap(const B &x) {
102   return UnwrapperHelper::Unwrap<A>(x);
103 }
Unwrap(B & x)104 template <typename A, typename B> A *Unwrap(B &x) {
105   return const_cast<A *>(Unwrap<A, B>(const_cast<const B &>(x)));
106 }
107 
108 // Get the CoindexedNamedObject if the entity is a coindexed object.
109 const CoindexedNamedObject *GetCoindexedNamedObject(const AllocateObject &);
110 const CoindexedNamedObject *GetCoindexedNamedObject(const DataRef &);
111 const CoindexedNamedObject *GetCoindexedNamedObject(const Designator &);
112 const CoindexedNamedObject *GetCoindexedNamedObject(const Variable &);
113 
114 // Detects parse tree nodes with "source" members.
115 template <typename A, typename = int> struct HasSource : std::false_type {};
116 template <typename A>
117 struct HasSource<A, decltype(static_cast<void>(A::source), 0)>
118     : std::true_type {};
119 
120 // Detects parse tree nodes with "typedExpr" members.
121 template <typename A, typename = int> struct HasTypedExpr : std::false_type {};
122 template <typename A>
123 struct HasTypedExpr<A, decltype(static_cast<void>(A::typedExpr), 0)>
124     : std::true_type {};
125 } // namespace Fortran::parser
126 #endif // FORTRAN_PARSER_TOOLS_H_
127