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