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