FLANG

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