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"
40using common::LogicalOperator;
41using common::RelationalOperator;
62template <
typename A>
using ResultType =
typename std::decay_t<A>::Result;
67 using Result = RESULT;
71#if defined(__APPLE__) && defined(__GNUC__)
73 const Derived &derived()
const;
75 Derived &derived() {
return *
static_cast<Derived *
>(
this); }
76 const Derived &derived()
const {
return *
static_cast<const Derived *
>(
this); }
80 template <
typename A> Derived &operator=(
const A &x) {
81 Derived &d{derived()};
86 template <
typename A> common::IfNoLvalue<Derived &, A> operator=(A &&x) {
87 Derived &d{derived()};
92 std::optional<DynamicType> GetType()
const;
95 std::string AsFortran()
const;
96#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
97 LLVM_DUMP_METHOD
void dump()
const;
99 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
112template <
typename DERIVED,
typename RESULT,
typename... OPERANDS>
117 using OperandTypes = std::tuple<OPERANDS..., std::monostate>;
120 using Derived = DERIVED;
121 using Result = RESULT;
122 static constexpr std::size_t operands{
sizeof...(OPERANDS)};
124 static_assert(IsSpecificIntrinsicType<Result> ||
125 (operands == 1 && std::is_same_v<Result, SomeDerived>));
126 template <
int J>
using Operand = std::tuple_element_t<J, OperandTypes>;
131 using Container = std::conditional_t<operands == 1,
132 common::CopyableIndirection<Expr<Operand<0>>>,
133 std::tuple<common::CopyableIndirection<Expr<OPERANDS>>...>>;
136 CLASS_BOILERPLATE(Operation)
137 explicit Operation(
const Expr<OPERANDS> &...x) : operand_{x...} {}
138 explicit Operation(
Expr<OPERANDS> &&...x) : operand_{std::move(x)...} {}
140 Derived &derived() {
return *
static_cast<Derived *
>(
this); }
141 const Derived &derived()
const {
return *
static_cast<const Derived *
>(
this); }
149 if constexpr (operands == 1) {
150 static_assert(J == 0);
151 return operand_.value();
153 return std::get<J>(operand_).value();
157 if constexpr (operands == 1) {
158 static_assert(J == 0);
159 return operand_.value();
161 return std::get<J>(operand_).value();
168 std::conditional_t<(operands > 1),
Expr<Operand<1>> &,
void> right() {
169 if constexpr (operands > 1) {
173 std::conditional_t<(operands > 1),
const Expr<Operand<1>> &,
void>
175 if constexpr (operands > 1) {
180 static constexpr std::conditional_t<Result::category != TypeCategory::Derived,
181 std::optional<DynamicType>,
void>
183 return Result::GetType();
186 int rank{left().Rank()};
187 if constexpr (operands > 1) {
188 return std::max(rank, right().Rank());
193 static constexpr int Corank() {
return 0; }
195 bool operator==(
const Operation &that)
const {
196 return operand_ == that.operand_;
199 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
209template <
typename TO, TypeCategory FROMCAT = TO::category>
210struct Convert :
public Operation<Convert<TO, FROMCAT>, TO, SomeKind<FROMCAT>> {
214 ((TO::category == TypeCategory::Integer ||
215 TO::category == TypeCategory::Real ||
216 TO::category == TypeCategory::Unsigned) &&
217 (FROMCAT == TypeCategory::Integer || FROMCAT == TypeCategory::Real ||
218 FROMCAT == TypeCategory::Unsigned)) ||
219 TO::category == FROMCAT);
222 using Base = Operation<Convert, Result, Operand>;
224 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
231 using Base = Operation<Parentheses, A, A>;
237 :
public Operation<Parentheses<SomeDerived>, SomeDerived, SomeDerived> {
239 using Result = SomeDerived;
240 using Operand = SomeDerived;
241 using Base = Operation<Parentheses, SomeDerived, SomeDerived>;
246template <
typename A>
struct Negate :
public Operation<Negate<A>, A, A> {
249 using Base = Operation<Negate, A, A>;
254struct ComplexComponent
255 :
public Operation<ComplexComponent<KIND>, Type<TypeCategory::Real, KIND>,
256 Type<TypeCategory::Complex, KIND>> {
259 using Base = Operation<ComplexComponent, Result, Operand>;
260 CLASS_BOILERPLATE(ComplexComponent)
262 : Base{x}, isImaginaryPart{isImaginary} {}
264 : Base{std::move(x)}, isImaginaryPart{isImaginary} {}
266 bool isImaginaryPart{
true};
270struct Not :
public Operation<Not<KIND>, Type<TypeCategory::Logical, KIND>,
271 Type<TypeCategory::Logical, KIND>> {
273 using Operand = Result;
274 using Base = Operation<Not, Result, Operand>;
284 :
public Operation<SetLength<KIND>, Type<TypeCategory::Character, KIND>,
285 Type<TypeCategory::Character, KIND>, SubscriptInteger> {
287 using CharacterOperand = Result;
288 using LengthOperand = SubscriptInteger;
289 using Base = Operation<SetLength, Result, CharacterOperand, LengthOperand>;
295template <
typename A>
struct Add :
public Operation<Add<A>, A, A, A> {
298 using Base = Operation<Add, A, A, A>;
302template <
typename A>
struct Subtract :
public Operation<Subtract<A>, A, A, A> {
305 using Base = Operation<Subtract, A, A, A>;
309template <
typename A>
struct Multiply :
public Operation<Multiply<A>, A, A, A> {
312 using Base = Operation<Multiply, A, A, A>;
316template <
typename A>
struct Divide :
public Operation<Divide<A>, A, A, A> {
319 using Base = Operation<Divide, A, A, A>;
323template <
typename A>
struct Power :
public Operation<Power<A>, A, A, A> {
326 using Base = Operation<Power, A, A, A>;
332 using Base = Operation<RealToIntPower, A, A, SomeInteger>;
334 using BaseOperand = A;
335 using ExponentOperand = SomeInteger;
339template <
typename A>
struct Extremum :
public Operation<Extremum<A>, A, A, A> {
342 using Base = Operation<Extremum, A, A, A>;
343 CLASS_BOILERPLATE(Extremum)
345 : Base{x, y}, ordering{ord} {}
347 : Base{std::move(x), std::move(y)}, ordering{ord} {}
348 bool operator==(
const Extremum &)
const;
349 Ordering ordering{Ordering::Greater};
354 :
public Operation<ComplexConstructor<KIND>,
355 Type<TypeCategory::Complex, KIND>, Type<TypeCategory::Real, KIND>,
356 Type<TypeCategory::Real, KIND>> {
359 using Base = Operation<ComplexConstructor, Result, Operand, Operand>;
365 :
public Operation<Concat<KIND>, Type<TypeCategory::Character, KIND>,
366 Type<TypeCategory::Character, KIND>,
367 Type<TypeCategory::Character, KIND>> {
369 using Operand = Result;
370 using Base = Operation<Concat, Result, Operand, Operand>;
375struct LogicalOperation
376 :
public Operation<LogicalOperation<KIND>,
377 Type<TypeCategory::Logical, KIND>, Type<TypeCategory::Logical, KIND>,
378 Type<TypeCategory::Logical, KIND>> {
380 using Operand = Result;
381 using Base = Operation<LogicalOperation, Result, Operand, Operand>;
382 CLASS_BOILERPLATE(LogicalOperation)
385 : Base{x, y}, logicalOperator{opr} {}
387 : Base{std::move(x), std::move(y)}, logicalOperator{opr} {}
388 bool operator==(
const LogicalOperation &)
const;
389 LogicalOperator logicalOperator;
394template <
typename T>
class ConditionalExpr {
397 CLASS_BOILERPLATE(ConditionalExpr)
400 : condition_{std::move(cond)}, thenValue_{std::move(thenVal)},
401 elseValue_{std::move(elseVal)} {}
402 bool operator==(
const ConditionalExpr &)
const;
405 Expr<Result> &thenValue() {
return thenValue_.value(); }
406 const Expr<Result> &thenValue()
const {
return thenValue_.value(); }
407 Expr<Result> &elseValue() {
return elseValue_.value(); }
408 const Expr<Result> &elseValue()
const {
return elseValue_.value(); }
409 int Rank()
const {
return thenValue().Rank(); }
410 std::optional<DynamicType> GetType()
const {
411 const auto thenType{thenValue().GetType()};
412 if constexpr (T::category == TypeCategory::Derived) {
414 if (thenType && !thenType->IsPolymorphic()) {
415 if (
const auto elseType{elseValue().GetType()}) {
416 if (elseType->IsPolymorphic()) {
424 static constexpr int Corank() {
return 0; }
425 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
428 common::CopyableIndirection<Expr<LogicalResult>> condition_;
429 common::CopyableIndirection<Expr<Result>> thenValue_;
430 common::CopyableIndirection<Expr<Result>> elseValue_;
437 using Result = SubscriptInteger;
439 static constexpr int Rank() {
return 0; }
440 static constexpr int Corank() {
return 0; }
444template <
typename RESULT>
class ImpliedDo {
446 using Result = RESULT;
447 using Index = ResultType<ImpliedDoIndex>;
450 : name_{name}, lower_{std::move(lower)}, upper_{std::move(upper)},
451 stride_{std::move(stride)}, values_{std::move(values)} {}
452 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ImpliedDo)
453 bool operator==(
const ImpliedDo &)
const;
456 const Expr<Index> &lower()
const {
return lower_.value(); }
458 const Expr<Index> &upper()
const {
return upper_.value(); }
460 const Expr<Index> &stride()
const {
return stride_.value(); }
463 return values_.value();
468 common::CopyableIndirection<Expr<Index>> lower_, upper_, stride_;
469 common::CopyableIndirection<ArrayConstructorValues<Result>> values_;
473 using Result = RESULT;
478template <
typename RESULT>
class ArrayConstructorValues {
480 using Result = RESULT;
481 using Values = std::vector<ArrayConstructorValue<Result>>;
482 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructorValues)
483 ArrayConstructorValues() {}
485 bool operator==(
const ArrayConstructorValues &)
const;
486 static constexpr int Rank() {
return 1; }
487 static constexpr int Corank() {
return 0; }
488 template <
typename A> common::NoLvalue<A> Push(A &&x) {
489 values_.emplace_back(std::move(x));
492 typename Values::iterator begin() {
return values_.begin(); }
493 typename Values::const_iterator begin()
const {
return values_.begin(); }
494 typename Values::iterator end() {
return values_.end(); }
495 typename Values::const_iterator end()
const {
return values_.end(); }
505template <
typename RESULT>
506class ArrayConstructor :
public ArrayConstructorValues<RESULT> {
508 using Result = RESULT;
509 using Base = ArrayConstructorValues<Result>;
510 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructor)
511 explicit ArrayConstructor(Base &&values) : Base{std::move(values)} {}
512 template <
typename T>
explicit ArrayConstructor(
const Expr<T> &) {}
513 static constexpr Result result() {
return Result{}; }
514 static constexpr DynamicType GetType() {
return Result::GetType(); }
515 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
519class ArrayConstructor<
Type<TypeCategory::Character, KIND>>
520 :
public ArrayConstructorValues<Type<TypeCategory::Character, KIND>> {
523 using Base = ArrayConstructorValues<Result>;
524 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructor)
525 explicit ArrayConstructor(Base &&values) : Base{std::move(values)} {}
526 template <
typename T>
explicit ArrayConstructor(
const Expr<T> &) {}
528 bool operator==(
const ArrayConstructor &)
const;
529 static constexpr Result result() {
return Result{}; }
530 static constexpr DynamicType GetType() {
return Result::GetType(); }
531 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
533 return length_ ? &length_->value() :
nullptr;
537 std::optional<common::CopyableIndirection<Expr<SubscriptInteger>>> length_;
541class ArrayConstructor<SomeDerived>
542 :
public ArrayConstructorValues<SomeDerived> {
544 using Result = SomeDerived;
545 using Base = ArrayConstructorValues<Result>;
546 CLASS_BOILERPLATE(ArrayConstructor)
549 : Base{std::move(v)}, result_{spec} {}
550 template <
typename A>
551 explicit ArrayConstructor(
const A &prototype)
552 : result_{prototype.GetType().value().GetDerivedTypeSpec()} {}
554 bool operator==(
const ArrayConstructor &)
const;
555 constexpr Result result()
const {
return result_; }
556 constexpr DynamicType GetType()
const {
return result_.GetType(); }
557 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
571 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
574 using Conversions = std::tuple<Convert<Result, TypeCategory::Integer>,
577 using Operations = std::tuple<Parentheses<Result>,
Negate<Result>,
580 using Indices = std::conditional_t<KIND == ImpliedDoIndex::Result::kind,
581 std::tuple<ImpliedDoIndex>, std::tuple<>>;
582 using TypeParamInquiries =
583 std::conditional_t<KIND == TypeParamInquiry::Result::kind,
584 std::tuple<TypeParamInquiry>, std::tuple<>>;
585 using DescriptorInquiries =
586 std::conditional_t<KIND == DescriptorInquiry::Result::kind,
587 std::tuple<DescriptorInquiry>, std::tuple<>>;
592 common::TupleToVariant<common::CombineTuples<Operations, Conversions, Indices,
593 TypeParamInquiries, DescriptorInquiries, Others>>
603 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
606 using Conversions = std::tuple<Convert<Result, TypeCategory::Integer>,
609 using Operations = std::tuple<Parentheses<Result>,
Negate<Result>,
616 common::TupleToVariant<common::CombineTuples<Operations, Conversions, Others>>
621class Expr<
Type<TypeCategory::Real, KIND>>
626 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
632 using Conversions = std::variant<Convert<Result, TypeCategory::Integer>,
643 common::CombineVariants<Operations, Conversions, Others> u;
647class Expr<
Type<TypeCategory::Complex, KIND>>
651 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
653 using Operations = std::variant<Parentheses<Result>,
Negate<Result>,
661 common::CombineVariants<Operations, Others> u;
664FOR_EACH_INTEGER_KIND(
extern template class Expr, )
665FOR_EACH_UNSIGNED_KIND(extern template class
Expr, )
666FOR_EACH_REAL_KIND(extern template class
Expr, )
667FOR_EACH_COMPLEX_KIND(extern template class
Expr, )
670class Expr<
Type<TypeCategory::Character, KIND>>
674 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
678 std::optional<Expr<SubscriptInteger>> LEN()
const;
686FOR_EACH_CHARACTER_KIND(
extern template class Expr, )
697class Relational : public Operation<Relational<T>, LogicalResult, T, T> {
699 using Result = LogicalResult;
700 using Base = Operation<Relational, LogicalResult, T, T>;
701 using Operand =
typename Base::template Operand<0>;
702 static_assert(Operand::category == TypeCategory::Integer ||
703 Operand::category == TypeCategory::Real ||
704 Operand::category == TypeCategory::Complex ||
705 Operand::category == TypeCategory::Character ||
706 Operand::category == TypeCategory::Unsigned);
707 CLASS_BOILERPLATE(Relational)
710 : Base{a, b}, opr{r} {}
712 : Base{std::move(a), std::move(b)}, opr{r} {}
713 bool operator==(
const Relational &)
const;
714 RelationalOperator opr;
718 using DirectlyComparableTypes = common::CombineTuples<IntegerTypes, RealTypes,
719 ComplexTypes, CharacterTypes, UnsignedTypes>;
722 using Result = LogicalResult;
723 EVALUATE_UNION_CLASS_BOILERPLATE(Relational)
724 static constexpr DynamicType GetType() {
return Result::GetType(); }
726 return common::visit([](
const auto &x) {
return x.Rank(); }, u);
728 static constexpr int Corank() {
return 0; }
729 llvm::raw_ostream &AsFortran(llvm::raw_ostream &o)
const;
730 common::MapTemplate<Relational, DirectlyComparableTypes> u;
733FOR_EACH_INTEGER_KIND(
extern template class Relational, )
734FOR_EACH_UNSIGNED_KIND(extern template class
Relational, )
735FOR_EACH_REAL_KIND(extern template class
Relational, )
736FOR_EACH_CHARACTER_KIND(extern template class
Relational, )
744class Expr<
Type<TypeCategory::Logical, KIND>>
748 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
755 using Relations = std::conditional_t<KIND == LogicalResult::kind,
756 std::tuple<Relational<SomeType>>, std::tuple<>>;
761 common::TupleToVariant<common::CombineTuples<Operations, Relations, Others>>
765FOR_EACH_LOGICAL_KIND(
extern template class Expr, )
781class StructureConstructor {
783 using Result = SomeDerived;
787 StructureConstructor(
789 StructureConstructor(
791 CLASS_BOILERPLATE(StructureConstructor)
793 constexpr Result result()
const {
return result_; }
795 return result_.derivedTypeSpec();
797 StructureConstructorValues &values() {
return values_; }
798 const StructureConstructorValues &values()
const {
return values_; }
800 bool operator==(
const StructureConstructor &)
const;
802 StructureConstructorValues::iterator begin() {
return values_.begin(); }
803 StructureConstructorValues::const_iterator begin()
const {
804 return values_.begin();
806 StructureConstructorValues::iterator end() {
return values_.end(); }
807 StructureConstructorValues::const_iterator end()
const {
808 return values_.end();
812 std::optional<Expr<SomeType>> Find(
const Symbol &)
const;
815 static constexpr int Rank() {
return 0; }
816 static constexpr int Corank() {
return 0; }
818 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
821 std::optional<Expr<SomeType>> CreateParentComponent(
const Symbol &)
const;
823 StructureConstructorValues values_;
829 using Result = SomeDerived;
830 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
840template <TypeCategory CAT>
844 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
846 common::MapTemplate<evaluate::Expr, CategoryTypes<CAT>> u;
851 using Result = SomeCharacter;
852 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
854 std::optional<Expr<SubscriptInteger>> LEN()
const;
855 common::MapTemplate<Expr, CategoryTypes<TypeCategory::Character>> u;
860using CategoryExpression = common::MapTemplate<Expr, SomeCategory>;
866using BOZLiteralConstant =
typename LargestReal::Scalar::Word;
870 constexpr bool operator==(
const NullPointer &)
const {
return true; }
871 static constexpr int Rank() {
return 0; }
872 static constexpr int Corank() {
return 0; }
878using TypelessExpression = std::variant<BOZLiteralConstant,
NullPointer,
886 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
893 template <TypeCategory CAT,
int KIND>
896 template <TypeCategory CAT,
int KIND>
900 template <TypeCategory CAT,
int KIND>
901 Expr &operator=(
const Expr<Type<CAT, KIND>> &x) {
902 u = Expr<SomeKind<CAT>>{x};
906 template <TypeCategory CAT,
int KIND>
907 Expr &operator=(Expr<Type<CAT, KIND>> &&x) {
908 u = Expr<SomeKind<CAT>>{std::move(x)};
913 common::CombineVariants<TypelessExpression, CategoryExpression> u;
923 : lhs(std::move(lhs)), rhs(std::move(rhs)) {}
926 using BoundsSpec = std::vector<Expr<SubscriptInteger>>;
927 using BoundsRemapping =
929 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
933 std::variant<Intrinsic, ProcedureRef, BoundsSpec, BoundsRemapping> u;
938struct GenericExprWrapper {
939 GenericExprWrapper() {}
942 ~GenericExprWrapper();
943 static void Deleter(GenericExprWrapper *);
944 std::optional<Expr<SomeType>> v;
948struct GenericAssignmentWrapper {
949 GenericAssignmentWrapper() {}
950 explicit GenericAssignmentWrapper(
Assignment &&x) : v{std::move(x)} {}
951 explicit GenericAssignmentWrapper(std::optional<Assignment> &&x)
953 ~GenericAssignmentWrapper();
954 static void Deleter(GenericAssignmentWrapper *);
955 std::optional<Assignment> v;
958FOR_EACH_CATEGORY_TYPE(
extern template class Expr, )
964#define INSTANTIATE_EXPRESSION_TEMPLATES \
965 FOR_EACH_INTRINSIC_KIND(template class Expr, ) \
966 FOR_EACH_CATEGORY_TYPE(template class Expr, ) \
967 FOR_EACH_INTEGER_KIND(template class Relational, ) \
968 FOR_EACH_UNSIGNED_KIND(template class Relational, ) \
969 FOR_EACH_REAL_KIND(template class Relational, ) \
970 FOR_EACH_CHARACTER_KIND(template class Relational, ) \
971 template class Relational<SomeType>; \
972 FOR_EACH_TYPE_AND_KIND(template class ExpressionBase, ) \
973 FOR_EACH_INTRINSIC_KIND(template class ArrayConstructorValues, ) \
974 FOR_EACH_INTRINSIC_KIND(template class ArrayConstructor, ) \
975 FOR_EACH_INTRINSIC_KIND(template class ConditionalExpr, )
Definition expression.h:478
Definition expression.h:506
Definition expression.h:920
Definition expression.h:394
Definition constant.h:147
Definition variable.h:381
Definition expression.h:65
Definition expression.h:444
Definition expression.h:697
Definition expression.h:781
Definition char-block.h:26
Definition expression.h:295
Definition expression.h:472
Definition expression.h:925
Definition expression.h:356
Definition expression.h:367
Definition expression.h:210
Definition expression.h:316
Definition expression.h:339
Definition expression.h:436
Definition expression.h:378
Definition expression.h:309
Definition expression.h:246
Definition expression.h:271
Definition expression.h:869
Definition expression.h:228
Definition expression.h:323
Definition expression.h:331
Definition expression.h:285
Definition expression.h:302