9#ifndef FORTRAN_EVALUATE_EXPRESSION_H_
10#define FORTRAN_EVALUATE_EXPRESSION_H_
21#include "formatting.h"
24#include "flang/Common/idioms.h"
25#include "flang/Common/indirection.h"
26#include "flang/Common/template.h"
27#include "flang/Parser/char-block.h"
28#include "flang/Support/Fortran.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__)
74 const Derived &derived()
const;
76 Derived &derived() {
return *
static_cast<Derived *
>(
this); }
77 const Derived &derived()
const {
return *
static_cast<const Derived *
>(
this); }
81 template <
typename A> Derived &operator=(
const A &x) {
82 Derived &d{derived()};
87 template <
typename A> common::IfNoLvalue<Derived &, A> operator=(A &&x) {
88 Derived &d{derived()};
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,
133 common::CopyableIndirection<Expr<Operand<0>>>,
134 std::tuple<common::CopyableIndirection<Expr<OPERANDS>>...>>;
137 CLASS_BOILERPLATE(Operation)
138 explicit Operation(
const Expr<OPERANDS> &...x) : operand_{x...} {}
139 explicit Operation(
Expr<OPERANDS> &&...x) : operand_{std::move(x)...} {}
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>
211struct Convert :
public Operation<Convert<TO, FROMCAT>, TO, SomeKind<FROMCAT>> {
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);
223 using Base = Operation<Convert, Result, Operand>;
225 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
232 using Base = Operation<Parentheses, A, A>;
238 :
public Operation<Parentheses<SomeDerived>, SomeDerived, SomeDerived> {
240 using Result = SomeDerived;
241 using Operand = SomeDerived;
242 using Base = Operation<Parentheses, SomeDerived, SomeDerived>;
247template <
typename A>
struct Negate :
public Operation<Negate<A>, A, A> {
250 using Base = Operation<Negate, A, A>;
255struct ComplexComponent
256 :
public Operation<ComplexComponent<KIND>, Type<TypeCategory::Real, KIND>,
257 Type<TypeCategory::Complex, KIND>> {
260 using Base = Operation<ComplexComponent, Result, Operand>;
261 CLASS_BOILERPLATE(ComplexComponent)
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>> {
274 using Operand = Result;
275 using Base = Operation<Not, Result, Operand>;
285 :
public Operation<SetLength<KIND>, Type<TypeCategory::Character, KIND>,
286 Type<TypeCategory::Character, KIND>, SubscriptInteger> {
288 using CharacterOperand = Result;
289 using LengthOperand = SubscriptInteger;
290 using Base = Operation<SetLength, Result, CharacterOperand, LengthOperand>;
296template <
typename A>
struct Add :
public Operation<Add<A>, A, A, A> {
299 using Base = Operation<Add, A, A, A>;
303template <
typename A>
struct Subtract :
public Operation<Subtract<A>, A, A, A> {
306 using Base = Operation<Subtract, A, A, A>;
310template <
typename A>
struct Multiply :
public Operation<Multiply<A>, A, A, A> {
313 using Base = Operation<Multiply, A, A, A>;
317template <
typename A>
struct Divide :
public Operation<Divide<A>, A, A, A> {
320 using Base = Operation<Divide, A, A, A>;
324template <
typename A>
struct Power :
public Operation<Power<A>, A, A, A> {
327 using Base = Operation<Power, A, A, A>;
333 using Base = Operation<RealToIntPower, A, A, SomeInteger>;
335 using BaseOperand = A;
336 using ExponentOperand = SomeInteger;
340template <
typename A>
struct Extremum :
public Operation<Extremum<A>, A, A, A> {
343 using Base = Operation<Extremum, A, A, A>;
344 CLASS_BOILERPLATE(Extremum)
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>> {
360 using Base = Operation<ComplexConstructor, Result, Operand, Operand>;
366 :
public Operation<Concat<KIND>, Type<TypeCategory::Character, KIND>,
367 Type<TypeCategory::Character, KIND>,
368 Type<TypeCategory::Character, KIND>> {
370 using Operand = Result;
371 using Base = Operation<Concat, Result, Operand, Operand>;
376struct LogicalOperation
377 :
public Operation<LogicalOperation<KIND>,
378 Type<TypeCategory::Logical, KIND>, Type<TypeCategory::Logical, KIND>,
379 Type<TypeCategory::Logical, KIND>> {
381 using Operand = Result;
382 using Base = Operation<LogicalOperation, Result, Operand, Operand>;
383 CLASS_BOILERPLATE(LogicalOperation)
386 : Base{x, y}, logicalOperator{opr} {}
388 : Base{std::move(x), std::move(y)}, logicalOperator{opr} {}
389 bool operator==(
const LogicalOperation &)
const;
390 LogicalOperator logicalOperator;
395template <
typename T>
class ConditionalExpr {
398 CLASS_BOILERPLATE(ConditionalExpr)
401 : condition_{std::move(cond)}, thenValue_{std::move(thenVal)},
402 elseValue_{std::move(elseVal)} {}
403 bool operator==(
const ConditionalExpr &)
const;
406 Expr<Result> &thenValue() {
return thenValue_.value(); }
407 const Expr<Result> &thenValue()
const {
return thenValue_.value(); }
408 Expr<Result> &elseValue() {
return elseValue_.value(); }
409 const Expr<Result> &elseValue()
const {
return elseValue_.value(); }
410 int Rank()
const {
return thenValue().Rank(); }
411 std::optional<DynamicType> GetType()
const {
412 const auto thenType{thenValue().GetType()};
413 if constexpr (T::category == TypeCategory::Derived) {
415 if (thenType && !thenType->IsPolymorphic()) {
416 if (
const auto elseType{elseValue().GetType()}) {
417 if (elseType->IsPolymorphic()) {
425 static constexpr int Corank() {
return 0; }
426 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
429 common::CopyableIndirection<Expr<LogicalResult>> condition_;
430 common::CopyableIndirection<Expr<Result>> thenValue_;
431 common::CopyableIndirection<Expr<Result>> elseValue_;
438 using Result = SubscriptInteger;
440 static constexpr int Rank() {
return 0; }
441 static constexpr int Corank() {
return 0; }
445template <
typename RESULT>
class ImpliedDo {
447 using Result = RESULT;
448 using Index = ResultType<ImpliedDoIndex>;
451 : name_{name}, lower_{std::move(lower)}, upper_{std::move(upper)},
452 stride_{std::move(stride)}, values_{std::move(values)} {}
453 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ImpliedDo)
454 bool operator==(
const ImpliedDo &)
const;
457 const Expr<Index> &lower()
const {
return lower_.value(); }
459 const Expr<Index> &upper()
const {
return upper_.value(); }
461 const Expr<Index> &stride()
const {
return stride_.value(); }
464 return values_.value();
469 common::CopyableIndirection<Expr<Index>> lower_, upper_, stride_;
470 common::CopyableIndirection<ArrayConstructorValues<Result>> values_;
474 using Result = RESULT;
479template <
typename RESULT>
class ArrayConstructorValues {
481 using Result = RESULT;
482 using Values = std::vector<ArrayConstructorValue<Result>>;
483 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructorValues)
484 ArrayConstructorValues() {}
486 bool operator==(
const ArrayConstructorValues &)
const;
487 static constexpr int Rank() {
return 1; }
488 static constexpr int Corank() {
return 0; }
489 template <
typename A> common::NoLvalue<A> Push(A &&x) {
490 values_.emplace_back(std::move(x));
493 typename Values::iterator begin() {
return values_.begin(); }
494 typename Values::const_iterator begin()
const {
return values_.begin(); }
495 typename Values::iterator end() {
return values_.end(); }
496 typename Values::const_iterator end()
const {
return values_.end(); }
506template <
typename RESULT>
507class ArrayConstructor :
public ArrayConstructorValues<RESULT> {
509 using Result = RESULT;
510 using Base = ArrayConstructorValues<Result>;
511 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructor)
512 explicit ArrayConstructor(Base &&values) : Base{std::move(values)} {}
513 template <
typename T>
explicit ArrayConstructor(
const Expr<T> &) {}
514 static constexpr Result result() {
return Result{}; }
515 static constexpr DynamicType GetType() {
return Result::GetType(); }
516 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
520class ArrayConstructor<
Type<TypeCategory::Character, KIND>>
521 :
public ArrayConstructorValues<Type<TypeCategory::Character, KIND>> {
524 using Base = ArrayConstructorValues<Result>;
525 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructor)
526 explicit ArrayConstructor(Base &&values) : Base{std::move(values)} {}
527 template <
typename T>
explicit ArrayConstructor(
const Expr<T> &) {}
529 bool operator==(
const ArrayConstructor &)
const;
530 static constexpr Result result() {
return Result{}; }
531 static constexpr DynamicType GetType() {
return Result::GetType(); }
532 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
534 return length_ ? &length_->value() :
nullptr;
538 std::optional<common::CopyableIndirection<Expr<SubscriptInteger>>> length_;
542class ArrayConstructor<SomeDerived>
543 :
public ArrayConstructorValues<SomeDerived> {
545 using Result = SomeDerived;
546 using Base = ArrayConstructorValues<Result>;
547 CLASS_BOILERPLATE(ArrayConstructor)
550 : Base{std::move(v)}, result_{spec} {}
551 template <
typename A>
552 explicit ArrayConstructor(
const A &prototype)
553 : result_{prototype.GetType().value().GetDerivedTypeSpec()} {}
555 bool operator==(
const ArrayConstructor &)
const;
556 constexpr Result result()
const {
return result_; }
557 constexpr DynamicType GetType()
const {
return result_.GetType(); }
558 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
572 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
575 using Conversions = std::tuple<Convert<Result, TypeCategory::Integer>,
578 using Operations = std::tuple<Parentheses<Result>,
Negate<Result>,
581 using Indices = std::conditional_t<KIND == ImpliedDoIndex::Result::kind,
582 std::tuple<ImpliedDoIndex>, std::tuple<>>;
583 using TypeParamInquiries =
584 std::conditional_t<KIND == TypeParamInquiry::Result::kind,
585 std::tuple<TypeParamInquiry>, std::tuple<>>;
586 using DescriptorInquiries =
587 std::conditional_t<KIND == DescriptorInquiry::Result::kind,
588 std::tuple<DescriptorInquiry>, std::tuple<>>;
593 common::TupleToVariant<common::CombineTuples<Operations, Conversions, Indices,
594 TypeParamInquiries, DescriptorInquiries, Others>>
604 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
607 using Conversions = std::tuple<Convert<Result, TypeCategory::Integer>,
610 using Operations = std::tuple<Parentheses<Result>,
Negate<Result>,
617 common::TupleToVariant<common::CombineTuples<Operations, Conversions, Others>>
622class Expr<
Type<TypeCategory::Real, KIND>>
627 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
633 using Conversions = std::variant<Convert<Result, TypeCategory::Integer>,
644 common::CombineVariants<Operations, Conversions, Others> u;
648class Expr<
Type<TypeCategory::Complex, KIND>>
652 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
654 using Operations = std::variant<Parentheses<Result>,
Negate<Result>,
662 common::CombineVariants<Operations, Others> u;
665FOR_EACH_INTEGER_KIND(
extern template class Expr, )
666FOR_EACH_UNSIGNED_KIND(extern template class
Expr, )
667FOR_EACH_REAL_KIND(extern template class
Expr, )
668FOR_EACH_COMPLEX_KIND(extern template class
Expr, )
671class Expr<
Type<TypeCategory::Character, KIND>>
675 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
679 std::optional<Expr<SubscriptInteger>> LEN()
const;
687FOR_EACH_CHARACTER_KIND(
extern template class Expr, )
698class Relational : public Operation<Relational<T>, LogicalResult, T, T> {
700 using Result = LogicalResult;
701 using Base = Operation<Relational, LogicalResult, T, T>;
702 using Operand =
typename Base::template Operand<0>;
703 static_assert(Operand::category == TypeCategory::Integer ||
704 Operand::category == TypeCategory::Real ||
705 Operand::category == TypeCategory::Complex ||
706 Operand::category == TypeCategory::Character ||
707 Operand::category == TypeCategory::Unsigned);
708 CLASS_BOILERPLATE(Relational)
711 : Base{a, b}, opr{r} {}
713 : Base{std::move(a), std::move(b)}, opr{r} {}
714 bool operator==(
const Relational &)
const;
715 RelationalOperator opr;
719 using DirectlyComparableTypes = common::CombineTuples<IntegerTypes, RealTypes,
720 ComplexTypes, CharacterTypes, UnsignedTypes>;
723 using Result = LogicalResult;
724 EVALUATE_UNION_CLASS_BOILERPLATE(Relational)
725 static constexpr DynamicType GetType() {
return Result::GetType(); }
727 return common::visit([](
const auto &x) {
return x.Rank(); }, u);
729 static constexpr int Corank() {
return 0; }
730 llvm::raw_ostream &AsFortran(llvm::raw_ostream &o)
const;
731 common::MapTemplate<Relational, DirectlyComparableTypes> u;
734FOR_EACH_INTEGER_KIND(
extern template class Relational, )
735FOR_EACH_UNSIGNED_KIND(extern template class
Relational, )
736FOR_EACH_REAL_KIND(extern template class
Relational, )
737FOR_EACH_CHARACTER_KIND(extern template class
Relational, )
745class Expr<
Type<TypeCategory::Logical, KIND>>
749 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
756 using Relations = std::conditional_t<KIND == LogicalResult::kind,
757 std::tuple<Relational<SomeType>>, std::tuple<>>;
762 common::TupleToVariant<common::CombineTuples<Operations, Relations, Others>>
766FOR_EACH_LOGICAL_KIND(
extern template class Expr, )
782class StructureConstructor {
784 using Result = SomeDerived;
788 StructureConstructor(
790 StructureConstructor(
792 CLASS_BOILERPLATE(StructureConstructor)
794 constexpr Result result()
const {
return result_; }
796 return result_.derivedTypeSpec();
798 StructureConstructorValues &values() {
return values_; }
799 const StructureConstructorValues &values()
const {
return values_; }
801 bool operator==(
const StructureConstructor &)
const;
803 StructureConstructorValues::iterator begin() {
return values_.begin(); }
804 StructureConstructorValues::const_iterator begin()
const {
805 return values_.begin();
807 StructureConstructorValues::iterator end() {
return values_.end(); }
808 StructureConstructorValues::const_iterator end()
const {
809 return values_.end();
813 std::optional<Expr<SomeType>> Find(
const Symbol &)
const;
816 static constexpr int Rank() {
return 0; }
817 static constexpr int Corank() {
return 0; }
819 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
822 std::optional<Expr<SomeType>> CreateParentComponent(
const Symbol &)
const;
824 StructureConstructorValues values_;
830 using Result = SomeDerived;
831 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
841template <TypeCategory CAT>
845 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
847 common::MapTemplate<evaluate::Expr, CategoryTypes<CAT>> u;
852 using Result = SomeCharacter;
853 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
855 std::optional<Expr<SubscriptInteger>> LEN()
const;
856 common::MapTemplate<Expr, CategoryTypes<TypeCategory::Character>> u;
861using CategoryExpression = common::MapTemplate<Expr, SomeCategory>;
867using BOZLiteralConstant =
typename LargestReal::Scalar::Word;
871 constexpr bool operator==(
const NullPointer &)
const {
return true; }
872 static constexpr int Rank() {
return 0; }
873 static constexpr int Corank() {
return 0; }
879using TypelessExpression = std::variant<BOZLiteralConstant,
NullPointer,
887 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
894 template <TypeCategory CAT,
int KIND>
897 template <TypeCategory CAT,
int KIND>
901 template <TypeCategory CAT,
int KIND>
902 Expr &operator=(
const Expr<Type<CAT, KIND>> &x) {
903 u = Expr<SomeKind<CAT>>{x};
907 template <TypeCategory CAT,
int KIND>
908 Expr &operator=(Expr<Type<CAT, KIND>> &&x) {
909 u = Expr<SomeKind<CAT>>{std::move(x)};
914 common::CombineVariants<TypelessExpression, CategoryExpression> u;
924 : lhs(std::move(lhs)), rhs(std::move(rhs)) {}
927 using BoundsSpec = std::vector<Expr<SubscriptInteger>>;
928 using BoundsRemapping =
930 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
934 std::variant<Intrinsic, ProcedureRef, BoundsSpec, BoundsRemapping> u;
939struct GenericExprWrapper {
940 GenericExprWrapper() {}
943 ~GenericExprWrapper();
944 static void Deleter(GenericExprWrapper *);
945 std::optional<Expr<SomeType>> v;
949struct GenericAssignmentWrapper {
950 GenericAssignmentWrapper() {}
951 explicit GenericAssignmentWrapper(
Assignment &&x) : v{std::move(x)} {}
952 explicit GenericAssignmentWrapper(std::optional<Assignment> &&x)
954 ~GenericAssignmentWrapper();
955 static void Deleter(GenericAssignmentWrapper *);
956 std::optional<Assignment> v;
959FOR_EACH_CATEGORY_TYPE(
extern template class Expr, )
965#define INSTANTIATE_EXPRESSION_TEMPLATES \
966 FOR_EACH_INTRINSIC_KIND(template class Expr, ) \
967 FOR_EACH_CATEGORY_TYPE(template class Expr, ) \
968 FOR_EACH_INTEGER_KIND(template class Relational, ) \
969 FOR_EACH_UNSIGNED_KIND(template class Relational, ) \
970 FOR_EACH_REAL_KIND(template class Relational, ) \
971 FOR_EACH_CHARACTER_KIND(template class Relational, ) \
972 template class Relational<SomeType>; \
973 FOR_EACH_TYPE_AND_KIND(template class ExpressionBase, ) \
974 FOR_EACH_INTRINSIC_KIND(template class ArrayConstructorValues, ) \
975 FOR_EACH_INTRINSIC_KIND(template class ArrayConstructor, ) \
976 FOR_EACH_INTRINSIC_KIND(template class ConditionalExpr, )
Definition expression.h:479
Definition expression.h:507
Definition expression.h:921
Definition expression.h:395
Definition constant.h:147
Definition variable.h:381
Definition expression.h:66
Definition expression.h:445
Definition expression.h:698
Definition expression.h:782
Definition char-block.h:28
Definition expression.h:296
Definition expression.h:473
Definition expression.h:926
Definition expression.h:357
Definition expression.h:368
Definition expression.h:211
Definition expression.h:317
Definition expression.h:340
Definition expression.h:437
Definition expression.h:379
Definition expression.h:310
Definition expression.h:247
Definition expression.h:272
Definition expression.h:870
Definition expression.h:229
Definition expression.h:324
Definition expression.h:332
Definition expression.h:286
Definition expression.h:303