1 | //===-- lib/Evaluate/expression.cpp ---------------------------------------===// |
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 | #include "flang/Evaluate/expression.h" |
10 | #include "int-power.h" |
11 | #include "flang/Common/idioms.h" |
12 | #include "flang/Evaluate/common.h" |
13 | #include "flang/Evaluate/tools.h" |
14 | #include "flang/Evaluate/variable.h" |
15 | #include "flang/Parser/char-block.h" |
16 | #include "flang/Parser/message.h" |
17 | #include "flang/Semantics/scope.h" |
18 | #include "flang/Semantics/symbol.h" |
19 | #include "flang/Semantics/tools.h" |
20 | #include "flang/Semantics/type.h" |
21 | #include "llvm/Support/raw_ostream.h" |
22 | #include <string> |
23 | #include <type_traits> |
24 | |
25 | using namespace Fortran::parser::literals; |
26 | |
27 | namespace Fortran::evaluate { |
28 | |
29 | template <int KIND> |
30 | std::optional<Expr<SubscriptInteger>> |
31 | Expr<Type<TypeCategory::Character, KIND>>::LEN() const { |
32 | using T = std::optional<Expr<SubscriptInteger>>; |
33 | return common::visit( |
34 | common::visitors{ |
35 | [](const Constant<Result> &c) -> T { |
36 | return AsExpr(Constant<SubscriptInteger>{c.LEN()}); |
37 | }, |
38 | [](const ArrayConstructor<Result> &a) -> T { |
39 | if (const auto *len{a.LEN()}) { |
40 | return T{*len}; |
41 | } else { |
42 | return std::nullopt; |
43 | } |
44 | }, |
45 | [](const Parentheses<Result> &x) { return x.left().LEN(); }, |
46 | [](const Convert<Result> &x) { |
47 | return common::visit( |
48 | [&](const auto &kx) { return kx.LEN(); }, x.left().u); |
49 | }, |
50 | [](const Concat<KIND> &c) -> T { |
51 | if (auto llen{c.left().LEN()}) { |
52 | if (auto rlen{c.right().LEN()}) { |
53 | return *std::move(llen) + *std::move(rlen); |
54 | } |
55 | } |
56 | return std::nullopt; |
57 | }, |
58 | [](const Extremum<Result> &c) -> T { |
59 | if (auto llen{c.left().LEN()}) { |
60 | if (auto rlen{c.right().LEN()}) { |
61 | return Expr<SubscriptInteger>{Extremum<SubscriptInteger>{ |
62 | Ordering::Greater, *std::move(llen), *std::move(rlen)}}; |
63 | } |
64 | } |
65 | return std::nullopt; |
66 | }, |
67 | [](const Designator<Result> &dr) { return dr.LEN(); }, |
68 | [](const FunctionRef<Result> &fr) { return fr.LEN(); }, |
69 | [](const SetLength<KIND> &x) -> T { return x.right(); }, |
70 | }, |
71 | u); |
72 | } |
73 | |
74 | Expr<SomeType>::~Expr() = default; |
75 | |
76 | #if defined(__APPLE__) && defined(__GNUC__) |
77 | template <typename A> |
78 | typename ExpressionBase<A>::Derived &ExpressionBase<A>::derived() { |
79 | return *static_cast<Derived *>(this); |
80 | } |
81 | |
82 | template <typename A> |
83 | const typename ExpressionBase<A>::Derived &ExpressionBase<A>::derived() const { |
84 | return *static_cast<const Derived *>(this); |
85 | } |
86 | #endif |
87 | |
88 | template <typename A> |
89 | std::optional<DynamicType> ExpressionBase<A>::GetType() const { |
90 | if constexpr (IsLengthlessIntrinsicType<Result>) { |
91 | return Result::GetType(); |
92 | } else { |
93 | return common::visit( |
94 | [&](const auto &x) -> std::optional<DynamicType> { |
95 | if constexpr (!common::HasMember<decltype(x), TypelessExpression>) { |
96 | return x.GetType(); |
97 | } |
98 | return std::nullopt; // w/o "else" to dodge bogus g++ 8.1 warning |
99 | }, |
100 | derived().u); |
101 | } |
102 | } |
103 | |
104 | template <typename A> int ExpressionBase<A>::Rank() const { |
105 | return common::visit( |
106 | [](const auto &x) { |
107 | if constexpr (common::HasMember<decltype(x), TypelessExpression>) { |
108 | return 0; |
109 | } else { |
110 | return x.Rank(); |
111 | } |
112 | }, |
113 | derived().u); |
114 | } |
115 | |
116 | template <typename A> int ExpressionBase<A>::Corank() const { |
117 | return common::visit( |
118 | [](const auto &x) { |
119 | if constexpr (common::HasMember<decltype(x), TypelessExpression>) { |
120 | return 0; |
121 | } else { |
122 | return x.Corank(); |
123 | } |
124 | }, |
125 | derived().u); |
126 | } |
127 | |
128 | DynamicType Parentheses<SomeDerived>::GetType() const { |
129 | return left().GetType().value(); |
130 | } |
131 | |
132 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
133 | template <typename A> LLVM_DUMP_METHOD void ExpressionBase<A>::dump() const { |
134 | llvm::errs() << "Expr is <{" << AsFortran() << "}>\n" ; |
135 | } |
136 | #endif |
137 | |
138 | // Equality testing |
139 | |
140 | template <typename A> bool Extremum<A>::operator==(const Extremum &that) const { |
141 | return ordering == that.ordering && Base::operator==(that); |
142 | } |
143 | |
144 | template <int KIND> |
145 | bool LogicalOperation<KIND>::operator==(const LogicalOperation &that) const { |
146 | return logicalOperator == that.logicalOperator && Base::operator==(that); |
147 | } |
148 | |
149 | template <typename A> |
150 | bool Relational<A>::operator==(const Relational &that) const { |
151 | return opr == that.opr && Base::operator==(that); |
152 | } |
153 | |
154 | bool Relational<SomeType>::operator==(const Relational &that) const { |
155 | return u == that.u; |
156 | } |
157 | |
158 | bool ImpliedDoIndex::operator==(const ImpliedDoIndex &that) const { |
159 | return name == that.name; |
160 | } |
161 | |
162 | template <typename T> |
163 | bool ImpliedDo<T>::operator==(const ImpliedDo<T> &that) const { |
164 | return name_ == that.name_ && lower_ == that.lower_ && |
165 | upper_ == that.upper_ && stride_ == that.stride_ && |
166 | values_ == that.values_; |
167 | } |
168 | |
169 | template <typename T> |
170 | bool ArrayConstructorValue<T>::operator==( |
171 | const ArrayConstructorValue<T> &that) const { |
172 | return u == that.u; |
173 | } |
174 | |
175 | template <typename R> |
176 | bool ArrayConstructorValues<R>::operator==( |
177 | const ArrayConstructorValues<R> &that) const { |
178 | return values_ == that.values_; |
179 | } |
180 | |
181 | template <int KIND> |
182 | auto ArrayConstructor<Type<TypeCategory::Character, KIND>>::set_LEN( |
183 | Expr<SubscriptInteger> &&len) -> ArrayConstructor & { |
184 | length_.emplace(std::move(len)); |
185 | return *this; |
186 | } |
187 | |
188 | template <int KIND> |
189 | bool ArrayConstructor<Type<TypeCategory::Character, KIND>>::operator==( |
190 | const ArrayConstructor &that) const { |
191 | return length_ == that.length_ && |
192 | static_cast<const Base &>(*this) == static_cast<const Base &>(that); |
193 | } |
194 | |
195 | bool ArrayConstructor<SomeDerived>::operator==( |
196 | const ArrayConstructor &that) const { |
197 | return result_ == that.result_ && |
198 | static_cast<const Base &>(*this) == static_cast<const Base &>(that); |
199 | ; |
200 | } |
201 | |
202 | StructureConstructor::StructureConstructor( |
203 | const semantics::DerivedTypeSpec &spec, |
204 | const StructureConstructorValues &values) |
205 | : result_{spec}, values_{values} {} |
206 | StructureConstructor::StructureConstructor( |
207 | const semantics::DerivedTypeSpec &spec, StructureConstructorValues &&values) |
208 | : result_{spec}, values_{std::move(values)} {} |
209 | |
210 | bool StructureConstructor::operator==(const StructureConstructor &that) const { |
211 | return result_ == that.result_ && values_ == that.values_; |
212 | } |
213 | |
214 | template <int KIND> |
215 | bool Expr<Type<TypeCategory::Integer, KIND>>::operator==( |
216 | const Expr<Type<TypeCategory::Integer, KIND>> &that) const { |
217 | return u == that.u; |
218 | } |
219 | |
220 | template <int KIND> |
221 | bool Expr<Type<TypeCategory::Real, KIND>>::operator==( |
222 | const Expr<Type<TypeCategory::Real, KIND>> &that) const { |
223 | return u == that.u; |
224 | } |
225 | |
226 | template <int KIND> |
227 | bool Expr<Type<TypeCategory::Complex, KIND>>::operator==( |
228 | const Expr<Type<TypeCategory::Complex, KIND>> &that) const { |
229 | return u == that.u; |
230 | } |
231 | |
232 | template <int KIND> |
233 | bool Expr<Type<TypeCategory::Logical, KIND>>::operator==( |
234 | const Expr<Type<TypeCategory::Logical, KIND>> &that) const { |
235 | return u == that.u; |
236 | } |
237 | |
238 | template <int KIND> |
239 | bool Expr<Type<TypeCategory::Character, KIND>>::operator==( |
240 | const Expr<Type<TypeCategory::Character, KIND>> &that) const { |
241 | return u == that.u; |
242 | } |
243 | |
244 | template <int KIND> |
245 | bool Expr<Type<TypeCategory::Unsigned, KIND>>::operator==( |
246 | const Expr<Type<TypeCategory::Unsigned, KIND>> &that) const { |
247 | return u == that.u; |
248 | } |
249 | |
250 | template <TypeCategory CAT> |
251 | bool Expr<SomeKind<CAT>>::operator==(const Expr<SomeKind<CAT>> &that) const { |
252 | return u == that.u; |
253 | } |
254 | |
255 | bool Expr<SomeDerived>::operator==(const Expr<SomeDerived> &that) const { |
256 | return u == that.u; |
257 | } |
258 | |
259 | bool Expr<SomeCharacter>::operator==(const Expr<SomeCharacter> &that) const { |
260 | return u == that.u; |
261 | } |
262 | |
263 | bool Expr<SomeType>::operator==(const Expr<SomeType> &that) const { |
264 | return u == that.u; |
265 | } |
266 | |
267 | DynamicType StructureConstructor::GetType() const { return result_.GetType(); } |
268 | |
269 | std::optional<Expr<SomeType>> StructureConstructor::CreateParentComponent( |
270 | const Symbol &component) const { |
271 | if (const semantics::DerivedTypeSpec * |
272 | parentSpec{GetParentTypeSpec(derivedTypeSpec())}) { |
273 | StructureConstructor structureConstructor{*parentSpec}; |
274 | if (const auto *parentDetails{ |
275 | component.detailsIf<semantics::DerivedTypeDetails>()}) { |
276 | auto parentIter{parentDetails->componentNames().begin()}; |
277 | for (const auto &childIter : values_) { |
278 | if (parentIter == parentDetails->componentNames().end()) { |
279 | break; // There are more components in the child |
280 | } |
281 | SymbolRef componentSymbol{childIter.first}; |
282 | structureConstructor.Add( |
283 | *componentSymbol, common::Clone(childIter.second.value())); |
284 | ++parentIter; |
285 | } |
286 | Constant<SomeDerived> constResult{std::move(structureConstructor)}; |
287 | Expr<SomeDerived> result{std::move(constResult)}; |
288 | return std::optional<Expr<SomeType>>{result}; |
289 | } |
290 | } |
291 | return std::nullopt; |
292 | } |
293 | |
294 | static const Symbol *GetParentComponentSymbol(const Symbol &symbol) { |
295 | if (symbol.test(Symbol::Flag::ParentComp)) { |
296 | // we have a created parent component |
297 | const auto &compObject{symbol.get<semantics::ObjectEntityDetails>()}; |
298 | if (const semantics::DeclTypeSpec * compType{compObject.type()}) { |
299 | const semantics::DerivedTypeSpec &dtSpec{compType->derivedTypeSpec()}; |
300 | const semantics::Symbol &compTypeSymbol{dtSpec.typeSymbol()}; |
301 | return &compTypeSymbol; |
302 | } |
303 | } |
304 | if (symbol.detailsIf<semantics::DerivedTypeDetails>()) { |
305 | // we have an implicit parent type component |
306 | return &symbol; |
307 | } |
308 | return nullptr; |
309 | } |
310 | |
311 | std::optional<Expr<SomeType>> StructureConstructor::Find( |
312 | const Symbol &component) const { |
313 | if (auto iter{values_.find(component)}; iter != values_.end()) { |
314 | return iter->second.value(); |
315 | } |
316 | // The component wasn't there directly, see if we're looking for the parent |
317 | // component of an extended type |
318 | if (const Symbol * typeSymbol{GetParentComponentSymbol(component)}) { |
319 | return CreateParentComponent(*typeSymbol); |
320 | } |
321 | // Look for the component in the parent type component. The parent type |
322 | // component is always the first one |
323 | if (!values_.empty()) { |
324 | const Expr<SomeType> *parentExpr{&values_.begin()->second.value()}; |
325 | if (const Expr<SomeDerived> *derivedExpr{ |
326 | std::get_if<Expr<SomeDerived>>(&parentExpr->u)}) { |
327 | if (const Constant<SomeDerived> *constExpr{ |
328 | std::get_if<Constant<SomeDerived>>(&derivedExpr->u)}) { |
329 | if (std::optional<StructureConstructor> parentComponentValue{ |
330 | constExpr->GetScalarValue()}) { |
331 | // Try to find the component in the parent structure constructor |
332 | return parentComponentValue->Find(component); |
333 | } |
334 | } |
335 | } |
336 | } |
337 | return std::nullopt; |
338 | } |
339 | |
340 | StructureConstructor &StructureConstructor::Add( |
341 | const Symbol &symbol, Expr<SomeType> &&expr) { |
342 | values_.emplace(symbol, std::move(expr)); |
343 | return *this; |
344 | } |
345 | |
346 | GenericExprWrapper::~GenericExprWrapper() {} |
347 | |
348 | void GenericExprWrapper::Deleter(GenericExprWrapper *p) { delete p; } |
349 | |
350 | GenericAssignmentWrapper::~GenericAssignmentWrapper() {} |
351 | |
352 | void GenericAssignmentWrapper::Deleter(GenericAssignmentWrapper *p) { |
353 | delete p; |
354 | } |
355 | |
356 | template <TypeCategory CAT> int Expr<SomeKind<CAT>>::GetKind() const { |
357 | return common::visit( |
358 | [](const auto &kx) { return std::decay_t<decltype(kx)>::Result::kind; }, |
359 | u); |
360 | } |
361 | |
362 | int Expr<SomeCharacter>::GetKind() const { |
363 | return common::visit( |
364 | [](const auto &kx) { return std::decay_t<decltype(kx)>::Result::kind; }, |
365 | u); |
366 | } |
367 | |
368 | std::optional<Expr<SubscriptInteger>> Expr<SomeCharacter>::LEN() const { |
369 | return common::visit([](const auto &kx) { return kx.LEN(); }, u); |
370 | } |
371 | |
372 | #ifdef _MSC_VER // disable bogus warning about missing definitions |
373 | #pragma warning(disable : 4661) |
374 | #endif |
375 | INSTANTIATE_EXPRESSION_TEMPLATES |
376 | } // namespace Fortran::evaluate |
377 | |