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