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 {
return thenValue().GetType(); }
412 static constexpr int Corank() {
return 0; }
413 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
416 common::CopyableIndirection<Expr<LogicalResult>> condition_;
417 common::CopyableIndirection<Expr<Result>> thenValue_;
418 common::CopyableIndirection<Expr<Result>> elseValue_;
425 using Result = SubscriptInteger;
427 static constexpr int Rank() {
return 0; }
428 static constexpr int Corank() {
return 0; }
432template <
typename RESULT>
class ImpliedDo {
434 using Result = RESULT;
435 using Index = ResultType<ImpliedDoIndex>;
438 : name_{name}, lower_{std::move(lower)}, upper_{std::move(upper)},
439 stride_{std::move(stride)}, values_{std::move(values)} {}
440 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ImpliedDo)
441 bool operator==(
const ImpliedDo &)
const;
444 const Expr<Index> &lower()
const {
return lower_.value(); }
446 const Expr<Index> &upper()
const {
return upper_.value(); }
448 const Expr<Index> &stride()
const {
return stride_.value(); }
451 return values_.value();
456 common::CopyableIndirection<Expr<Index>> lower_, upper_, stride_;
457 common::CopyableIndirection<ArrayConstructorValues<Result>> values_;
461 using Result = RESULT;
466template <
typename RESULT>
class ArrayConstructorValues {
468 using Result = RESULT;
469 using Values = std::vector<ArrayConstructorValue<Result>>;
470 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructorValues)
471 ArrayConstructorValues() {}
473 bool operator==(
const ArrayConstructorValues &)
const;
474 static constexpr int Rank() {
return 1; }
475 static constexpr int Corank() {
return 0; }
476 template <
typename A> common::NoLvalue<A> Push(A &&x) {
477 values_.emplace_back(std::move(x));
480 typename Values::iterator begin() {
return values_.begin(); }
481 typename Values::const_iterator begin()
const {
return values_.begin(); }
482 typename Values::iterator end() {
return values_.end(); }
483 typename Values::const_iterator end()
const {
return values_.end(); }
493template <
typename RESULT>
494class ArrayConstructor :
public ArrayConstructorValues<RESULT> {
496 using Result = RESULT;
497 using Base = ArrayConstructorValues<Result>;
498 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructor)
499 explicit ArrayConstructor(Base &&values) : Base{std::move(values)} {}
500 template <
typename T>
explicit ArrayConstructor(
const Expr<T> &) {}
501 static constexpr Result result() {
return Result{}; }
502 static constexpr DynamicType GetType() {
return Result::GetType(); }
503 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
507class ArrayConstructor<
Type<TypeCategory::Character, KIND>>
508 :
public ArrayConstructorValues<Type<TypeCategory::Character, KIND>> {
511 using Base = ArrayConstructorValues<Result>;
512 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructor)
513 explicit ArrayConstructor(Base &&values) : Base{std::move(values)} {}
514 template <
typename T>
explicit ArrayConstructor(
const Expr<T> &) {}
516 bool operator==(
const ArrayConstructor &)
const;
517 static constexpr Result result() {
return Result{}; }
518 static constexpr DynamicType GetType() {
return Result::GetType(); }
519 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
521 return length_ ? &length_->value() :
nullptr;
525 std::optional<common::CopyableIndirection<Expr<SubscriptInteger>>> length_;
529class ArrayConstructor<SomeDerived>
530 :
public ArrayConstructorValues<SomeDerived> {
532 using Result = SomeDerived;
533 using Base = ArrayConstructorValues<Result>;
534 CLASS_BOILERPLATE(ArrayConstructor)
537 : Base{std::move(v)}, result_{spec} {}
538 template <
typename A>
539 explicit ArrayConstructor(
const A &prototype)
540 : result_{prototype.GetType().value().GetDerivedTypeSpec()} {}
542 bool operator==(
const ArrayConstructor &)
const;
543 constexpr Result result()
const {
return result_; }
544 constexpr DynamicType GetType()
const {
return result_.GetType(); }
545 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
559 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
562 using Conversions = std::tuple<Convert<Result, TypeCategory::Integer>,
565 using Operations = std::tuple<Parentheses<Result>,
Negate<Result>,
568 using Indices = std::conditional_t<KIND == ImpliedDoIndex::Result::kind,
569 std::tuple<ImpliedDoIndex>, std::tuple<>>;
570 using TypeParamInquiries =
571 std::conditional_t<KIND == TypeParamInquiry::Result::kind,
572 std::tuple<TypeParamInquiry>, std::tuple<>>;
573 using DescriptorInquiries =
574 std::conditional_t<KIND == DescriptorInquiry::Result::kind,
575 std::tuple<DescriptorInquiry>, std::tuple<>>;
580 common::TupleToVariant<common::CombineTuples<Operations, Conversions, Indices,
581 TypeParamInquiries, DescriptorInquiries, Others>>
591 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
594 using Conversions = std::tuple<Convert<Result, TypeCategory::Integer>,
597 using Operations = std::tuple<Parentheses<Result>,
Negate<Result>,
604 common::TupleToVariant<common::CombineTuples<Operations, Conversions, Others>>
609class Expr<
Type<TypeCategory::Real, KIND>>
614 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
620 using Conversions = std::variant<Convert<Result, TypeCategory::Integer>,
631 common::CombineVariants<Operations, Conversions, Others> u;
635class Expr<
Type<TypeCategory::Complex, KIND>>
639 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
641 using Operations = std::variant<Parentheses<Result>,
Negate<Result>,
649 common::CombineVariants<Operations, Others> u;
652FOR_EACH_INTEGER_KIND(
extern template class Expr, )
653FOR_EACH_UNSIGNED_KIND(extern template class
Expr, )
654FOR_EACH_REAL_KIND(extern template class
Expr, )
655FOR_EACH_COMPLEX_KIND(extern template class
Expr, )
658class Expr<
Type<TypeCategory::Character, KIND>>
662 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
666 std::optional<Expr<SubscriptInteger>> LEN()
const;
674FOR_EACH_CHARACTER_KIND(
extern template class Expr, )
685class Relational : public Operation<Relational<T>, LogicalResult, T, T> {
687 using Result = LogicalResult;
688 using Base = Operation<Relational, LogicalResult, T, T>;
689 using Operand =
typename Base::template Operand<0>;
690 static_assert(Operand::category == TypeCategory::Integer ||
691 Operand::category == TypeCategory::Real ||
692 Operand::category == TypeCategory::Complex ||
693 Operand::category == TypeCategory::Character ||
694 Operand::category == TypeCategory::Unsigned);
695 CLASS_BOILERPLATE(Relational)
698 : Base{a, b}, opr{r} {}
700 : Base{std::move(a), std::move(b)}, opr{r} {}
701 bool operator==(
const Relational &)
const;
702 RelationalOperator opr;
706 using DirectlyComparableTypes = common::CombineTuples<IntegerTypes, RealTypes,
707 ComplexTypes, CharacterTypes, UnsignedTypes>;
710 using Result = LogicalResult;
711 EVALUATE_UNION_CLASS_BOILERPLATE(Relational)
712 static constexpr DynamicType GetType() {
return Result::GetType(); }
714 return common::visit([](
const auto &x) {
return x.Rank(); }, u);
716 static constexpr int Corank() {
return 0; }
717 llvm::raw_ostream &AsFortran(llvm::raw_ostream &o)
const;
718 common::MapTemplate<Relational, DirectlyComparableTypes> u;
721FOR_EACH_INTEGER_KIND(
extern template class Relational, )
722FOR_EACH_UNSIGNED_KIND(extern template class
Relational, )
723FOR_EACH_REAL_KIND(extern template class
Relational, )
724FOR_EACH_CHARACTER_KIND(extern template class
Relational, )
732class Expr<
Type<TypeCategory::Logical, KIND>>
736 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
743 using Relations = std::conditional_t<KIND == LogicalResult::kind,
744 std::tuple<Relational<SomeType>>, std::tuple<>>;
749 common::TupleToVariant<common::CombineTuples<Operations, Relations, Others>>
753FOR_EACH_LOGICAL_KIND(
extern template class Expr, )
769class StructureConstructor {
771 using Result = SomeDerived;
775 StructureConstructor(
777 StructureConstructor(
779 CLASS_BOILERPLATE(StructureConstructor)
781 constexpr Result result()
const {
return result_; }
783 return result_.derivedTypeSpec();
785 StructureConstructorValues &values() {
return values_; }
786 const StructureConstructorValues &values()
const {
return values_; }
788 bool operator==(
const StructureConstructor &)
const;
790 StructureConstructorValues::iterator begin() {
return values_.begin(); }
791 StructureConstructorValues::const_iterator begin()
const {
792 return values_.begin();
794 StructureConstructorValues::iterator end() {
return values_.end(); }
795 StructureConstructorValues::const_iterator end()
const {
796 return values_.end();
800 std::optional<Expr<SomeType>> Find(
const Symbol &)
const;
803 static constexpr int Rank() {
return 0; }
804 static constexpr int Corank() {
return 0; }
806 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
809 std::optional<Expr<SomeType>> CreateParentComponent(
const Symbol &)
const;
811 StructureConstructorValues values_;
817 using Result = SomeDerived;
818 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
828template <TypeCategory CAT>
832 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
834 common::MapTemplate<evaluate::Expr, CategoryTypes<CAT>> u;
839 using Result = SomeCharacter;
840 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
842 std::optional<Expr<SubscriptInteger>> LEN()
const;
843 common::MapTemplate<Expr, CategoryTypes<TypeCategory::Character>> u;
848using CategoryExpression = common::MapTemplate<Expr, SomeCategory>;
854using BOZLiteralConstant =
typename LargestReal::Scalar::Word;
858 constexpr bool operator==(
const NullPointer &)
const {
return true; }
859 static constexpr int Rank() {
return 0; }
860 static constexpr int Corank() {
return 0; }
866using TypelessExpression = std::variant<BOZLiteralConstant,
NullPointer,
874 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
881 template <TypeCategory CAT,
int KIND>
884 template <TypeCategory CAT,
int KIND>
888 template <TypeCategory CAT,
int KIND>
889 Expr &operator=(
const Expr<Type<CAT, KIND>> &x) {
890 u = Expr<SomeKind<CAT>>{x};
894 template <TypeCategory CAT,
int KIND>
895 Expr &operator=(Expr<Type<CAT, KIND>> &&x) {
896 u = Expr<SomeKind<CAT>>{std::move(x)};
901 common::CombineVariants<TypelessExpression, CategoryExpression> u;
911 : lhs(std::move(lhs)), rhs(std::move(rhs)) {}
914 using BoundsSpec = std::vector<Expr<SubscriptInteger>>;
915 using BoundsRemapping =
917 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
921 std::variant<Intrinsic, ProcedureRef, BoundsSpec, BoundsRemapping> u;
926struct GenericExprWrapper {
927 GenericExprWrapper() {}
930 ~GenericExprWrapper();
931 static void Deleter(GenericExprWrapper *);
932 std::optional<Expr<SomeType>> v;
936struct GenericAssignmentWrapper {
937 GenericAssignmentWrapper() {}
938 explicit GenericAssignmentWrapper(
Assignment &&x) : v{std::move(x)} {}
939 explicit GenericAssignmentWrapper(std::optional<Assignment> &&x)
941 ~GenericAssignmentWrapper();
942 static void Deleter(GenericAssignmentWrapper *);
943 std::optional<Assignment> v;
946FOR_EACH_CATEGORY_TYPE(
extern template class Expr, )
952#define INSTANTIATE_EXPRESSION_TEMPLATES \
953 FOR_EACH_INTRINSIC_KIND(template class Expr, ) \
954 FOR_EACH_CATEGORY_TYPE(template class Expr, ) \
955 FOR_EACH_INTEGER_KIND(template class Relational, ) \
956 FOR_EACH_UNSIGNED_KIND(template class Relational, ) \
957 FOR_EACH_REAL_KIND(template class Relational, ) \
958 FOR_EACH_CHARACTER_KIND(template class Relational, ) \
959 template class Relational<SomeType>; \
960 FOR_EACH_TYPE_AND_KIND(template class ExpressionBase, ) \
961 FOR_EACH_INTRINSIC_KIND(template class ArrayConstructorValues, ) \
962 FOR_EACH_INTRINSIC_KIND(template class ArrayConstructor, ) \
963 FOR_EACH_INTRINSIC_KIND(template class ConditionalExpr, )
Definition expression.h:466
Definition expression.h:494
Definition expression.h:908
Definition expression.h:395
Definition constant.h:147
Definition variable.h:381
Definition expression.h:66
Definition expression.h:432
Definition expression.h:685
Definition expression.h:769
Definition char-block.h:28
Definition expression.h:296
Definition expression.h:460
Definition expression.h:913
Definition expression.h:357
Definition expression.h:368
Definition expression.h:211
Definition expression.h:317
Definition expression.h:340
Definition expression.h:424
Definition expression.h:379
Definition expression.h:310
Definition expression.h:247
Definition expression.h:272
Definition expression.h:857
Definition expression.h:229
Definition expression.h:324
Definition expression.h:332
Definition expression.h:286
Definition expression.h:303