Warning: This file is not a C or C++ file. It does not have highlighting.
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 or entity declaration. |
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 | const Name &GetFirstName(const EntityDecl &); |
44 | |
45 | // When a parse tree node is an instance of a specific type wrapped in |
46 | // layers of packaging, return a pointer to that object. |
47 | // Implemented with mutually recursive template functions that are |
48 | // wrapped in a struct to avoid prototypes. |
49 | struct UnwrapperHelper { |
50 | |
51 | template <typename A, typename B> static const A *Unwrap(B *p) { |
52 | if (p) { |
53 | return Unwrap<A>(*p); |
54 | } else { |
55 | return nullptr; |
56 | } |
57 | } |
58 | |
59 | template <typename A, typename B, bool COPY> |
60 | static const A *Unwrap(const common::Indirection<B, COPY> &x) { |
61 | return Unwrap<A>(x.value()); |
62 | } |
63 | |
64 | template <typename A, typename... Bs> |
65 | static const A *Unwrap(const std::variant<Bs...> &x) { |
66 | return common::visit([](const auto &y) { return Unwrap<A>(y); }, x); |
67 | } |
68 | |
69 | template <typename A, std::size_t J = 0, typename... Bs> |
70 | static const A *Unwrap(const std::tuple<Bs...> &x) { |
71 | if constexpr (J < sizeof...(Bs)) { |
72 | if (auto result{Unwrap<A>(std::get<J>(x))}) { |
73 | return result; |
74 | } |
75 | return Unwrap<A, (J + 1)>(x); |
76 | } else { |
77 | return nullptr; |
78 | } |
79 | } |
80 | |
81 | template <typename A, typename B> |
82 | static const A *Unwrap(const std::optional<B> &o) { |
83 | if (o) { |
84 | return Unwrap<A>(*o); |
85 | } else { |
86 | return nullptr; |
87 | } |
88 | } |
89 | |
90 | template <typename A, typename B> |
91 | static const A *Unwrap(const UnlabeledStatement<B> &x) { |
92 | return Unwrap<A>(x.statement); |
93 | } |
94 | template <typename A, typename B> |
95 | static const A *Unwrap(const Statement<B> &x) { |
96 | return Unwrap<A>(x.statement); |
97 | } |
98 | |
99 | template <typename A, typename B> static const A *Unwrap(B &x) { |
100 | if constexpr (std::is_same_v<std::decay_t<A>, std::decay_t<B>>) { |
101 | return &x; |
102 | } else if constexpr (ConstraintTrait<B>) { |
103 | return Unwrap<A>(x.thing); |
104 | } else if constexpr (WrapperTrait<B>) { |
105 | return Unwrap<A>(x.v); |
106 | } else if constexpr (UnionTrait<B>) { |
107 | return Unwrap<A>(x.u); |
108 | } else { |
109 | return nullptr; |
110 | } |
111 | } |
112 | }; |
113 | |
114 | template <typename A, typename B> const A *Unwrap(const B &x) { |
115 | return UnwrapperHelper::Unwrap<A>(x); |
116 | } |
117 | template <typename A, typename B> A *Unwrap(B &x) { |
118 | return const_cast<A *>(Unwrap<A, B>(const_cast<const B &>(x))); |
119 | } |
120 | |
121 | // Get the CoindexedNamedObject if the entity is a coindexed object. |
122 | const CoindexedNamedObject *GetCoindexedNamedObject(const AllocateObject &); |
123 | const CoindexedNamedObject *GetCoindexedNamedObject(const DataRef &); |
124 | const CoindexedNamedObject *GetCoindexedNamedObject(const Designator &); |
125 | const CoindexedNamedObject *GetCoindexedNamedObject(const Variable &); |
126 | |
127 | // Detects parse tree nodes with "source" members. |
128 | template <typename A, typename = int> struct HasSource : std::false_type {}; |
129 | template <typename A> |
130 | struct HasSource<A, decltype(static_cast<void>(A::source), 0)> |
131 | : std::true_type {}; |
132 | |
133 | // Detects parse tree nodes with "typedExpr" members. |
134 | template <typename A, typename = int> struct HasTypedExpr : std::false_type {}; |
135 | template <typename A> |
136 | struct HasTypedExpr<A, decltype(static_cast<void>(A::typedExpr), 0)> |
137 | : std::true_type {}; |
138 | |
139 | // GetSource() |
140 | |
141 | template <bool GET_FIRST> struct GetSourceHelper { |
142 | |
143 | using Result = std::optional<CharBlock>; |
144 | |
145 | template <typename A> static Result GetSource(A *p) { |
146 | if (p) { |
147 | return GetSource(*p); |
148 | } else { |
149 | return std::nullopt; |
150 | } |
151 | } |
152 | template <typename A> |
153 | static Result GetSource(const common::Indirection<A> &x) { |
154 | return GetSource(x.value()); |
155 | } |
156 | |
157 | template <typename A, bool COPY> |
158 | static Result GetSource(const common::Indirection<A, COPY> &x) { |
159 | return GetSource(x.value()); |
160 | } |
161 | |
162 | template <typename... As> |
163 | static Result GetSource(const std::variant<As...> &x) { |
164 | return common::visit([](const auto &y) { return GetSource(y); }, x); |
165 | } |
166 | |
167 | template <std::size_t J = 0, typename... As> |
168 | static Result GetSource(const std::tuple<As...> &x) { |
169 | if constexpr (J < sizeof...(As)) { |
170 | constexpr std::size_t index{GET_FIRST ? J : sizeof...(As) - J - 1}; |
171 | if (auto result{GetSource(std::get<index>(x))}) { |
172 | return result; |
173 | } |
174 | return GetSource<(J + 1)>(x); |
175 | } else { |
176 | return {}; |
177 | } |
178 | } |
179 | |
180 | template <typename A> static Result GetSource(const std::optional<A> &o) { |
181 | if (o) { |
182 | return GetSource(*o); |
183 | } else { |
184 | return {}; |
185 | } |
186 | } |
187 | |
188 | template <typename A> static Result GetSource(const std::list<A> &x) { |
189 | if constexpr (GET_FIRST) { |
190 | for (const A &y : x) { |
191 | if (auto result{GetSource(y)}) { |
192 | return result; |
193 | } |
194 | } |
195 | } else { |
196 | for (auto iter{x.rbegin()}; iter != x.rend(); ++iter) { |
197 | if (auto result{GetSource(*iter)}) { |
198 | return result; |
199 | } |
200 | } |
201 | } |
202 | return {}; |
203 | } |
204 | |
205 | template <typename A> static Result GetSource(const std::vector<A> &x) { |
206 | if constexpr (GET_FIRST) { |
207 | for (const A &y : x) { |
208 | if (auto result{GetSource(y)}) { |
209 | return result; |
210 | } |
211 | } |
212 | } else { |
213 | for (auto iter{x.rbegin()}; iter != x.rend(); ++iter) { |
214 | if (auto result{GetSource(*iter)}) { |
215 | return result; |
216 | } |
217 | } |
218 | } |
219 | return {}; |
220 | } |
221 | |
222 | template <typename A> static Result GetSource(A &x) { |
223 | if constexpr (HasSource<A>::value) { |
224 | return x.source; |
225 | } else if constexpr (ConstraintTrait<A>) { |
226 | return GetSource(x.thing); |
227 | } else if constexpr (WrapperTrait<A>) { |
228 | return GetSource(x.v); |
229 | } else if constexpr (UnionTrait<A>) { |
230 | return GetSource(x.u); |
231 | } else if constexpr (TupleTrait<A>) { |
232 | return GetSource(x.t); |
233 | } else { |
234 | return {}; |
235 | } |
236 | } |
237 | }; |
238 | |
239 | template <typename A> std::optional<CharBlock> GetSource(const A &x) { |
240 | return GetSourceHelper<true>::GetSource(x); |
241 | } |
242 | template <typename A> std::optional<CharBlock> GetSource(A &x) { |
243 | return GetSourceHelper<true>::GetSource(const_cast<const A &>(x)); |
244 | } |
245 | |
246 | template <typename A> std::optional<CharBlock> GetLastSource(const A &x) { |
247 | return GetSourceHelper<false>::GetSource(x); |
248 | } |
249 | template <typename A> std::optional<CharBlock> GetLastSource(A &x) { |
250 | return GetSourceHelper<false>::GetSource(const_cast<const A &>(x)); |
251 | } |
252 | |
253 | } // namespace Fortran::parser |
254 | #endif // FORTRAN_PARSER_TOOLS_H_ |
255 |
Warning: This file is not a C or C++ file. It does not have highlighting.