forked from OSchip/llvm-project
[flang] checkpoint
Original-commit: flang-compiler/f18@e874c926d0 Reviewed-on: https://github.com/flang-compiler/f18/pull/183 Tree-same-pre-rewrite: false
This commit is contained in:
parent
e798ab7d91
commit
856123351c
|
@ -31,5 +31,7 @@ ENUM_CLASS(ImportKind, Default, Only, None, All)
|
||||||
// The attribute on a type parameter can be KIND or LEN.
|
// The attribute on a type parameter can be KIND or LEN.
|
||||||
ENUM_CLASS(TypeParamAttr, Kind, Len)
|
ENUM_CLASS(TypeParamAttr, Kind, Len)
|
||||||
|
|
||||||
|
ENUM_CLASS(RelationalOperator, LT, LE, EQ, NE, GE, GT)
|
||||||
|
|
||||||
} // namespace Fortran::common
|
} // namespace Fortran::common
|
||||||
#endif // FORTRAN_COMMON_FORTRAN_H_
|
#endif // FORTRAN_COMMON_FORTRAN_H_
|
||||||
|
|
|
@ -116,14 +116,12 @@ using HostUnsignedInt =
|
||||||
// - There is no default constructor (Class() {}), usually to prevent the
|
// - There is no default constructor (Class() {}), usually to prevent the
|
||||||
// need for std::monostate as a default constituent in a std::variant<>.
|
// need for std::monostate as a default constituent in a std::variant<>.
|
||||||
// - There are full copy and move semantics for construction and assignment.
|
// - There are full copy and move semantics for construction and assignment.
|
||||||
// - There's a Dump(std::ostream &) member function.
|
|
||||||
#define CLASS_BOILERPLATE(t) \
|
#define CLASS_BOILERPLATE(t) \
|
||||||
t() = delete; \
|
t() = delete; \
|
||||||
t(const t &) = default; \
|
t(const t &) = default; \
|
||||||
t(t &&) = default; \
|
t(t &&) = default; \
|
||||||
t &operator=(const t &) = default; \
|
t &operator=(const t &) = default; \
|
||||||
t &operator=(t &&) = default; \
|
t &operator=(t &&) = default;
|
||||||
std::ostream &Dump(std::ostream &) const;
|
|
||||||
|
|
||||||
// Force availability of copy construction and assignment
|
// Force availability of copy construction and assignment
|
||||||
template<typename A> using CopyableIndirection = common::Indirection<A, true>;
|
template<typename A> using CopyableIndirection = common::Indirection<A, true>;
|
||||||
|
|
|
@ -27,16 +27,7 @@ using namespace Fortran::parser::literals;
|
||||||
|
|
||||||
namespace Fortran::evaluate {
|
namespace Fortran::evaluate {
|
||||||
|
|
||||||
template<typename D, typename R, typename... O>
|
// Folding
|
||||||
std::ostream &Operation<D, R, O...>::Dump(std::ostream &o) const {
|
|
||||||
operand<0>().Dump(o << derived().prefix_);
|
|
||||||
if constexpr (operands() > 1) {
|
|
||||||
operand<1>().Dump(o << infix_);
|
|
||||||
}
|
|
||||||
return o << derived().suffix_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: dump Convert<Integer,x> as INT(x,KIND=), &c.
|
|
||||||
|
|
||||||
template<typename D, typename R, typename... O>
|
template<typename D, typename R, typename... O>
|
||||||
auto Operation<D, R, O...>::Fold(FoldingContext &context)
|
auto Operation<D, R, O...>::Fold(FoldingContext &context)
|
||||||
|
@ -134,9 +125,9 @@ auto Negate<A>::FoldScalar(FoldingContext &context, const Scalar<Operand> &c)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int KIND, bool R>
|
template<int KIND>
|
||||||
auto ComplexComponent<KIND, R>::FoldScalar(FoldingContext &context,
|
auto ComplexComponent<KIND>::FoldScalar(FoldingContext &context,
|
||||||
const Scalar<Operand> &z) -> std::optional<Scalar<Result>> {
|
const Scalar<Operand> &z) const -> std::optional<Scalar<Result>> {
|
||||||
return {isRealPart ? z.REAL() : z.AIMAG()};
|
return {isRealPart ? z.REAL() : z.AIMAG()};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +137,39 @@ auto Not<KIND>::FoldScalar(FoldingContext &context, const Scalar<Operand> &x)
|
||||||
return {Scalar<Result>{!x.IsTrue()}};
|
return {Scalar<Result>{!x.IsTrue()}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename A>
|
||||||
|
auto Add<A>::FoldScalar(FoldingContext &context, const Scalar<Operand> &x,
|
||||||
|
const Scalar<Operand> &y) -> std::optional<Scalar<Result>> {
|
||||||
|
if constexpr (Result::category == TypeCategory::Integer) {
|
||||||
|
auto sum{x.AddSigned(y)};
|
||||||
|
if (sum.overflow) {
|
||||||
|
context.messages.Say("INTEGER addition overflowed"_en_US);
|
||||||
|
} else {
|
||||||
|
return {std::move(sum.value)};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto sum{x.Add(y, context.rounding)};
|
||||||
|
RealFlagWarnings(context, sum.flags, "addition");
|
||||||
|
return {std::move(sum.value)};
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
// Dumping
|
// Dumping
|
||||||
|
|
||||||
|
template<typename D, typename R, typename... O>
|
||||||
|
std::ostream &Operation<D, R, O...>::Dump(std::ostream &o) const {
|
||||||
|
operand<0>().Dump(o << derived().prefix());
|
||||||
|
if constexpr (operands() > 1) {
|
||||||
|
operand<1>().Dump(o << derived().infix());
|
||||||
|
}
|
||||||
|
return o << derived().suffix();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename A> std::string Comparison<A>::infix() const {
|
||||||
|
return "."s + EnumToString(opr) + '.';
|
||||||
|
}
|
||||||
|
|
||||||
template<typename... A>
|
template<typename... A>
|
||||||
std::ostream &DumpExpr(std::ostream &o, const std::variant<A...> &u) {
|
std::ostream &DumpExpr(std::ostream &o, const std::variant<A...> &u) {
|
||||||
std::visit(common::visitors{[&](const BOZLiteralConstant &x) {
|
std::visit(common::visitors{[&](const BOZLiteralConstant &x) {
|
||||||
|
@ -180,18 +203,18 @@ std::ostream &Binary<CRTP, RESULT, A, B>::Dump(
|
||||||
template<int KIND>
|
template<int KIND>
|
||||||
std::ostream &Expr<Type<TypeCategory::Integer, KIND>>::Dump(
|
std::ostream &Expr<Type<TypeCategory::Integer, KIND>>::Dump(
|
||||||
std::ostream &o) const {
|
std::ostream &o) const {
|
||||||
std::visit(
|
std::visit(common::visitors{[&](const Scalar<Result> &n) {
|
||||||
common::visitors{[&](const Scalar<Result> &n) { o << n.SignedDecimal(); },
|
o << n.SignedDecimal() << '_' << KIND;
|
||||||
[&](const CopyableIndirection<DataRef> &d) { d->Dump(o); },
|
},
|
||||||
[&](const CopyableIndirection<FunctionRef> &d) { d->Dump(o); },
|
[&](const CopyableIndirection<DataRef> &d) { d->Dump(o); },
|
||||||
[&](const Add &a) { a.Dump(o, "+"); },
|
[&](const CopyableIndirection<FunctionRef> &d) { d->Dump(o); },
|
||||||
[&](const Subtract &s) { s.Dump(o, "-"); },
|
[&](const Subtract &s) { s.Dump(o, "-"); },
|
||||||
[&](const Multiply &m) { m.Dump(o, "*"); },
|
[&](const Multiply &m) { m.Dump(o, "*"); },
|
||||||
[&](const Divide &d) { d.Dump(o, "/"); },
|
[&](const Divide &d) { d.Dump(o, "/"); },
|
||||||
[&](const Power &p) { p.Dump(o, "**"); },
|
[&](const Power &p) { p.Dump(o, "**"); },
|
||||||
[&](const Max &m) { m.Dump(o, ",", "MAX("); },
|
[&](const Max &m) { m.Dump(o, ",", "MAX("); },
|
||||||
[&](const Min &m) { m.Dump(o, ",", "MIN("); },
|
[&](const Min &m) { m.Dump(o, ",", "MIN("); },
|
||||||
[&](const auto &x) { x.Dump(o); }},
|
[&](const auto &x) { x.Dump(o); }},
|
||||||
u_);
|
u_);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
@ -205,20 +228,14 @@ std::ostream &Expr<Type<TypeCategory::Real, KIND>>::Dump(
|
||||||
[&](const CopyableIndirection<DataRef> &d) { d->Dump(o); },
|
[&](const CopyableIndirection<DataRef> &d) { d->Dump(o); },
|
||||||
[&](const CopyableIndirection<ComplexPart> &d) { d->Dump(o); },
|
[&](const CopyableIndirection<ComplexPart> &d) { d->Dump(o); },
|
||||||
[&](const CopyableIndirection<FunctionRef> &d) { d->Dump(o); },
|
[&](const CopyableIndirection<FunctionRef> &d) { d->Dump(o); },
|
||||||
[&](const Convert<Result, SomeInteger> &c) { c.Dump(o); },
|
|
||||||
[&](const Convert<Result, SomeReal> &c) { c.Dump(o); },
|
|
||||||
[&](const ComplexComponent<KIND, true> &z) { z.Dump(o); },
|
|
||||||
[&](const ComplexComponent<KIND, false> &z) { z.Dump(o); },
|
|
||||||
[&](const Parentheses<Result> &p) { p.Dump(o); },
|
|
||||||
[&](const Negate<Result> &n) { n.Dump(o); },
|
|
||||||
[&](const Add &a) { a.Dump(o, "+"); },
|
|
||||||
[&](const Subtract &s) { s.Dump(o, "-"); },
|
[&](const Subtract &s) { s.Dump(o, "-"); },
|
||||||
[&](const Multiply &m) { m.Dump(o, "*"); },
|
[&](const Multiply &m) { m.Dump(o, "*"); },
|
||||||
[&](const Divide &d) { d.Dump(o, "/"); },
|
[&](const Divide &d) { d.Dump(o, "/"); },
|
||||||
[&](const Power &p) { p.Dump(o, "**"); },
|
[&](const Power &p) { p.Dump(o, "**"); },
|
||||||
[&](const IntPower &p) { p.Dump(o, "**"); },
|
[&](const IntPower &p) { p.Dump(o, "**"); },
|
||||||
[&](const Max &m) { m.Dump(o, ",", "MAX("); },
|
[&](const Max &m) { m.Dump(o, ",", "MAX("); },
|
||||||
[&](const Min &m) { m.Dump(o, ",", "MIN("); }},
|
[&](const Min &m) { m.Dump(o, ",", "MIN("); },
|
||||||
|
[&](const auto &x) { x.Dump(o); }},
|
||||||
u_);
|
u_);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
@ -231,7 +248,6 @@ std::ostream &Expr<Type<TypeCategory::Complex, KIND>>::Dump(
|
||||||
},
|
},
|
||||||
[&](const CopyableIndirection<DataRef> &d) { d->Dump(o); },
|
[&](const CopyableIndirection<DataRef> &d) { d->Dump(o); },
|
||||||
[&](const CopyableIndirection<FunctionRef> &d) { d->Dump(o); },
|
[&](const CopyableIndirection<FunctionRef> &d) { d->Dump(o); },
|
||||||
[&](const Add &a) { a.Dump(o, "+"); },
|
|
||||||
[&](const Subtract &s) { s.Dump(o, "-"); },
|
[&](const Subtract &s) { s.Dump(o, "-"); },
|
||||||
[&](const Multiply &m) { m.Dump(o, "*"); },
|
[&](const Multiply &m) { m.Dump(o, "*"); },
|
||||||
[&](const Divide &d) { d.Dump(o, "/"); },
|
[&](const Divide &d) { d.Dump(o, "/"); },
|
||||||
|
@ -247,7 +263,8 @@ template<int KIND>
|
||||||
std::ostream &Expr<Type<TypeCategory::Character, KIND>>::Dump(
|
std::ostream &Expr<Type<TypeCategory::Character, KIND>>::Dump(
|
||||||
std::ostream &o) const {
|
std::ostream &o) const {
|
||||||
std::visit(common::visitors{[&](const Scalar<Result> &s) {
|
std::visit(common::visitors{[&](const Scalar<Result> &s) {
|
||||||
o << parser::QuoteCharacterLiteral(s);
|
o << KIND << '_'
|
||||||
|
<< parser::QuoteCharacterLiteral(s);
|
||||||
},
|
},
|
||||||
// [&](const Parentheses<Result> &p) { p.Dump(o); },
|
// [&](const Parentheses<Result> &p) { p.Dump(o); },
|
||||||
[&](const Concat &concat) { concat.Dump(o, "//"); },
|
[&](const Concat &concat) { concat.Dump(o, "//"); },
|
||||||
|
@ -258,18 +275,12 @@ std::ostream &Expr<Type<TypeCategory::Character, KIND>>::Dump(
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename A> std::ostream &Comparison<A>::Dump(std::ostream &o) const {
|
|
||||||
o << '(' << A::Dump() << "::";
|
|
||||||
this->left().Dump(o);
|
|
||||||
o << '.' << EnumToString(this->opr) << '.';
|
|
||||||
return this->right().Dump(o) << ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int KIND>
|
template<int KIND>
|
||||||
std::ostream &Expr<Type<TypeCategory::Logical, KIND>>::Dump(
|
std::ostream &Expr<Type<TypeCategory::Logical, KIND>>::Dump(
|
||||||
std::ostream &o) const {
|
std::ostream &o) const {
|
||||||
std::visit(common::visitors{[&](const Scalar<Result> &tf) {
|
std::visit(common::visitors{[&](const Scalar<Result> &tf) {
|
||||||
o << (tf.IsTrue() ? ".TRUE." : ".FALSE.");
|
o << (tf.IsTrue() ? ".TRUE." : ".FALSE.") << '_'
|
||||||
|
<< KIND;
|
||||||
},
|
},
|
||||||
[&](const CopyableIndirection<DataRef> &d) { d->Dump(o); },
|
[&](const CopyableIndirection<DataRef> &d) { d->Dump(o); },
|
||||||
[&](const CopyableIndirection<FunctionRef> &d) { d->Dump(o); },
|
[&](const CopyableIndirection<FunctionRef> &d) { d->Dump(o); },
|
||||||
|
@ -333,18 +344,6 @@ auto Binary<CRTP, RESULT, A, B>::Fold(FoldingContext &context)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int KIND>
|
|
||||||
auto Expr<Type<TypeCategory::Integer, KIND>>::Add::FoldScalar(
|
|
||||||
FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
|
|
||||||
-> std::optional<Scalar<Result>> {
|
|
||||||
auto sum{a.AddSigned(b)};
|
|
||||||
if (sum.overflow) {
|
|
||||||
context.messages.Say("integer addition overflowed"_en_US);
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
return {std::move(sum.value)};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int KIND>
|
template<int KIND>
|
||||||
auto Expr<Type<TypeCategory::Integer, KIND>>::Subtract::FoldScalar(
|
auto Expr<Type<TypeCategory::Integer, KIND>>::Subtract::FoldScalar(
|
||||||
FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
|
FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
|
||||||
|
@ -450,15 +449,6 @@ auto Expr<Type<TypeCategory::Integer, KIND>>::Fold(FoldingContext &context)
|
||||||
u_);
|
u_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int KIND>
|
|
||||||
auto Expr<Type<TypeCategory::Real, KIND>>::Add::FoldScalar(
|
|
||||||
FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
|
|
||||||
-> std::optional<Scalar<Result>> {
|
|
||||||
auto sum{a.Add(b, context.rounding)};
|
|
||||||
RealFlagWarnings(context, sum.flags, "real addition");
|
|
||||||
return {std::move(sum.value)};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int KIND>
|
template<int KIND>
|
||||||
auto Expr<Type<TypeCategory::Real, KIND>>::Subtract::FoldScalar(
|
auto Expr<Type<TypeCategory::Real, KIND>>::Subtract::FoldScalar(
|
||||||
FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
|
FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
|
||||||
|
@ -555,15 +545,6 @@ auto Expr<Type<TypeCategory::Real, KIND>>::Fold(FoldingContext &context)
|
||||||
u_);
|
u_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int KIND>
|
|
||||||
auto Expr<Type<TypeCategory::Complex, KIND>>::Add::FoldScalar(
|
|
||||||
FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
|
|
||||||
-> std::optional<Scalar<Result>> {
|
|
||||||
auto sum{a.Add(b, context.rounding)};
|
|
||||||
RealFlagWarnings(context, sum.flags, "complex addition");
|
|
||||||
return {std::move(sum.value)};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int KIND>
|
template<int KIND>
|
||||||
auto Expr<Type<TypeCategory::Complex, KIND>>::Subtract::FoldScalar(
|
auto Expr<Type<TypeCategory::Complex, KIND>>::Subtract::FoldScalar(
|
||||||
FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
|
FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "type.h"
|
#include "type.h"
|
||||||
#include "variable.h"
|
#include "variable.h"
|
||||||
|
#include "../lib/common/fortran.h"
|
||||||
#include "../lib/common/idioms.h"
|
#include "../lib/common/idioms.h"
|
||||||
#include "../lib/parser/char-block.h"
|
#include "../lib/parser/char-block.h"
|
||||||
#include "../lib/parser/message.h"
|
#include "../lib/parser/message.h"
|
||||||
|
@ -33,54 +34,51 @@
|
||||||
|
|
||||||
namespace Fortran::evaluate {
|
namespace Fortran::evaluate {
|
||||||
|
|
||||||
|
using common::RelationalOperator;
|
||||||
|
|
||||||
template<typename A> class Expr;
|
template<typename A> class Expr;
|
||||||
|
|
||||||
template<typename DERIVED, typename RESULT, typename... OPERAND>
|
template<typename DERIVED, typename RESULT, typename... OPERAND>
|
||||||
class Operation {
|
class Operation {
|
||||||
private:
|
|
||||||
using OperandTypes = std::tuple<OPERAND...>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Derived = DERIVED;
|
using Derived = DERIVED;
|
||||||
using Result = RESULT;
|
using Result = RESULT;
|
||||||
|
using OperandTypes = std::tuple<OPERAND...>;
|
||||||
|
using OperandTuple = std::tuple<Expr<OPERAND>...>;
|
||||||
template<int J> using Operand = std::tuple_element_t<J, OperandTypes>;
|
template<int J> using Operand = std::tuple_element_t<J, OperandTypes>;
|
||||||
using FoldableTrait = std::true_type;
|
using FoldableTrait = std::true_type;
|
||||||
|
|
||||||
static_assert(Result::kind > 0); // Operations have specific Result types
|
static_assert(Result::kind > 0); // Operations have specific Result types
|
||||||
|
|
||||||
#if !__clang__
|
|
||||||
CLASS_BOILERPLATE(Operation)
|
CLASS_BOILERPLATE(Operation)
|
||||||
#else // clang 6.0 erroneously deletes the "=default" copy constructor
|
Operation(const Expr<OPERAND> &... x) : operand_{OperandTuple{x...}} {}
|
||||||
Operation() = delete;
|
Operation(Expr<OPERAND> &&... x)
|
||||||
Operation(const Operation &that) : operand_{that.operand_} {}
|
: operand_{OperandTuple{std::forward<Expr<OPERAND>>(x)...}} {}
|
||||||
Operation(Operation &&) = default;
|
|
||||||
Operation &operator=(const Operation &) = default;
|
|
||||||
Operation &operator=(Operation &&) = default;
|
|
||||||
std::ostream &Dump(std::ostream &) const;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Operation(Expr<OPERAND> &&... x) : operand_{std::move(x)...} {}
|
|
||||||
Operation(const Expr<OPERAND> &... x) : operand_{x...} {}
|
|
||||||
|
|
||||||
DERIVED &derived() { return *static_cast<DERIVED *>(this); }
|
DERIVED &derived() { return *static_cast<DERIVED *>(this); }
|
||||||
const DERIVED &derived() const { return *static_cast<const DERIVED *>(this); }
|
const DERIVED &derived() const { return *static_cast<const DERIVED *>(this); }
|
||||||
|
|
||||||
static constexpr auto operands() { return sizeof...(OPERAND); }
|
static constexpr auto operands() { return std::tuple_size_v<OperandTypes>; }
|
||||||
template<int J> Expr<Operand<J>> &operand() { return *std::get<J>(operand_); }
|
template<int J> Expr<Operand<J>> &operand() { return std::get<J>(*operand_); }
|
||||||
template<int J> const Expr<Operand<J>> &operand() const {
|
template<int J> const Expr<Operand<J>> &operand() const {
|
||||||
return *std::get<J>(operand_);
|
return std::get<J>(*operand_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
std::optional<Scalar<Result>> Fold(FoldingContext &); // TODO rank > 0
|
std::optional<Scalar<Result>> Fold(FoldingContext &); // TODO rank > 0
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Overridable strings for Dump()
|
// Overridable string functions for Dump()
|
||||||
static constexpr const char *prefix_{"("}, *infix_{""}, *suffix_{")"};
|
static const char *prefix() { return "("; }
|
||||||
|
static const char *infix() { return ","; }
|
||||||
|
static const char *suffix() { return ")"; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::tuple<CopyableIndirection<Expr<OPERAND>>...> operand_;
|
CopyableIndirection<OperandTuple> operand_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Unary operations
|
||||||
|
|
||||||
template<typename TO, typename FROM>
|
template<typename TO, typename FROM>
|
||||||
struct Convert : public Operation<Convert<TO, FROM>, TO, FROM> {
|
struct Convert : public Operation<Convert<TO, FROM>, TO, FROM> {
|
||||||
using Base = Operation<Convert<TO, FROM>, TO, FROM>;
|
using Base = Operation<Convert<TO, FROM>, TO, FROM>;
|
||||||
|
@ -110,24 +108,29 @@ template<typename A> struct Negate : public Operation<Negate<A>, A, A> {
|
||||||
using Operand = typename Base::template Operand<0>;
|
using Operand = typename Base::template Operand<0>;
|
||||||
static std::optional<Scalar<Result>> FoldScalar(
|
static std::optional<Scalar<Result>> FoldScalar(
|
||||||
FoldingContext &, const Scalar<Operand> &);
|
FoldingContext &, const Scalar<Operand> &);
|
||||||
static constexpr const char *prefix_{"(-"};
|
static const char *prefix() { return "(-"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: re vs. im can be dynamic
|
template<int KIND>
|
||||||
template<int KIND, bool realPart = true>
|
|
||||||
struct ComplexComponent
|
struct ComplexComponent
|
||||||
: public Operation<ComplexComponent<KIND, realPart>,
|
: public Operation<ComplexComponent<KIND>, Type<TypeCategory::Real, KIND>,
|
||||||
Type<TypeCategory::Real, KIND>, Type<TypeCategory::Complex, KIND>> {
|
Type<TypeCategory::Complex, KIND>> {
|
||||||
using Base = Operation<ComplexComponent, Type<TypeCategory::Real, KIND>,
|
using Base = Operation<ComplexComponent, Type<TypeCategory::Real, KIND>,
|
||||||
Type<TypeCategory::Complex, KIND>>;
|
Type<TypeCategory::Complex, KIND>>;
|
||||||
static constexpr bool isRealPart{realPart};
|
|
||||||
using Base::Base;
|
|
||||||
using typename Base::Result;
|
using typename Base::Result;
|
||||||
using Operand = typename Base::template Operand<0>;
|
using Operand = typename Base::template Operand<0>;
|
||||||
static std::optional<Scalar<Result>> FoldScalar(
|
CLASS_BOILERPLATE(ComplexComponent)
|
||||||
FoldingContext &, const Scalar<Operand> &);
|
ComplexComponent(bool isReal, const Expr<Operand> &x)
|
||||||
static constexpr const char *prefix_{"(("};
|
: Base{x}, isRealPart{isReal} {}
|
||||||
static constexpr const char *suffix_{isRealPart ? ")%RE)" : ")%IM)"};
|
ComplexComponent(bool isReal, Expr<Operand> &&x)
|
||||||
|
: Base{std::move(x)}, isRealPart{isReal} {}
|
||||||
|
|
||||||
|
std::optional<Scalar<Result>> FoldScalar(
|
||||||
|
FoldingContext &, const Scalar<Operand> &) const;
|
||||||
|
static const char *prefix() { return "(("; }
|
||||||
|
const char *suffix() const { return isRealPart ? "%RE)" : "%IM)"; }
|
||||||
|
|
||||||
|
bool isRealPart{true};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<int KIND>
|
template<int KIND>
|
||||||
|
@ -140,7 +143,19 @@ struct Not : public Operation<Not<KIND>, Type<TypeCategory::Logical, KIND>,
|
||||||
using Operand = typename Base::template Operand<0>;
|
using Operand = typename Base::template Operand<0>;
|
||||||
static std::optional<Scalar<Result>> FoldScalar(
|
static std::optional<Scalar<Result>> FoldScalar(
|
||||||
FoldingContext &, const Scalar<Operand> &);
|
FoldingContext &, const Scalar<Operand> &);
|
||||||
static constexpr const char *prefix_{"(.NOT."};
|
static const char *prefix() { return "(.NOT."; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Binary operations
|
||||||
|
|
||||||
|
template<typename A> struct Add : public Operation<Add<A>, A, A, A> {
|
||||||
|
using Base = Operation<Add, A, A, A>;
|
||||||
|
using Base::Base;
|
||||||
|
using typename Base::Result;
|
||||||
|
using Operand = typename Base::template Operand<0>;
|
||||||
|
static std::optional<Scalar<Result>> FoldScalar(
|
||||||
|
FoldingContext &, const Scalar<Operand> &, const Scalar<Operand> &);
|
||||||
|
static const char *infix() { return "+"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename CRTP, typename RESULT, typename A = RESULT, typename B = A>
|
template<typename CRTP, typename RESULT, typename A = RESULT, typename B = A>
|
||||||
|
@ -179,11 +194,6 @@ public:
|
||||||
using FoldableTrait = std::true_type;
|
using FoldableTrait = std::true_type;
|
||||||
|
|
||||||
template<typename CRTP> using Bin = Binary<CRTP, Result>;
|
template<typename CRTP> using Bin = Binary<CRTP, Result>;
|
||||||
struct Add : public Bin<Add> {
|
|
||||||
using Bin<Add>::Bin;
|
|
||||||
static std::optional<Scalar<Result>> FoldScalar(
|
|
||||||
FoldingContext &, const Scalar<Result> &, const Scalar<Result> &);
|
|
||||||
};
|
|
||||||
struct Subtract : public Bin<Subtract> {
|
struct Subtract : public Bin<Subtract> {
|
||||||
using Bin<Subtract>::Bin;
|
using Bin<Subtract>::Bin;
|
||||||
static std::optional<Scalar<Result>> FoldScalar(
|
static std::optional<Scalar<Result>> FoldScalar(
|
||||||
|
@ -247,14 +257,15 @@ public:
|
||||||
// TODO: Also succeed when parenthesized constant
|
// TODO: Also succeed when parenthesized constant
|
||||||
return common::GetIf<Scalar<Result>>(u_);
|
return common::GetIf<Scalar<Result>>(u_);
|
||||||
}
|
}
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
std::optional<Scalar<Result>> Fold(FoldingContext &c);
|
std::optional<Scalar<Result>> Fold(FoldingContext &c);
|
||||||
int Rank() const { return 1; } // TODO
|
int Rank() const { return 1; } // TODO
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::variant<Scalar<Result>, CopyableIndirection<DataRef>,
|
std::variant<Scalar<Result>, CopyableIndirection<DataRef>,
|
||||||
CopyableIndirection<FunctionRef>, Convert<Result, SomeInteger>,
|
CopyableIndirection<FunctionRef>, Convert<Result, SomeInteger>,
|
||||||
Convert<Result, SomeReal>, Parentheses<Result>, Negate<Result>, Add,
|
Convert<Result, SomeReal>, Parentheses<Result>, Negate<Result>,
|
||||||
Subtract, Multiply, Divide, Power, Max, Min>
|
Add<Result>, Subtract, Multiply, Divide, Power, Max, Min>
|
||||||
u_;
|
u_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -268,11 +279,6 @@ public:
|
||||||
// Complex are done via decomposition to Real and reconstruction.
|
// Complex are done via decomposition to Real and reconstruction.
|
||||||
|
|
||||||
template<typename CRTP> using Bin = Binary<CRTP, Result>;
|
template<typename CRTP> using Bin = Binary<CRTP, Result>;
|
||||||
struct Add : public Bin<Add> {
|
|
||||||
using Bin<Add>::Bin;
|
|
||||||
static std::optional<Scalar<Result>> FoldScalar(
|
|
||||||
FoldingContext &, const Scalar<Result> &, const Scalar<Result> &);
|
|
||||||
};
|
|
||||||
struct Subtract : public Bin<Subtract> {
|
struct Subtract : public Bin<Subtract> {
|
||||||
using Bin<Subtract>::Bin;
|
using Bin<Subtract>::Bin;
|
||||||
static std::optional<Scalar<Result>> FoldScalar(
|
static std::optional<Scalar<Result>> FoldScalar(
|
||||||
|
@ -337,6 +343,7 @@ public:
|
||||||
// TODO: parenthesized constants too
|
// TODO: parenthesized constants too
|
||||||
return common::GetIf<Scalar<Result>>(u_);
|
return common::GetIf<Scalar<Result>>(u_);
|
||||||
}
|
}
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
std::optional<Scalar<Result>> Fold(FoldingContext &c);
|
std::optional<Scalar<Result>> Fold(FoldingContext &c);
|
||||||
int Rank() const { return 1; } // TODO
|
int Rank() const { return 1; } // TODO
|
||||||
|
|
||||||
|
@ -344,9 +351,8 @@ private:
|
||||||
std::variant<Scalar<Result>, CopyableIndirection<DataRef>,
|
std::variant<Scalar<Result>, CopyableIndirection<DataRef>,
|
||||||
CopyableIndirection<ComplexPart>, CopyableIndirection<FunctionRef>,
|
CopyableIndirection<ComplexPart>, CopyableIndirection<FunctionRef>,
|
||||||
Convert<Result, SomeInteger>, Convert<Result, SomeReal>,
|
Convert<Result, SomeInteger>, Convert<Result, SomeReal>,
|
||||||
ComplexComponent<KIND, true>, ComplexComponent<KIND, false>,
|
ComplexComponent<KIND>, Parentheses<Result>, Negate<Result>, Add<Result>,
|
||||||
Parentheses<Result>, Negate<Result>, Add, Subtract, Multiply, Divide,
|
Subtract, Multiply, Divide, Power, IntPower, Max, Min>
|
||||||
Power, IntPower, Max, Min>
|
|
||||||
u_;
|
u_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -356,11 +362,6 @@ public:
|
||||||
using FoldableTrait = std::true_type;
|
using FoldableTrait = std::true_type;
|
||||||
|
|
||||||
template<typename CRTP> using Bin = Binary<CRTP, Result>;
|
template<typename CRTP> using Bin = Binary<CRTP, Result>;
|
||||||
struct Add : public Bin<Add> {
|
|
||||||
using Bin<Add>::Bin;
|
|
||||||
static std::optional<Scalar<Result>> FoldScalar(
|
|
||||||
FoldingContext &, const Scalar<Result> &, const Scalar<Result> &);
|
|
||||||
};
|
|
||||||
struct Subtract : public Bin<Subtract> {
|
struct Subtract : public Bin<Subtract> {
|
||||||
using Bin<Subtract>::Bin;
|
using Bin<Subtract>::Bin;
|
||||||
static std::optional<Scalar<Result>> FoldScalar(
|
static std::optional<Scalar<Result>> FoldScalar(
|
||||||
|
@ -405,13 +406,14 @@ public:
|
||||||
// TODO: parenthesized constants too
|
// TODO: parenthesized constants too
|
||||||
return common::GetIf<Scalar<Result>>(u_);
|
return common::GetIf<Scalar<Result>>(u_);
|
||||||
}
|
}
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
std::optional<Scalar<Result>> Fold(FoldingContext &c);
|
std::optional<Scalar<Result>> Fold(FoldingContext &c);
|
||||||
int Rank() const { return 1; } // TODO
|
int Rank() const { return 1; } // TODO
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::variant<Scalar<Result>, CopyableIndirection<DataRef>,
|
std::variant<Scalar<Result>, CopyableIndirection<DataRef>,
|
||||||
CopyableIndirection<FunctionRef>, Parentheses<Result>, Negate<Result>,
|
CopyableIndirection<FunctionRef>, Parentheses<Result>, Negate<Result>,
|
||||||
Add, Subtract, Multiply, Divide, Power, IntPower, CMPLX>
|
Add<Result>, Subtract, Multiply, Divide, Power, IntPower, CMPLX>
|
||||||
u_;
|
u_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -464,6 +466,7 @@ public:
|
||||||
// TODO: parenthesized constants too
|
// TODO: parenthesized constants too
|
||||||
return common::GetIf<Scalar<Result>>(u_);
|
return common::GetIf<Scalar<Result>>(u_);
|
||||||
}
|
}
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
std::optional<Scalar<Result>> Fold(FoldingContext &c);
|
std::optional<Scalar<Result>> Fold(FoldingContext &c);
|
||||||
int Rank() const { return 1; } // TODO
|
int Rank() const { return 1; } // TODO
|
||||||
Expr<SubscriptInteger> LEN() const;
|
Expr<SubscriptInteger> LEN() const;
|
||||||
|
@ -479,21 +482,23 @@ private:
|
||||||
// The Comparison class template is a helper for constructing logical
|
// The Comparison class template is a helper for constructing logical
|
||||||
// expressions with polymorphism over the cross product of the possible
|
// expressions with polymorphism over the cross product of the possible
|
||||||
// categories and kinds of comparable operands.
|
// categories and kinds of comparable operands.
|
||||||
ENUM_CLASS(RelationalOperator, LT, LE, EQ, NE, GE, GT)
|
|
||||||
|
|
||||||
template<typename A>
|
template<typename A>
|
||||||
struct Comparison : public Binary<Comparison<A>, LogicalResult, A> {
|
struct Comparison : public Operation<Comparison<A>, LogicalResult, A, A> {
|
||||||
using Result = LogicalResult;
|
using Base = Operation<Comparison, LogicalResult, A, A>;
|
||||||
using Operand = A;
|
using typename Base::Result;
|
||||||
using Base = Binary<Comparison, Result, Operand>;
|
using Operand = typename Base::template Operand<0>;
|
||||||
CLASS_BOILERPLATE(Comparison)
|
CLASS_BOILERPLATE(Comparison)
|
||||||
Comparison(
|
Comparison(
|
||||||
RelationalOperator r, const Expr<Operand> &a, const Expr<Operand> &b)
|
RelationalOperator r, const Expr<Operand> &a, const Expr<Operand> &b)
|
||||||
: Base{a, b}, opr{r} {}
|
: Base{a, b}, opr{r} {}
|
||||||
Comparison(RelationalOperator r, Expr<Operand> &&a, Expr<Operand> &&b)
|
Comparison(RelationalOperator r, Expr<Operand> &&a, Expr<Operand> &&b)
|
||||||
: Base{std::move(a), std::move(b)}, opr{r} {}
|
: Base{std::move(a), std::move(b)}, opr{r} {}
|
||||||
|
|
||||||
std::optional<Scalar<Result>> FoldScalar(
|
std::optional<Scalar<Result>> FoldScalar(
|
||||||
FoldingContext &c, const Scalar<Operand> &, const Scalar<Operand> &);
|
FoldingContext &c, const Scalar<Operand> &, const Scalar<Operand> &);
|
||||||
|
std::string infix() const;
|
||||||
|
|
||||||
RelationalOperator opr;
|
RelationalOperator opr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -506,6 +511,7 @@ template<TypeCategory CAT> struct CategoryComparison {
|
||||||
template<int KIND> CategoryComparison(const KindComparison<KIND> &x) : u{x} {}
|
template<int KIND> CategoryComparison(const KindComparison<KIND> &x) : u{x} {}
|
||||||
template<int KIND>
|
template<int KIND>
|
||||||
CategoryComparison(KindComparison<KIND> &&x) : u{std::move(x)} {}
|
CategoryComparison(KindComparison<KIND> &&x) : u{std::move(x)} {}
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
std::optional<Scalar<Result>> Fold(FoldingContext &c);
|
std::optional<Scalar<Result>> Fold(FoldingContext &c);
|
||||||
int Rank() const { return 1; } // TODO
|
int Rank() const { return 1; } // TODO
|
||||||
|
|
||||||
|
@ -555,6 +561,7 @@ public:
|
||||||
// TODO: parenthesized constants too
|
// TODO: parenthesized constants too
|
||||||
return common::GetIf<Scalar<Result>>(u_);
|
return common::GetIf<Scalar<Result>>(u_);
|
||||||
}
|
}
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
std::optional<Scalar<Result>> Fold(FoldingContext &c);
|
std::optional<Scalar<Result>> Fold(FoldingContext &c);
|
||||||
int Rank() const { return 1; } // TODO
|
int Rank() const { return 1; } // TODO
|
||||||
|
|
||||||
|
@ -581,6 +588,7 @@ public:
|
||||||
template<int KIND> Expr(const KindExpr<KIND> &x) : u{x} {}
|
template<int KIND> Expr(const KindExpr<KIND> &x) : u{x} {}
|
||||||
template<int KIND> Expr(KindExpr<KIND> &&x) : u{std::move(x)} {}
|
template<int KIND> Expr(KindExpr<KIND> &&x) : u{std::move(x)} {}
|
||||||
std::optional<Scalar<Result>> ScalarValue() const;
|
std::optional<Scalar<Result>> ScalarValue() const;
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
std::optional<Scalar<Result>> Fold(FoldingContext &);
|
std::optional<Scalar<Result>> Fold(FoldingContext &);
|
||||||
int Rank() const;
|
int Rank() const;
|
||||||
|
|
||||||
|
@ -612,6 +620,7 @@ public:
|
||||||
Expr(Expr<Type<CAT, KIND>> &&x) : u{Expr<SomeKind<CAT>>{std::move(x)}} {}
|
Expr(Expr<Type<CAT, KIND>> &&x) : u{Expr<SomeKind<CAT>>{std::move(x)}} {}
|
||||||
|
|
||||||
std::optional<Scalar<Result>> ScalarValue() const;
|
std::optional<Scalar<Result>> ScalarValue() const;
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
std::optional<Scalar<Result>> Fold(FoldingContext &);
|
std::optional<Scalar<Result>> Fold(FoldingContext &);
|
||||||
int Rank() const;
|
int Rank() const;
|
||||||
|
|
||||||
|
@ -625,9 +634,7 @@ using GenericExpr = Expr<SomeType>; // TODO: delete name?
|
||||||
template<typename A> using ResultType = typename std::decay_t<A>::Result;
|
template<typename A> using ResultType = typename std::decay_t<A>::Result;
|
||||||
|
|
||||||
// Convenience functions and operator overloadings for expression construction.
|
// Convenience functions and operator overloadings for expression construction.
|
||||||
// These definitions are created with temporary helper macros to reduce
|
|
||||||
// C++ boilerplate. All combinations of lvalue and rvalue references are
|
|
||||||
// allowed for operands.
|
|
||||||
template<TypeCategory C, int K>
|
template<TypeCategory C, int K>
|
||||||
Expr<Type<C, K>> operator-(const Expr<Type<C, K>> &x) {
|
Expr<Type<C, K>> operator-(const Expr<Type<C, K>> &x) {
|
||||||
return {Negate<Type<C, K>>{x}};
|
return {Negate<Type<C, K>>{x}};
|
||||||
|
@ -638,7 +645,26 @@ Expr<SomeKind<C>> operator-(const Expr<SomeKind<C>> &x) {
|
||||||
[](const auto &y) -> Expr<SomeKind<C>> { return {-y}; }, x.u);
|
[](const auto &y) -> Expr<SomeKind<C>> { return {-y}; }, x.u);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BINARY(FUNC, CONSTR) \
|
#define BINARY(op, CONSTR) \
|
||||||
|
template<TypeCategory C, int K> \
|
||||||
|
Expr<Type<C, K>> operator op( \
|
||||||
|
const Expr<Type<C, K>> &x, const Expr<Type<C, K>> &y) { \
|
||||||
|
return {CONSTR<Type<C, K>>{x, y}}; \
|
||||||
|
} \
|
||||||
|
template<TypeCategory C> \
|
||||||
|
Expr<SomeKind<C>> operator op( \
|
||||||
|
const Expr<SomeKind<C>> &x, const Expr<SomeKind<C>> &y) { \
|
||||||
|
return std::visit( \
|
||||||
|
[](const auto &xk, const auto &yk) -> Expr<SomeKind<C>> { \
|
||||||
|
return {xk op yk}; \
|
||||||
|
}, \
|
||||||
|
x.u, y.u); \
|
||||||
|
}
|
||||||
|
|
||||||
|
BINARY(+, Add)
|
||||||
|
#undef BINARY
|
||||||
|
|
||||||
|
#define OLDBINARY(FUNC, CONSTR) \
|
||||||
template<typename A> A FUNC(const A &x, const A &y) { \
|
template<typename A> A FUNC(const A &x, const A &y) { \
|
||||||
return {typename A::CONSTR{x, y}}; \
|
return {typename A::CONSTR{x, y}}; \
|
||||||
} \
|
} \
|
||||||
|
@ -655,12 +681,11 @@ Expr<SomeKind<C>> operator-(const Expr<SomeKind<C>> &x) {
|
||||||
return {typename A::CONSTR{std::move(x), std::move(y)}}; \
|
return {typename A::CONSTR{std::move(x), std::move(y)}}; \
|
||||||
}
|
}
|
||||||
|
|
||||||
BINARY(operator+, Add)
|
OLDBINARY(operator-, Subtract)
|
||||||
BINARY(operator-, Subtract)
|
OLDBINARY(operator*, Multiply)
|
||||||
BINARY(operator*, Multiply)
|
OLDBINARY(operator/, Divide)
|
||||||
BINARY(operator/, Divide)
|
OLDBINARY(Power, Power)
|
||||||
BINARY(Power, Power)
|
#undef OLDBINARY
|
||||||
#undef BINARY
|
|
||||||
|
|
||||||
#define BINARY(FUNC, OP) \
|
#define BINARY(FUNC, OP) \
|
||||||
template<typename A> Expr<LogicalResult> FUNC(const A &x, const A &y) { \
|
template<typename A> Expr<LogicalResult> FUNC(const A &x, const A &y) { \
|
||||||
|
|
|
@ -62,6 +62,7 @@ public:
|
||||||
DataRef &base() { return *base_; }
|
DataRef &base() { return *base_; }
|
||||||
const Symbol &symbol() const { return *symbol_; }
|
const Symbol &symbol() const { return *symbol_; }
|
||||||
Expr<SubscriptInteger> LEN() const;
|
Expr<SubscriptInteger> LEN() const;
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CopyableIndirection<DataRef> base_;
|
CopyableIndirection<DataRef> base_;
|
||||||
|
@ -78,6 +79,7 @@ public:
|
||||||
std::optional<Expr<SubscriptInteger>> lower() const;
|
std::optional<Expr<SubscriptInteger>> lower() const;
|
||||||
std::optional<Expr<SubscriptInteger>> upper() const;
|
std::optional<Expr<SubscriptInteger>> upper() const;
|
||||||
std::optional<Expr<SubscriptInteger>> stride() const;
|
std::optional<Expr<SubscriptInteger>> stride() const;
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::optional<IndirectSubscriptIntegerExpr> lower_, upper_, stride_;
|
std::optional<IndirectSubscriptIntegerExpr> lower_, upper_, stride_;
|
||||||
|
@ -93,6 +95,7 @@ public:
|
||||||
: u_{IndirectSubscriptIntegerExpr::Make(std::move(s))} {}
|
: u_{IndirectSubscriptIntegerExpr::Make(std::move(s))} {}
|
||||||
explicit Subscript(const Triplet &t) : u_{t} {}
|
explicit Subscript(const Triplet &t) : u_{t} {}
|
||||||
explicit Subscript(Triplet &&t) : u_{std::move(t)} {}
|
explicit Subscript(Triplet &&t) : u_{std::move(t)} {}
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::variant<IndirectSubscriptIntegerExpr, Triplet> u_;
|
std::variant<IndirectSubscriptIntegerExpr, Triplet> u_;
|
||||||
|
@ -111,6 +114,7 @@ public:
|
||||||
ArrayRef(Component &&c, std::vector<Subscript> &&ss)
|
ArrayRef(Component &&c, std::vector<Subscript> &&ss)
|
||||||
: u_{std::move(c)}, subscript_(std::move(ss)) {}
|
: u_{std::move(c)}, subscript_(std::move(ss)) {}
|
||||||
Expr<SubscriptInteger> LEN() const;
|
Expr<SubscriptInteger> LEN() const;
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::variant<const Symbol *, Component> u_;
|
std::variant<const Symbol *, Component> u_;
|
||||||
|
@ -133,6 +137,7 @@ public:
|
||||||
CoarrayRef &setStat(Variable &&);
|
CoarrayRef &setStat(Variable &&);
|
||||||
CoarrayRef &setTeam(Variable &&, bool isTeamNumber = false);
|
CoarrayRef &setTeam(Variable &&, bool isTeamNumber = false);
|
||||||
Expr<SubscriptInteger> LEN() const;
|
Expr<SubscriptInteger> LEN() const;
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<const Symbol *> base_;
|
std::vector<const Symbol *> base_;
|
||||||
|
@ -154,6 +159,7 @@ public:
|
||||||
explicit DataRef(ArrayRef &&a) : u_{std::move(a)} {}
|
explicit DataRef(ArrayRef &&a) : u_{std::move(a)} {}
|
||||||
explicit DataRef(CoarrayRef &&a) : u_{std::move(a)} {}
|
explicit DataRef(CoarrayRef &&a) : u_{std::move(a)} {}
|
||||||
Expr<SubscriptInteger> LEN() const;
|
Expr<SubscriptInteger> LEN() const;
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::variant<const Symbol *, Component, ArrayRef, CoarrayRef> u_;
|
std::variant<const Symbol *, Component, ArrayRef, CoarrayRef> u_;
|
||||||
|
@ -176,6 +182,7 @@ public:
|
||||||
Expr<SubscriptInteger> last() const;
|
Expr<SubscriptInteger> last() const;
|
||||||
Expr<SubscriptInteger> LEN() const;
|
Expr<SubscriptInteger> LEN() const;
|
||||||
std::optional<std::string> Fold(FoldingContext &);
|
std::optional<std::string> Fold(FoldingContext &);
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::variant<DataRef, std::string> u_;
|
std::variant<DataRef, std::string> u_;
|
||||||
|
@ -192,6 +199,7 @@ public:
|
||||||
ComplexPart(DataRef &&z, Part p) : complex_{std::move(z)}, part_{p} {}
|
ComplexPart(DataRef &&z, Part p) : complex_{std::move(z)}, part_{p} {}
|
||||||
const DataRef &complex() const { return complex_; }
|
const DataRef &complex() const { return complex_; }
|
||||||
Part part() const { return part_; }
|
Part part() const { return part_; }
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DataRef complex_;
|
DataRef complex_;
|
||||||
|
@ -206,6 +214,7 @@ public:
|
||||||
explicit Designator(DataRef &&d) : u_{std::move(d)} {}
|
explicit Designator(DataRef &&d) : u_{std::move(d)} {}
|
||||||
explicit Designator(Substring &&s) : u_{std::move(s)} {}
|
explicit Designator(Substring &&s) : u_{std::move(s)} {}
|
||||||
explicit Designator(ComplexPart &&c) : u_{std::move(c)} {}
|
explicit Designator(ComplexPart &&c) : u_{std::move(c)} {}
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::variant<DataRef, Substring, ComplexPart> u_;
|
std::variant<DataRef, Substring, ComplexPart> u_;
|
||||||
|
@ -219,6 +228,7 @@ public:
|
||||||
explicit ProcedureDesignator(const Component &c) : u_{c} {}
|
explicit ProcedureDesignator(const Component &c) : u_{c} {}
|
||||||
explicit ProcedureDesignator(Component &&c) : u_{std::move(c)} {}
|
explicit ProcedureDesignator(Component &&c) : u_{std::move(c)} {}
|
||||||
Expr<SubscriptInteger> LEN() const;
|
Expr<SubscriptInteger> LEN() const;
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::variant<IntrinsicProcedure, const Symbol *, Component> u_;
|
std::variant<IntrinsicProcedure, const Symbol *, Component> u_;
|
||||||
|
@ -232,6 +242,7 @@ public:
|
||||||
: proc_{std::move(p)}, argument_(std::move(a)) {}
|
: proc_{std::move(p)}, argument_(std::move(a)) {}
|
||||||
const ProcedureDesignator &proc() const { return proc_; }
|
const ProcedureDesignator &proc() const { return proc_; }
|
||||||
const std::vector<ArgumentType> &argument() const { return argument_; }
|
const std::vector<ArgumentType> &argument() const { return argument_; }
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ProcedureDesignator proc_;
|
ProcedureDesignator proc_;
|
||||||
|
@ -245,6 +256,7 @@ public:
|
||||||
CLASS_BOILERPLATE(Variable)
|
CLASS_BOILERPLATE(Variable)
|
||||||
explicit Variable(Designator &&d) : u_{std::move(d)} {}
|
explicit Variable(Designator &&d) : u_{std::move(d)} {}
|
||||||
explicit Variable(FunctionRef &&p) : u_{std::move(p)} {}
|
explicit Variable(FunctionRef &&p) : u_{std::move(p)} {}
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::variant<Designator, FunctionRef> u_;
|
std::variant<Designator, FunctionRef> u_;
|
||||||
|
@ -255,6 +267,7 @@ public:
|
||||||
CLASS_BOILERPLATE(ActualFunctionArg)
|
CLASS_BOILERPLATE(ActualFunctionArg)
|
||||||
explicit ActualFunctionArg(Expr<SomeType> &&x) : u_{std::move(x)} {}
|
explicit ActualFunctionArg(Expr<SomeType> &&x) : u_{std::move(x)} {}
|
||||||
explicit ActualFunctionArg(Variable &&x) : u_{std::move(x)} {}
|
explicit ActualFunctionArg(Variable &&x) : u_{std::move(x)} {}
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::variant<CopyableIndirection<Expr<SomeType>>, Variable> u_;
|
std::variant<CopyableIndirection<Expr<SomeType>>, Variable> u_;
|
||||||
|
@ -264,6 +277,7 @@ struct Label { // TODO: this is a placeholder
|
||||||
CLASS_BOILERPLATE(Label)
|
CLASS_BOILERPLATE(Label)
|
||||||
explicit Label(int lab) : label{lab} {}
|
explicit Label(int lab) : label{lab} {}
|
||||||
int label;
|
int label;
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ActualSubroutineArg {
|
class ActualSubroutineArg {
|
||||||
|
@ -272,6 +286,7 @@ public:
|
||||||
explicit ActualSubroutineArg(Expr<SomeType> &&x) : u_{std::move(x)} {}
|
explicit ActualSubroutineArg(Expr<SomeType> &&x) : u_{std::move(x)} {}
|
||||||
explicit ActualSubroutineArg(Variable &&x) : u_{std::move(x)} {}
|
explicit ActualSubroutineArg(Variable &&x) : u_{std::move(x)} {}
|
||||||
explicit ActualSubroutineArg(const Label &l) : u_{&l} {}
|
explicit ActualSubroutineArg(const Label &l) : u_{&l} {}
|
||||||
|
std::ostream &Dump(std::ostream &) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::variant<CopyableIndirection<Expr<SomeType>>, Variable, const Label *> u_;
|
std::variant<CopyableIndirection<Expr<SomeType>>, Variable, const Label *> u_;
|
||||||
|
|
|
@ -31,24 +31,24 @@ template<typename A> std::string Dump(const A &x) {
|
||||||
int main() {
|
int main() {
|
||||||
using DefaultIntegerExpr = Expr<DefaultInteger>;
|
using DefaultIntegerExpr = Expr<DefaultInteger>;
|
||||||
TEST(DefaultIntegerExpr::Result::Dump() == "Integer(4)");
|
TEST(DefaultIntegerExpr::Result::Dump() == "Integer(4)");
|
||||||
MATCH("666", Dump(DefaultIntegerExpr{666}));
|
MATCH("666_4", Dump(DefaultIntegerExpr{666}));
|
||||||
MATCH("(-1)", Dump(-DefaultIntegerExpr{1}));
|
MATCH("(-1_4)", Dump(-DefaultIntegerExpr{1}));
|
||||||
auto ex1{
|
auto ex1{
|
||||||
DefaultIntegerExpr{2} + DefaultIntegerExpr{3} * -DefaultIntegerExpr{4}};
|
DefaultIntegerExpr{2} + DefaultIntegerExpr{3} * -DefaultIntegerExpr{4}};
|
||||||
MATCH("(2+(3*(-4)))", Dump(ex1));
|
MATCH("(2_4+(3_4*(-4_4)))", Dump(ex1));
|
||||||
Fortran::parser::CharBlock src;
|
Fortran::parser::CharBlock src;
|
||||||
Fortran::parser::ContextualMessages messages{src, nullptr};
|
Fortran::parser::ContextualMessages messages{src, nullptr};
|
||||||
FoldingContext context{messages};
|
FoldingContext context{messages};
|
||||||
ex1.Fold(context);
|
ex1.Fold(context);
|
||||||
MATCH("-10", Dump(ex1));
|
MATCH("-10_4", Dump(ex1));
|
||||||
MATCH("(Integer(4)::6.LE.7)",
|
MATCH("(6_4.LE.7_4)",
|
||||||
Dump(DefaultIntegerExpr{6} <= DefaultIntegerExpr{7}));
|
Dump(DefaultIntegerExpr{6} <= DefaultIntegerExpr{7}));
|
||||||
DefaultIntegerExpr a{1};
|
DefaultIntegerExpr a{1};
|
||||||
DefaultIntegerExpr b{2};
|
DefaultIntegerExpr b{2};
|
||||||
MATCH("(1/2)", Dump(a / b));
|
MATCH("(1_4/2_4)", Dump(a / b));
|
||||||
MATCH("1", Dump(a));
|
MATCH("1_4", Dump(a));
|
||||||
a = b;
|
a = b;
|
||||||
MATCH("2", Dump(a));
|
MATCH("2_4", Dump(a));
|
||||||
MATCH("2", Dump(b));
|
MATCH("2_4", Dump(b));
|
||||||
return testing::Complete();
|
return testing::Complete();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue