2018-06-18 21:09:56 +02:00
|
|
|
// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
#ifndef FORTRAN_EVALUATE_EXPRESSION_H_
|
|
|
|
#define FORTRAN_EVALUATE_EXPRESSION_H_
|
|
|
|
|
2018-06-22 20:02:54 +02:00
|
|
|
// Represent Fortran expressions in a type-safe manner.
|
|
|
|
// Expressions are the sole owners of their constituents; there is no
|
|
|
|
// context-independent hash table or sharing of common subexpressions.
|
|
|
|
// Both deep copy and move semantics are supported for expression construction.
|
|
|
|
// TODO: variable and function references
|
|
|
|
|
2018-06-19 23:16:01 +02:00
|
|
|
#include "common.h"
|
2018-06-18 21:09:56 +02:00
|
|
|
#include "type.h"
|
2018-06-21 20:03:00 +02:00
|
|
|
#include <memory>
|
2018-06-20 20:55:10 +02:00
|
|
|
#include <ostream>
|
2018-06-18 21:09:56 +02:00
|
|
|
#include <variant>
|
|
|
|
|
|
|
|
namespace Fortran::evaluate {
|
|
|
|
|
2018-06-22 00:35:25 +02:00
|
|
|
// Some forward definitions
|
|
|
|
template<int KIND> struct IntegerExpr;
|
|
|
|
template<int KIND> struct RealExpr;
|
|
|
|
template<int KIND> struct ComplexExpr;
|
|
|
|
template<int KIND> struct CharacterExpr;
|
|
|
|
struct AnyIntegerExpr;
|
|
|
|
struct AnyRealExpr;
|
|
|
|
struct AnyComplexExpr;
|
|
|
|
struct AnyCharacterExpr;
|
|
|
|
struct AnyIntegerOrRealExpr;
|
|
|
|
|
2018-06-22 22:00:13 +02:00
|
|
|
// Helper base classes to manage subexpressions, which are known as data members
|
|
|
|
// named 'x' and (for binary operations) 'y'.
|
2018-06-22 20:02:54 +02:00
|
|
|
template<typename A> struct Unary {
|
|
|
|
Unary(const A &a) : x{std::make_unique<A>(a)} {}
|
|
|
|
Unary(std::unique_ptr<const A> &&a) : x{std::move(a)} {}
|
|
|
|
Unary(A &&a) : x{std::make_unique<A>(std::move(a))} {}
|
2018-06-22 22:00:13 +02:00
|
|
|
Unary(const Unary &that) : x{std::make_unique<A>(*that.x)} {}
|
2018-06-22 20:02:54 +02:00
|
|
|
Unary(Unary &&) = default;
|
2018-06-22 21:22:50 +02:00
|
|
|
Unary &operator=(const Unary &that) {
|
2018-06-22 22:00:13 +02:00
|
|
|
x = std::make_unique<A>(*that.x);
|
2018-06-22 21:22:50 +02:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
Unary &operator=(Unary &&) = default;
|
2018-06-22 20:02:54 +02:00
|
|
|
std::unique_ptr<const A> x;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename A, typename B> struct Binary {
|
|
|
|
Binary(const A &a, const B &b)
|
|
|
|
: x{std::make_unique<A>(a)}, y{std::make_unique<B>(b)} {}
|
|
|
|
Binary(std::unique_ptr<const A> &&a, std::unique_ptr<const B> &&b)
|
|
|
|
: x{std::move(a)}, y{std::move(b)} {}
|
|
|
|
Binary(A &&a, B &&b)
|
|
|
|
: x{std::make_unique<A>(std::move(a))}, y{std::make_unique<B>(
|
|
|
|
std::move(b))} {}
|
2018-06-22 21:22:50 +02:00
|
|
|
Binary(const Binary &that)
|
2018-06-22 22:00:13 +02:00
|
|
|
: x{std::make_unique<A>(*that.x)}, y{std::make_unique<B>(*that.y)} {}
|
2018-06-22 20:02:54 +02:00
|
|
|
Binary(Binary &&) = default;
|
2018-06-22 21:22:50 +02:00
|
|
|
Binary &operator=(const Binary &that) {
|
2018-06-22 22:00:13 +02:00
|
|
|
x = std::make_unique<A>(*that.x);
|
|
|
|
y = std::make_unique<B>(*that.y);
|
2018-06-22 21:22:50 +02:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
Binary &operator=(Binary &&) = default;
|
2018-06-22 20:02:54 +02:00
|
|
|
std::unique_ptr<const A> x;
|
|
|
|
std::unique_ptr<const B> y;
|
|
|
|
};
|
|
|
|
|
2018-06-22 00:35:25 +02:00
|
|
|
template<int KIND> struct IntegerExpr {
|
|
|
|
using Result = Type<Category::Integer, KIND>;
|
2018-06-19 23:16:01 +02:00
|
|
|
using Constant = typename Result::Value;
|
2018-06-22 20:02:54 +02:00
|
|
|
struct Convert : Unary<AnyIntegerOrRealExpr> {
|
|
|
|
using Unary<AnyIntegerOrRealExpr>::Unary;
|
|
|
|
};
|
|
|
|
using Un = Unary<IntegerExpr>;
|
|
|
|
using Bin = Binary<IntegerExpr, IntegerExpr>;
|
|
|
|
struct Parentheses : public Un {
|
|
|
|
using Un::Un;
|
2018-06-19 23:16:01 +02:00
|
|
|
};
|
2018-06-22 20:02:54 +02:00
|
|
|
struct Negate : public Un {
|
|
|
|
using Un::Un;
|
2018-06-20 19:53:49 +02:00
|
|
|
};
|
2018-06-22 20:02:54 +02:00
|
|
|
struct Add : public Bin {
|
|
|
|
using Bin::Bin;
|
|
|
|
};
|
|
|
|
struct Subtract : public Bin {
|
|
|
|
using Bin::Bin;
|
|
|
|
};
|
|
|
|
struct Multiply : public Bin {
|
|
|
|
using Bin::Bin;
|
|
|
|
};
|
|
|
|
struct Divide : public Bin {
|
|
|
|
using Bin::Bin;
|
|
|
|
};
|
|
|
|
struct Power : public Bin {
|
|
|
|
using Bin::Bin;
|
2018-06-20 19:53:49 +02:00
|
|
|
};
|
2018-06-18 21:09:56 +02:00
|
|
|
|
2018-06-22 00:35:25 +02:00
|
|
|
IntegerExpr() = delete;
|
2018-06-22 20:02:54 +02:00
|
|
|
IntegerExpr(const IntegerExpr &) = default;
|
2018-06-22 00:35:25 +02:00
|
|
|
IntegerExpr(IntegerExpr &&) = default;
|
|
|
|
IntegerExpr(const Constant &x) : u{x} {}
|
|
|
|
IntegerExpr(std::int64_t n) : u{Constant{n}} {}
|
|
|
|
IntegerExpr(int n) : u{Constant{n}} {}
|
|
|
|
template<typename A> IntegerExpr(A &&x) : u{std::move(x)} {}
|
2018-06-22 21:22:50 +02:00
|
|
|
IntegerExpr &operator=(const IntegerExpr &) = default;
|
|
|
|
IntegerExpr &operator=(IntegerExpr &&) = default;
|
2018-06-21 21:47:28 +02:00
|
|
|
|
2018-06-21 01:50:27 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-06-21 21:47:28 +02:00
|
|
|
|
2018-06-20 19:53:49 +02:00
|
|
|
std::variant<Constant, Convert, Parentheses, Negate, Add, Subtract, Multiply,
|
|
|
|
Divide, Power>
|
|
|
|
u;
|
2018-06-19 23:16:01 +02:00
|
|
|
};
|
|
|
|
|
2018-06-22 00:35:25 +02:00
|
|
|
using DefaultIntegerExpr = IntegerExpr<DefaultInteger::kind>;
|
|
|
|
|
|
|
|
template<int KIND> struct RealExpr {
|
|
|
|
using Result = Type<Category::Real, KIND>;
|
2018-06-21 20:03:00 +02:00
|
|
|
using Constant = typename Result::Value;
|
2018-06-22 20:02:54 +02:00
|
|
|
// N.B. Real->Complex and Complex->Real conversions are done with CMPLX
|
|
|
|
// and part access operations (resp.). Conversions between kinds of
|
|
|
|
// Complex are done via decomposition to Real and reconstruction.
|
|
|
|
struct Convert : Unary<AnyIntegerOrRealExpr> {
|
|
|
|
using Unary<AnyIntegerOrRealExpr>::Unary;
|
|
|
|
};
|
|
|
|
using Un = Unary<RealExpr>;
|
|
|
|
using Bin = Binary<RealExpr, RealExpr>;
|
|
|
|
struct Parentheses : public Un {
|
|
|
|
using Un::Un;
|
|
|
|
};
|
|
|
|
struct Negate : public Un {
|
|
|
|
using Un::Un;
|
|
|
|
};
|
|
|
|
struct Add : public Bin {
|
|
|
|
using Bin::Bin;
|
|
|
|
};
|
|
|
|
struct Subtract : public Bin {
|
|
|
|
using Bin::Bin;
|
|
|
|
};
|
|
|
|
struct Multiply : public Bin {
|
|
|
|
using Bin::Bin;
|
|
|
|
};
|
|
|
|
struct Divide : public Bin {
|
|
|
|
using Bin::Bin;
|
|
|
|
};
|
|
|
|
struct Power : public Bin {
|
|
|
|
using Bin::Bin;
|
|
|
|
};
|
|
|
|
struct IntPower : public Binary<RealExpr, AnyIntegerExpr> {
|
|
|
|
using Binary<RealExpr, AnyIntegerExpr>::Binary;
|
|
|
|
};
|
|
|
|
using CplxUn = Unary<ComplexExpr<KIND>>;
|
|
|
|
struct RealPart : public CplxUn {
|
|
|
|
using CplxUn::CplxUn;
|
|
|
|
};
|
|
|
|
struct AIMAG : public CplxUn {
|
|
|
|
using CplxUn::CplxUn;
|
|
|
|
};
|
2018-06-21 20:03:00 +02:00
|
|
|
|
2018-06-22 00:35:25 +02:00
|
|
|
RealExpr() = delete;
|
2018-06-22 20:02:54 +02:00
|
|
|
RealExpr(const RealExpr &) = default;
|
2018-06-22 00:35:25 +02:00
|
|
|
RealExpr(RealExpr &&) = default;
|
|
|
|
RealExpr(const Constant &x) : u{x} {}
|
|
|
|
template<typename A> RealExpr(A &&x) : u{std::move(x)} {}
|
2018-06-22 21:22:50 +02:00
|
|
|
RealExpr &operator=(const RealExpr &) = default;
|
|
|
|
RealExpr &operator=(RealExpr &&) = default;
|
2018-06-21 21:47:28 +02:00
|
|
|
|
2018-06-21 01:50:27 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-06-21 21:47:28 +02:00
|
|
|
|
2018-06-20 19:53:49 +02:00
|
|
|
std::variant<Constant, Convert, Parentheses, Negate, Add, Subtract, Multiply,
|
2018-06-21 21:47:28 +02:00
|
|
|
Divide, Power, IntPower, RealPart, AIMAG>
|
2018-06-20 19:53:49 +02:00
|
|
|
u;
|
2018-06-19 23:16:01 +02:00
|
|
|
};
|
|
|
|
|
2018-06-22 00:35:25 +02:00
|
|
|
template<int KIND> struct ComplexExpr {
|
|
|
|
using Result = Type<Category::Complex, KIND>;
|
2018-06-21 20:03:00 +02:00
|
|
|
using Constant = typename Result::Value;
|
2018-06-22 20:02:54 +02:00
|
|
|
using Un = Unary<ComplexExpr>;
|
|
|
|
using Bin = Binary<ComplexExpr, ComplexExpr>;
|
|
|
|
struct Parentheses : public Un {
|
|
|
|
using Un::Un;
|
2018-06-21 20:03:00 +02:00
|
|
|
};
|
2018-06-22 20:02:54 +02:00
|
|
|
struct Negate : public Un {
|
|
|
|
using Un::Un;
|
2018-06-21 20:03:00 +02:00
|
|
|
};
|
2018-06-22 20:02:54 +02:00
|
|
|
struct Add : public Bin {
|
|
|
|
using Bin::Bin;
|
2018-06-21 20:03:00 +02:00
|
|
|
};
|
2018-06-22 20:02:54 +02:00
|
|
|
struct Subtract : public Bin {
|
|
|
|
using Bin::Bin;
|
|
|
|
};
|
|
|
|
struct Multiply : public Bin {
|
|
|
|
using Bin::Bin;
|
|
|
|
};
|
|
|
|
struct Divide : public Bin {
|
|
|
|
using Bin::Bin;
|
|
|
|
};
|
|
|
|
struct Power : public Bin {
|
|
|
|
using Bin::Bin;
|
|
|
|
};
|
|
|
|
struct IntPower : public Binary<ComplexExpr, AnyIntegerExpr> {
|
|
|
|
using Binary<ComplexExpr, AnyIntegerExpr>::Binary;
|
|
|
|
};
|
|
|
|
struct CMPLX : public Binary<RealExpr<KIND>, RealExpr<KIND>> {
|
|
|
|
using Binary<RealExpr<KIND>, RealExpr<KIND>>::Binary;
|
2018-06-20 19:53:49 +02:00
|
|
|
};
|
2018-06-21 20:03:00 +02:00
|
|
|
|
2018-06-22 00:35:25 +02:00
|
|
|
ComplexExpr() = delete;
|
2018-06-22 20:02:54 +02:00
|
|
|
ComplexExpr(const ComplexExpr &) = default;
|
2018-06-22 00:35:25 +02:00
|
|
|
ComplexExpr(ComplexExpr &&) = default;
|
|
|
|
ComplexExpr(const Constant &x) : u{x} {}
|
|
|
|
template<typename A> ComplexExpr(A &&x) : u{std::move(x)} {}
|
2018-06-22 21:22:50 +02:00
|
|
|
ComplexExpr &operator=(const ComplexExpr &) = default;
|
|
|
|
ComplexExpr &operator=(ComplexExpr &&) = default;
|
2018-06-21 21:47:28 +02:00
|
|
|
|
2018-06-21 01:50:27 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-06-21 21:47:28 +02:00
|
|
|
|
2018-06-20 19:53:49 +02:00
|
|
|
std::variant<Constant, Parentheses, Negate, Add, Subtract, Multiply, Divide,
|
2018-06-21 21:47:28 +02:00
|
|
|
Power, IntPower, CMPLX>
|
2018-06-20 19:53:49 +02:00
|
|
|
u;
|
2018-06-19 23:16:01 +02:00
|
|
|
};
|
|
|
|
|
2018-06-22 00:35:25 +02:00
|
|
|
template<int KIND> struct CharacterExpr {
|
|
|
|
using Result = Type<Category::Character, KIND>;
|
|
|
|
using Constant = typename Result::Value;
|
2018-06-22 20:02:54 +02:00
|
|
|
using LengthExpr = IntegerExpr<IntrinsicTypeParameterType::kind>;
|
|
|
|
struct Concat : public Binary<CharacterExpr, CharacterExpr> {
|
|
|
|
using Binary<CharacterExpr, CharacterExpr>::Binary;
|
2018-06-22 00:35:25 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
CharacterExpr() = delete;
|
2018-06-22 20:02:54 +02:00
|
|
|
CharacterExpr(const CharacterExpr &) = default;
|
2018-06-22 00:35:25 +02:00
|
|
|
CharacterExpr(CharacterExpr &&) = default;
|
|
|
|
CharacterExpr(const Constant &x) : u{x} {}
|
2018-06-22 20:02:54 +02:00
|
|
|
CharacterExpr(Constant &&x) : u{std::move(x)} {}
|
|
|
|
CharacterExpr(Concat &&x) : u{std::move(x)} {}
|
2018-06-22 21:22:50 +02:00
|
|
|
CharacterExpr &operator=(const CharacterExpr &) = default;
|
|
|
|
CharacterExpr &operator=(CharacterExpr &&) = default;
|
2018-06-22 00:35:25 +02:00
|
|
|
|
2018-06-22 20:02:54 +02:00
|
|
|
IntegerExpr<IntrinsicTypeParameterType::kind> LEN() const;
|
2018-06-22 00:35:25 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
|
|
|
|
|
|
|
std::variant<Constant, Concat> u;
|
|
|
|
};
|
|
|
|
|
2018-06-21 21:47:28 +02:00
|
|
|
// The Comparison class template is a helper for constructing logical
|
2018-06-22 22:00:13 +02:00
|
|
|
// expressions with polymorphism over the cross product of the possible
|
|
|
|
// categories and kinds of comparable operands.
|
2018-06-21 20:03:00 +02:00
|
|
|
template<typename T> struct Comparison {
|
2018-06-22 20:02:54 +02:00
|
|
|
struct LT : public Binary<T, T> {
|
|
|
|
using Binary<T, T>::Binary;
|
|
|
|
};
|
|
|
|
struct LE : public Binary<T, T> {
|
|
|
|
using Binary<T, T>::Binary;
|
|
|
|
};
|
|
|
|
struct EQ : public Binary<T, T> {
|
|
|
|
using Binary<T, T>::Binary;
|
|
|
|
};
|
|
|
|
struct NE : public Binary<T, T> {
|
|
|
|
using Binary<T, T>::Binary;
|
|
|
|
};
|
|
|
|
struct GE : public Binary<T, T> {
|
|
|
|
using Binary<T, T>::Binary;
|
|
|
|
};
|
|
|
|
struct GT : public Binary<T, T> {
|
|
|
|
using Binary<T, T>::Binary;
|
2018-06-20 19:53:49 +02:00
|
|
|
};
|
2018-06-21 20:03:00 +02:00
|
|
|
|
|
|
|
Comparison() = delete;
|
2018-06-22 20:02:54 +02:00
|
|
|
Comparison(const Comparison &) = default;
|
2018-06-21 20:03:00 +02:00
|
|
|
Comparison(Comparison &&) = default;
|
|
|
|
template<typename A> Comparison(A &&x) : u{std::move(x)} {}
|
2018-06-22 21:22:50 +02:00
|
|
|
Comparison &operator=(const Comparison &) = default;
|
|
|
|
Comparison &operator=(Comparison &&) = default;
|
2018-06-21 20:03:00 +02:00
|
|
|
|
|
|
|
std::ostream &Dump(std::ostream &) const;
|
|
|
|
|
|
|
|
std::variant<LT, LE, EQ, NE, GE, GT> u;
|
|
|
|
};
|
|
|
|
|
2018-06-22 00:35:25 +02:00
|
|
|
// COMPLEX admits only .EQ. and .NE. comparisons.
|
|
|
|
template<int KIND> struct Comparison<ComplexExpr<KIND>> {
|
2018-06-22 20:02:54 +02:00
|
|
|
using Bin = Binary<ComplexExpr<KIND>, ComplexExpr<KIND>>;
|
|
|
|
struct EQ : public Bin {
|
|
|
|
using Bin::Bin;
|
|
|
|
};
|
|
|
|
struct NE : public Bin {
|
|
|
|
using Bin::Bin;
|
2018-06-20 19:53:49 +02:00
|
|
|
};
|
2018-06-19 23:16:01 +02:00
|
|
|
|
2018-06-21 20:03:00 +02:00
|
|
|
Comparison() = delete;
|
2018-06-22 20:02:54 +02:00
|
|
|
Comparison(const Comparison &) = default;
|
2018-06-21 20:03:00 +02:00
|
|
|
Comparison(Comparison &&) = default;
|
|
|
|
template<typename A> Comparison(A &&x) : u{std::move(x)} {}
|
2018-06-22 21:22:50 +02:00
|
|
|
Comparison &operator=(const Comparison &) = default;
|
|
|
|
Comparison &operator=(Comparison &&) = default;
|
2018-06-19 23:16:01 +02:00
|
|
|
|
2018-06-21 20:03:00 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-06-19 23:16:01 +02:00
|
|
|
|
2018-06-21 20:03:00 +02:00
|
|
|
std::variant<EQ, NE> u;
|
|
|
|
};
|
2018-06-20 01:26:48 +02:00
|
|
|
|
2018-06-21 20:03:00 +02:00
|
|
|
struct IntegerComparison {
|
2018-06-21 21:47:28 +02:00
|
|
|
IntegerComparison() = delete;
|
2018-06-22 20:02:54 +02:00
|
|
|
IntegerComparison(const IntegerComparison &) = default;
|
2018-06-21 21:47:28 +02:00
|
|
|
IntegerComparison(IntegerComparison &&) = default;
|
|
|
|
template<typename A> IntegerComparison(A &&x) : u{std::move(x)} {}
|
2018-06-22 21:22:50 +02:00
|
|
|
IntegerComparison &operator=(const IntegerComparison &) = default;
|
|
|
|
IntegerComparison &operator=(IntegerComparison &&) = default;
|
2018-06-21 21:47:28 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-06-22 00:35:25 +02:00
|
|
|
template<int KIND> using C = Comparison<IntegerExpr<KIND>>;
|
2018-06-21 20:03:00 +02:00
|
|
|
IntegerKindsVariant<C> u;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct RealComparison {
|
2018-06-21 21:47:28 +02:00
|
|
|
RealComparison() = delete;
|
2018-06-22 20:02:54 +02:00
|
|
|
RealComparison(const RealComparison &) = default;
|
2018-06-21 21:47:28 +02:00
|
|
|
RealComparison(RealComparison &&) = default;
|
|
|
|
template<typename A> RealComparison(A &&x) : u{std::move(x)} {}
|
2018-06-22 21:22:50 +02:00
|
|
|
RealComparison &operator=(const RealComparison &) = default;
|
|
|
|
RealComparison &operator=(RealComparison &&) = default;
|
2018-06-21 21:47:28 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-06-22 00:35:25 +02:00
|
|
|
template<int KIND> using C = Comparison<RealExpr<KIND>>;
|
2018-06-21 20:03:00 +02:00
|
|
|
RealKindsVariant<C> u;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ComplexComparison {
|
2018-06-21 21:47:28 +02:00
|
|
|
ComplexComparison() = delete;
|
|
|
|
ComplexComparison(ComplexComparison &&) = default;
|
|
|
|
template<typename A> ComplexComparison(A &&x) : u{std::move(x)} {}
|
2018-06-22 21:22:50 +02:00
|
|
|
ComplexComparison &operator=(const ComplexComparison &) = default;
|
|
|
|
ComplexComparison &operator=(ComplexComparison &&) = default;
|
2018-06-21 21:47:28 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-06-22 00:35:25 +02:00
|
|
|
template<int KIND> using C = Comparison<ComplexExpr<KIND>>;
|
|
|
|
ComplexKindsVariant<C> u;
|
2018-06-21 20:03:00 +02:00
|
|
|
};
|
2018-06-19 23:16:01 +02:00
|
|
|
|
2018-06-21 20:03:00 +02:00
|
|
|
struct CharacterComparison {
|
2018-06-21 21:47:28 +02:00
|
|
|
CharacterComparison() = delete;
|
2018-06-22 20:02:54 +02:00
|
|
|
CharacterComparison(const CharacterComparison &) = default;
|
2018-06-21 21:47:28 +02:00
|
|
|
CharacterComparison(CharacterComparison &&) = default;
|
|
|
|
template<typename A> CharacterComparison(A &&x) : u{std::move(x)} {}
|
2018-06-22 21:22:50 +02:00
|
|
|
CharacterComparison &operator=(const CharacterComparison &) = default;
|
|
|
|
CharacterComparison &operator=(CharacterComparison &&) = default;
|
2018-06-21 21:47:28 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-06-22 00:35:25 +02:00
|
|
|
template<int KIND> using C = Comparison<CharacterExpr<KIND>>;
|
2018-06-21 20:03:00 +02:00
|
|
|
CharacterKindsVariant<C> u;
|
|
|
|
};
|
|
|
|
|
2018-06-22 00:35:25 +02:00
|
|
|
// No need to distinguish the various kinds of LOGICAL expression results.
|
|
|
|
struct LogicalExpr {
|
2018-06-21 21:47:28 +02:00
|
|
|
using Constant = bool;
|
2018-06-22 20:02:54 +02:00
|
|
|
struct Not : Unary<LogicalExpr> {
|
|
|
|
using Unary<LogicalExpr>::Unary;
|
2018-06-20 19:53:49 +02:00
|
|
|
};
|
2018-06-22 20:02:54 +02:00
|
|
|
using Bin = Binary<LogicalExpr, LogicalExpr>;
|
|
|
|
struct And : public Bin {
|
|
|
|
using Bin::Bin;
|
|
|
|
};
|
|
|
|
struct Or : public Bin {
|
|
|
|
using Bin::Bin;
|
|
|
|
};
|
|
|
|
struct Eqv : public Bin {
|
|
|
|
using Bin::Bin;
|
|
|
|
};
|
|
|
|
struct Neqv : public Bin {
|
|
|
|
using Bin::Bin;
|
2018-06-21 20:03:00 +02:00
|
|
|
};
|
2018-06-20 19:53:49 +02:00
|
|
|
|
2018-06-22 00:35:25 +02:00
|
|
|
LogicalExpr() = delete;
|
2018-06-22 20:02:54 +02:00
|
|
|
LogicalExpr(const LogicalExpr &) = default;
|
2018-06-22 00:35:25 +02:00
|
|
|
LogicalExpr(LogicalExpr &&) = default;
|
2018-06-22 20:02:54 +02:00
|
|
|
LogicalExpr(Constant x) : u{x} {}
|
|
|
|
template<int KIND>
|
|
|
|
LogicalExpr(const Comparison<IntegerExpr<KIND>> &x)
|
|
|
|
: u{IntegerComparison{x}} {}
|
2018-06-20 19:53:49 +02:00
|
|
|
template<int KIND>
|
2018-06-22 00:35:25 +02:00
|
|
|
LogicalExpr(Comparison<IntegerExpr<KIND>> &&x)
|
2018-06-20 19:53:49 +02:00
|
|
|
: u{IntegerComparison{std::move(x)}} {}
|
|
|
|
template<int KIND>
|
2018-06-22 20:02:54 +02:00
|
|
|
LogicalExpr(const Comparison<RealExpr<KIND>> &x) : u{RealComparison{x}} {}
|
|
|
|
template<int KIND>
|
2018-06-22 00:35:25 +02:00
|
|
|
LogicalExpr(Comparison<RealExpr<KIND>> &&x)
|
2018-06-20 19:53:49 +02:00
|
|
|
: u{RealComparison{std::move(x)}} {}
|
|
|
|
template<int KIND>
|
2018-06-22 20:02:54 +02:00
|
|
|
LogicalExpr(const Comparison<ComplexExpr<KIND>> &x)
|
|
|
|
: u{ComplexComparison{x}} {}
|
|
|
|
template<int KIND>
|
2018-06-22 00:35:25 +02:00
|
|
|
LogicalExpr(Comparison<ComplexExpr<KIND>> &&x)
|
2018-06-20 19:53:49 +02:00
|
|
|
: u{ComplexComparison{std::move(x)}} {}
|
|
|
|
template<int KIND>
|
2018-06-22 20:02:54 +02:00
|
|
|
LogicalExpr(const Comparison<CharacterExpr<KIND>> &x)
|
|
|
|
: u{CharacterComparison{x}} {}
|
|
|
|
template<int KIND>
|
2018-06-22 00:35:25 +02:00
|
|
|
LogicalExpr(Comparison<CharacterExpr<KIND>> &&x)
|
2018-06-20 19:53:49 +02:00
|
|
|
: u{CharacterComparison{std::move(x)}} {}
|
2018-06-22 00:35:25 +02:00
|
|
|
template<typename A> LogicalExpr(A &&x) : u{std::move(x)} {}
|
2018-06-22 21:22:50 +02:00
|
|
|
LogicalExpr &operator=(const LogicalExpr &) = default;
|
|
|
|
LogicalExpr &operator=(LogicalExpr &&) = default;
|
2018-06-20 01:26:48 +02:00
|
|
|
|
2018-06-21 01:50:27 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
|
|
|
|
2018-06-20 19:53:49 +02:00
|
|
|
std::variant<Constant, Not, And, Or, Eqv, Neqv, IntegerComparison,
|
|
|
|
RealComparison, ComplexComparison, CharacterComparison>
|
|
|
|
u;
|
2018-06-19 23:16:01 +02:00
|
|
|
};
|
|
|
|
|
2018-06-22 00:35:25 +02:00
|
|
|
// Dynamically polymorphic expressions that can hold any supported kind.
|
|
|
|
struct AnyIntegerExpr {
|
|
|
|
AnyIntegerExpr() = delete;
|
2018-06-22 20:02:54 +02:00
|
|
|
AnyIntegerExpr(const AnyIntegerExpr &) = default;
|
2018-06-22 00:35:25 +02:00
|
|
|
AnyIntegerExpr(AnyIntegerExpr &&) = default;
|
2018-06-22 20:02:54 +02:00
|
|
|
template<int KIND> AnyIntegerExpr(const IntegerExpr<KIND> &x) : u{x} {}
|
|
|
|
template<int KIND> AnyIntegerExpr(IntegerExpr<KIND> &&x) : u{std::move(x)} {}
|
2018-06-22 21:22:50 +02:00
|
|
|
AnyIntegerExpr &operator=(const AnyIntegerExpr &) = default;
|
|
|
|
AnyIntegerExpr &operator=(AnyIntegerExpr &&) = default;
|
2018-06-21 01:50:27 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-06-22 00:35:25 +02:00
|
|
|
IntegerKindsVariant<IntegerExpr> u;
|
2018-06-20 19:53:49 +02:00
|
|
|
};
|
2018-06-22 00:35:25 +02:00
|
|
|
struct AnyRealExpr {
|
|
|
|
AnyRealExpr() = delete;
|
2018-06-22 20:02:54 +02:00
|
|
|
AnyRealExpr(const AnyRealExpr &) = default;
|
2018-06-22 00:35:25 +02:00
|
|
|
AnyRealExpr(AnyRealExpr &&) = default;
|
2018-06-22 20:02:54 +02:00
|
|
|
template<int KIND> AnyRealExpr(const RealExpr<KIND> &x) : u{x} {}
|
|
|
|
template<int KIND> AnyRealExpr(RealExpr<KIND> &&x) : u{std::move(x)} {}
|
2018-06-22 21:22:50 +02:00
|
|
|
AnyRealExpr &operator=(const AnyRealExpr &) = default;
|
|
|
|
AnyRealExpr &operator=(AnyRealExpr &&) = default;
|
2018-06-22 00:35:25 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-06-20 19:53:49 +02:00
|
|
|
RealKindsVariant<RealExpr> u;
|
|
|
|
};
|
2018-06-22 00:35:25 +02:00
|
|
|
struct AnyComplexExpr {
|
|
|
|
AnyComplexExpr() = delete;
|
2018-06-22 20:02:54 +02:00
|
|
|
AnyComplexExpr(const AnyComplexExpr &) = default;
|
2018-06-22 00:35:25 +02:00
|
|
|
AnyComplexExpr(AnyComplexExpr &&) = default;
|
2018-06-22 20:02:54 +02:00
|
|
|
template<int KIND> AnyComplexExpr(const ComplexExpr<KIND> &x) : u{x} {}
|
|
|
|
template<int KIND> AnyComplexExpr(ComplexExpr<KIND> &&x) : u{std::move(x)} {}
|
2018-06-22 21:22:50 +02:00
|
|
|
AnyComplexExpr &operator=(const AnyComplexExpr &) = default;
|
|
|
|
AnyComplexExpr &operator=(AnyComplexExpr &&) = default;
|
2018-06-22 00:35:25 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-06-20 19:53:49 +02:00
|
|
|
ComplexKindsVariant<ComplexExpr> u;
|
|
|
|
};
|
2018-06-22 00:35:25 +02:00
|
|
|
struct AnyCharacterExpr {
|
|
|
|
AnyCharacterExpr() = delete;
|
2018-06-22 20:02:54 +02:00
|
|
|
AnyCharacterExpr(const AnyCharacterExpr &) = default;
|
2018-06-22 00:35:25 +02:00
|
|
|
AnyCharacterExpr(AnyCharacterExpr &&) = default;
|
2018-06-22 20:02:54 +02:00
|
|
|
template<int KIND> AnyCharacterExpr(const CharacterExpr<KIND> &x) : u{x} {}
|
|
|
|
template<int KIND>
|
|
|
|
AnyCharacterExpr(CharacterExpr<KIND> &&x) : u{std::move(x)} {}
|
2018-06-22 21:22:50 +02:00
|
|
|
AnyCharacterExpr &operator=(const AnyCharacterExpr &) = default;
|
|
|
|
AnyCharacterExpr &operator=(AnyCharacterExpr &&) = default;
|
2018-06-22 00:35:25 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
|
|
|
CharacterKindsVariant<CharacterExpr> u;
|
2018-06-20 19:53:49 +02:00
|
|
|
};
|
|
|
|
|
2018-06-22 00:35:25 +02:00
|
|
|
struct AnyIntegerOrRealExpr {
|
|
|
|
AnyIntegerOrRealExpr() = delete;
|
2018-06-22 20:02:54 +02:00
|
|
|
AnyIntegerOrRealExpr(const AnyIntegerOrRealExpr &) = default;
|
2018-06-22 00:35:25 +02:00
|
|
|
AnyIntegerOrRealExpr(AnyIntegerOrRealExpr &&) = default;
|
2018-06-20 19:53:49 +02:00
|
|
|
template<int KIND>
|
2018-06-22 20:02:54 +02:00
|
|
|
AnyIntegerOrRealExpr(const IntegerExpr<KIND> &x) : u{AnyIntegerExpr{x}} {}
|
|
|
|
template<int KIND>
|
2018-06-22 00:35:25 +02:00
|
|
|
AnyIntegerOrRealExpr(IntegerExpr<KIND> &&x)
|
|
|
|
: u{AnyIntegerExpr{std::move(x)}} {}
|
2018-06-20 19:53:49 +02:00
|
|
|
template<int KIND>
|
2018-06-22 20:02:54 +02:00
|
|
|
AnyIntegerOrRealExpr(const RealExpr<KIND> &x) : u{AnyRealExpr{x}} {}
|
|
|
|
template<int KIND>
|
2018-06-22 00:35:25 +02:00
|
|
|
AnyIntegerOrRealExpr(RealExpr<KIND> &&x) : u{AnyRealExpr{std::move(x)}} {}
|
2018-06-22 20:02:54 +02:00
|
|
|
AnyIntegerOrRealExpr(const AnyIntegerExpr &x) : u{x} {}
|
|
|
|
AnyIntegerOrRealExpr(AnyIntegerExpr &&x) : u{std::move(x)} {}
|
|
|
|
AnyIntegerOrRealExpr(const AnyRealExpr &x) : u{x} {}
|
|
|
|
AnyIntegerOrRealExpr(AnyRealExpr &&x) : u{std::move(x)} {}
|
2018-06-22 21:22:50 +02:00
|
|
|
AnyIntegerOrRealExpr &operator=(const AnyIntegerOrRealExpr &) = default;
|
|
|
|
AnyIntegerOrRealExpr &operator=(AnyIntegerOrRealExpr &&) = default;
|
2018-06-21 21:47:28 +02:00
|
|
|
std::ostream &Dump(std::ostream &) const;
|
2018-06-22 00:35:25 +02:00
|
|
|
std::variant<AnyIntegerExpr, AnyRealExpr> u;
|
2018-06-19 23:16:01 +02:00
|
|
|
};
|
2018-06-20 20:55:10 +02:00
|
|
|
|
2018-06-22 21:22:50 +02:00
|
|
|
// Convenience functions and operator overloadings for expression construction.
|
|
|
|
#define UNARY(FUNC, CONSTR) \
|
|
|
|
template<typename A> A FUNC(const A &x) { return {typename A::CONSTR{x}}; }
|
|
|
|
UNARY(Parentheses, Parentheses)
|
|
|
|
UNARY(operator-, Negate)
|
|
|
|
#undef UNARY
|
|
|
|
|
|
|
|
#define BINARY(FUNC, CONSTR) \
|
|
|
|
template<typename A> A FUNC(const A &x, const A &y) { \
|
|
|
|
return {typename A::CONSTR{x, y}}; \
|
|
|
|
} \
|
|
|
|
template<typename A> \
|
|
|
|
std::enable_if_t<!std::is_reference_v<A>, A> FUNC(const A &x, A &&y) { \
|
|
|
|
return {typename A::CONSTR{A{x}, std::move(y)}}; \
|
|
|
|
} \
|
|
|
|
template<typename A> \
|
|
|
|
std::enable_if_t<!std::is_reference_v<A>, A> FUNC(A &&x, const A &y) { \
|
|
|
|
return {typename A::CONSTR{std::move(x), A{y}}}; \
|
|
|
|
} \
|
|
|
|
template<typename A> \
|
|
|
|
std::enable_if_t<!std::is_reference_v<A>, A> FUNC(A &&x, A &&y) { \
|
|
|
|
return {typename A::CONSTR{std::move(x), std::move(y)}}; \
|
|
|
|
}
|
|
|
|
|
|
|
|
BINARY(operator+, Add)
|
|
|
|
BINARY(operator-, Subtract)
|
|
|
|
BINARY(operator*, Multiply)
|
|
|
|
BINARY(operator/, Divide)
|
|
|
|
BINARY(Power, Power)
|
|
|
|
#undef BINARY
|
|
|
|
|
|
|
|
#define BINARY(FUNC, CONSTR) \
|
|
|
|
template<typename A> LogicalExpr FUNC(const A &x, const A &y) { \
|
|
|
|
return {Comparison<A>{typename Comparison<A>::CONSTR{x, y}}}; \
|
|
|
|
} \
|
|
|
|
template<typename A> \
|
|
|
|
std::enable_if_t<!std::is_reference_v<A>, LogicalExpr> FUNC( \
|
|
|
|
const A &x, A &&y) { \
|
|
|
|
return { \
|
|
|
|
Comparison<A>{typename Comparison<A>::CONSTR{A{x}, std::move(y)}}}; \
|
|
|
|
} \
|
|
|
|
template<typename A> \
|
|
|
|
std::enable_if_t<!std::is_reference_v<A>, LogicalExpr> FUNC( \
|
|
|
|
A &&x, const A &y) { \
|
|
|
|
return { \
|
|
|
|
Comparison<A>{typename Comparison<A>::CONSTR{std::move(x), A{y}}}}; \
|
|
|
|
} \
|
|
|
|
template<typename A> \
|
|
|
|
std::enable_if_t<!std::is_reference_v<A>, LogicalExpr> FUNC(A &&x, A &&y) { \
|
|
|
|
return {Comparison<A>{ \
|
|
|
|
typename Comparison<A>::CONSTR{std::move(x), std::move(y)}}}; \
|
|
|
|
}
|
|
|
|
|
|
|
|
BINARY(operator<, LT)
|
|
|
|
BINARY(operator<=, LE)
|
|
|
|
BINARY(operator==, EQ)
|
|
|
|
BINARY(operator!=, NE)
|
|
|
|
BINARY(operator>=, GE)
|
|
|
|
BINARY(operator>, GT)
|
|
|
|
#undef BINARY
|
|
|
|
|
2018-06-22 22:00:13 +02:00
|
|
|
// External class template instantiations are in expression.cc.
|
2018-06-22 00:35:25 +02:00
|
|
|
extern template struct IntegerExpr<1>;
|
|
|
|
extern template struct IntegerExpr<2>;
|
|
|
|
extern template struct IntegerExpr<4>;
|
|
|
|
extern template struct IntegerExpr<8>;
|
|
|
|
extern template struct IntegerExpr<16>;
|
|
|
|
extern template struct RealExpr<2>;
|
|
|
|
extern template struct RealExpr<4>;
|
|
|
|
extern template struct RealExpr<8>;
|
|
|
|
extern template struct RealExpr<10>;
|
|
|
|
extern template struct RealExpr<16>;
|
|
|
|
extern template struct ComplexExpr<2>;
|
|
|
|
extern template struct ComplexExpr<4>;
|
|
|
|
extern template struct ComplexExpr<8>;
|
|
|
|
extern template struct ComplexExpr<10>;
|
|
|
|
extern template struct ComplexExpr<16>;
|
|
|
|
extern template struct CharacterExpr<1>;
|
2018-06-18 21:09:56 +02:00
|
|
|
} // namespace Fortran::evaluate
|
|
|
|
#endif // FORTRAN_EVALUATE_EXPRESSION_H_
|