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