From f8f98ca3b6a12fb5b7f8d14c69d5cdf427e66097 Mon Sep 17 00:00:00 2001 From: peter klausler Date: Thu, 5 Jul 2018 14:19:19 -0700 Subject: [PATCH] [flang] More abstraction in expressions. Original-commit: flang-compiler/f18@2dc425acf58e9c4a836d6cb73b436b0059a5309f Reviewed-on: https://github.com/flang-compiler/f18/pull/117 Tree-same-pre-rewrite: false --- flang/lib/evaluate/expression.cc | 133 +++++----- flang/lib/evaluate/expression.h | 519 ++++++++++++++------------------------ flang/lib/evaluate/type.h | 30 ++- flang/test/evaluate/expression.cc | 2 +- 4 files changed, 267 insertions(+), 417 deletions(-) diff --git a/flang/lib/evaluate/expression.cc b/flang/lib/evaluate/expression.cc index 834aec7..fcf2fcd 100644 --- a/flang/lib/evaluate/expression.cc +++ b/flang/lib/evaluate/expression.cc @@ -27,31 +27,25 @@ std::ostream &DumpExprWithType(std::ostream &o, const std::variant &u) { std::visit( [&](const auto &x) { using Ty = typename std::remove_reference_t::Result; - x.Dump(o << '(' << Ty::Dump() << ' ') << ')'; + x.Dump(o << '(' << Ty::Dump() << "::") << ')'; }, u); return o; } -std::ostream &AnyIntegerExpr::Dump(std::ostream &o) const { - return DumpExprWithType(o, u); -} - -std::ostream &AnyRealExpr::Dump(std::ostream &o) const { - return DumpExprWithType(o, u); -} - template std::ostream &DumpExpr(std::ostream &o, const std::variant &u) { std::visit([&](const auto &x) { x.Dump(o); }, u); return o; } -std::ostream &AnyCharacterExpr::Dump(std::ostream &o) const { +template +std::ostream &AnyKindExpr::Dump(std::ostream &o) const { return DumpExpr(o, u); } -std::ostream &AnyComplexExpr::Dump(std::ostream &o) const { +template +std::ostream &AnyKindComparison::Dump(std::ostream &o) const { return DumpExpr(o, u); } @@ -68,27 +62,25 @@ std::ostream &Binary::Dump(std::ostream &o, const char *opr) const { } template -std::ostream &IntegerExpr::Dump(std::ostream &o) const { +std::ostream &Expr::Dump(std::ostream &o) const { std::visit( common::visitors{[&](const Constant &n) { o << n.SignedDecimal(); }, - [&](const Convert &j) { j.x->Dump(o); }, - [&](const Convert &a) { a.x->Dump(o); }, [&](const Parentheses &p) { p.Dump(o, "("); }, [&](const Negate &n) { n.Dump(o, "(-"); }, [&](const Add &a) { a.Dump(o, "+"); }, [&](const Subtract &s) { s.Dump(o, "-"); }, [&](const Multiply &m) { m.Dump(o, "*"); }, [&](const Divide &d) { d.Dump(o, "/"); }, - [&](const Power &p) { p.Dump(o, "**"); }}, + [&](const Power &p) { p.Dump(o, "**"); }, + [&](const auto &convert) { DumpExprWithType(o, convert.x->u); }}, u); return o; } -template std::ostream &RealExpr::Dump(std::ostream &o) const { +template +std::ostream &Expr::Dump(std::ostream &o) const { std::visit( common::visitors{[&](const Constant &n) { o << n.DumpHexadecimal(); }, - [&](const Convert &j) { j.x->Dump(o); }, - [&](const Convert &a) { a.x->Dump(o); }, [&](const Parentheses &p) { p.Dump(o, "("); }, [&](const Negate &n) { n.Dump(o, "(-"); }, [&](const Add &a) { a.Dump(o, "+"); }, @@ -98,13 +90,14 @@ template std::ostream &RealExpr::Dump(std::ostream &o) const { [&](const Power &p) { p.Dump(o, "**"); }, [&](const IntPower &p) { p.Dump(o, "**"); }, [&](const RealPart &z) { z.Dump(o, "REAL("); }, - [&](const AIMAG &p) { p.Dump(o, "AIMAG("); }}, + [&](const AIMAG &p) { p.Dump(o, "AIMAG("); }, + [&](const auto &convert) { DumpExprWithType(o, convert.x->u); }}, u); return o; } template -std::ostream &ComplexExpr::Dump(std::ostream &o) const { +std::ostream &Expr::Dump(std::ostream &o) const { std::visit( common::visitors{[&](const Constant &n) { o << n.DumpHexadecimal(); }, [&](const Parentheses &p) { p.Dump(o, "("); }, @@ -121,53 +114,22 @@ std::ostream &ComplexExpr::Dump(std::ostream &o) const { } template -std::ostream &CharacterExpr::Dump(std::ostream &o) const { +std::ostream &Expr::Dump(std::ostream &o) const { std::visit(common::visitors{[&](const Constant &s) { o << '"' << s << '"'; }, [&](const Concat &c) { c.y->Dump(c.x->Dump(o) << "//"); }}, u); return o; } -template std::ostream &Comparison::Dump(std::ostream &o) const { - std::visit(common::visitors{[&](const LT &c) { c.Dump(o, ".LT."); }, - [&](const LE &c) { c.Dump(o, ".LE."); }, - [&](const EQ &c) { c.Dump(o, ".EQ."); }, - [&](const NE &c) { c.Dump(o, ".NE."); }, - [&](const GE &c) { c.Dump(o, ".GE."); }, - [&](const GT &c) { c.Dump(o, ".GT."); }}, - u); - return o; -} - -template -std::ostream &Comparison>::Dump(std::ostream &o) const { - std::visit(common::visitors{[&](const EQ &c) { c.Dump(o, ".EQ."); }, - [&](const NE &c) { c.Dump(o, ".NE."); }}, - u); - return o; -} - -std::ostream &IntegerComparison::Dump(std::ostream &o) const { - std::visit([&](const auto &c) { c.Dump(o); }, u); - return o; +template std::ostream &Comparison::Dump(std::ostream &o) const { + using Ty = typename A::Result; + o << '(' << Ty::Dump() << "::"; + this->x->Dump(o); + o << '.' << EnumToString(this->opr) << '.'; + return this->y->Dump(o) << ')'; } -std::ostream &RealComparison::Dump(std::ostream &o) const { - std::visit([&](const auto &c) { c.Dump(o); }, u); - return o; -} - -std::ostream &ComplexComparison::Dump(std::ostream &o) const { - std::visit([&](const auto &c) { c.Dump(o); }, u); - return o; -} - -std::ostream &CharacterComparison::Dump(std::ostream &o) const { - std::visit([&](const auto &c) { c.Dump(o); }, u); - return o; -} - -std::ostream &LogicalExpr::Dump(std::ostream &o) const { +std::ostream &Expr::Dump(std::ostream &o) const { std::visit( common::visitors{[&](const bool &tf) { o << (tf ? ".T." : ".F."); }, [&](const Not &n) { n.Dump(o, "(.NOT."); }, @@ -180,7 +142,8 @@ std::ostream &LogicalExpr::Dump(std::ostream &o) const { return o; } -template void IntegerExpr::Fold(FoldingContext &context) { +template +void Expr::Fold(FoldingContext &context) { std::visit(common::visitors{[&](const Parentheses &p) { p.x->Fold(context); if (auto c{std::get_if(&p.x->u)}) { @@ -247,20 +210,38 @@ typename CharacterExpr::LengthExpr CharacterExpr::LEN() const { u); } -template struct IntegerExpr<1>; -template struct IntegerExpr<2>; -template struct IntegerExpr<4>; -template struct IntegerExpr<8>; -template struct IntegerExpr<16>; -template struct RealExpr<2>; -template struct RealExpr<4>; -template struct RealExpr<8>; -template struct RealExpr<10>; -template struct RealExpr<16>; -template struct ComplexExpr<2>; -template struct ComplexExpr<4>; -template struct ComplexExpr<8>; -template struct ComplexExpr<10>; -template struct ComplexExpr<16>; -template struct CharacterExpr<1>; +template struct Expr; +template struct Expr; +template struct Expr; +template struct Expr; +template struct Expr; +template struct Expr; +template struct Expr; +template struct Expr; +template struct Expr; +template struct Expr; +template struct Expr; +template struct Expr; +template struct Expr; +template struct Expr; +template struct Expr; +template struct Expr; +template struct Expr; + +template struct Comparison>; +template struct Comparison>; +template struct Comparison>; +template struct Comparison>; +template struct Comparison>; +template struct Comparison>; +template struct Comparison>; +template struct Comparison>; +template struct Comparison>; +template struct Comparison>; +template struct Comparison>; +template struct Comparison>; +template struct Comparison>; +template struct Comparison>; +template struct Comparison>; +template struct Comparison>; } // namespace Fortran::evaluate diff --git a/flang/lib/evaluate/expression.h b/flang/lib/evaluate/expression.h index 7cd77a4..d012889 100644 --- a/flang/lib/evaluate/expression.h +++ b/flang/lib/evaluate/expression.h @@ -26,6 +26,7 @@ #include "common.h" #include "type.h" +#include "../lib/common/idioms.h" #include "../lib/parser/char-block.h" #include "../lib/parser/message.h" #include @@ -35,22 +36,27 @@ namespace Fortran::evaluate { // Some forward definitions -template struct IntegerExpr; -template struct RealExpr; -template struct ComplexExpr; -template struct CharacterExpr; -struct AnyIntegerExpr; -struct AnyRealExpr; -struct AnyComplexExpr; -struct AnyCharacterExpr; +template struct Expr; +template struct AnyKindExpr; + +template using IntegerExpr = Expr; +using DefaultIntegerExpr = IntegerExpr; +template using RealExpr = Expr; +template using ComplexExpr = Expr; +template using CharacterExpr = Expr; +using LogicalExpr = Expr; +using AnyKindIntegerExpr = AnyKindExpr; +using AnyKindRealExpr = AnyKindExpr; +using AnyKindComplexExpr = AnyKindExpr; +using AnyKindCharacterExpr = AnyKindExpr; struct FoldingContext { const parser::CharBlock &at; parser::Messages *messages; }; -// Helper base classes to manage subexpressions, which are known as data members -// named 'x' and, for binary operations, 'y'. +// Helper base classes to manage subexpressions, which are known as data +// members named 'x' and, for binary operations, 'y'. template struct Unary { Unary(const A &a) : x{std::make_unique(a)} {} Unary(std::unique_ptr &&a) : x{std::move(a)} {} @@ -66,7 +72,7 @@ template struct Unary { std::unique_ptr x; }; -template struct Binary { +template struct Binary { Binary(const A &a, const B &b) : x{std::make_unique(a)}, y{std::make_unique(b)} {} Binary(std::unique_ptr &&a, std::unique_ptr &&b) @@ -88,12 +94,12 @@ template struct Binary { std::unique_ptr y; }; -template struct IntegerExpr { +template struct Expr { using Result = Type; using Constant = typename Result::Value; template struct Convert : Unary { using Unary::Unary; }; - using Un = Unary; - using Bin = Binary; + using Un = Unary; + using Bin = Binary; struct Parentheses : public Un { using Un::Un; }; @@ -116,49 +122,41 @@ template struct IntegerExpr { using Bin::Bin; }; - IntegerExpr() = delete; - IntegerExpr(const IntegerExpr &) = default; - IntegerExpr(IntegerExpr &&) = default; - IntegerExpr(const Constant &x) : u{x} {} - IntegerExpr(std::int64_t n) : u{Constant{n}} {} - IntegerExpr(int n) : u{Constant{n}} {} - template - IntegerExpr(const IntegerExpr &x) - : u{Convert{AnyIntegerExpr{x}}} {} - template - IntegerExpr(IntegerExpr &&x) - : u{Convert{AnyIntegerExpr{std::move(x)}}} {} - template - IntegerExpr(const RealExpr &x) : u{Convert{AnyRealExpr{x}}} {} - template - IntegerExpr(RealExpr &&x) - : u{Convert{AnyRealExpr{std::move(x)}}} {} - template IntegerExpr(const A &x) : u{x} {} + Expr() = delete; + Expr(const Expr &) = default; + Expr(Expr &&) = default; + Expr(const Constant &x) : u{x} {} + Expr(std::int64_t n) : u{Constant{n}} {} + Expr(int n) : u{Constant{n}} {} + template + Expr(const Expr &x) + : u{Convert>{AnyKindExpr{x}}} {} + template + Expr(Expr &&x) + : u{Convert>{AnyKindExpr{std::move(x)}}} {} + template Expr(const A &x) : u{x} {} template - IntegerExpr(std::enable_if_t, A> &&x) - : u(std::move(x)) {} - IntegerExpr &operator=(const IntegerExpr &) = default; - IntegerExpr &operator=(IntegerExpr &&) = default; + Expr(std::enable_if_t, A> &&x) : u(std::move(x)) {} + Expr &operator=(const Expr &) = default; + Expr &operator=(Expr &&) = default; std::ostream &Dump(std::ostream &) const; void Fold(FoldingContext &); - std::variant, Convert, + std::variant, Convert, Parentheses, Negate, Add, Subtract, Multiply, Divide, Power> u; }; -using DefaultIntegerExpr = IntegerExpr; - -template struct RealExpr { +template struct Expr { using Result = Type; using Constant = typename Result::Value; // 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. template struct Convert : Unary { using Unary::Unary; }; - using Un = Unary; - using Bin = Binary; + using Un = Unary; + using Bin = Binary; struct Parentheses : public Un { using Un::Un; }; @@ -180,8 +178,8 @@ template struct RealExpr { struct Power : public Bin { using Bin::Bin; }; - struct IntPower : public Binary { - using Binary::Binary; + struct IntPower : public Binary { + using Binary::Binary; }; using CplxUn = Unary>; struct RealPart : public CplxUn { @@ -191,41 +189,35 @@ template struct RealExpr { using CplxUn::CplxUn; }; - RealExpr() = delete; - RealExpr(const RealExpr &) = default; - RealExpr(RealExpr &&) = default; - RealExpr(const Constant &x) : u{x} {} - template - RealExpr(const IntegerExpr &x) - : u{Convert{AnyIntegerExpr{x}}} {} - template - RealExpr(IntegerExpr &&x) - : u{Convert{AnyIntegerExpr{std::move(x)}}} {} - template - RealExpr(const RealExpr &x) : u{Convert{AnyRealExpr{x}}} {} - template - RealExpr(RealExpr &&x) - : u{Convert{AnyRealExpr{std::move(x)}}} {} - template RealExpr(const A &x) : u{x} {} + Expr() = delete; + Expr(const Expr &) = default; + Expr(Expr &&) = default; + Expr(const Constant &x) : u{x} {} + template + Expr(const Expr &x) + : u{Convert>{AnyKindExpr{x}}} {} + template + Expr(Expr &&x) + : u{Convert>{AnyKindExpr{std::move(x)}}} {} + template Expr(const A &x) : u{x} {} template - RealExpr(std::enable_if_t, A> &&x) - : u{std::move(x)} {} - RealExpr &operator=(const RealExpr &) = default; - RealExpr &operator=(RealExpr &&) = default; + Expr(std::enable_if_t, A> &&x) : u{std::move(x)} {} + Expr &operator=(const Expr &) = default; + Expr &operator=(Expr &&) = default; std::ostream &Dump(std::ostream &) const; - std::variant, Convert, + std::variant, Convert, Parentheses, Negate, Add, Subtract, Multiply, Divide, Power, IntPower, RealPart, AIMAG> u; }; -template struct ComplexExpr { +template struct Expr { using Result = Type; using Constant = typename Result::Value; - using Un = Unary; - using Bin = Binary; + using Un = Unary; + using Bin = Binary; struct Parentheses : public Un { using Un::Un; }; @@ -247,23 +239,22 @@ template struct ComplexExpr { struct Power : public Bin { using Bin::Bin; }; - struct IntPower : public Binary { - using Binary::Binary; + struct IntPower : public Binary { + using Binary::Binary; }; - struct CMPLX : public Binary, RealExpr> { - using Binary, RealExpr>::Binary; + struct CMPLX : public Binary> { + using Binary>::Binary; }; - ComplexExpr() = delete; - ComplexExpr(const ComplexExpr &) = default; - ComplexExpr(ComplexExpr &&) = default; - ComplexExpr(const Constant &x) : u{x} {} - template ComplexExpr(const A &x) : u{x} {} + Expr() = delete; + Expr(const Expr &) = default; + Expr(Expr &&) = default; + Expr(const Constant &x) : u{x} {} + template Expr(const A &x) : u{x} {} template - ComplexExpr(std::enable_if_t, A> &&x) - : u{std::move(x)} {} - ComplexExpr &operator=(const ComplexExpr &) = default; - ComplexExpr &operator=(ComplexExpr &&) = default; + Expr(std::enable_if_t, A> &&x) : u{std::move(x)} {} + Expr &operator=(const Expr &) = default; + Expr &operator=(Expr &&) = default; std::ostream &Dump(std::ostream &) const; @@ -272,23 +263,23 @@ template struct ComplexExpr { u; }; -template struct CharacterExpr { +template struct Expr { using Result = Type; using Constant = typename Result::Value; using LengthExpr = IntegerExpr; - struct Concat : public Binary { - using Binary::Binary; + struct Concat : public Binary { + using Binary::Binary; }; - CharacterExpr() = delete; - CharacterExpr(const CharacterExpr &) = default; - CharacterExpr(CharacterExpr &&) = default; - CharacterExpr(const Constant &x) : u{x} {} - CharacterExpr(Constant &&x) : u{std::move(x)} {} - CharacterExpr(const Concat &x) : u{x} {} - CharacterExpr(Concat &&x) : u{std::move(x)} {} - CharacterExpr &operator=(const CharacterExpr &) = default; - CharacterExpr &operator=(CharacterExpr &&) = default; + Expr() = delete; + Expr(const Expr &) = default; + Expr(Expr &&) = default; + Expr(const Constant &x) : u{x} {} + Expr(Constant &&x) : u{std::move(x)} {} + Expr(const Concat &x) : u{x} {} + Expr(Concat &&x) : u{std::move(x)} {} + Expr &operator=(const Expr &) = default; + Expr &operator=(Expr &&) = default; LengthExpr LEN() const; std::ostream &Dump(std::ostream &) const; @@ -299,130 +290,63 @@ template struct CharacterExpr { // The Comparison class template is a helper for constructing logical // expressions with polymorphism over the cross product of the possible // categories and kinds of comparable operands. -template struct Comparison { - struct LT : public Binary { - using Binary::Binary; - }; - struct LE : public Binary { - using Binary::Binary; - }; - struct EQ : public Binary { - using Binary::Binary; - }; - struct NE : public Binary { - using Binary::Binary; - }; - struct GE : public Binary { - using Binary::Binary; - }; - struct GT : public Binary { - using Binary::Binary; - }; +ENUM_CLASS(RelationalOperator, LT, LE, EQ, NE, GE, GT) - Comparison() = delete; +template struct Comparison : Binary { Comparison(const Comparison &) = default; Comparison(Comparison &&) = default; - template Comparison(const A &x) : u{x} {} - template - Comparison(std::enable_if_t, A> &&x) - : u{std::move(x)} {} + Comparison(RelationalOperator r, const EXPR &a, const EXPR &b) + : Binary{a, b}, opr{r} {} + Comparison(RelationalOperator r, EXPR &&a, EXPR &&b) + : Binary{std::move(a), std::move(b)}, opr{r} {} Comparison &operator=(const Comparison &) = default; Comparison &operator=(Comparison &&) = default; std::ostream &Dump(std::ostream &) const; - - std::variant u; + RelationalOperator opr; }; -// COMPLEX admits only .EQ. and .NE. comparisons. -template struct Comparison> { - using Bin = Binary, ComplexExpr>; - struct EQ : public Bin { - using Bin::Bin; - }; - struct NE : public Bin { - using Bin::Bin; - }; - - Comparison() = delete; - Comparison(const Comparison &) = default; - Comparison(Comparison &&) = default; - template Comparison(const A &x) : u{x} {} - template - Comparison(std::enable_if_t, A> &&x) - : u{std::move(x)} {} - Comparison &operator=(const Comparison &) = default; - Comparison &operator=(Comparison &&) = default; - - std::ostream &Dump(std::ostream &) const; - - std::variant u; -}; - -struct IntegerComparison { - IntegerComparison() = delete; - IntegerComparison(const IntegerComparison &) = default; - IntegerComparison(IntegerComparison &&) = default; - template IntegerComparison(const A &x) : u{x} {} - template IntegerComparison(A &&x) : u{std::move(x)} {} - IntegerComparison &operator=(const IntegerComparison &) = default; - IntegerComparison &operator=(IntegerComparison &&) = default; - std::ostream &Dump(std::ostream &) const; - template using C = Comparison>; - IntegerKindsVariant u; -}; - -struct RealComparison { - RealComparison() = delete; - RealComparison(const RealComparison &) = default; - RealComparison(RealComparison &&) = default; - template RealComparison(const A &x) : u{x} {} - template - RealComparison(std::enable_if_t, A> &&x) - : u{std::move(x)} {} - RealComparison &operator=(const RealComparison &) = default; - RealComparison &operator=(RealComparison &&) = default; - std::ostream &Dump(std::ostream &) const; - template using C = Comparison>; - RealKindsVariant u; -}; - -struct ComplexComparison { - ComplexComparison() = delete; - ComplexComparison(ComplexComparison &&) = default; - template ComplexComparison(const A &x) : u{x} {} - template - ComplexComparison(std::enable_if_t, A> &&x) - : u{std::move(x)} {} - ComplexComparison &operator=(const ComplexComparison &) = default; - ComplexComparison &operator=(ComplexComparison &&) = default; - std::ostream &Dump(std::ostream &) const; - template using C = Comparison>; - ComplexKindsVariant u; -}; - -struct CharacterComparison { - CharacterComparison() = delete; - CharacterComparison(const CharacterComparison &) = default; - CharacterComparison(CharacterComparison &&) = default; - template CharacterComparison(const A &x) : u{x} {} - template - CharacterComparison(std::enable_if_t, A> &&x) - : u{std::move(x)} {} - CharacterComparison &operator=(const CharacterComparison &) = default; - CharacterComparison &operator=(CharacterComparison &&) = default; +extern template struct Comparison>; +extern template struct Comparison>; +extern template struct Comparison>; +extern template struct Comparison>; +extern template struct Comparison>; +extern template struct Comparison>; +extern template struct Comparison>; +extern template struct Comparison>; +extern template struct Comparison>; +extern template struct Comparison>; +extern template struct Comparison>; +extern template struct Comparison>; +extern template struct Comparison>; +extern template struct Comparison>; +extern template struct Comparison>; +extern template struct Comparison>; + +// Dynamically polymorphic comparisonsq that can hold any supported kind +// of a category. +template struct AnyKindComparison { + AnyKindComparison() = delete; + AnyKindComparison(const AnyKindComparison &) = default; + AnyKindComparison(AnyKindComparison &&) = default; + template + AnyKindComparison(const Comparison> &x) : u{x} {} + template + AnyKindComparison(Comparison> &&x) : u{std::move(x)} {} + AnyKindComparison &operator=(const AnyKindComparison &) = default; + AnyKindComparison &operator=(AnyKindComparison &&) = default; std::ostream &Dump(std::ostream &) const; - template using C = Comparison>; - CharacterKindsVariant u; + template using KindComparison = Comparison>; + typename KindsVariant::type u; }; // No need to distinguish the various kinds of LOGICAL expression results. -struct LogicalExpr { +template<> struct Expr { using Constant = bool; - struct Not : Unary { - using Unary::Unary; + struct Not : Unary { + using Unary::Unary; }; - using Bin = Binary; + using Bin = Binary; struct And : public Bin { using Bin::Bin; }; @@ -436,121 +360,79 @@ struct LogicalExpr { using Bin::Bin; }; - LogicalExpr() = delete; - LogicalExpr(const LogicalExpr &) = default; - LogicalExpr(LogicalExpr &&) = default; - LogicalExpr(Constant x) : u{x} {} - template - LogicalExpr(const Comparison> &x) - : u{IntegerComparison{x}} {} - template - LogicalExpr(Comparison> &&x) - : u{IntegerComparison{std::move(x)}} {} - template - LogicalExpr(const Comparison> &x) : u{RealComparison{x}} {} - template - LogicalExpr(Comparison> &&x) - : u{RealComparison{std::move(x)}} {} - template - LogicalExpr(const Comparison> &x) - : u{ComplexComparison{x}} {} - template - LogicalExpr(Comparison> &&x) - : u{ComplexComparison{std::move(x)}} {} - template - LogicalExpr(const Comparison> &x) - : u{CharacterComparison{x}} {} - template - LogicalExpr(Comparison> &&x) - : u{CharacterComparison{std::move(x)}} {} - template LogicalExpr(const A &x) : u{x} {} + Expr() = delete; + Expr(const Expr &) = default; + Expr(Expr &&) = default; + Expr(Constant x) : u{x} {} + template + Expr(const Comparison> &x) : u{AnyKindComparison{x}} {} + template + Expr(Comparison> &&x) + : u{AnyKindComparison{std::move(x)}} {} + template Expr(const A &x) : u{x} {} template - LogicalExpr(std::enable_if_t, A> &&x) - : u{std::move(x)} {} - LogicalExpr &operator=(const LogicalExpr &) = default; - LogicalExpr &operator=(LogicalExpr &&) = default; + Expr(std::enable_if_t, A> &&x) : u{std::move(x)} {} + Expr &operator=(const Expr &) = default; + Expr &operator=(Expr &&) = default; std::ostream &Dump(std::ostream &) const; - std::variant + std::variant, AnyKindComparison, + AnyKindComparison, + AnyKindComparison> u; }; -// Dynamically polymorphic expressions that can hold any supported kind. -struct AnyIntegerExpr { - AnyIntegerExpr() = delete; - AnyIntegerExpr(const AnyIntegerExpr &) = default; - AnyIntegerExpr(AnyIntegerExpr &&) = default; - template AnyIntegerExpr(const IntegerExpr &x) : u{x} {} - template AnyIntegerExpr(IntegerExpr &&x) : u{std::move(x)} {} - AnyIntegerExpr &operator=(const AnyIntegerExpr &) = default; - AnyIntegerExpr &operator=(AnyIntegerExpr &&) = default; +extern template struct Expr; +extern template struct Expr; +extern template struct Expr; +extern template struct Expr; +extern template struct Expr; +extern template struct Expr; +extern template struct Expr; +extern template struct Expr; +extern template struct Expr; +extern template struct Expr; +extern template struct Expr; +extern template struct Expr; +extern template struct Expr; +extern template struct Expr; +extern template struct Expr; +extern template struct Expr; +extern template struct Expr; + +// Dynamically polymorphic expressions that can hold any supported kind +// of a category. +template struct AnyKindExpr { + AnyKindExpr() = delete; + AnyKindExpr(const AnyKindExpr &) = default; + AnyKindExpr(AnyKindExpr &&) = default; + template AnyKindExpr(const Expr &x) : u{x} {} + template AnyKindExpr(Expr &&x) : u{std::move(x)} {} + AnyKindExpr &operator=(const AnyKindExpr &) = default; + AnyKindExpr &operator=(AnyKindExpr &&) = default; std::ostream &Dump(std::ostream &) const; - IntegerKindsVariant u; -}; -struct AnyRealExpr { - AnyRealExpr() = delete; - AnyRealExpr(const AnyRealExpr &) = default; - AnyRealExpr(AnyRealExpr &&) = default; - template AnyRealExpr(const RealExpr &x) : u{x} {} - template AnyRealExpr(RealExpr &&x) : u{std::move(x)} {} - AnyRealExpr &operator=(const AnyRealExpr &) = default; - AnyRealExpr &operator=(AnyRealExpr &&) = default; - std::ostream &Dump(std::ostream &) const; - RealKindsVariant u; -}; -struct AnyComplexExpr { - AnyComplexExpr() = delete; - AnyComplexExpr(const AnyComplexExpr &) = default; - AnyComplexExpr(AnyComplexExpr &&) = default; - template AnyComplexExpr(const ComplexExpr &x) : u{x} {} - template AnyComplexExpr(ComplexExpr &&x) : u{std::move(x)} {} - AnyComplexExpr &operator=(const AnyComplexExpr &) = default; - AnyComplexExpr &operator=(AnyComplexExpr &&) = default; - std::ostream &Dump(std::ostream &) const; - ComplexKindsVariant u; -}; -struct AnyCharacterExpr { - AnyCharacterExpr() = delete; - AnyCharacterExpr(const AnyCharacterExpr &) = default; - AnyCharacterExpr(AnyCharacterExpr &&) = default; - template AnyCharacterExpr(const CharacterExpr &x) : u{x} {} - template - AnyCharacterExpr(CharacterExpr &&x) : u{std::move(x)} {} - AnyCharacterExpr &operator=(const AnyCharacterExpr &) = default; - AnyCharacterExpr &operator=(AnyCharacterExpr &&) = default; - std::ostream &Dump(std::ostream &) const; - CharacterKindsVariant u; + template using KindExpr = Expr; + typename KindsVariant::type u; }; struct AnyExpr { AnyExpr() = delete; AnyExpr(const AnyExpr &) = default; AnyExpr(AnyExpr &&) = default; - template - AnyExpr(const IntegerExpr &x) : u{AnyIntegerExpr{x}} {} - template - AnyExpr(IntegerExpr &&x) : u{AnyIntegerExpr{std::move(x)}} {} - template AnyExpr(const RealExpr &x) : u{AnyRealExpr{x}} {} - template - AnyExpr(RealExpr &&x) : u{AnyRealExpr{std::move(x)}} {} - template - AnyExpr(const ComplexExpr &x) : u{AnyComplexExpr{x}} {} - template - AnyExpr(ComplexExpr &&x) : u{AnyComplexExpr{std::move(x)}} {} - template - AnyExpr(const CharacterExpr &x) : u{AnyCharacterExpr{x}} {} - template - AnyExpr(CharacterExpr &&x) : u{AnyCharacterExpr{std::move(x)}} {} + template + AnyExpr(const Expr &x) : u{AnyKindExpr{x}} {} + template + AnyExpr(Expr &&x) : u{AnyKindExpr{std::move(x)}} {} template AnyExpr(const A &x) : u{x} {} template AnyExpr(std::enable_if_t, A> &&x) : u{std::move(x)} {} AnyExpr &operator=(const AnyExpr &) = default; AnyExpr &operator=(AnyExpr &&) = default; std::ostream &Dump(std::ostream &) const; - std::variant + std::variant u; }; @@ -588,52 +470,31 @@ BINARY(operator/, Divide) BINARY(Power, Power) #undef BINARY -#define BINARY(FUNC, CONSTR) \ +#define BINARY(FUNC, OP) \ template LogicalExpr FUNC(const A &x, const A &y) { \ - return {Comparison{typename Comparison::CONSTR{x, y}}}; \ + return {Comparison{OP, x, y}}; \ } \ template \ std::enable_if_t, LogicalExpr> FUNC( \ const A &x, A &&y) { \ - return { \ - Comparison{typename Comparison::CONSTR{A{x}, std::move(y)}}}; \ + return {Comparison{OP, x, std::move(y)}}; \ } \ template \ std::enable_if_t, LogicalExpr> FUNC( \ A &&x, const A &y) { \ - return { \ - Comparison{typename Comparison::CONSTR{std::move(x), A{y}}}}; \ + return {Comparison{OP, std::move(x), y}}; \ } \ template \ std::enable_if_t, LogicalExpr> FUNC(A &&x, A &&y) { \ - return {Comparison{ \ - typename Comparison::CONSTR{std::move(x), std::move(y)}}}; \ + return {Comparison{OP, std::move(x), std::move(y)}}; \ } -BINARY(operator<, LT) -BINARY(operator<=, LE) -BINARY(operator==, EQ) -BINARY(operator!=, NE) -BINARY(operator>=, GE) -BINARY(operator>, GT) +BINARY(operator<, RelationalOperator::LT) +BINARY(operator<=, RelationalOperator::LE) +BINARY(operator==, RelationalOperator::EQ) +BINARY(operator!=, RelationalOperator::NE) +BINARY(operator>=, RelationalOperator::GE) +BINARY(operator>, RelationalOperator::GT) #undef BINARY - -// External class template instantiations are in expression.cc. -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>; } // namespace Fortran::evaluate #endif // FORTRAN_EVALUATE_EXPRESSION_H_ diff --git a/flang/lib/evaluate/type.h b/flang/lib/evaluate/type.h index 3ef5ee5..04fa0d5 100644 --- a/flang/lib/evaluate/type.h +++ b/flang/lib/evaluate/type.h @@ -95,6 +95,9 @@ template struct Type { static constexpr int kind{KIND}; static constexpr bool hasLen{true}; using Value = std::string; + static std::string Dump() { + return EnumToString(category) + '(' + std::to_string(kind) + ')'; + } }; // Default REAL just simply has to be IEEE-754 single precision today. @@ -115,16 +118,21 @@ using DefaultCharacter = Type; // These templates create instances of std::variant<> that can contain // applications of some class template to all of the supported kinds of // a category of intrinsic type. -template class T> -using IntegerKindsVariant = std::variant, T<2>, T<4>, T<8>, T<16>>; -template class T> -using RealKindsVariant = std::variant, T<4>, T<8>, T<10>, T<16>>; -template class T> using ComplexKindsVariant = RealKindsVariant; -template class T> -using LogicalKindsVariant = std::variant, T<2>, T<4>, T<8>>; -template class T> -using CharacterKindsVariant = - std::variant>; // TODO larger CHARACTER kinds, incl. Kanji - +template class T> struct KindsVariant; +template class T> struct KindsVariant { + using type = std::variant, T<2>, T<4>, T<8>, T<16>>; +}; +template class T> struct KindsVariant { + using type = std::variant, T<4>, T<8>, T<10>, T<16>>; +}; +template class T> struct KindsVariant { + using type = typename KindsVariant::type; +}; +template class T> struct KindsVariant { + using type = std::variant>; // TODO larger CHARACTER kinds, incl. Kanji +}; +template class T> struct KindsVariant { + using type = std::variant, T<2>, T<4>, T<8>>; +}; } // namespace Fortran::evaluate #endif // FORTRAN_EVALUATE_TYPE_H_ diff --git a/flang/test/evaluate/expression.cc b/flang/test/evaluate/expression.cc index e33df6b..c2a7491 100644 --- a/flang/test/evaluate/expression.cc +++ b/flang/test/evaluate/expression.cc @@ -37,7 +37,7 @@ int main() { FoldingContext context{src, nullptr}; ex1.Fold(context); MATCH("-10", Dump(ex1)); - MATCH("(6.LE.7)", Dump(DefaultIntegerExpr{6} <= DefaultIntegerExpr{7})); + MATCH("(Integer(4)::6.LE.7)", Dump(DefaultIntegerExpr{6} <= DefaultIntegerExpr{7})); DefaultIntegerExpr a{1}; DefaultIntegerExpr b{2}; MATCH("(1/2)", Dump(a / b)); -- 2.7.4