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