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