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