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;
60template <
typename A>
using ResultType =
typename std::decay_t<A>::Result;
61template <
typename A>
constexpr int ResultKind = std::decay_t<A>::kind();
66 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>;
129 constexpr int kind()
const {
return kind_; }
134 using Container = std::conditional_t<operands == 1,
135 common::CopyableIndirection<Expr<Operand<0>>>,
136 std::tuple<common::CopyableIndirection<Expr<OPERANDS>>...>>;
139 CLASS_BOILERPLATE(Operation)
141 : kind_{kind}, operand_{x...} {
142 CHECK_KIND(kind, RESULT);
145 : kind_{kind}, operand_{std::move(x)...} {
146 CHECK_KIND(kind, RESULT);
149 Derived &derived() {
return *
static_cast<Derived *
>(
this); }
150 const Derived &derived()
const {
return *
static_cast<const Derived *
>(
this); }
158 if constexpr (operands == 1) {
159 static_assert(J == 0);
160 return operand_.value();
162 return std::get<J>(operand_).value();
166 if constexpr (operands == 1) {
167 static_assert(J == 0);
168 return operand_.value();
170 return std::get<J>(operand_).value();
177 std::conditional_t<(operands > 1),
Expr<Operand<1>> &,
void> right() {
178 if constexpr (operands > 1) {
182 std::conditional_t<(operands > 1),
const Expr<Operand<1>> &,
void>
184 if constexpr (operands > 1) {
189 constexpr std::optional<DynamicType> GetType()
const {
193 int rank{left().Rank()};
194 if constexpr (operands > 1) {
195 return std::max(rank, right().Rank());
200 static constexpr int Corank() {
return 0; }
202 bool operator==(
const Operation &that)
const {
203 return kind() == that.kind() && operand_ == that.operand_;
206 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
217template <
typename TO, TypeCategory FROMCAT = TO::category>
218struct Convert :
public Operation<Convert<TO, FROMCAT>, TO, SomeKind<FROMCAT>> {
222 ((TO::category == TypeCategory::Integer ||
223 TO::category == TypeCategory::Real ||
224 TO::category == TypeCategory::Unsigned) &&
225 (FROMCAT == TypeCategory::Integer || FROMCAT == TypeCategory::Real ||
226 FROMCAT == TypeCategory::Unsigned)) ||
227 TO::category == FROMCAT);
230 using Base = Operation<Convert, Result, Operand>;
233 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
237struct Parentheses :
public Operation<Parentheses<A>, A, A> {
240 using Base = Operation<Parentheses, A, A>;
243 explicit Parentheses(
const Expr<A> &x) : Base{x.kind(), x} {}
244 explicit Parentheses(
Expr<A> &&x) : Base{x.kind(), std::move(x)} {}
248struct Parentheses<SomeDerived>
249 :
public Operation<Parentheses<SomeDerived>, SomeDerived, SomeDerived> {
251 using Result = SomeDerived;
252 using Operand = SomeDerived;
253 using Base = Operation<Parentheses, SomeDerived, SomeDerived>;
261template <
typename A>
struct Negate :
public Operation<Negate<A>, A, A> {
264 using Base = Operation<Negate, A, A>;
267 explicit Negate(
const Expr<A> &x) : Base{x.kind(), x} {}
268 explicit Negate(
Expr<A> &&x) : Base{x.kind(), std::move(x)} {}
271struct ComplexComponent
272 :
public Operation<ComplexComponent, Type<TypeCategory::Real>,
273 Type<TypeCategory::Complex>> {
276 using Base = Operation<ComplexComponent, Result, Operand>;
277 CLASS_BOILERPLATE(ComplexComponent)
281 bool isImaginaryPart{
true};
284struct Not :
public Operation<Not, Type<TypeCategory::Logical>,
285 Type<TypeCategory::Logical>> {
287 using Operand = Result;
288 using Base = Operation<Not, Result, Operand>;
296struct SetLength :
public Operation<SetLength, Type<TypeCategory::Character>,
297 Type<TypeCategory::Character>, SubscriptInteger> {
299 using CharacterOperand = Result;
300 using LengthOperand = SubscriptInteger;
301 using Base = Operation<SetLength, Result, CharacterOperand, LengthOperand>;
307template <
typename A>
struct Add :
public Operation<Add<A>, A, A, A> {
310 using Base = Operation<Add, A, A, A>;
314template <
typename A>
struct Subtract :
public Operation<Subtract<A>, A, A, A> {
317 using Base = Operation<Subtract, A, A, A>;
321template <
typename A>
struct Multiply :
public Operation<Multiply<A>, A, A, A> {
324 using Base = Operation<Multiply, A, A, A>;
328template <
typename A>
struct Divide :
public Operation<Divide<A>, A, A, A> {
331 using Base = Operation<Divide, A, A, A>;
335template <
typename A>
struct Power :
public Operation<Power<A>, A, A, A> {
338 using Base = Operation<Power, A, A, A>;
344 using Base = Operation<RealToIntPower, A, A, SomeInteger>;
346 using BaseOperand = A;
347 using ExponentOperand = SomeInteger;
351template <
typename A>
struct Extremum :
public Operation<Extremum<A>, A, A, A> {
354 using Base = Operation<Extremum, A, A, A>;
355 CLASS_BOILERPLATE(Extremum)
357 : Base{x.kind(), x, y}, ordering{ord} {
358 CHECK(x.kind() == y.kind());
361 : Base{x.kind(), std::move(x), std::move(y)}, ordering{ord} {
362 CHECK(this->left().kind() == this->right().kind());
364 bool operator==(
const Extremum &)
const;
365 Ordering ordering{Ordering::Greater};
368struct ComplexConstructor
369 :
public Operation<ComplexConstructor, Type<TypeCategory::Complex>,
370 Type<TypeCategory::Real>, Type<TypeCategory::Real>> {
373 using Base = Operation<ComplexConstructor, Result, Operand, Operand>;
383 :
public Operation<Concat, Type<TypeCategory::Character>,
384 Type<TypeCategory::Character>, Type<TypeCategory::Character>> {
386 using Operand = Result;
387 using Base = Operation<Concat, Result, Operand, Operand>;
396struct LogicalOperation
397 :
public Operation<LogicalOperation, Type<TypeCategory::Logical>,
398 Type<TypeCategory::Logical>, Type<TypeCategory::Logical>> {
400 using Operand = Result;
401 using Base = Operation<LogicalOperation, Result, Operand, Operand>;
402 CLASS_BOILERPLATE(LogicalOperation)
406 bool operator==(
const LogicalOperation &)
const;
407 LogicalOperator logicalOperator;
412template <
typename T>
class ConditionalExpr {
416 constexpr int kind()
const {
return kind_; }
418 CLASS_BOILERPLATE(ConditionalExpr)
421 : kind_{thenVal.kind()}, condition_{std::move(cond)},
422 thenValue_{std::move(thenVal)}, elseValue_{std::move(elseVal)} {
423 CHECK_KIND(kind(), Result);
424 CHECK(thenValue().kind() == elseValue().kind());
426 bool operator==(
const ConditionalExpr &)
const;
429 Expr<Result> &thenValue() {
return thenValue_.value(); }
430 const Expr<Result> &thenValue()
const {
return thenValue_.value(); }
431 Expr<Result> &elseValue() {
return elseValue_.value(); }
432 const Expr<Result> &elseValue()
const {
return elseValue_.value(); }
433 int Rank()
const {
return thenValue().Rank(); }
434 std::optional<DynamicType> GetType()
const {
435 const auto thenType{thenValue().GetType()};
436 if constexpr (T::category == TypeCategory::Derived) {
438 if (thenType && !thenType->IsPolymorphic()) {
439 if (
const auto elseType{elseValue().GetType()}) {
440 if (elseType->IsPolymorphic()) {
448 static constexpr int Corank() {
return 0; }
449 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
453 common::CopyableIndirection<Expr<LogicalResult>> condition_;
454 common::CopyableIndirection<Expr<Result>> thenValue_;
455 common::CopyableIndirection<Expr<Result>> elseValue_;
462 using Result = SubscriptInteger;
465 static constexpr int kind() {
return SubscriptIntegerKind; }
468 return {TypeCategory::Integer, kind()};
470 static constexpr int Rank() {
return 0; }
471 static constexpr int Corank() {
return 0; }
475template <
typename RESULT>
class ImpliedDo {
477 using Result = RESULT;
478 using Index = ResultType<ImpliedDoIndex>;
481 : name_{name}, lower_{std::move(lower)}, upper_{std::move(upper)},
482 stride_{std::move(stride)}, values_{std::move(values)} {}
483 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ImpliedDo)
484 bool operator==(
const ImpliedDo &)
const;
487 const Expr<Index> &lower()
const {
return lower_.value(); }
489 const Expr<Index> &upper()
const {
return upper_.value(); }
491 const Expr<Index> &stride()
const {
return stride_.value(); }
494 return values_.value();
499 common::CopyableIndirection<Expr<Index>> lower_, upper_, stride_;
500 common::CopyableIndirection<ArrayConstructorValues<Result>> values_;
504 using Result = RESULT;
509template <
typename RESULT>
class ArrayConstructorValues {
511 using Result = RESULT;
512 using Values = std::vector<ArrayConstructorValue<Result>>;
513 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructorValues)
514 ArrayConstructorValues() {}
516 bool operator==(
const ArrayConstructorValues &)
const;
517 static constexpr int Rank() {
return 1; }
518 static constexpr int Corank() {
return 0; }
519 template <
typename A> common::NoLvalue<A> Push(A &&x) {
520 values_.emplace_back(std::move(x));
523 typename Values::iterator begin() {
return values_.begin(); }
524 typename Values::const_iterator begin()
const {
return values_.begin(); }
525 typename Values::iterator end() {
return values_.end(); }
526 typename Values::const_iterator end()
const {
return values_.end(); }
536template <
typename RESULT>
537class ArrayConstructor :
public ArrayConstructorValues<RESULT> {
539 using Result = RESULT;
540 using Base = ArrayConstructorValues<Result>;
542 constexpr int kind()
const {
return kind_; }
544 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructor)
545 explicit ArrayConstructor(
int kind, Base &&values)
546 : Base{std::move(values)}, kind_{kind} {
547 CHECK_KIND(kind, RESULT);
549 template <
typename T>
550 explicit ArrayConstructor(
int kind,
const Expr<T> &) : kind_{kind} {
551 CHECK_KIND(kind, RESULT);
553 static constexpr Result result(
int kind) {
return Result{kind}; }
554 DynamicType GetType()
const {
return {Result::category, kind_}; }
555 bool operator==(
const ArrayConstructor &that)
const {
556 return kind() == that.kind() && Base::operator==(that);
558 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
565class ArrayConstructor<
Type<TypeCategory::Character>>
566 :
public ArrayConstructorValues<Type<TypeCategory::Character>> {
569 using Base = ArrayConstructorValues<Result>;
571 constexpr int kind()
const {
return kind_; }
573 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructor)
574 explicit ArrayConstructor(
int kind, Base &&values)
575 : Base{std::move(values)}, kind_{kind} {
576 CHECK_KIND(kind, Result);
578 template <
typename T>
579 explicit ArrayConstructor(
int kind,
const Expr<T> &) : kind_{kind} {
580 CHECK_KIND(kind, Result);
583 bool operator==(
const ArrayConstructor &)
const;
584 static constexpr Result result(
int kind) {
return Result{kind}; }
585 DynamicType GetType()
const {
return {Result::category, kind()}; }
586 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
588 return length_ ? &length_->value() :
nullptr;
593 std::optional<common::CopyableIndirection<Expr<SubscriptInteger>>> length_;
597class ArrayConstructor<SomeDerived>
598 :
public ArrayConstructorValues<SomeDerived> {
600 using Result = SomeDerived;
601 using Base = ArrayConstructorValues<Result>;
603 static constexpr int kind() {
return 0; }
605 CLASS_BOILERPLATE(ArrayConstructor)
608 : Base{std::move(v)}, result_{spec} {}
609 template <
typename A>
610 explicit ArrayConstructor(
const A &prototype)
611 : result_{prototype.GetType().value().GetDerivedTypeSpec()} {}
612 template <
typename A>
613 explicit ArrayConstructor(
int kind,
const A &prototype)
614 : result_{prototype.GetType().value().GetDerivedTypeSpec()} {
618 bool operator==(
const ArrayConstructor &)
const;
619 constexpr Result result()
const {
return result_; }
620 constexpr DynamicType GetType()
const {
return result_.GetType(); }
621 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
635 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
638 using Conversions = std::tuple<Convert<Result, TypeCategory::Integer>,
641 using Operations = std::tuple<Parentheses<Result>,
Negate<Result>,
644 using Indices = std::tuple<ImpliedDoIndex>;
645 using TypeParamInquiries = std::tuple<TypeParamInquiry>;
646 using DescriptorInquiries = std::tuple<DescriptorInquiry>;
647 using RankOneBoundElements = std::tuple<RankOneBoundElement>;
652 common::TupleToVariant<common::CombineTuples<Operations, Conversions, Indices,
653 TypeParamInquiries, DescriptorInquiries, RankOneBoundElements, Others>>
663 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
666 using Conversions = std::tuple<Convert<Result, TypeCategory::Integer>,
669 using Operations = std::tuple<Parentheses<Result>,
Negate<Result>,
676 common::TupleToVariant<common::CombineTuples<Operations, Conversions, Others>>
681class Expr<
Type<TypeCategory::Real>>
686 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
687 explicit Expr(
int kind,
const Scalar<Result> &x)
693 using Conversions = std::variant<Convert<Result, TypeCategory::Integer>,
696 using Operations = std::variant<ComplexComponent, Parentheses<Result>,
704 common::CombineVariants<Operations, Conversions, Others> u;
708class Expr<
Type<TypeCategory::Complex>>
712 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
713 explicit Expr(
int kind,
const Scalar<Result> &x)
715 using Operations = std::variant<Parentheses<Result>,
Negate<Result>,
723 common::CombineVariants<Operations, Others> u;
727class Expr<
Type<TypeCategory::Character>>
731 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
732 explicit Expr(
int kind,
const Scalar<Result> &x)
734 explicit Expr(
int kind, Scalar<Result> &&x)
737 std::optional<Expr<SubscriptInteger>> LEN()
const;
754class Relational :
public Operation<Relational<T>, LogicalResult, T, T> {
756 using Result = LogicalResult;
757 using Base = Operation<Relational, LogicalResult, T, T>;
758 using Operand =
typename Base::template Operand<0>;
759 static_assert(Operand::category == TypeCategory::Integer ||
760 Operand::category == TypeCategory::Real ||
761 Operand::category == TypeCategory::Complex ||
762 Operand::category == TypeCategory::Character ||
763 Operand::category == TypeCategory::Unsigned);
764 CLASS_BOILERPLATE(Relational)
767 : Base{LogicalResultKind, a, b}, opr{r} {
768 CHECK(a.kind() == b.kind());
771 : Base{LogicalResultKind, std::move(a), std::move(b)}, opr{r} {
772 CHECK(this->left().kind() == this->right().kind());
774 static constexpr std::optional<DynamicType> GetType() {
775 return DynamicType{TypeCategory::Logical, LogicalResultKind};
777 bool operator==(
const Relational &)
const;
778 RelationalOperator opr;
782 using DirectlyComparableTypes = common::CombineTuples<IntegerTypes, RealTypes,
783 ComplexTypes, CharacterTypes, UnsignedTypes>;
786 using Result = LogicalResult;
787 EVALUATE_UNION_CLASS_BOILERPLATE(Relational)
789 return common::visit([](
const auto &x) {
return x.kind(); }, u);
792 return {TypeCategory::Logical, LogicalResultKind};
795 return common::visit([](
const auto &x) {
return x.Rank(); }, u);
797 static constexpr int Corank() {
return 0; }
798 llvm::raw_ostream &AsFortran(llvm::raw_ostream &o)
const;
799 common::MapTemplate<Relational, DirectlyComparableTypes> u;
811class Expr<
Type<TypeCategory::Logical>>
815 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
817 explicit Expr(
const Scalar<Result> &x) : u{
Constant<Result>{x.kind(), x}} {}
818 explicit Expr(
int kind,
const Scalar<Result> &x)
820 explicit Expr(
int kind,
bool x)
826 using Relations = std::tuple<Relational<SomeType>>;
831 common::TupleToVariant<common::CombineTuples<Operations, Relations, Others>>
849class StructureConstructor {
851 using Result = SomeDerived;
853 static constexpr int kind() {
return 0; }
857 StructureConstructor(
859 StructureConstructor(
861 CLASS_BOILERPLATE(StructureConstructor)
863 constexpr Result result()
const {
return result_; }
865 return result_.derivedTypeSpec();
867 StructureConstructorValues &values() {
return values_; }
868 const StructureConstructorValues &values()
const {
return values_; }
870 bool operator==(
const StructureConstructor &)
const;
872 StructureConstructorValues::iterator begin() {
return values_.begin(); }
873 StructureConstructorValues::const_iterator begin()
const {
874 return values_.begin();
876 StructureConstructorValues::iterator end() {
return values_.end(); }
877 StructureConstructorValues::const_iterator end()
const {
878 return values_.end();
882 std::optional<Expr<SomeType>> Find(
const Symbol &)
const;
885 static constexpr int Rank() {
return 0; }
886 static constexpr int Corank() {
return 0; }
888 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
891 std::optional<Expr<SomeType>> CreateParentComponent(
const Symbol &)
const;
893 StructureConstructorValues values_;
899 using Result = SomeDerived;
900 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
911template <TypeCategory CAT>
915 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
919 common::MapTemplate<evaluate::Expr, CategoryTypes<CAT>> u;
924 using Result = SomeCharacter;
925 EVALUATE_UNION_CLASS_BOILERPLATE(
Expr)
926 std::optional<Expr<SubscriptInteger>> LEN()
const;
927 common::MapTemplate<Expr, CategoryTypes<TypeCategory::Character>> u;
932using CategoryExpression = common::MapTemplate<Expr, SomeCategory>;
938using BOZLiteralConstant =
typename LargestReal::Scalar::Word;
939inline constexpr int BOZLiteralConstantKind = LargestRealKind;
943 static constexpr int kind() {
return 0; }
945 constexpr bool operator==(
const NullPointer &)
const {
return true; }
946 static constexpr int Rank() {
return 0; }
947 static constexpr int Corank() {
return 0; }
953using TypelessExpression = std::variant<BOZLiteralConstant,
NullPointer,
962 static constexpr int kind() {
return 0; }
964 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
971 template <TypeCategory CAT>
972 explicit Expr(
const Expr<Type<CAT>> &x) : u{Expr<SomeKind<CAT>>{x}} {}
974 template <TypeCategory CAT>
977 template <TypeCategory CAT> Expr &operator=(
const Expr<Type<CAT>> &x) {
978 u = Expr<SomeKind<CAT>>{x};
982 template <TypeCategory CAT> Expr &operator=(Expr<Type<CAT>> &&x) {
983 u = Expr<SomeKind<CAT>>{std::move(x)};
988 common::CombineVariants<TypelessExpression, CategoryExpression> u;
998 : lhs(std::move(lhs)), rhs(std::move(rhs)) {}
1001 using BoundsSpec = std::vector<Expr<SubscriptInteger>>;
1002 using BoundsRemapping =
1004 llvm::raw_ostream &AsFortran(llvm::raw_ostream &)
const;
1008 std::variant<Intrinsic, ProcedureRef, BoundsSpec, BoundsRemapping> u;
1013struct GenericExprWrapper {
1014 GenericExprWrapper() {}
1016 : v{std::move(x)} {}
1017 ~GenericExprWrapper();
1018 static void Deleter(GenericExprWrapper *);
1019 std::optional<Expr<SomeType>> v;
1023struct GenericAssignmentWrapper {
1024 GenericAssignmentWrapper() {}
1025 explicit GenericAssignmentWrapper(
Assignment &&x) : v{std::move(x)} {}
1026 explicit GenericAssignmentWrapper(std::optional<Assignment> &&x)
1027 : v{std::move(x)} {}
1028 ~GenericAssignmentWrapper();
1029 static void Deleter(GenericAssignmentWrapper *);
1030 std::optional<Assignment> v;
1033FOR_EACH_CATEGORY_TYPE(
extern template class Expr, )
1039#define INSTANTIATE_EXPRESSION_TEMPLATES \
1040 FOR_EACH_CATEGORY_TYPE(template class Expr, ) \
1041 template class Relational<Type<TypeCategory::Integer>>; \
1042 template class Relational<Type<TypeCategory::Unsigned>>; \
1043 template class Relational<Type<TypeCategory::Real>>; \
1044 template class Relational<Type<TypeCategory::Character>>; \
1045 FOR_EACH_TYPE_AND_KIND(template class ExpressionBase, ) \
1046 FOR_EACH_INTRINSIC_KIND(template class ArrayConstructorValues, ) \
1047 FOR_EACH_INTRINSIC_KIND(template class ArrayConstructor, ) \
1048 FOR_EACH_INTRINSIC_KIND(template class ConditionalExpr, )
1050template <
typename T>
1051inline Expr<T> MakeConstantExpr(
int kind,
const Scalar<T> &v) {
1052 CHECK(kind == v.kind());
1056template <
typename T>
inline Expr<T> MakeConstantExpr(
int kind, Scalar<T> &&v) {
1057 CHECK(kind == v.kind());
1058 return Expr<T>{Constant<T>{kind, std::move(v)}};
1061template <
typename T>
1062inline Expr<T> MakeConstantExpr(
int kind,
const Constant<T> &c) {
1063 CHECK(kind == c.kind());
1067template <
typename T>
1068inline Expr<T> MakeConstantExpr(
int kind, Constant<T> &&c) {
1069 CHECK(kind == c.kind());
1070 return Expr<T>{std::move(c)};
1073template <
typename T,
1075 std::enable_if_t<std::is_same_v<T, Type<TypeCategory::Character>>>>
1076inline Expr<T> MakeConstantExpr(
int kind,
const std::string &v) {
1077 return Expr<T>{MakeConstant<T>(kind, v)};
1080template <
typename T,
1081 typename = std::enable_if_t<std::is_same_v<T, Type<TypeCategory::Integer>>>>
1082inline Expr<T> MakeConstantExpr(
int kind, int64_t v) {
1083 return Expr<T>{Constant<T>{kind, Scalar<T>{kind, v}}};
1086template <
typename T,
1088 std::enable_if_t<std::is_same_v<T, Type<TypeCategory::Unsigned>>>>
1089inline Expr<T> MakeConstantExpr(
int kind, uint64_t v) {
1090 return Expr<T>{Constant<T>{kind, Scalar<T>{kind, v}}};
1093template <
typename T,
1094 typename = std::enable_if_t<std::is_same_v<T, Type<TypeCategory::Logical>>>>
1095inline Expr<T> MakeConstantExpr(
int kind,
bool v) {
1096 return Expr<T>{Constant<T>{kind, Scalar<T>{kind, v}}};
1099template <
typename T>
inline Expr<T> MakeZeroExpr(
int kind) {
1100 return MakeConstantExpr<T>(kind, Scalar<T>::Zero(kind));
1103inline Expr<SubscriptInteger> MakeSubscriptIntExpr(int64_t v) {
1104 return Expr<SubscriptInteger>{MakeSubscriptIntConstant(v)};
1107inline Expr<SubscriptInteger> MakeSubscriptIntExpr(
1108 const Scalar<SubscriptInteger> &v) {
1109 return Expr<SubscriptInteger>{
1110 Constant<SubscriptInteger>{SubscriptIntegerKind, v}};
1113inline Expr<SubscriptInteger> MakeSubscriptIntExpr(
1114 Scalar<SubscriptInteger> &&v) {
1115 return Expr<SubscriptInteger>{
1116 Constant<SubscriptInteger>{SubscriptIntegerKind, std::move(v)}};
1119inline Expr<CInteger> MakeCIntegerExpr(int32_t v) {
1120 return Expr<CInteger>{MakeCIntegerConstant(v)};
1123inline Expr<LogicalResult> MakeLogicalResultExpr(
bool v) {
1124 return Expr<LogicalResult>{MakeLogicalResultConstant(v)};
1127inline Expr<Ascii> MakeAsciiExpr(
const std::string &v) {
1128 return Expr<Ascii>{MakeConstant<Ascii>(AsciiKind, v)};
1131inline Expr<Ascii> MakeAsciiExpr(std::string &&v) {
1132 return Expr<Ascii>{MakeConstant<Ascii>(AsciiKind, std::move(v))};
Definition expression.h:509
Definition expression.h:537
Definition expression.h:995
Definition expression.h:412
Definition constant.h:191
Definition variable.h:386
Definition expression.h:64
Definition expression.h:475
Definition expression.h:754
Definition expression.h:849
Definition char-block.h:27
Definition expression.h:307
Definition expression.h:503
Definition expression.h:1000
Definition expression.h:370
Definition expression.h:384
Definition expression.h:218
Definition expression.h:328
Definition expression.h:351
Definition expression.h:461
Definition expression.h:398
Definition expression.h:321
Definition expression.h:261
Definition expression.h:285
Definition expression.h:942
Definition expression.h:237
Definition expression.h:335
Definition expression.h:343
Definition expression.h:297
Definition expression.h:314