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;
397 using Result = SubscriptInteger;
399 static constexpr int Rank() {
return 0; }
400 static constexpr int Corank() {
return 0; }
404template <
typename RESULT>
class ImpliedDo {
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();
428 common::CopyableIndirection<Expr<Index>> lower_, upper_, stride_;
429 common::CopyableIndirection<ArrayConstructorValues<Result>> values_;
433 using Result = RESULT;
438template <
typename RESULT>
class ArrayConstructorValues {
440 using Result = RESULT;
441 using Values = std::vector<ArrayConstructorValue<Result>>;
442 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructorValues)
443 ArrayConstructorValues() {}
445 bool operator==(
const ArrayConstructorValues &)
const;
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>
466class ArrayConstructor :
public ArrayConstructorValues<RESULT> {
468 using Result = RESULT;
469 using Base = ArrayConstructorValues<Result>;
470 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructor)
471 explicit ArrayConstructor(Base &&values) : Base{std::move(values)} {}
472 template <
typename T>
explicit ArrayConstructor(
const Expr<T> &) {}
473 static constexpr Result result() {
return Result{}; }
474 static constexpr DynamicType GetType() {
return Result::GetType(); }
475 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
479class ArrayConstructor<
Type<TypeCategory::Character, KIND>>
480 :
public ArrayConstructorValues<Type<TypeCategory::Character, KIND>> {
483 using Base = ArrayConstructorValues<Result>;
484 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructor)
485 explicit ArrayConstructor(Base &&values) : Base{std::move(values)} {}
486 template <
typename T>
explicit ArrayConstructor(
const Expr<T> &) {}
488 bool operator==(
const ArrayConstructor &)
const;
489 static constexpr Result result() {
return Result{}; }
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_;
501class ArrayConstructor<SomeDerived>
502 :
public ArrayConstructorValues<SomeDerived> {
504 using Result = SomeDerived;
505 using Base = ArrayConstructorValues<Result>;
506 CLASS_BOILERPLATE(ArrayConstructor)
509 : Base{std::move(v)}, result_{spec} {}
510 template <
typename A>
511 explicit ArrayConstructor(
const A &prototype)
512 : result_{prototype.GetType().value().GetDerivedTypeSpec()} {}
514 bool operator==(
const ArrayConstructor &)
const;
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>,
569 using Operations = std::tuple<Parentheses<Result>,
Negate<Result>,
576 common::TupleToVariant<common::CombineTuples<Operations, Conversions, Others>>
581class Expr<
Type<TypeCategory::Real, KIND>>
586 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
592 using Conversions = std::variant<Convert<Result, TypeCategory::Integer>,
602 common::CombineVariants<Operations, Conversions, Others> u;
606class Expr<
Type<TypeCategory::Complex, KIND>>
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, )
629class Expr<
Type<TypeCategory::Character, KIND>>
633 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
637 std::optional<Expr<SubscriptInteger>> LEN()
const;
645FOR_EACH_CHARACTER_KIND(
extern template class Expr, )
656class Relational : public Operation<Relational<T>, LogicalResult, T, T> {
658 using Result = LogicalResult;
659 using Base = Operation<Relational, LogicalResult, T, T>;
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);
666 CLASS_BOILERPLATE(Relational)
669 : Base{a, b}, opr{r} {}
671 : Base{std::move(a), std::move(b)}, opr{r} {}
672 bool operator==(
const Relational &)
const;
673 RelationalOperator opr;
677 using DirectlyComparableTypes = common::CombineTuples<IntegerTypes, RealTypes,
678 ComplexTypes, CharacterTypes, UnsignedTypes>;
681 using Result = LogicalResult;
682 EVALUATE_UNION_CLASS_BOILERPLATE(Relational)
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, )
703class Expr<
Type<TypeCategory::Logical, KIND>>
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, )
740class StructureConstructor {
742 using Result = SomeDerived;
746 StructureConstructor(
748 StructureConstructor(
750 CLASS_BOILERPLATE(StructureConstructor)
752 constexpr Result result()
const {
return result_; }
754 return result_.derivedTypeSpec();
756 StructureConstructorValues &values() {
return values_; }
757 const StructureConstructorValues &values()
const {
return values_; }
759 bool operator==(
const StructureConstructor &)
const;
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_;
788 using Result = SomeDerived;
789 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
798template <TypeCategory CAT>
802 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
804 common::MapTemplate<evaluate::Expr, CategoryTypes<CAT>> u;
809 using Result = SomeCharacter;
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>
859 Expr &operator=(
const Expr<Type<CAT, KIND>> &x) {
860 u = Expr<SomeKind<CAT>>{x};
864 template <TypeCategory CAT,
int KIND>
865 Expr &operator=(Expr<Type<CAT, KIND>> &&x) {
866 u = Expr<SomeKind<CAT>>{std::move(x)};
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;
896struct GenericExprWrapper {
897 GenericExprWrapper() {}
900 ~GenericExprWrapper();
901 static void Deleter(GenericExprWrapper *);
902 std::optional<Expr<SomeType>> v;
906struct GenericAssignmentWrapper {
907 GenericAssignmentWrapper() {}
908 explicit GenericAssignmentWrapper(
Assignment &&x) : v{std::move(x)} {}
909 explicit GenericAssignmentWrapper(std::optional<Assignment> &&x)
911 ~GenericAssignmentWrapper();
912 static void Deleter(GenericAssignmentWrapper *);
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 expression.h:438
Definition expression.h:466
Definition expression.h:878
Definition constant.h:147
Definition variable.h:377
Definition expression.h:66
Definition expression.h:404
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:357
Definition expression.h:368
Definition expression.h:211
Definition expression.h:317
Definition expression.h:340
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