9#ifndef FORTRAN_EVALUATE_EXPRESSION_H_
10#define FORTRAN_EVALUATE_EXPRESSION_H_
21#include "formatting.h"
24#include "flang/Common/Fortran.h"
25#include "flang/Common/idioms.h"
26#include "flang/Common/indirection.h"
27#include "flang/Common/template.h"
28#include "flang/Parser/char-block.h"
41using common::LogicalOperator;
42using common::RelationalOperator;
63template <
typename A>
using ResultType =
typename std::decay_t<A>::Result;
68 using Result = RESULT;
72#if defined(__APPLE__) && defined(__GNUC__)
77 const Derived &derived()
const {
return *
static_cast<const Derived *
>(
this); }
81 template <
typename A>
Derived &operator=(
const A &x) {
87 template <
typename A> common::IfNoLvalue<Derived &, A> operator=(A &&x) {
93 std::optional<DynamicType> GetType()
const;
96 std::string AsFortran()
const;
97#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
98 LLVM_DUMP_METHOD
void dump()
const;
100 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
113template <
typename DERIVED,
typename RESULT,
typename... OPERANDS>
118 using OperandTypes = std::tuple<OPERANDS..., std::monostate>;
121 using Derived = DERIVED;
122 using Result = RESULT;
123 static constexpr std::size_t operands{
sizeof...(OPERANDS)};
125 static_assert(IsSpecificIntrinsicType<Result> ||
126 (operands == 1 && std::is_same_v<Result, SomeDerived>));
127 template <
int J>
using Operand = std::tuple_element_t<J, OperandTypes>;
132 using Container = std::conditional_t<operands == 1,
134 std::tuple<common::CopyableIndirection<Expr<OPERANDS>>...>>;
141 Derived &derived() {
return *
static_cast<Derived *
>(
this); }
142 const Derived &derived()
const {
return *
static_cast<const Derived *
>(
this); }
150 if constexpr (operands == 1) {
151 static_assert(J == 0);
152 return operand_.value();
154 return std::get<J>(operand_).value();
158 if constexpr (operands == 1) {
159 static_assert(J == 0);
160 return operand_.value();
162 return std::get<J>(operand_).value();
169 std::conditional_t<(operands > 1),
Expr<Operand<1>> &,
void> right() {
170 if constexpr (operands > 1) {
174 std::conditional_t<(operands > 1),
const Expr<Operand<1>> &,
void>
176 if constexpr (operands > 1) {
181 static constexpr std::conditional_t<Result::category != TypeCategory::Derived,
182 std::optional<DynamicType>,
void>
184 return Result::GetType();
187 int rank{left().Rank()};
188 if constexpr (operands > 1) {
189 return std::max(rank, right().Rank());
194 static constexpr int Corank() {
return 0; }
196 bool operator==(
const Operation &that)
const {
197 return operand_ == that.operand_;
200 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
210template <
typename TO, TypeCategory FROMCAT = TO::category>
215 ((TO::category == TypeCategory::Integer ||
216 TO::category == TypeCategory::Real ||
217 TO::category == TypeCategory::Unsigned) &&
218 (FROMCAT == TypeCategory::Integer || FROMCAT == TypeCategory::Real ||
219 FROMCAT == TypeCategory::Unsigned)) ||
220 TO::category == FROMCAT);
225 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
238 :
public Operation<Parentheses<SomeDerived>, SomeDerived, SomeDerived> {
256 :
public Operation<ComplexComponent<KIND>, Type<TypeCategory::Real, KIND>,
257 Type<TypeCategory::Complex, KIND>> {
263 :
Base{x}, isImaginaryPart{isImaginary} {}
265 :
Base{std::move(x)}, isImaginaryPart{isImaginary} {}
267 bool isImaginaryPart{
true};
271struct Not :
public Operation<Not<KIND>, Type<TypeCategory::Logical, KIND>,
272 Type<TypeCategory::Logical, KIND>> {
285 :
public Operation<SetLength<KIND>, Type<TypeCategory::Character, KIND>,
286 Type<TypeCategory::Character, KIND>, SubscriptInteger> {
335 using BaseOperand = A;
346 :
Base{x, y}, ordering{ord} {}
348 :
Base{std::move(x), std::move(y)}, ordering{ord} {}
349 bool operator==(
const Extremum &)
const;
350 Ordering ordering{Ordering::Greater};
355 :
public Operation<ComplexConstructor<KIND>,
356 Type<TypeCategory::Complex, KIND>, Type<TypeCategory::Real, KIND>,
357 Type<TypeCategory::Real, KIND>> {
366 :
public Operation<Concat<KIND>, Type<TypeCategory::Character, KIND>,
367 Type<TypeCategory::Character, KIND>,
368 Type<TypeCategory::Character, KIND>> {
377 :
public Operation<LogicalOperation<KIND>,
378 Type<TypeCategory::Logical, KIND>, Type<TypeCategory::Logical, KIND>,
379 Type<TypeCategory::Logical, KIND>> {
386 :
Base{x, y}, logicalOperator{opr} {}
388 :
Base{std::move(x), std::move(y)}, logicalOperator{opr} {}
390 LogicalOperator logicalOperator;
399 static constexpr int Rank() {
return 0; }
400 static constexpr int Corank() {
return 0; }
406 using Result = RESULT;
407 using Index = ResultType<ImpliedDoIndex>;
410 : name_{name}, lower_{std::move(lower)}, upper_{std::move(upper)},
411 stride_{std::move(stride)}, values_{std::move(values)} {}
412 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(
ImpliedDo)
413 bool operator==(
const ImpliedDo &)
const;
416 const Expr<Index> &lower()
const {
return lower_.value(); }
418 const Expr<Index> &upper()
const {
return upper_.value(); }
420 const Expr<Index> &stride()
const {
return stride_.value(); }
423 return values_.value();
433 using Result = RESULT;
440 using Result = RESULT;
441 using Values = std::vector<ArrayConstructorValue<Result>>;
446 static constexpr int Rank() {
return 1; }
447 static constexpr int Corank() {
return 0; }
448 template <
typename A> common::NoLvalue<A> Push(A &&x) {
449 values_.emplace_back(std::move(x));
452 typename Values::iterator begin() {
return values_.begin(); }
453 typename Values::const_iterator begin()
const {
return values_.begin(); }
454 typename Values::iterator end() {
return values_.end(); }
455 typename Values::const_iterator end()
const {
return values_.end(); }
465template <
typename RESULT>
468 using Result = RESULT;
473 static constexpr Result result() {
return Result{}; }
474 static constexpr DynamicType GetType() {
return Result::GetType(); }
475 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
490 static constexpr DynamicType GetType() {
return Result::GetType(); }
491 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
493 return length_ ? &length_->value() :
nullptr;
497 std::optional<common::CopyableIndirection<Expr<SubscriptInteger>>> length_;
509 :
Base{std::move(v)}, result_{spec} {}
510 template <
typename A>
512 : result_{prototype.GetType().value().GetDerivedTypeSpec()} {}
515 constexpr Result result()
const {
return result_; }
516 constexpr DynamicType GetType()
const {
return result_.GetType(); }
517 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
531 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
534 using Conversions = std::tuple<Convert<Result, TypeCategory::Integer>,
537 using Operations = std::tuple<Parentheses<Result>,
Negate<Result>,
540 using Indices = std::conditional_t<KIND == ImpliedDoIndex::Result::kind,
541 std::tuple<ImpliedDoIndex>, std::tuple<>>;
542 using TypeParamInquiries =
543 std::conditional_t<KIND == TypeParamInquiry::Result::kind,
544 std::tuple<TypeParamInquiry>, std::tuple<>>;
545 using DescriptorInquiries =
546 std::conditional_t<KIND == DescriptorInquiry::Result::kind,
547 std::tuple<DescriptorInquiry>, std::tuple<>>;
552 common::TupleToVariant<common::CombineTuples<Operations, Conversions, Indices,
553 TypeParamInquiries, DescriptorInquiries, Others>>
563 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
566 using Conversions = std::tuple<Convert<Result, TypeCategory::Integer>,
576 common::TupleToVariant<common::CombineTuples<Operations, Conversions, Others>>
586 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
592 using Conversions = std::variant<Convert<Result, TypeCategory::Integer>,
602 common::CombineVariants<Operations, Conversions, Others> u;
610 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
612 using Operations = std::variant<Parentheses<Result>,
Negate<Result>,
620 common::CombineVariants<Operations, Others> u;
623FOR_EACH_INTEGER_KIND(
extern template class Expr, )
624FOR_EACH_UNSIGNED_KIND(extern template class
Expr, )
625FOR_EACH_REAL_KIND(extern template class
Expr, )
626FOR_EACH_COMPLEX_KIND(extern template class
Expr, )
633 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
637 std::optional<Expr<SubscriptInteger>> LEN()
const;
645FOR_EACH_CHARACTER_KIND(
extern template class Expr, )
660 using Operand =
typename Base::template Operand<0>;
661 static_assert(Operand::category == TypeCategory::Integer ||
662 Operand::category == TypeCategory::Real ||
663 Operand::category == TypeCategory::Complex ||
664 Operand::category == TypeCategory::Character ||
665 Operand::category == TypeCategory::Unsigned);
669 :
Base{a, b}, opr{r} {}
671 :
Base{std::move(a), std::move(b)}, opr{r} {}
673 RelationalOperator opr;
677 using DirectlyComparableTypes = common::CombineTuples<IntegerTypes, RealTypes,
678 ComplexTypes, CharacterTypes, UnsignedTypes>;
683 static constexpr DynamicType GetType() {
return Result::GetType(); }
685 return common::visit([](
const auto &x) {
return x.Rank(); }, u);
687 static constexpr int Corank() {
return 0; }
688 llvm::raw_ostream &AsFortran(llvm::raw_ostream &o)
const;
689 common::MapTemplate<Relational, DirectlyComparableTypes> u;
692FOR_EACH_INTEGER_KIND(
extern template class Relational, )
693FOR_EACH_UNSIGNED_KIND(extern template class
Relational, )
694FOR_EACH_REAL_KIND(extern template class
Relational, )
695FOR_EACH_CHARACTER_KIND(extern template class
Relational, )
707 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
714 using Relations = std::conditional_t<KIND == LogicalResult::kind,
715 std::tuple<Relational<SomeType>>, std::tuple<>>;
720 common::TupleToVariant<common::CombineTuples<Operations, Relations, Others>>
724FOR_EACH_LOGICAL_KIND(
extern template class Expr, )
752 constexpr Result result()
const {
return result_; }
754 return result_.derivedTypeSpec();
756 StructureConstructorValues &values() {
return values_; }
757 const StructureConstructorValues &values()
const {
return values_; }
761 StructureConstructorValues::iterator begin() {
return values_.begin(); }
762 StructureConstructorValues::const_iterator begin()
const {
763 return values_.begin();
765 StructureConstructorValues::iterator end() {
return values_.end(); }
766 StructureConstructorValues::const_iterator end()
const {
767 return values_.end();
771 std::optional<Expr<SomeType>> Find(
const Symbol &)
const;
774 static constexpr int Rank() {
return 0; }
775 static constexpr int Corank() {
return 0; }
777 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
780 std::optional<Expr<SomeType>> CreateParentComponent(
const Symbol &)
const;
782 StructureConstructorValues values_;
789 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
798template <TypeCategory CAT>
802 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
804 common::MapTemplate<evaluate::Expr, CategoryTypes<CAT>> u;
810 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
812 std::optional<Expr<SubscriptInteger>> LEN()
const;
813 common::MapTemplate<Expr, CategoryTypes<TypeCategory::Character>> u;
818using CategoryExpression = common::MapTemplate<Expr, SomeCategory>;
824using BOZLiteralConstant =
typename LargestReal::Scalar::Word;
828 constexpr bool operator==(
const NullPointer &)
const {
return true; }
829 static constexpr int Rank() {
return 0; }
830 static constexpr int Corank() {
return 0; }
836using TypelessExpression = std::variant<BOZLiteralConstant,
NullPointer,
844 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
851 template <TypeCategory CAT,
int KIND>
854 template <TypeCategory CAT,
int KIND>
858 template <TypeCategory CAT,
int KIND>
864 template <TypeCategory CAT,
int KIND>
871 common::CombineVariants<TypelessExpression, CategoryExpression> u;
881 : lhs(std::move(lhs)), rhs(std::move(rhs)) {}
884 using BoundsSpec = std::vector<Expr<SubscriptInteger>>;
885 using BoundsRemapping =
887 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
891 std::variant<Intrinsic, ProcedureRef, BoundsSpec, BoundsRemapping> u;
902 std::optional<Expr<SomeType>> v;
913 std::optional<Assignment> v;
916FOR_EACH_CATEGORY_TYPE(
extern template class Expr, )
922#define INSTANTIATE_EXPRESSION_TEMPLATES \
923 FOR_EACH_INTRINSIC_KIND(template class Expr, ) \
924 FOR_EACH_CATEGORY_TYPE(template class Expr, ) \
925 FOR_EACH_INTEGER_KIND(template class Relational, ) \
926 FOR_EACH_UNSIGNED_KIND(template class Relational, ) \
927 FOR_EACH_REAL_KIND(template class Relational, ) \
928 FOR_EACH_CHARACTER_KIND(template class Relational, ) \
929 template class Relational<SomeType>; \
930 FOR_EACH_TYPE_AND_KIND(template class ExpressionBase, ) \
931 FOR_EACH_INTRINSIC_KIND(template class ArrayConstructorValues, ) \
932 FOR_EACH_INTRINSIC_KIND(template class ArrayConstructor, )
Definition: indirection.h:72
Definition: expression.h:438
Definition: expression.h:466
Definition: expression.h:878
Definition: constant.h:141
Definition: variable.h:393
Definition: expression.h:66
Definition: expression.h:404
Definition: expression.h:114
Definition: expression.h:656
Definition: expression.h:740
Definition: char-block.h:28
Definition: expression.h:296
Definition: expression.h:432
Definition: expression.h:883
Definition: expression.h:257
Definition: expression.h:357
Definition: expression.h:368
Definition: expression.h:211
Definition: expression.h:317
Definition: expression.h:340
Definition: expression.h:906
Definition: expression.h:896
Definition: expression.h:396
Definition: expression.h:379
Definition: expression.h:310
Definition: expression.h:247
Definition: expression.h:272
Definition: expression.h:827
Definition: expression.h:229
Definition: expression.h:324
Definition: expression.h:332
Definition: expression.h:286
Definition: expression.h:303