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