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/idioms.h"
25#include "flang/Common/indirection.h"
26#include "flang/Common/template.h"
27#include "flang/Parser/char-block.h"
28#include "flang/Support/Fortran.h"
29#include <algorithm>
30#include <list>
31#include <tuple>
32#include <type_traits>
33#include <variant>
34
35namespace llvm {
36class raw_ostream;
37}
38
39namespace Fortran::evaluate {
40
41using common::LogicalOperator;
42using 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>.)
63template <typename A> using ResultType = typename std::decay_t<A>::Result;
64
65// Common Expr<> behaviors: every Expr<T> derives from ExpressionBase<T>.
66template <typename RESULT> class ExpressionBase {
67public:
68 using Result = RESULT;
69
70private:
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
80public:
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.
113template <typename DERIVED, typename RESULT, typename... OPERANDS>
114class 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
120public:
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.
131private:
132 using Container = std::conditional_t<operands == 1,
133 common::CopyableIndirection<Expr<Operand<0>>>,
134 std::tuple<common::CopyableIndirection<Expr<OPERANDS>>...>>;
135
136public:
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
202private:
203 Container operand_;
204};
205
206// Unary operations
207
208// Conversions to specific types from expressions of known category and
209// dynamic kind.
210template <typename TO, TypeCategory FROMCAT = TO::category>
211struct 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
228template <typename A>
229struct 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
236template <>
237struct Parentheses<SomeDerived>
238 : public Operation<Parentheses<SomeDerived>, SomeDerived, SomeDerived> {
239public:
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
247template <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
254template <int KIND>
255struct 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
270template <int KIND>
271struct Not : public Operation<Not<KIND>, Type<TypeCategory::Logical, KIND>,
272 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.
283template <int KIND>
285 : public Operation<SetLength<KIND>, Type<TypeCategory::Character, KIND>,
286 Type<TypeCategory::Character, KIND>, SubscriptInteger> {
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
296template <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
303template <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
310template <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
317template <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
324template <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
331template <typename A>
332struct 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
340template <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
353template <int KIND>
355 : public Operation<ComplexConstructor<KIND>,
356 Type<TypeCategory::Complex, KIND>, Type<TypeCategory::Real, KIND>,
357 Type<TypeCategory::Real, KIND>> {
359 using Operand = Type<TypeCategory::Real, KIND>;
360 using Base = Operation<ComplexConstructor, Result, Operand, Operand>;
361 using Base::Base;
362};
363
364template <int KIND>
365struct Concat
366 : public Operation<Concat<KIND>, Type<TypeCategory::Character, KIND>,
367 Type<TypeCategory::Character, KIND>,
368 Type<TypeCategory::Character, KIND>> {
370 using Operand = Result;
371 using Base = Operation<Concat, Result, Operand, Operand>;
372 using Base::Base;
373};
374
375template <int KIND>
376struct LogicalOperation
377 : public Operation<LogicalOperation<KIND>,
378 Type<TypeCategory::Logical, KIND>, Type<TypeCategory::Logical, KIND>,
379 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// Fortran 2023 conditional expression: (cond ? val : cond ? val : ... : else)
394// All branches have the same type and rank (verified during semantic analysis).
395template <typename T> class ConditionalExpr {
396public:
397 using Result = T;
398 CLASS_BOILERPLATE(ConditionalExpr)
399 ConditionalExpr(Expr<LogicalResult> &&cond, Expr<Result> &&thenVal,
400 Expr<Result> &&elseVal)
401 : condition_{std::move(cond)}, thenValue_{std::move(thenVal)},
402 elseValue_{std::move(elseVal)} {}
403 bool operator==(const ConditionalExpr &) const;
404 Expr<LogicalResult> &condition() { return condition_.value(); }
405 const Expr<LogicalResult> &condition() const { return condition_.value(); }
406 Expr<Result> &thenValue() { return thenValue_.value(); }
407 const Expr<Result> &thenValue() const { return thenValue_.value(); }
408 Expr<Result> &elseValue() { return elseValue_.value(); }
409 const Expr<Result> &elseValue() const { return elseValue_.value(); }
410 int Rank() const { return thenValue().Rank(); }
411 std::optional<DynamicType> GetType() const {
412 const auto thenType{thenValue().GetType()};
413 if constexpr (T::category == TypeCategory::Derived) {
414 // F2023 10.1.4(7) A conditional-expr is polymorphic if any branch is
415 if (thenType && !thenType->IsPolymorphic()) {
416 if (const auto elseType{elseValue().GetType()}) {
417 if (elseType->IsPolymorphic()) {
418 return elseType;
419 }
420 }
421 }
422 }
423 return thenType;
424 }
425 static constexpr int Corank() { return 0; }
426 llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
427
428private:
429 common::CopyableIndirection<Expr<LogicalResult>> condition_;
430 common::CopyableIndirection<Expr<Result>> thenValue_;
431 common::CopyableIndirection<Expr<Result>> elseValue_;
432};
433
434// Array constructors
435template <typename RESULT> class ArrayConstructorValues;
436
438 using Result = SubscriptInteger;
439 bool operator==(const ImpliedDoIndex &) const;
440 static constexpr int Rank() { return 0; }
441 static constexpr int Corank() { return 0; }
442 parser::CharBlock name; // nested implied DOs must use distinct names
443};
444
445template <typename RESULT> class ImpliedDo {
446public:
447 using Result = RESULT;
448 using Index = ResultType<ImpliedDoIndex>;
449 ImpliedDo(parser::CharBlock name, Expr<Index> &&lower, Expr<Index> &&upper,
451 : name_{name}, lower_{std::move(lower)}, upper_{std::move(upper)},
452 stride_{std::move(stride)}, values_{std::move(values)} {}
453 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ImpliedDo)
454 bool operator==(const ImpliedDo &) const;
455 parser::CharBlock name() const { return name_; }
456 Expr<Index> &lower() { return lower_.value(); }
457 const Expr<Index> &lower() const { return lower_.value(); }
458 Expr<Index> &upper() { return upper_.value(); }
459 const Expr<Index> &upper() const { return upper_.value(); }
460 Expr<Index> &stride() { return stride_.value(); }
461 const Expr<Index> &stride() const { return stride_.value(); }
462 ArrayConstructorValues<Result> &values() { return values_.value(); }
463 const ArrayConstructorValues<Result> &values() const {
464 return values_.value();
465 }
466
467private:
468 parser::CharBlock name_;
469 common::CopyableIndirection<Expr<Index>> lower_, upper_, stride_;
470 common::CopyableIndirection<ArrayConstructorValues<Result>> values_;
471};
472
473template <typename RESULT> struct ArrayConstructorValue {
474 using Result = RESULT;
475 EVALUATE_UNION_CLASS_BOILERPLATE(ArrayConstructorValue)
476 std::variant<Expr<Result>, ImpliedDo<Result>> u;
477};
478
479template <typename RESULT> class ArrayConstructorValues {
480public:
481 using Result = RESULT;
482 using Values = std::vector<ArrayConstructorValue<Result>>;
483 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructorValues)
484 ArrayConstructorValues() {}
485
486 bool operator==(const ArrayConstructorValues &) const;
487 static constexpr int Rank() { return 1; }
488 static constexpr int Corank() { return 0; }
489 template <typename A> common::NoLvalue<A> Push(A &&x) {
490 values_.emplace_back(std::move(x));
491 }
492
493 typename Values::iterator begin() { return values_.begin(); }
494 typename Values::const_iterator begin() const { return values_.begin(); }
495 typename Values::iterator end() { return values_.end(); }
496 typename Values::const_iterator end() const { return values_.end(); }
497
498protected:
499 Values values_;
500};
501
502// Note that there are specializations of ArrayConstructor for character
503// and derived types, since they must carry additional type information,
504// but that an empty ArrayConstructor can be constructed for any type
505// given an expression from which such type information may be gleaned.
506template <typename RESULT>
507class ArrayConstructor : public ArrayConstructorValues<RESULT> {
508public:
509 using Result = RESULT;
510 using Base = ArrayConstructorValues<Result>;
511 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructor)
512 explicit ArrayConstructor(Base &&values) : Base{std::move(values)} {}
513 template <typename T> explicit ArrayConstructor(const Expr<T> &) {}
514 static constexpr Result result() { return Result{}; }
515 static constexpr DynamicType GetType() { return Result::GetType(); }
516 llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
517};
518
519template <int KIND>
520class ArrayConstructor<Type<TypeCategory::Character, KIND>>
521 : public ArrayConstructorValues<Type<TypeCategory::Character, KIND>> {
522public:
524 using Base = ArrayConstructorValues<Result>;
525 DEFAULT_CONSTRUCTORS_AND_ASSIGNMENTS(ArrayConstructor)
526 explicit ArrayConstructor(Base &&values) : Base{std::move(values)} {}
527 template <typename T> explicit ArrayConstructor(const Expr<T> &) {}
528 ArrayConstructor &set_LEN(Expr<SubscriptInteger> &&);
529 bool operator==(const ArrayConstructor &) const;
530 static constexpr Result result() { return Result{}; }
531 static constexpr DynamicType GetType() { return Result::GetType(); }
532 llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
533 const Expr<SubscriptInteger> *LEN() const {
534 return length_ ? &length_->value() : nullptr;
535 }
536
537private:
538 std::optional<common::CopyableIndirection<Expr<SubscriptInteger>>> length_;
539};
540
541template <>
542class ArrayConstructor<SomeDerived>
543 : public ArrayConstructorValues<SomeDerived> {
544public:
545 using Result = SomeDerived;
546 using Base = ArrayConstructorValues<Result>;
547 CLASS_BOILERPLATE(ArrayConstructor)
548
549 ArrayConstructor(const semantics::DerivedTypeSpec &spec, Base &&v)
550 : Base{std::move(v)}, result_{spec} {}
551 template <typename A>
552 explicit ArrayConstructor(const A &prototype)
553 : result_{prototype.GetType().value().GetDerivedTypeSpec()} {}
554
555 bool operator==(const ArrayConstructor &) const;
556 constexpr Result result() const { return result_; }
557 constexpr DynamicType GetType() const { return result_.GetType(); }
558 llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
559
560private:
561 Result result_;
562};
563
564// Expression representations for each type category.
565
566template <int KIND>
567class Expr<Type<TypeCategory::Integer, KIND>>
568 : public ExpressionBase<Type<TypeCategory::Integer, KIND>> {
569public:
571
572 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
573
574private:
575 using Conversions = std::tuple<Convert<Result, TypeCategory::Integer>,
578 using Operations = std::tuple<Parentheses<Result>, Negate<Result>,
581 using Indices = std::conditional_t<KIND == ImpliedDoIndex::Result::kind,
582 std::tuple<ImpliedDoIndex>, std::tuple<>>;
583 using TypeParamInquiries =
584 std::conditional_t<KIND == TypeParamInquiry::Result::kind,
585 std::tuple<TypeParamInquiry>, std::tuple<>>;
586 using DescriptorInquiries =
587 std::conditional_t<KIND == DescriptorInquiry::Result::kind,
588 std::tuple<DescriptorInquiry>, std::tuple<>>;
589 using Others = std::tuple<Constant<Result>, ArrayConstructor<Result>,
591
592public:
593 common::TupleToVariant<common::CombineTuples<Operations, Conversions, Indices,
594 TypeParamInquiries, DescriptorInquiries, Others>>
595 u;
596};
597
598template <int KIND>
599class Expr<Type<TypeCategory::Unsigned, KIND>>
600 : public ExpressionBase<Type<TypeCategory::Unsigned, KIND>> {
601public:
603
604 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
605
606private:
607 using Conversions = std::tuple<Convert<Result, TypeCategory::Integer>,
610 using Operations = std::tuple<Parentheses<Result>, Negate<Result>,
613 using Others = std::tuple<Constant<Result>, ArrayConstructor<Result>,
615
616public:
617 common::TupleToVariant<common::CombineTuples<Operations, Conversions, Others>>
618 u;
619};
620
621template <int KIND>
622class Expr<Type<TypeCategory::Real, KIND>>
623 : public ExpressionBase<Type<TypeCategory::Real, KIND>> {
624public:
625 using Result = Type<TypeCategory::Real, KIND>;
626
627 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
628 explicit Expr(const Scalar<Result> &x) : u{Constant<Result>{x}} {}
629
630private:
631 // N.B. Real->Complex and Complex->Real conversions are done with CMPLX
632 // and part access operations (resp.).
633 using Conversions = std::variant<Convert<Result, TypeCategory::Integer>,
636 using Operations = std::variant<ComplexComponent<KIND>, Parentheses<Result>,
640 using Others = std::variant<Constant<Result>, ArrayConstructor<Result>,
642
643public:
644 common::CombineVariants<Operations, Conversions, Others> u;
645};
646
647template <int KIND>
648class Expr<Type<TypeCategory::Complex, KIND>>
649 : public ExpressionBase<Type<TypeCategory::Complex, KIND>> {
650public:
652 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
653 explicit Expr(const Scalar<Result> &x) : u{Constant<Result>{x}} {}
654 using Operations = std::variant<Parentheses<Result>, Negate<Result>,
658 using Others = std::variant<Constant<Result>, ArrayConstructor<Result>,
660
661public:
662 common::CombineVariants<Operations, Others> u;
663};
664
665FOR_EACH_INTEGER_KIND(extern template class Expr, )
666FOR_EACH_UNSIGNED_KIND(extern template class Expr, )
667FOR_EACH_REAL_KIND(extern template class Expr, )
668FOR_EACH_COMPLEX_KIND(extern template class Expr, )
669
670template <int KIND>
671class Expr<Type<TypeCategory::Character, KIND>>
672 : public ExpressionBase<Type<TypeCategory::Character, KIND>> {
673public:
675 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
676 explicit Expr(const Scalar<Result> &x) : u{Constant<Result>{x}} {}
677 explicit Expr(Scalar<Result> &&x) : u{Constant<Result>{std::move(x)}} {}
678
679 std::optional<Expr<SubscriptInteger>> LEN() const;
680
681 std::variant<Constant<Result>, ArrayConstructor<Result>, Designator<Result>,
684 u;
685};
686
687FOR_EACH_CHARACTER_KIND(extern template class Expr, )
688
689// The Relational class template is a helper for constructing logical
690// expressions with polymorphism over the cross product of the possible
691// categories and kinds of comparable operands.
692// Fortran defines a numeric relation with distinct types or kinds as
693// first undergoing the same operand conversions that occur with the intrinsic
694// addition operator. Character relations must have the same kind.
695// There are no relations between LOGICAL values.
696
697template <typename T>
698class Relational : public Operation<Relational<T>, LogicalResult, T, T> {
699public:
700 using Result = LogicalResult;
701 using Base = Operation<Relational, LogicalResult, T, T>;
702 using Operand = typename Base::template Operand<0>;
703 static_assert(Operand::category == TypeCategory::Integer ||
704 Operand::category == TypeCategory::Real ||
705 Operand::category == TypeCategory::Complex ||
706 Operand::category == TypeCategory::Character ||
707 Operand::category == TypeCategory::Unsigned);
708 CLASS_BOILERPLATE(Relational)
709 Relational(
710 RelationalOperator r, const Expr<Operand> &a, const Expr<Operand> &b)
711 : Base{a, b}, opr{r} {}
712 Relational(RelationalOperator r, Expr<Operand> &&a, Expr<Operand> &&b)
713 : Base{std::move(a), std::move(b)}, opr{r} {}
714 bool operator==(const Relational &) const;
715 RelationalOperator opr;
716};
717
718template <> class Relational<SomeType> {
719 using DirectlyComparableTypes = common::CombineTuples<IntegerTypes, RealTypes,
720 ComplexTypes, CharacterTypes, UnsignedTypes>;
721
722public:
723 using Result = LogicalResult;
724 EVALUATE_UNION_CLASS_BOILERPLATE(Relational)
725 static constexpr DynamicType GetType() { return Result::GetType(); }
726 int Rank() const {
727 return common::visit([](const auto &x) { return x.Rank(); }, u);
728 }
729 static constexpr int Corank() { return 0; }
730 llvm::raw_ostream &AsFortran(llvm::raw_ostream &o) const;
731 common::MapTemplate<Relational, DirectlyComparableTypes> u;
732};
733
734FOR_EACH_INTEGER_KIND(extern template class Relational, )
735FOR_EACH_UNSIGNED_KIND(extern template class Relational, )
736FOR_EACH_REAL_KIND(extern template class Relational, )
737FOR_EACH_CHARACTER_KIND(extern template class Relational, )
738extern template class Relational<SomeType>;
739
740// Logical expressions of a kind bigger than LogicalResult
741// do not include Relational<> operations as possibilities,
742// since the results of Relationals are always LogicalResult
743// (kind=4).
744template <int KIND>
745class Expr<Type<TypeCategory::Logical, KIND>>
746 : public ExpressionBase<Type<TypeCategory::Logical, KIND>> {
747public:
749 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
750 explicit Expr(const Scalar<Result> &x) : u{Constant<Result>{x}} {}
751 explicit Expr(bool x) : u{Constant<Result>{x}} {}
752
753private:
754 using Operations = std::tuple<Convert<Result>, Parentheses<Result>, Not<KIND>,
756 using Relations = std::conditional_t<KIND == LogicalResult::kind,
757 std::tuple<Relational<SomeType>>, std::tuple<>>;
758 using Others = std::tuple<Constant<Result>, ArrayConstructor<Result>,
760
761public:
762 common::TupleToVariant<common::CombineTuples<Operations, Relations, Others>>
763 u;
764};
765
766FOR_EACH_LOGICAL_KIND(extern template class Expr, )
767
768// StructureConstructor pairs a StructureConstructorValues instance
769// (a map associating symbols with expressions) with a derived type
770// specification. There are two other similar classes:
771// - ArrayConstructor<SomeDerived> comprises a derived type spec &
772// zero or more instances of Expr<SomeDerived>; it has rank 1
773// but not (in the most general case) a known shape.
774// - Constant<SomeDerived> comprises a derived type spec, zero or more
775// homogeneous instances of StructureConstructorValues whose type
776// parameters and component expressions are all constant, and a
777// known shape (possibly scalar).
778// StructureConstructor represents a scalar value of derived type that
779// is not necessarily a constant. It is used only as an Expr<SomeDerived>
780// alternative and as the type Scalar<SomeDerived> (with an assumption
781// of constant component value expressions).
782class StructureConstructor {
783public:
784 using Result = SomeDerived;
785
786 explicit StructureConstructor(const semantics::DerivedTypeSpec &spec)
787 : result_{spec} {}
788 StructureConstructor(
789 const semantics::DerivedTypeSpec &, const StructureConstructorValues &);
790 StructureConstructor(
791 const semantics::DerivedTypeSpec &, StructureConstructorValues &&);
792 CLASS_BOILERPLATE(StructureConstructor)
793
794 constexpr Result result() const { return result_; }
795 const semantics::DerivedTypeSpec &derivedTypeSpec() const {
796 return result_.derivedTypeSpec();
797 }
798 StructureConstructorValues &values() { return values_; }
799 const StructureConstructorValues &values() const { return values_; }
800
801 bool operator==(const StructureConstructor &) const;
802
803 StructureConstructorValues::iterator begin() { return values_.begin(); }
804 StructureConstructorValues::const_iterator begin() const {
805 return values_.begin();
806 }
807 StructureConstructorValues::iterator end() { return values_.end(); }
808 StructureConstructorValues::const_iterator end() const {
809 return values_.end();
810 }
811
812 // can return nullopt
813 std::optional<Expr<SomeType>> Find(const Symbol &) const;
814
815 StructureConstructor &Add(const semantics::Symbol &, Expr<SomeType> &&);
816 static constexpr int Rank() { return 0; }
817 static constexpr int Corank() { return 0; }
818 DynamicType GetType() const;
819 llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
820
821private:
822 std::optional<Expr<SomeType>> CreateParentComponent(const Symbol &) const;
823 Result result_;
824 StructureConstructorValues values_;
825};
826
827// An expression whose result has a derived type.
828template <> class Expr<SomeDerived> : public ExpressionBase<SomeDerived> {
829public:
830 using Result = SomeDerived;
831 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
832 std::variant<Constant<Result>, ArrayConstructor<Result>, StructureConstructor,
835 u;
836};
837
838// A polymorphic expression of known intrinsic type category, but dynamic
839// kind, represented as a discriminated union over Expr<Type<CAT, K>>
840// for each supported kind K in the category.
841template <TypeCategory CAT>
842class Expr<SomeKind<CAT>> : public ExpressionBase<SomeKind<CAT>> {
843public:
844 using Result = SomeKind<CAT>;
845 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
846 int GetKind() const;
847 common::MapTemplate<evaluate::Expr, CategoryTypes<CAT>> u;
848};
849
850template <> class Expr<SomeCharacter> : public ExpressionBase<SomeCharacter> {
851public:
852 using Result = SomeCharacter;
853 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
854 int GetKind() const;
855 std::optional<Expr<SubscriptInteger>> LEN() const;
856 common::MapTemplate<Expr, CategoryTypes<TypeCategory::Character>> u;
857};
858
859// A variant comprising the Expr<> instantiations over SomeDerived and
860// SomeKind<CATEGORY>.
861using CategoryExpression = common::MapTemplate<Expr, SomeCategory>;
862
863// BOZ literal "typeless" constants must be wide enough to hold a numeric
864// value of any supported kind of INTEGER or REAL. They must also be
865// distinguishable from other integer constants, since they are permitted
866// to be used in only a few situations.
867using BOZLiteralConstant = typename LargestReal::Scalar::Word;
868
869// Null pointers without MOLD= arguments are typed by context.
871 constexpr bool operator==(const NullPointer &) const { return true; }
872 static constexpr int Rank() { return 0; }
873 static constexpr int Corank() { return 0; }
874};
875
876// Procedure pointer targets are treated as if they were typeless.
877// They are either procedure designators or values returned from
878// references to functions that return procedure (not object) pointers.
879using TypelessExpression = std::variant<BOZLiteralConstant, NullPointer,
881
882// A completely generic expression, polymorphic across all of the intrinsic type
883// categories and each of their kinds.
884template <> class Expr<SomeType> : public ExpressionBase<SomeType> {
885public:
886 using Result = SomeType;
887 EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
888
889 // Owning references to these generic expressions can appear in other
890 // compiler data structures (viz., the parse tree and symbol table), so
891 // its destructor is externalized to reduce redundant default instances.
892 ~Expr();
893
894 template <TypeCategory CAT, int KIND>
895 explicit Expr(const Expr<Type<CAT, KIND>> &x) : u{Expr<SomeKind<CAT>>{x}} {}
896
897 template <TypeCategory CAT, int KIND>
898 explicit Expr(Expr<Type<CAT, KIND>> &&x)
899 : u{Expr<SomeKind<CAT>>{std::move(x)}} {}
900
901 template <TypeCategory CAT, int KIND>
902 Expr &operator=(const Expr<Type<CAT, KIND>> &x) {
903 u = Expr<SomeKind<CAT>>{x};
904 return *this;
905 }
906
907 template <TypeCategory CAT, int KIND>
908 Expr &operator=(Expr<Type<CAT, KIND>> &&x) {
909 u = Expr<SomeKind<CAT>>{std::move(x)};
910 return *this;
911 }
912
913public:
914 common::CombineVariants<TypelessExpression, CategoryExpression> u;
915};
916
917// An assignment is either intrinsic, user-defined (with a ProcedureRef to
918// specify the procedure to call), or pointer assignment (with possibly empty
919// BoundsSpec or non-empty BoundsRemapping). In all cases there are Exprs
920// representing the LHS and RHS of the assignment.
921class Assignment {
922public:
923 Assignment(Expr<SomeType> &&lhs, Expr<SomeType> &&rhs)
924 : lhs(std::move(lhs)), rhs(std::move(rhs)) {}
925
926 struct Intrinsic {};
927 using BoundsSpec = std::vector<Expr<SubscriptInteger>>;
928 using BoundsRemapping =
929 std::vector<std::pair<Expr<SubscriptInteger>, Expr<SubscriptInteger>>>;
930 llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
931
932 Expr<SomeType> lhs;
933 Expr<SomeType> rhs;
934 std::variant<Intrinsic, ProcedureRef, BoundsSpec, BoundsRemapping> u;
935};
936
937// This wrapper class is used, by means of a forward reference with
938// an owning pointer, to cache analyzed expressions in parse tree nodes.
939struct GenericExprWrapper {
940 GenericExprWrapper() {}
941 explicit GenericExprWrapper(std::optional<Expr<SomeType>> &&x)
942 : v{std::move(x)} {}
943 ~GenericExprWrapper();
944 static void Deleter(GenericExprWrapper *);
945 std::optional<Expr<SomeType>> v; // vacant if error
946};
947
948// Like GenericExprWrapper but for analyzed assignments
949struct GenericAssignmentWrapper {
950 GenericAssignmentWrapper() {}
951 explicit GenericAssignmentWrapper(Assignment &&x) : v{std::move(x)} {}
952 explicit GenericAssignmentWrapper(std::optional<Assignment> &&x)
953 : v{std::move(x)} {}
954 ~GenericAssignmentWrapper();
955 static void Deleter(GenericAssignmentWrapper *);
956 std::optional<Assignment> v; // vacant if error
957};
958
959FOR_EACH_CATEGORY_TYPE(extern template class Expr, )
960FOR_EACH_TYPE_AND_KIND(extern template class ExpressionBase, )
961FOR_EACH_INTRINSIC_KIND(extern template class ArrayConstructorValues, )
962FOR_EACH_INTRINSIC_KIND(extern template class ArrayConstructor, )
963
964// Template instantiations to resolve these "extern template" declarations.
965#define INSTANTIATE_EXPRESSION_TEMPLATES \
966 FOR_EACH_INTRINSIC_KIND(template class Expr, ) \
967 FOR_EACH_CATEGORY_TYPE(template class Expr, ) \
968 FOR_EACH_INTEGER_KIND(template class Relational, ) \
969 FOR_EACH_UNSIGNED_KIND(template class Relational, ) \
970 FOR_EACH_REAL_KIND(template class Relational, ) \
971 FOR_EACH_CHARACTER_KIND(template class Relational, ) \
972 template class Relational<SomeType>; \
973 FOR_EACH_TYPE_AND_KIND(template class ExpressionBase, ) \
974 FOR_EACH_INTRINSIC_KIND(template class ArrayConstructorValues, ) \
975 FOR_EACH_INTRINSIC_KIND(template class ArrayConstructor, ) \
976 FOR_EACH_INTRINSIC_KIND(template class ConditionalExpr, )
977} // namespace Fortran::evaluate
978#endif // FORTRAN_EVALUATE_EXPRESSION_H_
Definition expression.h:507
Definition expression.h:921
Definition expression.h:395
Definition constant.h:147
Definition variable.h:381
Definition type.h:74
Definition common.h:215
Definition expression.h:66
Definition common.h:217
Definition call.h:294
Definition expression.h:445
Definition call.h:234
Definition expression.h:698
Definition expression.h:782
Definition type.h:57
Definition char-block.h:28
Definition symbol.h:832
Definition call.h:34
Definition expression.h:296
Definition expression.h:473
Definition expression.h:926
Definition expression.h:357
Definition expression.h:368
Definition expression.h:211
Definition expression.h:317
Definition expression.h:340
Definition expression.h:437
Definition expression.h:379
Definition expression.h:310
Definition expression.h:247
Definition expression.h:272
Definition expression.h:870
Definition expression.h:229
Definition expression.h:324
Definition expression.h:332
Definition expression.h:286
Definition type.h:399
Definition type.h:417
Definition expression.h:303