//===-- lib/Evaluate/expression.cpp ---------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "flang/Evaluate/expression.h" #include "int-power.h" #include "flang/Common/idioms.h" #include "flang/Evaluate/common.h" #include "flang/Evaluate/tools.h" #include "flang/Evaluate/variable.h" #include "flang/Parser/message.h" #include "llvm/Support/raw_ostream.h" #include #include using namespace Fortran::parser::literals; namespace Fortran::evaluate { template std::optional> Expr>::LEN() const { using T = std::optional>; return std::visit( common::visitors{ [](const Constant &c) -> T { return AsExpr(Constant{c.LEN()}); }, [](const ArrayConstructor &a) -> T { return a.LEN(); }, [](const Parentheses &x) { return x.left().LEN(); }, [](const Convert &x) { return std::visit( [&](const auto &kx) { return kx.LEN(); }, x.left().u); }, [](const Concat &c) -> T { if (auto llen{c.left().LEN()}) { if (auto rlen{c.right().LEN()}) { return *std::move(llen) + *std::move(rlen); } } return std::nullopt; }, [](const Extremum &c) -> T { if (auto llen{c.left().LEN()}) { if (auto rlen{c.right().LEN()}) { return Expr{Extremum{ Ordering::Greater, *std::move(llen), *std::move(rlen)}}; } } return std::nullopt; }, [](const Designator &dr) { return dr.LEN(); }, [](const FunctionRef &fr) { return fr.LEN(); }, [](const SetLength &x) -> T { return x.right(); }, }, u); } Expr::~Expr() = default; #if defined(__APPLE__) && defined(__GNUC__) template typename ExpressionBase::Derived &ExpressionBase::derived() { return *static_cast(this); } template const typename ExpressionBase::Derived &ExpressionBase::derived() const { return *static_cast(this); } #endif template std::optional ExpressionBase::GetType() const { if constexpr (IsLengthlessIntrinsicType) { return Result::GetType(); } else { return std::visit( [&](const auto &x) -> std::optional { if constexpr (!common::HasMember) { return x.GetType(); } return std::nullopt; // w/o "else" to dodge bogus g++ 8.1 warning }, derived().u); } } template int ExpressionBase::Rank() const { return std::visit( [](const auto &x) { if constexpr (common::HasMember) { return 0; } else { return x.Rank(); } }, derived().u); } // Equality testing bool ImpliedDoIndex::operator==(const ImpliedDoIndex &that) const { return name == that.name; } template bool ImpliedDo::operator==(const ImpliedDo &that) const { return name_ == that.name_ && lower_ == that.lower_ && upper_ == that.upper_ && stride_ == that.stride_ && values_ == that.values_; } template bool ArrayConstructorValue::operator==( const ArrayConstructorValue &that) const { return u == that.u; } template bool ArrayConstructorValues::operator==( const ArrayConstructorValues &that) const { return values_ == that.values_; } template bool ArrayConstructor>::operator==( const ArrayConstructor &that) const { return length_ == that.length_ && static_cast(*this) == static_cast(that); } bool ArrayConstructor::operator==( const ArrayConstructor &that) const { return result_ == that.result_ && static_cast(*this) == static_cast(that); ; } StructureConstructor::StructureConstructor( const semantics::DerivedTypeSpec &spec, const StructureConstructorValues &values) : result_{spec}, values_{values} {} StructureConstructor::StructureConstructor( const semantics::DerivedTypeSpec &spec, StructureConstructorValues &&values) : result_{spec}, values_{std::move(values)} {} bool StructureConstructor::operator==(const StructureConstructor &that) const { return result_ == that.result_ && values_ == that.values_; } bool Relational::operator==(const Relational &that) const { return u == that.u; } template bool Expr>::operator==( const Expr> &that) const { return u == that.u; } template bool Expr>::operator==( const Expr> &that) const { return u == that.u; } template bool Expr>::operator==( const Expr> &that) const { return u == that.u; } template bool Expr>::operator==( const Expr> &that) const { return u == that.u; } template bool Expr>::operator==( const Expr> &that) const { return u == that.u; } template bool Expr>::operator==(const Expr> &that) const { return u == that.u; } bool Expr::operator==(const Expr &that) const { return u == that.u; } bool Expr::operator==(const Expr &that) const { return u == that.u; } bool Expr::operator==(const Expr &that) const { return u == that.u; } DynamicType StructureConstructor::GetType() const { return result_.GetType(); } const Expr *StructureConstructor::Find( const Symbol &component) const { if (auto iter{values_.find(component)}; iter != values_.end()) { return &iter->second.value(); } else { return nullptr; } } StructureConstructor &StructureConstructor::Add( const Symbol &symbol, Expr &&expr) { values_.emplace(symbol, std::move(expr)); return *this; } GenericExprWrapper::~GenericExprWrapper() {} void GenericExprWrapper::Deleter(GenericExprWrapper *p) { delete p; } GenericAssignmentWrapper::~GenericAssignmentWrapper() {} void GenericAssignmentWrapper::Deleter(GenericAssignmentWrapper *p) { delete p; } template int Expr>::GetKind() const { return std::visit( [](const auto &kx) { return std::decay_t::Result::kind; }, u); } int Expr::GetKind() const { return std::visit( [](const auto &kx) { return std::decay_t::Result::kind; }, u); } std::optional> Expr::LEN() const { return std::visit([](const auto &kx) { return kx.LEN(); }, u); } INSTANTIATE_EXPRESSION_TEMPLATES } // namespace Fortran::evaluate