1 //===-- include/flang/Evaluate/expression.h ---------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef FORTRAN_EVALUATE_EXPRESSION_H_ 10 #define FORTRAN_EVALUATE_EXPRESSION_H_ 11 12 // Represent Fortran expressions in a type-safe manner. 13 // Expressions are the sole owners of their constituents; i.e., there is no 14 // context-independent hash table or sharing of common subexpressions, and 15 // thus these are trees, not DAGs. Both deep copy and move semantics are 16 // supported for expression construction. Expressions may be compared 17 // for equality. 18 19 #include "common.h" 20 #include "constant.h" 21 #include "formatting.h" 22 #include "type.h" 23 #include "variable.h" 24 #include "flang/Common/Fortran.h" 25 #include "flang/Common/idioms.h" 26 #include "flang/Common/indirection.h" 27 #include "flang/Common/template.h" 28 #include "flang/Parser/char-block.h" 29 #include <algorithm> 30 #include <list> 31 #include <tuple> 32 #include <type_traits> 33 #include <variant> 34 35 namespace llvm { 36 class raw_ostream; 37 } 38 39 namespace Fortran::evaluate { 40 41 using common::LogicalOperator; 42 using common::RelationalOperator; 43 44 // Expressions are represented by specializations of the class template Expr. 45 // Each of these specializations wraps a single data member "u" that 46 // is a std::variant<> discriminated union over all of the representational 47 // types for the constants, variables, operations, and other entities that 48 // can be valid expressions in that context: 49 // - Expr<Type<CATEGORY, KIND>> represents an expression whose result is of a 50 // specific intrinsic type category and kind, e.g. Type<TypeCategory::Real, 4> 51 // - Expr<SomeDerived> wraps data and procedure references that result in an 52 // instance of a derived type (or CLASS(*) unlimited polymorphic) 53 // - Expr<SomeKind<CATEGORY>> is a union of Expr<Type<CATEGORY, K>> for each 54 // kind type parameter value K in that intrinsic type category. It represents 55 // an expression with known category and any kind. 56 // - Expr<SomeType> is a union of Expr<SomeKind<CATEGORY>> over the five 57 // intrinsic type categories of Fortran. It represents any valid expression. 58 // 59 // Everything that can appear in, or as, a valid Fortran expression must be 60 // represented with an instance of some class containing a Result typedef that 61 // maps to some instantiation of Type<CATEGORY, KIND>, SomeKind<CATEGORY>, 62 // or SomeType. (Exception: BOZ literal constants in generic Expr<SomeType>.) 63 template <typename A> using ResultType = typename std::decay_t<A>::Result; 64 65 // Common Expr<> behaviors: every Expr<T> derives from ExpressionBase<T>. 66 template <typename RESULT> class ExpressionBase { 67 public: 68 using Result = RESULT; 69 70 private: 71 using Derived = Expr<Result>; 72 #if defined(__APPLE__) && defined(__GNUC__) 73 Derived &derived(); 74 const Derived &derived() const; 75 #else derived()76 Derived &derived() { return *static_cast<Derived *>(this); } derived()77 const Derived &derived() const { return *static_cast<const Derived *>(this); } 78 #endif 79 80 public: 81 template <typename A> Derived &operator=(const A &x) { 82 Derived &d{derived()}; 83 d.u = x; 84 return d; 85 } 86 87 template <typename A> common::IfNoLvalue<Derived &, A> operator=(A &&x) { 88 Derived &d{derived()}; 89 d.u = std::move(x); 90 return d; 91 } 92 93 std::optional<DynamicType> GetType() const; 94 int Rank() const; 95 std::string AsFortran() const; 96 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 97 LLVM_DUMP_METHOD void dump() const; 98 #endif 99 llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; 100 static Derived Rewrite(FoldingContext &, Derived &&); 101 }; 102 103 // Operations always have specific Fortran result types (i.e., with known 104 // intrinsic type category and kind parameter value). The classes that 105 // represent the operations all inherit from this Operation<> base class 106 // template. Note that Operation has as its first type parameter (DERIVED) a 107 // "curiously reoccurring template pattern (CRTP)" reference to the specific 108 // operation class being derived from Operation; e.g., Add is defined with 109 // struct Add : public Operation<Add, ...>. Uses of instances of Operation<>, 110 // including its own member functions, can access each specific class derived 111 // from it via its derived() member function with compile-time type safety. 112 template <typename DERIVED, typename RESULT, typename... OPERANDS> 113 class Operation { 114 // The extra final member is a dummy that allows a safe unused reference 115 // to element 1 to arise indirectly in the definition of "right()" below 116 // when the operation has but a single operand. 117 using OperandTypes = std::tuple<OPERANDS..., std::monostate>; 118 119 public: 120 using Derived = DERIVED; 121 using Result = RESULT; 122 static constexpr std::size_t operands{sizeof...(OPERANDS)}; 123 // Allow specific intrinsic types and Parentheses<SomeDerived> 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>; 127 128 // Unary operations wrap a single Expr with a CopyableIndirection. 129 // Binary operations wrap a tuple of CopyableIndirections to Exprs. 130 private: 131 using Container = std::conditional_t<operands == 1, 132 common::CopyableIndirection<Expr<Operand<0>>>, 133 std::tuple<common::CopyableIndirection<Expr<OPERANDS>>...>>; 134 135 public: CLASS_BOILERPLATE(Operation)136 CLASS_BOILERPLATE(Operation) 137 explicit Operation(const Expr<OPERANDS> &...x) : operand_{x...} {} Operation(Expr<OPERANDS> &&...x)138 explicit Operation(Expr<OPERANDS> &&...x) : operand_{std::move(x)...} {} 139 derived()140 Derived &derived() { return *static_cast<Derived *>(this); } derived()141 const Derived &derived() const { return *static_cast<const Derived *>(this); } 142 143 // References to operand expressions from member functions of derived 144 // classes for specific operators can be made by index, e.g. operand<0>(), 145 // which must be spelled like "this->template operand<0>()" when 146 // inherited in a derived class template. There are convenience aliases 147 // left() and right() that are not templates. operand()148 template <int J> Expr<Operand<J>> &operand() { 149 if constexpr (operands == 1) { 150 static_assert(J == 0); 151 return operand_.value(); 152 } else { 153 return std::get<J>(operand_).value(); 154 } 155 } operand()156 template <int J> const Expr<Operand<J>> &operand() const { 157 if constexpr (operands == 1) { 158 static_assert(J == 0); 159 return operand_.value(); 160 } else { 161 return std::get<J>(operand_).value(); 162 } 163 } 164 left()165 Expr<Operand<0>> &left() { return operand<0>(); } left()166 const Expr<Operand<0>> &left() const { return operand<0>(); } 167 right()168 std::conditional_t<(operands > 1), Expr<Operand<1>> &, void> right() { 169 if constexpr (operands > 1) { 170 return operand<1>(); 171 } 172 } 173 std::conditional_t<(operands > 1), const Expr<Operand<1>> &, void> right()174 right() const { 175 if constexpr (operands > 1) { 176 return operand<1>(); 177 } 178 } 179 180 static constexpr std::conditional_t<Result::category != TypeCategory::Derived, 181 std::optional<DynamicType>, void> GetType()182 GetType() { 183 return Result::GetType(); 184 } Rank()185 int Rank() const { 186 int rank{left().Rank()}; 187 if constexpr (operands > 1) { 188 return std::max(rank, right().Rank()); 189 } else { 190 return rank; 191 } 192 } 193 194 bool operator==(const Operation &that) const { 195 return operand_ == that.operand_; 196 } 197 198 llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; 199 200 private: 201 Container operand_; 202 }; 203 204 // Unary operations 205 206 // Conversions to specific types from expressions of known category and 207 // dynamic kind. 208 template <typename TO, TypeCategory FROMCAT = TO::category> 209 struct Convert : public Operation<Convert<TO, FROMCAT>, TO, SomeKind<FROMCAT>> { 210 // Fortran doesn't have conversions between kinds of CHARACTER apart from 211 // assignments, and in those the data must be convertible to/from 7-bit ASCII. 212 static_assert(((TO::category == TypeCategory::Integer || 213 TO::category == TypeCategory::Real) && 214 (FROMCAT == TypeCategory::Integer || 215 FROMCAT == TypeCategory::Real)) || 216 TO::category == FROMCAT); 217 using Result = TO; 218 using Operand = SomeKind<FROMCAT>; 219 using Base = Operation<Convert, Result, Operand>; 220 using Base::Base; 221 llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; 222 }; 223 224 template <typename A> 225 struct Parentheses : public Operation<Parentheses<A>, A, A> { 226 using Result = A; 227 using Operand = A; 228 using Base = Operation<Parentheses, A, A>; 229 using Base::Base; 230 }; 231 232 template <> 233 struct Parentheses<SomeDerived> 234 : public Operation<Parentheses<SomeDerived>, SomeDerived, SomeDerived> { 235 public: 236 using Result = SomeDerived; 237 using Operand = SomeDerived; 238 using Base = Operation<Parentheses, SomeDerived, SomeDerived>; 239 using Base::Base; 240 DynamicType GetType() const; 241 }; 242 243 template <typename A> struct Negate : public Operation<Negate<A>, A, A> { 244 using Result = A; 245 using Operand = A; 246 using Base = Operation<Negate, A, A>; 247 using Base::Base; 248 }; 249 250 template <int KIND> 251 struct ComplexComponent 252 : public Operation<ComplexComponent<KIND>, Type<TypeCategory::Real, KIND>, 253 Type<TypeCategory::Complex, KIND>> { 254 using Result = Type<TypeCategory::Real, KIND>; 255 using Operand = Type<TypeCategory::Complex, KIND>; 256 using Base = Operation<ComplexComponent, Result, Operand>; 257 CLASS_BOILERPLATE(ComplexComponent) 258 ComplexComponent(bool isImaginary, const Expr<Operand> &x) 259 : Base{x}, isImaginaryPart{isImaginary} {} 260 ComplexComponent(bool isImaginary, Expr<Operand> &&x) 261 : Base{std::move(x)}, isImaginaryPart{isImaginary} {} 262 263 bool isImaginaryPart{true}; 264 }; 265 266 template <int KIND> 267 struct Not : public Operation<Not<KIND>, Type<TypeCategory::Logical, KIND>, 268 Type<TypeCategory::Logical, KIND>> { 269 using Result = Type<TypeCategory::Logical, KIND>; 270 using Operand = Result; 271 using Base = Operation<Not, Result, Operand>; 272 using Base::Base; 273 }; 274 275 // Character lengths are determined by context in Fortran and do not 276 // have explicit syntax for changing them. Expressions represent 277 // changes of length (e.g., for assignments and structure constructors) 278 // with this operation. 279 template <int KIND> 280 struct SetLength 281 : public Operation<SetLength<KIND>, Type<TypeCategory::Character, KIND>, 282 Type<TypeCategory::Character, KIND>, SubscriptInteger> { 283 using Result = Type<TypeCategory::Character, KIND>; 284 using CharacterOperand = Result; 285 using LengthOperand = SubscriptInteger; 286 using Base = Operation<SetLength, Result, CharacterOperand, LengthOperand>; 287 using Base::Base; 288 }; 289 290 // Binary operations 291 292 template <typename A> struct Add : public Operation<Add<A>, A, A, A> { 293 using Result = A; 294 using Operand = A; 295 using Base = Operation<Add, A, A, A>; 296 using Base::Base; 297 }; 298 299 template <typename A> struct Subtract : public Operation<Subtract<A>, A, A, A> { 300 using Result = A; 301 using Operand = A; 302 using Base = Operation<Subtract, A, A, A>; 303 using Base::Base; 304 }; 305 306 template <typename A> struct Multiply : public Operation<Multiply<A>, A, A, A> { 307 using Result = A; 308 using Operand = A; 309 using Base = Operation<Multiply, A, A, A>; 310 using Base::Base; 311 }; 312 313 template <typename A> struct Divide : public Operation<Divide<A>, A, A, A> { 314 using Result = A; 315 using Operand = A; 316 using Base = Operation<Divide, A, A, A>; 317 using Base::Base; 318 }; 319 320 template <typename A> struct Power : public Operation<Power<A>, A, A, A> { 321 using Result = A; 322 using Operand = A; 323 using Base = Operation<Power, A, A, A>; 324 using Base::Base; 325 }; 326 327 template <typename A> 328 struct RealToIntPower : public Operation<RealToIntPower<A>, A, A, SomeInteger> { 329 using Base = Operation<RealToIntPower, A, A, SomeInteger>; 330 using Result = A; 331 using BaseOperand = A; 332 using ExponentOperand = SomeInteger; 333 using Base::Base; 334 }; 335 336 template <typename A> struct Extremum : public Operation<Extremum<A>, A, A, A> { 337 using Result = A; 338 using Operand = A; 339 using Base = Operation<Extremum, A, A, A>; 340 CLASS_BOILERPLATE(Extremum) 341 Extremum(Ordering ord, const Expr<Operand> &x, const Expr<Operand> &y) 342 : Base{x, y}, ordering{ord} {} 343 Extremum(Ordering ord, Expr<Operand> &&x, Expr<Operand> &&y) 344 : Base{std::move(x), std::move(y)}, ordering{ord} {} 345 Ordering ordering{Ordering::Greater}; 346 }; 347 348 template <int KIND> 349 struct ComplexConstructor 350 : public Operation<ComplexConstructor<KIND>, 351 Type<TypeCategory::Complex, KIND>, Type<TypeCategory::Real, KIND>, 352 Type<TypeCategory::Real, KIND>> { 353 using Result = Type<TypeCategory::Complex, KIND>; 354 using Operand = Type<TypeCategory::Real, KIND>; 355 using Base = Operation<ComplexConstructor, Result, Operand, Operand>; 356 using Base::Base; 357 }; 358 359 template <int KIND> 360 struct Concat 361 : public Operation<Concat<KIND>, Type<TypeCategory::Character, KIND>, 362 Type<TypeCategory::Character, KIND>, 363 Type<TypeCategory::Character, KIND>> { 364 using Result = Type<TypeCategory::Character, KIND>; 365 using Operand = Result; 366 using Base = Operation<Concat, Result, Operand, Operand>; 367 using Base::Base; 368 }; 369 370 template <int KIND> 371 struct LogicalOperation 372 : public Operation<LogicalOperation<KIND>, 373 Type<TypeCategory::Logical, KIND>, Type<TypeCategory::Logical, KIND>, 374 Type<TypeCategory::Logical, KIND>> { 375 using Result = Type<TypeCategory::Logical, KIND>; 376 using Operand = Result; 377 using Base = Operation<LogicalOperation, Result, Operand, Operand>; 378 CLASS_BOILERPLATE(LogicalOperation) 379 LogicalOperation( 380 LogicalOperator opr, const Expr<Operand> &x, const Expr<Operand> &y) 381 : Base{x, y}, logicalOperator{opr} {} 382 LogicalOperation(LogicalOperator opr, Expr<Operand> &&x, Expr<Operand> &&y) 383 : Base{std::move(x), std::move(y)}, logicalOperator{opr} {} 384 LogicalOperator logicalOperator; 385 }; 386 387 // Array constructors 388 template <typename RESULT> class ArrayConstructorValues; 389 390 struct ImpliedDoIndex { 391 using Result = SubscriptInteger; 392 bool operator==(const ImpliedDoIndex &) const; 393 static constexpr int Rank() { return 0; } 394 parser::CharBlock name; // nested implied DOs must use distinct names 395 }; 396 397 template <typename RESULT> class ImpliedDo { 398 public: 399 using Result = RESULT; 400 using Index = ResultType<ImpliedDoIndex>; 401 ImpliedDo(parser::CharBlock name, Expr<Index> &&lower, Expr<Index> &&upper, 402 Expr<Index> &&stride, ArrayConstructorValues<Result> &&values) 403 : name_{name}, lower_{std::move(lower)}, upper_{std::move(upper)}, 404 stride_{std::move(stride)}, values_{std::move(values)} {} 405 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ImpliedDo) 406 bool operator==(const ImpliedDo &) const; 407 parser::CharBlock name() const { return name_; } 408 Expr<Index> &lower() { return lower_.value(); } 409 const Expr<Index> &lower() const { return lower_.value(); } 410 Expr<Index> &upper() { return upper_.value(); } 411 const Expr<Index> &upper() const { return upper_.value(); } 412 Expr<Index> &stride() { return stride_.value(); } 413 const Expr<Index> &stride() const { return stride_.value(); } 414 ArrayConstructorValues<Result> &values() { return values_.value(); } 415 const ArrayConstructorValues<Result> &values() const { 416 return values_.value(); 417 } 418 419 private: 420 parser::CharBlock name_; 421 common::CopyableIndirection<Expr<Index>> lower_, upper_, stride_; 422 common::CopyableIndirection<ArrayConstructorValues<Result>> values_; 423 }; 424 425 template <typename RESULT> struct ArrayConstructorValue { 426 using Result = RESULT; 427 EVALUATE_UNION_CLASS_BOILERPLATE(ArrayConstructorValue) 428 std::variant<Expr<Result>, ImpliedDo<Result>> u; 429 }; 430 431 template <typename RESULT> class ArrayConstructorValues { 432 public: 433 using Result = RESULT; 434 using Values = std::vector<ArrayConstructorValue<Result>>; 435 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructorValues) 436 ArrayConstructorValues() {} 437 438 bool operator==(const ArrayConstructorValues &) const; 439 static constexpr int Rank() { return 1; } 440 template <typename A> common::NoLvalue<A> Push(A &&x) { 441 values_.emplace_back(std::move(x)); 442 } 443 444 typename Values::iterator begin() { return values_.begin(); } 445 typename Values::const_iterator begin() const { return values_.begin(); } 446 typename Values::iterator end() { return values_.end(); } 447 typename Values::const_iterator end() const { return values_.end(); } 448 449 protected: 450 Values values_; 451 }; 452 453 // Note that there are specializations of ArrayConstructor for character 454 // and derived types, since they must carry additional type information, 455 // but that an empty ArrayConstructor can be constructed for any type 456 // given an expression from which such type information may be gleaned. 457 template <typename RESULT> 458 class ArrayConstructor : public ArrayConstructorValues<RESULT> { 459 public: 460 using Result = RESULT; 461 using Base = ArrayConstructorValues<Result>; 462 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructor) 463 explicit ArrayConstructor(Base &&values) : Base{std::move(values)} {} 464 template <typename T> explicit ArrayConstructor(const Expr<T> &) {} 465 static constexpr Result result() { return Result{}; } 466 static constexpr DynamicType GetType() { return Result::GetType(); } 467 llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; 468 }; 469 470 template <int KIND> 471 class ArrayConstructor<Type<TypeCategory::Character, KIND>> 472 : public ArrayConstructorValues<Type<TypeCategory::Character, KIND>> { 473 public: 474 using Result = Type<TypeCategory::Character, KIND>; 475 using Base = ArrayConstructorValues<Result>; 476 CLASS_BOILERPLATE(ArrayConstructor) 477 ArrayConstructor(Expr<SubscriptInteger> &&len, Base &&v) 478 : Base{std::move(v)}, length_{std::move(len)} {} 479 template <typename A> 480 explicit ArrayConstructor(const A &prototype) 481 : length_{prototype.LEN().value()} {} 482 bool operator==(const ArrayConstructor &) const; 483 static constexpr Result result() { return Result{}; } 484 static constexpr DynamicType GetType() { return Result::GetType(); } 485 llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; 486 const Expr<SubscriptInteger> &LEN() const { return length_.value(); } 487 488 private: 489 common::CopyableIndirection<Expr<SubscriptInteger>> length_; 490 }; 491 492 template <> 493 class ArrayConstructor<SomeDerived> 494 : public ArrayConstructorValues<SomeDerived> { 495 public: 496 using Result = SomeDerived; 497 using Base = ArrayConstructorValues<Result>; 498 CLASS_BOILERPLATE(ArrayConstructor) 499 500 ArrayConstructor(const semantics::DerivedTypeSpec &spec, Base &&v) 501 : Base{std::move(v)}, result_{spec} {} 502 template <typename A> 503 explicit ArrayConstructor(const A &prototype) 504 : result_{prototype.GetType().value().GetDerivedTypeSpec()} {} 505 506 bool operator==(const ArrayConstructor &) const; 507 constexpr Result result() const { return result_; } 508 constexpr DynamicType GetType() const { return result_.GetType(); } 509 llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; 510 511 private: 512 Result result_; 513 }; 514 515 // Expression representations for each type category. 516 517 template <int KIND> 518 class Expr<Type<TypeCategory::Integer, KIND>> 519 : public ExpressionBase<Type<TypeCategory::Integer, KIND>> { 520 public: 521 using Result = Type<TypeCategory::Integer, KIND>; 522 523 EVALUATE_UNION_CLASS_BOILERPLATE(Expr) 524 525 private: 526 using Conversions = std::tuple<Convert<Result, TypeCategory::Integer>, 527 Convert<Result, TypeCategory::Real>>; 528 using Operations = std::tuple<Parentheses<Result>, Negate<Result>, 529 Add<Result>, Subtract<Result>, Multiply<Result>, Divide<Result>, 530 Power<Result>, Extremum<Result>>; 531 using Indices = std::conditional_t<KIND == ImpliedDoIndex::Result::kind, 532 std::tuple<ImpliedDoIndex>, std::tuple<>>; 533 using TypeParamInquiries = 534 std::conditional_t<KIND == TypeParamInquiry::Result::kind, 535 std::tuple<TypeParamInquiry>, std::tuple<>>; 536 using DescriptorInquiries = 537 std::conditional_t<KIND == DescriptorInquiry::Result::kind, 538 std::tuple<DescriptorInquiry>, std::tuple<>>; 539 using Others = std::tuple<Constant<Result>, ArrayConstructor<Result>, 540 Designator<Result>, FunctionRef<Result>>; 541 542 public: 543 common::TupleToVariant<common::CombineTuples<Operations, Conversions, Indices, 544 TypeParamInquiries, DescriptorInquiries, Others>> 545 u; 546 }; 547 548 template <int KIND> 549 class Expr<Type<TypeCategory::Real, KIND>> 550 : public ExpressionBase<Type<TypeCategory::Real, KIND>> { 551 public: 552 using Result = Type<TypeCategory::Real, KIND>; 553 554 EVALUATE_UNION_CLASS_BOILERPLATE(Expr) 555 explicit Expr(const Scalar<Result> &x) : u{Constant<Result>{x}} {} 556 557 private: 558 // N.B. Real->Complex and Complex->Real conversions are done with CMPLX 559 // and part access operations (resp.). 560 using Conversions = std::variant<Convert<Result, TypeCategory::Integer>, 561 Convert<Result, TypeCategory::Real>>; 562 using Operations = std::variant<ComplexComponent<KIND>, Parentheses<Result>, 563 Negate<Result>, Add<Result>, Subtract<Result>, Multiply<Result>, 564 Divide<Result>, Power<Result>, RealToIntPower<Result>, Extremum<Result>>; 565 using Others = std::variant<Constant<Result>, ArrayConstructor<Result>, 566 Designator<Result>, FunctionRef<Result>>; 567 568 public: 569 common::CombineVariants<Operations, Conversions, Others> u; 570 }; 571 572 template <int KIND> 573 class Expr<Type<TypeCategory::Complex, KIND>> 574 : public ExpressionBase<Type<TypeCategory::Complex, KIND>> { 575 public: 576 using Result = Type<TypeCategory::Complex, KIND>; 577 EVALUATE_UNION_CLASS_BOILERPLATE(Expr) 578 explicit Expr(const Scalar<Result> &x) : u{Constant<Result>{x}} {} 579 using Operations = std::variant<Parentheses<Result>, Negate<Result>, 580 Convert<Result, TypeCategory::Complex>, Add<Result>, Subtract<Result>, 581 Multiply<Result>, Divide<Result>, Power<Result>, RealToIntPower<Result>, 582 ComplexConstructor<KIND>>; 583 using Others = std::variant<Constant<Result>, ArrayConstructor<Result>, 584 Designator<Result>, FunctionRef<Result>>; 585 586 public: 587 common::CombineVariants<Operations, Others> u; 588 }; 589 590 FOR_EACH_INTEGER_KIND(extern template class Expr, ) 591 FOR_EACH_REAL_KIND(extern template class Expr, ) 592 FOR_EACH_COMPLEX_KIND(extern template class Expr, ) 593 594 template <int KIND> 595 class Expr<Type<TypeCategory::Character, KIND>> 596 : public ExpressionBase<Type<TypeCategory::Character, KIND>> { 597 public: 598 using Result = Type<TypeCategory::Character, KIND>; 599 EVALUATE_UNION_CLASS_BOILERPLATE(Expr) 600 explicit Expr(const Scalar<Result> &x) : u{Constant<Result>{x}} {} 601 explicit Expr(Scalar<Result> &&x) : u{Constant<Result>{std::move(x)}} {} 602 603 std::optional<Expr<SubscriptInteger>> LEN() const; 604 605 std::variant<Constant<Result>, ArrayConstructor<Result>, Designator<Result>, 606 FunctionRef<Result>, Parentheses<Result>, Convert<Result>, Concat<KIND>, 607 Extremum<Result>, SetLength<KIND>> 608 u; 609 }; 610 611 FOR_EACH_CHARACTER_KIND(extern template class Expr, ) 612 613 // The Relational class template is a helper for constructing logical 614 // expressions with polymorphism over the cross product of the possible 615 // categories and kinds of comparable operands. 616 // Fortran defines a numeric relation with distinct types or kinds as 617 // first undergoing the same operand conversions that occur with the intrinsic 618 // addition operator. Character relations must have the same kind. 619 // There are no relations between LOGICAL values. 620 621 template <typename T> 622 struct Relational : public Operation<Relational<T>, LogicalResult, T, T> { 623 using Result = LogicalResult; 624 using Base = Operation<Relational, LogicalResult, T, T>; 625 using Operand = typename Base::template Operand<0>; 626 static_assert(Operand::category == TypeCategory::Integer || 627 Operand::category == TypeCategory::Real || 628 Operand::category == TypeCategory::Complex || 629 Operand::category == TypeCategory::Character); 630 CLASS_BOILERPLATE(Relational) 631 Relational( 632 RelationalOperator r, const Expr<Operand> &a, const Expr<Operand> &b) 633 : Base{a, b}, opr{r} {} 634 Relational(RelationalOperator r, Expr<Operand> &&a, Expr<Operand> &&b) 635 : Base{std::move(a), std::move(b)}, opr{r} {} 636 RelationalOperator opr; 637 }; 638 639 template <> class Relational<SomeType> { 640 using DirectlyComparableTypes = common::CombineTuples<IntegerTypes, RealTypes, 641 ComplexTypes, CharacterTypes>; 642 643 public: 644 using Result = LogicalResult; 645 EVALUATE_UNION_CLASS_BOILERPLATE(Relational) 646 static constexpr DynamicType GetType() { return Result::GetType(); } 647 int Rank() const { 648 return std::visit([](const auto &x) { return x.Rank(); }, u); 649 } 650 llvm::raw_ostream &AsFortran(llvm::raw_ostream &o) const; 651 common::MapTemplate<Relational, DirectlyComparableTypes> u; 652 }; 653 654 FOR_EACH_INTEGER_KIND(extern template struct Relational, ) 655 FOR_EACH_REAL_KIND(extern template struct Relational, ) 656 FOR_EACH_CHARACTER_KIND(extern template struct Relational, ) 657 extern template struct Relational<SomeType>; 658 659 // Logical expressions of a kind bigger than LogicalResult 660 // do not include Relational<> operations as possibilities, 661 // since the results of Relationals are always LogicalResult 662 // (kind=1). 663 template <int KIND> 664 class Expr<Type<TypeCategory::Logical, KIND>> 665 : public ExpressionBase<Type<TypeCategory::Logical, KIND>> { 666 public: 667 using Result = Type<TypeCategory::Logical, KIND>; 668 EVALUATE_UNION_CLASS_BOILERPLATE(Expr) 669 explicit Expr(const Scalar<Result> &x) : u{Constant<Result>{x}} {} 670 explicit Expr(bool x) : u{Constant<Result>{x}} {} 671 672 private: 673 using Operations = std::tuple<Convert<Result>, Parentheses<Result>, Not<KIND>, 674 LogicalOperation<KIND>>; 675 using Relations = std::conditional_t<KIND == LogicalResult::kind, 676 std::tuple<Relational<SomeType>>, std::tuple<>>; 677 using Others = std::tuple<Constant<Result>, ArrayConstructor<Result>, 678 Designator<Result>, FunctionRef<Result>>; 679 680 public: 681 common::TupleToVariant<common::CombineTuples<Operations, Relations, Others>> 682 u; 683 }; 684 685 FOR_EACH_LOGICAL_KIND(extern template class Expr, ) 686 687 // StructureConstructor pairs a StructureConstructorValues instance 688 // (a map associating symbols with expressions) with a derived type 689 // specification. There are two other similar classes: 690 // - ArrayConstructor<SomeDerived> comprises a derived type spec & 691 // zero or more instances of Expr<SomeDerived>; it has rank 1 692 // but not (in the most general case) a known shape. 693 // - Constant<SomeDerived> comprises a derived type spec, zero or more 694 // homogeneous instances of StructureConstructorValues whose type 695 // parameters and component expressions are all constant, and a 696 // known shape (possibly scalar). 697 // StructureConstructor represents a scalar value of derived type that 698 // is not necessarily a constant. It is used only as an Expr<SomeDerived> 699 // alternative and as the type Scalar<SomeDerived> (with an assumption 700 // of constant component value expressions). 701 class StructureConstructor { 702 public: 703 using Result = SomeDerived; 704 705 explicit StructureConstructor(const semantics::DerivedTypeSpec &spec) 706 : result_{spec} {} 707 StructureConstructor( 708 const semantics::DerivedTypeSpec &, const StructureConstructorValues &); 709 StructureConstructor( 710 const semantics::DerivedTypeSpec &, StructureConstructorValues &&); 711 CLASS_BOILERPLATE(StructureConstructor) 712 713 constexpr Result result() const { return result_; } 714 const semantics::DerivedTypeSpec &derivedTypeSpec() const { 715 return result_.derivedTypeSpec(); 716 } 717 StructureConstructorValues &values() { return values_; } 718 const StructureConstructorValues &values() const { return values_; } 719 720 bool operator==(const StructureConstructor &) const; 721 722 StructureConstructorValues::iterator begin() { return values_.begin(); } 723 StructureConstructorValues::const_iterator begin() const { 724 return values_.begin(); 725 } 726 StructureConstructorValues::iterator end() { return values_.end(); } 727 StructureConstructorValues::const_iterator end() const { 728 return values_.end(); 729 } 730 731 // can return nullopt 732 std::optional<Expr<SomeType>> Find(const Symbol &) const; 733 734 StructureConstructor &Add(const semantics::Symbol &, Expr<SomeType> &&); 735 int Rank() const { return 0; } 736 DynamicType GetType() const; 737 llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; 738 739 private: 740 std::optional<Expr<SomeType>> CreateParentComponent(const Symbol &) const; 741 Result result_; 742 StructureConstructorValues values_; 743 }; 744 745 // An expression whose result has a derived type. 746 template <> class Expr<SomeDerived> : public ExpressionBase<SomeDerived> { 747 public: 748 using Result = SomeDerived; 749 EVALUATE_UNION_CLASS_BOILERPLATE(Expr) 750 std::variant<Constant<Result>, ArrayConstructor<Result>, StructureConstructor, 751 Designator<Result>, FunctionRef<Result>, Parentheses<Result>> 752 u; 753 }; 754 755 // A polymorphic expression of known intrinsic type category, but dynamic 756 // kind, represented as a discriminated union over Expr<Type<CAT, K>> 757 // for each supported kind K in the category. 758 template <TypeCategory CAT> 759 class Expr<SomeKind<CAT>> : public ExpressionBase<SomeKind<CAT>> { 760 public: 761 using Result = SomeKind<CAT>; 762 EVALUATE_UNION_CLASS_BOILERPLATE(Expr) 763 int GetKind() const; 764 common::MapTemplate<evaluate::Expr, CategoryTypes<CAT>> u; 765 }; 766 767 template <> class Expr<SomeCharacter> : public ExpressionBase<SomeCharacter> { 768 public: 769 using Result = SomeCharacter; 770 EVALUATE_UNION_CLASS_BOILERPLATE(Expr) 771 int GetKind() const; 772 std::optional<Expr<SubscriptInteger>> LEN() const; 773 common::MapTemplate<Expr, CategoryTypes<TypeCategory::Character>> u; 774 }; 775 776 // A variant comprising the Expr<> instantiations over SomeDerived and 777 // SomeKind<CATEGORY>. 778 using CategoryExpression = common::MapTemplate<Expr, SomeCategory>; 779 780 // BOZ literal "typeless" constants must be wide enough to hold a numeric 781 // value of any supported kind of INTEGER or REAL. They must also be 782 // distinguishable from other integer constants, since they are permitted 783 // to be used in only a few situations. 784 using BOZLiteralConstant = typename LargestReal::Scalar::Word; 785 786 // Null pointers without MOLD= arguments are typed by context. 787 struct NullPointer { 788 constexpr bool operator==(const NullPointer &) const { return true; } 789 constexpr int Rank() const { return 0; } 790 }; 791 792 // Procedure pointer targets are treated as if they were typeless. 793 // They are either procedure designators or values returned from 794 // references to functions that return procedure (not object) pointers. 795 using TypelessExpression = std::variant<BOZLiteralConstant, NullPointer, 796 ProcedureDesignator, ProcedureRef>; 797 798 // A completely generic expression, polymorphic across all of the intrinsic type 799 // categories and each of their kinds. 800 template <> class Expr<SomeType> : public ExpressionBase<SomeType> { 801 public: 802 using Result = SomeType; 803 EVALUATE_UNION_CLASS_BOILERPLATE(Expr) 804 805 // Owning references to these generic expressions can appear in other 806 // compiler data structures (viz., the parse tree and symbol table), so 807 // its destructor is externalized to reduce redundant default instances. 808 ~Expr(); 809 810 template <TypeCategory CAT, int KIND> 811 explicit Expr(const Expr<Type<CAT, KIND>> &x) : u{Expr<SomeKind<CAT>>{x}} {} 812 813 template <TypeCategory CAT, int KIND> 814 explicit Expr(Expr<Type<CAT, KIND>> &&x) 815 : u{Expr<SomeKind<CAT>>{std::move(x)}} {} 816 817 template <TypeCategory CAT, int KIND> 818 Expr &operator=(const Expr<Type<CAT, KIND>> &x) { 819 u = Expr<SomeKind<CAT>>{x}; 820 return *this; 821 } 822 823 template <TypeCategory CAT, int KIND> 824 Expr &operator=(Expr<Type<CAT, KIND>> &&x) { 825 u = Expr<SomeKind<CAT>>{std::move(x)}; 826 return *this; 827 } 828 829 public: 830 common::CombineVariants<TypelessExpression, CategoryExpression> u; 831 }; 832 833 // An assignment is either intrinsic, user-defined (with a ProcedureRef to 834 // specify the procedure to call), or pointer assignment (with possibly empty 835 // BoundsSpec or non-empty BoundsRemapping). In all cases there are Exprs 836 // representing the LHS and RHS of the assignment. 837 class Assignment { 838 public: 839 Assignment(Expr<SomeType> &&lhs, Expr<SomeType> &&rhs) 840 : lhs(std::move(lhs)), rhs(std::move(rhs)) {} 841 842 struct Intrinsic {}; 843 using BoundsSpec = std::vector<Expr<SubscriptInteger>>; 844 using BoundsRemapping = 845 std::vector<std::pair<Expr<SubscriptInteger>, Expr<SubscriptInteger>>>; 846 llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; 847 848 Expr<SomeType> lhs; 849 Expr<SomeType> rhs; 850 std::variant<Intrinsic, ProcedureRef, BoundsSpec, BoundsRemapping> u; 851 }; 852 853 // This wrapper class is used, by means of a forward reference with 854 // an owning pointer, to cache analyzed expressions in parse tree nodes. 855 struct GenericExprWrapper { 856 GenericExprWrapper() {} 857 explicit GenericExprWrapper(std::optional<Expr<SomeType>> &&x) 858 : v{std::move(x)} {} 859 ~GenericExprWrapper(); 860 static void Deleter(GenericExprWrapper *); 861 std::optional<Expr<SomeType>> v; // vacant if error 862 }; 863 864 // Like GenericExprWrapper but for analyzed assignments 865 struct GenericAssignmentWrapper { 866 GenericAssignmentWrapper() {} 867 explicit GenericAssignmentWrapper(Assignment &&x) : v{std::move(x)} {} 868 explicit GenericAssignmentWrapper(std::optional<Assignment> &&x) 869 : v{std::move(x)} {} 870 ~GenericAssignmentWrapper(); 871 static void Deleter(GenericAssignmentWrapper *); 872 std::optional<Assignment> v; // vacant if error 873 }; 874 875 FOR_EACH_CATEGORY_TYPE(extern template class Expr, ) 876 FOR_EACH_TYPE_AND_KIND(extern template class ExpressionBase, ) 877 FOR_EACH_INTRINSIC_KIND(extern template class ArrayConstructorValues, ) 878 FOR_EACH_INTRINSIC_KIND(extern template class ArrayConstructor, ) 879 880 // Template instantiations to resolve these "extern template" declarations. 881 #define INSTANTIATE_EXPRESSION_TEMPLATES \ 882 FOR_EACH_INTRINSIC_KIND(template class Expr, ) \ 883 FOR_EACH_CATEGORY_TYPE(template class Expr, ) \ 884 FOR_EACH_INTEGER_KIND(template struct Relational, ) \ 885 FOR_EACH_REAL_KIND(template struct Relational, ) \ 886 FOR_EACH_CHARACTER_KIND(template struct Relational, ) \ 887 template struct Relational<SomeType>; \ 888 FOR_EACH_TYPE_AND_KIND(template class ExpressionBase, ) \ 889 FOR_EACH_INTRINSIC_KIND(template class ArrayConstructorValues, ) \ 890 FOR_EACH_INTRINSIC_KIND(template class ArrayConstructor, ) 891 } // namespace Fortran::evaluate 892 #endif // FORTRAN_EVALUATE_EXPRESSION_H_ 893