xref: /llvm-project/flang/lib/Evaluate/expression.cpp (revision 8670e49901d116b2094aeb0a5117edef9e69cdcf)
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/message.h"
16 #include "llvm/Support/raw_ostream.h"
17 #include <string>
18 #include <type_traits>
19 
20 using namespace Fortran::parser::literals;
21 
22 namespace Fortran::evaluate {
23 
24 template<int KIND>
25 std::optional<Expr<SubscriptInteger>>
26 Expr<Type<TypeCategory::Character, KIND>>::LEN() const {
27   using T = std::optional<Expr<SubscriptInteger>>;
28   return std::visit(
29       common::visitors{
30           [](const Constant<Result> &c) -> T {
31             return AsExpr(Constant<SubscriptInteger>{c.LEN()});
32           },
33           [](const ArrayConstructor<Result> &a) -> T { return a.LEN(); },
34           [](const Parentheses<Result> &x) { return x.left().LEN(); },
35           [](const Convert<Result> &x) {
36             return std::visit(
37                 [&](const auto &kx) { return kx.LEN(); }, x.left().u);
38           },
39           [](const Concat<KIND> &c) -> T {
40             if (auto llen{c.left().LEN()}) {
41               if (auto rlen{c.right().LEN()}) {
42                 return *std::move(llen) + *std::move(rlen);
43               }
44             }
45             return std::nullopt;
46           },
47           [](const Extremum<Result> &c) -> T {
48             if (auto llen{c.left().LEN()}) {
49               if (auto rlen{c.right().LEN()}) {
50                 return Expr<SubscriptInteger>{Extremum<SubscriptInteger>{
51                     Ordering::Greater, *std::move(llen), *std::move(rlen)}};
52               }
53             }
54             return std::nullopt;
55           },
56           [](const Designator<Result> &dr) { return dr.LEN(); },
57           [](const FunctionRef<Result> &fr) { return fr.LEN(); },
58           [](const SetLength<KIND> &x) -> T { return x.right(); },
59       },
60       u);
61 }
62 
63 Expr<SomeType>::~Expr() = default;
64 
65 #if defined(__APPLE__) && defined(__GNUC__)
66 template<typename A>
67 typename ExpressionBase<A>::Derived &ExpressionBase<A>::derived() {
68   return *static_cast<Derived *>(this);
69 }
70 
71 template<typename A>
72 const typename ExpressionBase<A>::Derived &ExpressionBase<A>::derived() const {
73   return *static_cast<const Derived *>(this);
74 }
75 #endif
76 
77 template<typename A>
78 std::optional<DynamicType> ExpressionBase<A>::GetType() const {
79   if constexpr (IsLengthlessIntrinsicType<Result>) {
80     return Result::GetType();
81   } else {
82     return std::visit(
83         [&](const auto &x) -> std::optional<DynamicType> {
84           if constexpr (!common::HasMember<decltype(x), TypelessExpression>) {
85             return x.GetType();
86           }
87           return std::nullopt;  // w/o "else" to dodge bogus g++ 8.1 warning
88         },
89         derived().u);
90   }
91 }
92 
93 template<typename A> int ExpressionBase<A>::Rank() const {
94   return std::visit(
95       [](const auto &x) {
96         if constexpr (common::HasMember<decltype(x), TypelessExpression>) {
97           return 0;
98         } else {
99           return x.Rank();
100         }
101       },
102       derived().u);
103 }
104 
105 // Equality testing
106 
107 bool ImpliedDoIndex::operator==(const ImpliedDoIndex &that) const {
108   return name == that.name;
109 }
110 
111 template<typename T>
112 bool ImpliedDo<T>::operator==(const ImpliedDo<T> &that) const {
113   return name_ == that.name_ && lower_ == that.lower_ &&
114       upper_ == that.upper_ && stride_ == that.stride_ &&
115       values_ == that.values_;
116 }
117 
118 template<typename T>
119 bool ArrayConstructorValue<T>::operator==(
120     const ArrayConstructorValue<T> &that) const {
121   return u == that.u;
122 }
123 
124 template<typename R>
125 bool ArrayConstructorValues<R>::operator==(
126     const ArrayConstructorValues<R> &that) const {
127   return values_ == that.values_;
128 }
129 
130 template<int KIND>
131 bool ArrayConstructor<Type<TypeCategory::Character, KIND>>::operator==(
132     const ArrayConstructor &that) const {
133   return length_ == that.length_ &&
134       static_cast<const Base &>(*this) == static_cast<const Base &>(that);
135 }
136 
137 bool ArrayConstructor<SomeDerived>::operator==(
138     const ArrayConstructor &that) const {
139   return result_ == that.result_ &&
140       static_cast<const Base &>(*this) == static_cast<const Base &>(that);
141   ;
142 }
143 
144 StructureConstructor::StructureConstructor(
145     const semantics::DerivedTypeSpec &spec,
146     const StructureConstructorValues &values)
147   : result_{spec}, values_{values} {}
148 StructureConstructor::StructureConstructor(
149     const semantics::DerivedTypeSpec &spec, StructureConstructorValues &&values)
150   : result_{spec}, values_{std::move(values)} {}
151 
152 bool StructureConstructor::operator==(const StructureConstructor &that) const {
153   return result_ == that.result_ && values_ == that.values_;
154 }
155 
156 bool Relational<SomeType>::operator==(const Relational<SomeType> &that) const {
157   return u == that.u;
158 }
159 
160 template<int KIND>
161 bool Expr<Type<TypeCategory::Integer, KIND>>::operator==(
162     const Expr<Type<TypeCategory::Integer, KIND>> &that) const {
163   return u == that.u;
164 }
165 
166 template<int KIND>
167 bool Expr<Type<TypeCategory::Real, KIND>>::operator==(
168     const Expr<Type<TypeCategory::Real, KIND>> &that) const {
169   return u == that.u;
170 }
171 
172 template<int KIND>
173 bool Expr<Type<TypeCategory::Complex, KIND>>::operator==(
174     const Expr<Type<TypeCategory::Complex, KIND>> &that) const {
175   return u == that.u;
176 }
177 
178 template<int KIND>
179 bool Expr<Type<TypeCategory::Logical, KIND>>::operator==(
180     const Expr<Type<TypeCategory::Logical, KIND>> &that) const {
181   return u == that.u;
182 }
183 
184 template<int KIND>
185 bool Expr<Type<TypeCategory::Character, KIND>>::operator==(
186     const Expr<Type<TypeCategory::Character, KIND>> &that) const {
187   return u == that.u;
188 }
189 
190 template<TypeCategory CAT>
191 bool Expr<SomeKind<CAT>>::operator==(const Expr<SomeKind<CAT>> &that) const {
192   return u == that.u;
193 }
194 
195 bool Expr<SomeDerived>::operator==(const Expr<SomeDerived> &that) const {
196   return u == that.u;
197 }
198 
199 bool Expr<SomeCharacter>::operator==(const Expr<SomeCharacter> &that) const {
200   return u == that.u;
201 }
202 
203 bool Expr<SomeType>::operator==(const Expr<SomeType> &that) const {
204   return u == that.u;
205 }
206 
207 DynamicType StructureConstructor::GetType() const { return result_.GetType(); }
208 
209 const Expr<SomeType> *StructureConstructor::Find(
210     const Symbol &component) const {
211   if (auto iter{values_.find(component)}; iter != values_.end()) {
212     return &iter->second.value();
213   } else {
214     return nullptr;
215   }
216 }
217 
218 StructureConstructor &StructureConstructor::Add(
219     const Symbol &symbol, Expr<SomeType> &&expr) {
220   values_.emplace(symbol, std::move(expr));
221   return *this;
222 }
223 
224 GenericExprWrapper::~GenericExprWrapper() {}
225 
226 GenericAssignmentWrapper::~GenericAssignmentWrapper() {}
227 
228 template<TypeCategory CAT> int Expr<SomeKind<CAT>>::GetKind() const {
229   return std::visit(
230       [](const auto &kx) { return std::decay_t<decltype(kx)>::Result::kind; },
231       u);
232 }
233 
234 int Expr<SomeCharacter>::GetKind() const {
235   return std::visit(
236       [](const auto &kx) { return std::decay_t<decltype(kx)>::Result::kind; },
237       u);
238 }
239 
240 std::optional<Expr<SubscriptInteger>> Expr<SomeCharacter>::LEN() const {
241   return std::visit([](const auto &kx) { return kx.LEN(); }, u);
242 }
243 
244 INSTANTIATE_EXPRESSION_TEMPLATES
245 }
246 DEFINE_DELETER(Fortran::evaluate::GenericExprWrapper)
247 DEFINE_DELETER(Fortran::evaluate::GenericAssignmentWrapper)
248