From 5566d70ef2f57a7628c240884ebcb059ca2888f6 Mon Sep 17 00:00:00 2001 From: peter klausler Date: Tue, 14 Aug 2018 15:11:53 -0700 Subject: [PATCH] [flang] More cleaning Original-commit: flang-compiler/f18@8227229f625dd7a88760ea96810c9456295d8a43 Reviewed-on: https://github.com/flang-compiler/f18/pull/183 Tree-same-pre-rewrite: false --- flang/lib/evaluate/expression.h | 86 +++++++++++++------------------ flang/lib/evaluate/tools.cc | 44 ++++++++-------- flang/lib/evaluate/tools.h | 10 ++-- flang/lib/evaluate/type.h | 19 ++++--- flang/lib/semantics/expression.cc | 75 ++++++++++++++------------- flang/lib/semantics/expression.h | 5 +- 6 files changed, 113 insertions(+), 126 deletions(-) diff --git a/flang/lib/evaluate/expression.h b/flang/lib/evaluate/expression.h index 4a45de124f54..78efe9203711 100644 --- a/flang/lib/evaluate/expression.h +++ b/flang/lib/evaluate/expression.h @@ -34,14 +34,6 @@ namespace Fortran::evaluate { template class Expr; -// An expression whose result is within one particular type category and -// of any supported kind. -using SomeKindIntegerExpr = Expr>; -using SomeKindRealExpr = Expr>; -using SomeKindComplexExpr = Expr>; -using SomeKindCharacterExpr = Expr>; -using SomeKindLogicalExpr = Expr>; - // Helper base classes for packaging subexpressions. template class Unary { public: @@ -96,16 +88,14 @@ public: using Result = Type; using FoldableTrait = std::true_type; - struct ConvertInteger - : public Unary> { - using Unary>::Unary; + struct ConvertInteger : public Unary { + using Unary::Unary; static std::optional> FoldScalar( FoldingContext &, const SomeKindScalar &); }; - struct ConvertReal - : public Unary> { - using Unary>::Unary; + struct ConvertReal : public Unary { + using Unary::Unary; static std::optional> FoldScalar( FoldingContext &, const SomeKindScalar &); }; @@ -166,22 +156,22 @@ public: Expr(std::int64_t n) : u_{Scalar{n}} {} Expr(std::uint64_t n) : u_{Scalar{n}} {} Expr(int n) : u_{Scalar{n}} {} - Expr(const SomeKindIntegerExpr &x) : u_{ConvertInteger{x}} {} - Expr(SomeKindIntegerExpr &&x) : u_{ConvertInteger{std::move(x)}} {} + Expr(const Expr &x) : u_{ConvertInteger{x}} {} + Expr(Expr &&x) : u_{ConvertInteger{std::move(x)}} {} template Expr(const Expr> &x) - : u_{ConvertInteger{SomeKindIntegerExpr{x}}} {} + : u_{ConvertInteger{Expr{x}}} {} template Expr(Expr> &&x) - : u_{ConvertInteger{SomeKindIntegerExpr{std::move(x)}}} {} - Expr(const SomeKindRealExpr &x) : u_{ConvertReal{x}} {} - Expr(SomeKindRealExpr &&x) : u_{ConvertReal{std::move(x)}} {} + : u_{ConvertInteger{Expr{std::move(x)}}} {} + Expr(const Expr &x) : u_{ConvertReal{x}} {} + Expr(Expr &&x) : u_{ConvertReal{std::move(x)}} {} template Expr(const Expr> &x) - : u_{ConvertReal{SomeKindRealExpr{x}}} {} + : u_{ConvertReal{Expr{x}}} {} template Expr(Expr> &&x) - : u_{ConvertReal{SomeKindRealExpr{std::move(x)}}} {} + : u_{ConvertReal{Expr{std::move(x)}}} {} template Expr(const A &x) : u_{x} {} template Expr(std::enable_if_t && @@ -210,15 +200,13 @@ public: // 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 ConvertInteger - : public Unary> { - using Unary>::Unary; + struct ConvertInteger : public Unary { + using Unary::Unary; static std::optional> FoldScalar( FoldingContext &, const SomeKindScalar &); }; - struct ConvertReal - : public Unary> { - using Unary>::Unary; + struct ConvertReal : public Unary { + using Unary::Unary; static std::optional> FoldScalar( FoldingContext &, const SomeKindScalar &); }; @@ -261,10 +249,8 @@ public: static std::optional> FoldScalar( FoldingContext &, const Scalar &, const Scalar &); }; - struct IntPower - : public Binary> { - using Binary>::Binary; + struct IntPower : public Binary { + using Binary::Binary; static std::optional> FoldScalar(FoldingContext &, const Scalar &, const SomeKindScalar &); }; @@ -294,22 +280,22 @@ public: CLASS_BOILERPLATE(Expr) Expr(const Scalar &x) : u_{x} {} - Expr(const SomeKindIntegerExpr &x) : u_{ConvertInteger{x}} {} - Expr(SomeKindIntegerExpr &&x) : u_{ConvertInteger{std::move(x)}} {} + Expr(const Expr &x) : u_{ConvertInteger{x}} {} + Expr(Expr &&x) : u_{ConvertInteger{std::move(x)}} {} template Expr(const Expr> &x) - : u_{ConvertInteger{SomeKindIntegerExpr{x}}} {} + : u_{ConvertInteger{Expr{x}}} {} template Expr(Expr> &&x) - : u_{ConvertInteger{SomeKindIntegerExpr{std::move(x)}}} {} - Expr(const SomeKindRealExpr &x) : u_{ConvertReal{x}} {} - Expr(SomeKindRealExpr &&x) : u_{ConvertReal{std::move(x)}} {} + : u_{ConvertInteger{Expr{std::move(x)}}} {} + Expr(const Expr &x) : u_{ConvertReal{x}} {} + Expr(Expr &&x) : u_{ConvertReal{std::move(x)}} {} template Expr(const Expr> &x) - : u_{ConvertReal{SomeKindRealExpr{x}}} {} + : u_{ConvertReal{Expr{x}}} {} template Expr(Expr> &&x) - : u_{ConvertReal{SomeKindRealExpr{std::move(x)}}} {} + : u_{ConvertReal{Expr{std::move(x)}}} {} template Expr(const A &x) : u_{x} {} template Expr(std::enable_if_t, A> &&x) : u_{std::move(x)} {} @@ -372,10 +358,8 @@ public: static std::optional> FoldScalar( FoldingContext &, const Scalar &, const Scalar &); }; - struct IntPower - : public Binary> { - using Binary>::Binary; + struct IntPower : public Binary { + using Binary::Binary; static std::optional> FoldScalar(FoldingContext &, const Scalar &, const SomeKindScalar &); }; @@ -595,11 +579,11 @@ public: typename KindsVariant::type u; }; -extern template class Expr>; -extern template class Expr>; -extern template class Expr>; -extern template class Expr>; -extern template class Expr>; +extern template class Expr; +extern template class Expr; +extern template class Expr; +extern template class Expr; +extern template class Expr; // BOZ literal constants need to be wide enough to hold an integer or real // value of any supported kind. They also need to be distinguishable from @@ -629,8 +613,8 @@ public: std::optional> Fold(FoldingContext &); int Rank() const { return 1; } // TODO - std::variant + std::variant, Expr, Expr, + Expr, Expr, BOZLiteralConstant> u; }; diff --git a/flang/lib/evaluate/tools.cc b/flang/lib/evaluate/tools.cc index f9c7aa1e6716..d22d71e57854 100644 --- a/flang/lib/evaluate/tools.cc +++ b/flang/lib/evaluate/tools.cc @@ -20,53 +20,51 @@ using namespace Fortran::parser::literals; namespace Fortran::evaluate { -SomeKindRealExpr ConvertToTypeOf( - const SomeKindRealExpr &to, const SomeKindIntegerExpr &from) { +Expr ConvertToTypeOf( + const Expr &to, const Expr &from) { return std::visit( - [&](const auto &rk) { return SomeKindRealExpr{decltype(rk){to}}; }, to.u); + [&](const auto &rk) { return Expr{decltype(rk){to}}; }, to.u); } -SomeKindRealExpr ConvertToTypeOf( - const SomeKindRealExpr &to, const SomeKindRealExpr &from) { +Expr ConvertToTypeOf( + const Expr &to, const Expr &from) { return std::visit( - [&](const auto &rk) { return SomeKindRealExpr{decltype(rk){to}}; }, to.u); + [&](const auto &rk) { return Expr{decltype(rk){to}}; }, to.u); } -std::optional> -ConvertRealOperands( +std::optional, Expr>> ConvertRealOperands( parser::ContextualMessages &messages, GenericExpr &&x, GenericExpr &&y) { return std::visit( - common::visitors{ - [&](SomeKindIntegerExpr &&ix, SomeKindIntegerExpr &&iy) { - // Can happen in a CMPLX() constructor. Per F'2018, both integer - // operands are converted to default REAL. - return std::optional{std::make_pair( - SomeKindRealExpr{Expr{std::move(ix)}}, - SomeKindRealExpr{Expr{std::move(iy)}})}; - }, - [&](SomeKindIntegerExpr &&ix, SomeKindRealExpr &&ry) { + common::visitors{[&](Expr &&ix, Expr &&iy) { + // Can happen in a CMPLX() constructor. Per F'2018, + // both integer operands are converted to default REAL. + return std::optional{std::make_pair( + Expr{Expr{std::move(ix)}}, + Expr{Expr{std::move(iy)}})}; + }, + [&](Expr &&ix, Expr &&ry) { auto rx{ConvertToTypeOf(ry, std::move(ix))}; return std::optional{std::make_pair(std::move(rx), std::move(ry))}; }, - [&](SomeKindRealExpr &&rx, SomeKindIntegerExpr &&iy) { + [&](Expr &&rx, Expr &&iy) { auto ry{ConvertToTypeOf(rx, std::move(iy))}; return std::optional{std::make_pair(std::move(rx), std::move(ry))}; }, - [&](SomeKindRealExpr &&rx, SomeKindRealExpr &&ry) { + [&](Expr &&rx, Expr &&ry) { ConvertToSameKind(rx, ry); return std::optional{std::make_pair(std::move(rx), std::move(ry))}; }, [&](const auto &, const auto &) - -> std::optional> { + -> std::optional, Expr>> { messages.Say("operands must be INTEGER or REAL"_err_en_US); return std::nullopt; }}, std::move(x.u), std::move(y.u)); } -std::optional> -ConvertRealOperands(parser::ContextualMessages &messages, - std::optional &&x, std::optional &&y) { +std::optional, Expr>> ConvertRealOperands( + parser::ContextualMessages &messages, std::optional &&x, + std::optional &&y) { if (x.has_value() && y.has_value()) { return ConvertRealOperands(messages, std::move(*x), std::move(*y)); } diff --git a/flang/lib/evaluate/tools.h b/flang/lib/evaluate/tools.h index 352b57558427..6b437cbd019b 100644 --- a/flang/lib/evaluate/tools.h +++ b/flang/lib/evaluate/tools.h @@ -24,15 +24,15 @@ namespace Fortran::evaluate { // Convert the second argument to the same type and kind of the first. -SomeKindRealExpr ConvertToTypeOf( - const SomeKindRealExpr &to, const SomeKindIntegerExpr &from); -SomeKindRealExpr ConvertToTypeOf( - const SomeKindRealExpr &to, const SomeKindRealExpr &from); +Expr ConvertToTypeOf( + const Expr &to, const Expr &from); +Expr ConvertToTypeOf( + const Expr &to, const Expr &from); // Ensure that both operands of an intrinsic REAL operation or CMPLX() // are INTEGER or REAL, and convert them as necessary to the same REAL type. using ConvertRealOperandsResult = - std::optional>; + std::optional, Expr>>; ConvertRealOperandsResult ConvertRealOperands( parser::ContextualMessages &, GenericExpr &&, GenericExpr &&); diff --git a/flang/lib/evaluate/type.h b/flang/lib/evaluate/type.h index a5f528bd7259..49aa673b8885 100644 --- a/flang/lib/evaluate/type.h +++ b/flang/lib/evaluate/type.h @@ -107,6 +107,7 @@ struct Type // Type functions template using Scalar = typename std::decay_t::Scalar; + template using SameKind = Type::kind>; @@ -201,13 +202,6 @@ template struct SomeKindScalar { typename KindsVariant::type u; }; -struct GenericScalar; - -// Represents a completely generic type. -struct SomeType { - using Scalar = GenericScalar; -}; - // Holds a scalar constant of any intrinsic category and size. struct GenericScalar { CLASS_BOILERPLATE(GenericScalar) @@ -239,5 +233,16 @@ template struct SomeKind { using Scalar = SomeKindScalar; }; +using SomeInteger = SomeKind; +using SomeReal = SomeKind; +using SomeComplex = SomeKind; +using SomeCharacter = SomeKind; +using SomeLogical = SomeKind; + +// Represents a completely generic type. +struct SomeType { + using Scalar = GenericScalar; +}; + } // namespace Fortran::evaluate #endif // FORTRAN_EVALUATE_TYPE_H_ diff --git a/flang/lib/semantics/expression.cc b/flang/lib/semantics/expression.cc index de74add6da59..7b9cbef51b4e 100644 --- a/flang/lib/semantics/expression.cc +++ b/flang/lib/semantics/expression.cc @@ -24,6 +24,9 @@ using namespace Fortran::parser::literals; namespace Fortran::semantics { using common::TypeCategory; +using evaluate::Expr; +using evaluate::GenericExpr; +using evaluate::Type; // AnalyzeHelper is a local template function that keeps the API // member function ExpressionAnalyzer::Analyze from having to be a @@ -77,31 +80,29 @@ MaybeExpr AnalyzeHelper( return result; } -// TODO: Return -// std::optional>> here -// instead +// TODO: Return std::optional> here instead template MaybeExpr AnalyzeHelper( ExpressionAnalyzer &ea, const parser::Integer &tree) { MaybeExpr result{AnalyzeHelper(ea, tree.thing)}; if (result.has_value() && - !std::holds_alternative(result->u)) { + !std::holds_alternative>(result->u)) { ea.context().messages.Say("must be integer"_err_en_US); return std::nullopt; } return result; } -static std::optional AnalyzeLiteral( +static std::optional> AnalyzeLiteral( ExpressionAnalyzer &ea, const parser::CharLiteralConstant &x) { auto kind{ea.Analyze(std::get>(x.t), ExpressionAnalyzer::KindParam{1})}; switch (kind) { #define CASE(k) \ case k: { \ - using Ty = evaluate::Type; \ - return {evaluate::SomeKindCharacterExpr{ \ - evaluate::Expr{std::get(x.t)}}}; \ + using Ty = Type; \ + return { \ + Expr{Expr{std::get(x.t)}}}; \ } FOR_EACH_CHARACTER_KIND(CASE, ) #undef CASE @@ -114,7 +115,7 @@ static std::optional AnalyzeLiteral( template MaybeExpr PackageGeneric(std::optional &&x) { std::function f{ - [](A &&y) -> GenericExpr { return {std::move(y)}; }}; + [](A &&y) { return GenericExpr{std::move(y)}; }}; return common::MapOptional(f, std::move(x)); } @@ -131,11 +132,11 @@ MaybeExpr AnalyzeHelper( } // TODO: ensure that any kind parameter is 1 std::string str{std::get(x.t).GetString()}; - std::optional> lb, ub; + std::optional> lb, ub; if (lbTree.has_value()) { if (MaybeExpr lbExpr{AnalyzeHelper(ea, *lbTree)}) { - if (auto *ie{std::get_if(&lbExpr->u)}) { - lb = evaluate::Expr{std::move(*ie)}; + if (auto *ie{std::get_if>(&lbExpr->u)}) { + lb = Expr{std::move(*ie)}; } else { ea.context().messages.Say( "scalar integer expression required for substring lower bound"_err_en_US); @@ -144,8 +145,8 @@ MaybeExpr AnalyzeHelper( } if (ubTree.has_value()) { if (MaybeExpr ubExpr{AnalyzeHelper(ea, *ubTree)}) { - if (auto *ie{std::get_if(&ubExpr->u)}) { - ub = evaluate::Expr{std::move(*ie)}; + if (auto *ie{std::get_if>(&ubExpr->u)}) { + ub = Expr{std::move(*ie)}; } else { ea.context().messages.Say( "scalar integer expression required for substring upper bound"_err_en_US); @@ -157,14 +158,14 @@ MaybeExpr AnalyzeHelper( } evaluate::Substring substring{std::move(str), std::move(lb), std::move(ub)}; evaluate::CopyableIndirection ind{std::move(substring)}; - evaluate::Expr chExpr{std::move(ind)}; + Expr chExpr{std::move(ind)}; chExpr.Fold(ea.context()); - return {GenericExpr{evaluate::SomeKindCharacterExpr{std::move(chExpr)}}}; + return {GenericExpr{Expr{std::move(chExpr)}}}; } // Common handling of parser::IntLiteralConstant and SignedIntLiteralConstant template -std::optional IntLiteralConstant( +std::optional> IntLiteralConstant( ExpressionAnalyzer &ea, const PARSED &x) { auto kind{ea.Analyze(std::get>(x.t), ea.defaultIntegerKind())}; @@ -172,8 +173,8 @@ std::optional IntLiteralConstant( switch (kind) { #define CASE(k) \ case k: { \ - using Ty = evaluate::Type; \ - return {evaluate::ToSomeKindExpr(evaluate::Expr{value})}; \ + using Ty = Type; \ + return {evaluate::ToSomeKindExpr(Expr{value})}; \ } FOR_EACH_INTEGER_KIND(CASE, ) #undef CASE @@ -184,12 +185,12 @@ std::optional IntLiteralConstant( } } -static std::optional AnalyzeLiteral( +static std::optional> AnalyzeLiteral( ExpressionAnalyzer &ea, const parser::IntLiteralConstant &x) { return IntLiteralConstant(ea, x); } -static std::optional AnalyzeLiteral( +static std::optional> AnalyzeLiteral( ExpressionAnalyzer &ea, const parser::SignedIntLiteralConstant &x) { return IntLiteralConstant(ea, x); } @@ -220,10 +221,10 @@ static std::optional AnalyzeLiteral( } template -std::optional ReadRealLiteral( +std::optional> ReadRealLiteral( parser::CharBlock source, evaluate::FoldingContext &context) { const char *p{source.begin()}; - using RealType = evaluate::Type; + using RealType = Type; auto valWithFlags{evaluate::Scalar::Read(p, context.rounding)}; CHECK(p == source.end()); evaluate::RealFlagWarnings( @@ -232,10 +233,10 @@ std::optional ReadRealLiteral( if (context.flushDenormalsToZero) { value = value.FlushDenormalToZero(); } - return {evaluate::ToSomeKindExpr(evaluate::Expr{value})}; + return {evaluate::ToSomeKindExpr(Expr{value})}; } -static std::optional AnalyzeLiteral( +static std::optional> AnalyzeLiteral( ExpressionAnalyzer &ea, const parser::RealLiteralConstant &x) { // Use a local message context around the real literal. parser::ContextualMessages ctxMsgs{x.real.source, ea.context().messages}; @@ -269,7 +270,7 @@ static std::optional AnalyzeLiteral( } } -static std::optional AnalyzeLiteral( +static std::optional> AnalyzeLiteral( ExpressionAnalyzer &ea, const parser::SignedRealLiteralConstant &x) { auto result{AnalyzeLiteral(ea, std::get(x.t))}; if (result.has_value()) { @@ -321,19 +322,19 @@ MaybeExpr AnalyzeHelper(ExpressionAnalyzer &ea, const parser::ComplexPart &x) { // to default REAL and the result is default COMPLEX. Otherwise, the // kind of the result is the kind of largest REAL component, and the other // component is converted if necessary its type. -static std::optional AnalyzeLiteral( +static std::optional> AnalyzeLiteral( ExpressionAnalyzer &ea, const parser::ComplexLiteralConstant &z) { const parser::ComplexPart &re{std::get<0>(z.t)}, &im{std::get<1>(z.t)}; return ea.ConstructComplex(AnalyzeHelper(ea, re), AnalyzeHelper(ea, im)); } -static std::optional AnalyzeLiteral( +static std::optional> AnalyzeLiteral( ExpressionAnalyzer &ea, const parser::HollerithLiteralConstant &x) { - evaluate::Expr expr{x.v}; - return {evaluate::SomeKindCharacterExpr{expr}}; + Expr expr{x.v}; + return {Expr{expr}}; } -static std::optional AnalyzeLiteral( +static std::optional> AnalyzeLiteral( ExpressionAnalyzer &ea, const parser::LogicalLiteralConstant &x) { auto kind{ea.Analyze(std::get>(x.t), ea.defaultLogicalKind())}; @@ -341,8 +342,8 @@ static std::optional AnalyzeLiteral( switch (kind) { #define CASE(k) \ case k: { \ - using Ty = evaluate::Type; \ - return {evaluate::SomeKindLogicalExpr{evaluate::Expr{value}}}; \ + using Ty = Type; \ + return {Expr{Expr{value}}}; \ } FOR_EACH_LOGICAL_KIND(CASE, ) #undef CASE @@ -596,8 +597,8 @@ ExpressionAnalyzer::KindParam ExpressionAnalyzer::Analyze( kindParam->u); } -std::optional -ExpressionAnalyzer::ConstructComplex(MaybeExpr &&real, MaybeExpr &&imaginary) { +std::optional> ExpressionAnalyzer::ConstructComplex( + MaybeExpr &&real, MaybeExpr &&imaginary) { // TODO: pmk abstract further, this will be a common pattern auto partial{[&](GenericExpr &&x, GenericExpr &&y) { return evaluate::ConvertRealOperands( @@ -609,10 +610,10 @@ ExpressionAnalyzer::ConstructComplex(MaybeExpr &&real, MaybeExpr &&imaginary) { auto converted{common::MapOptional(f, std::move(real), std::move(imaginary))}; if (auto joined{common::JoinOptionals(std::move(converted))}) { return {std::visit( - [](auto &&rx, auto &&ix) -> evaluate::SomeKindComplexExpr { + [](auto &&rx, auto &&ix) -> Expr { using realType = evaluate::ResultType; using zType = evaluate::SameKind; - using zExpr = evaluate::Expr; + using zExpr = Expr; return {zExpr{typename zExpr::CMPLX{std::move(rx), std::move(ix)}}}; }, std::move(joined->first.u), std::move(joined->second.u))}; diff --git a/flang/lib/semantics/expression.h b/flang/lib/semantics/expression.h index b0340a027e35..9faea6833807 100644 --- a/flang/lib/semantics/expression.h +++ b/flang/lib/semantics/expression.h @@ -23,8 +23,7 @@ namespace Fortran::semantics { -using evaluate::GenericExpr; -using MaybeExpr = std::optional; +using MaybeExpr = std::optional; class ExpressionAnalyzer { public: @@ -44,7 +43,7 @@ public: KindParam Analyze(const std::optional &, KindParam defaultKind, KindParam kanjiKind = -1 /* not allowed here */); - std::optional ConstructComplex( + std::optional> ConstructComplex( MaybeExpr &&real, MaybeExpr &&imaginary); private: