Warning: This file is not a C or C++ file. It does not have highlighting.

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

Warning: This file is not a C or C++ file. It does not have highlighting.

source code of flang/include/flang/Evaluate/expression.h