From f9d4cef84ee096e4ab803667918915706802c033 Mon Sep 17 00:00:00 2001 From: peter klausler Date: Fri, 7 Sep 2018 16:54:33 -0700 Subject: [PATCH] [flang] cleaning up TODOs Original-commit: flang-compiler/f18@cfd67de3cdda968e01928bdab4a9767dd30ab869 Reviewed-on: https://github.com/flang-compiler/f18/pull/183 Tree-same-pre-rewrite: false --- flang/lib/evaluate/expression.cc | 19 +++++++++---- flang/lib/evaluate/expression.h | 11 +++++--- flang/lib/evaluate/tools.cc | 9 ++++++ flang/lib/evaluate/tools.h | 15 +--------- flang/lib/evaluate/type.h | 18 ++++++++++-- flang/lib/evaluate/variable.h | 5 +--- flang/lib/semantics/expression.cc | 47 ++++++++++++++++++++++++++++--- 7 files changed, 90 insertions(+), 34 deletions(-) diff --git a/flang/lib/evaluate/expression.cc b/flang/lib/evaluate/expression.cc index 4bf30433aeff..a40027e6e2b2 100644 --- a/flang/lib/evaluate/expression.cc +++ b/flang/lib/evaluate/expression.cc @@ -438,12 +438,17 @@ std::ostream &LogicalOperation::Infix(std::ostream &o) const { template std::ostream &Constant::Dump(std::ostream &o) const { if constexpr (T::category == TypeCategory::Integer) { - return o << value.SignedDecimal() << '_' << Result::kind; + return o << value.SignedDecimal() << '_' << T::kind; } else if constexpr (T::category == TypeCategory::Real || T::category == TypeCategory::Complex) { - return o << value.DumpHexadecimal() << '_' << Result::kind; + return o << value.DumpHexadecimal() << '_' << T::kind; } else if constexpr (T::category == TypeCategory::Character) { - return o << Result::kind << '_' << parser::QuoteCharacterLiteral(value); + if constexpr (T::kind == 1) { + return o << T::kind << '_' << parser::QuoteCharacterLiteral(value); + } else { + return o << T::kind + << "_'(wide character dumping unimplemented)'"; // TODO + } } else if constexpr (T::category == TypeCategory::Logical) { if (value.IsTrue()) { o << ".TRUE."; @@ -555,7 +560,9 @@ template class Expr>; template class Expr>; template class Expr>; template class Expr>; -template class Expr>; // TODO others +template class Expr>; +template class Expr>; +template class Expr>; template class Expr>; template class Expr>; template class Expr>; @@ -577,7 +584,9 @@ template struct Relational>; template struct Relational>; template struct Relational>; template struct Relational>; -template struct Relational>; // TODO others +template struct Relational>; +template struct Relational>; +template struct Relational>; template struct Relational; template struct ExpressionBase>; diff --git a/flang/lib/evaluate/expression.h b/flang/lib/evaluate/expression.h index 1b80d523fb13..3d9050d1318e 100644 --- a/flang/lib/evaluate/expression.h +++ b/flang/lib/evaluate/expression.h @@ -551,7 +551,9 @@ public: u; }; -extern template class Expr>; // TODO more +extern template class Expr>; +extern template class Expr>; +extern template class Expr>; // The Relational class template is a helper for constructing logical // expressions with polymorphism over the cross product of the possible @@ -581,7 +583,7 @@ struct Relational : public Operation, LogicalResult, A, A> { }; template<> class Relational { - // COMPLEX data is compared piecewise. + // COMPLEX data are compared piecewise. using DirectlyComparableTypes = common::CombineTuples; @@ -606,8 +608,9 @@ extern template struct Relational>; extern template struct Relational>; extern template struct Relational>; extern template struct Relational>; -extern template struct Relational>; // TODO - // more +extern template struct Relational>; +extern template struct Relational>; +extern template struct Relational>; extern template struct Relational; template diff --git a/flang/lib/evaluate/tools.cc b/flang/lib/evaluate/tools.cc index a89c27c02897..fb85185be2a8 100644 --- a/flang/lib/evaluate/tools.cc +++ b/flang/lib/evaluate/tools.cc @@ -344,6 +344,15 @@ std::optional> Negation( std::move(x.u)); } +Expr LogicalNegation(Expr &&x) { + return std::visit( + [](auto &&xk) { + return AsCategoryExpr( + AsExpr(Not::kind>{std::move(xk)})); + }, + std::move(x.u)); +} + template Expr PackageRelation( RelationalOperator opr, Expr &&x, Expr &&y) { diff --git a/flang/lib/evaluate/tools.h b/flang/lib/evaluate/tools.h index 161c70ed8e40..d3bf4a925c74 100644 --- a/flang/lib/evaluate/tools.h +++ b/flang/lib/evaluate/tools.h @@ -26,19 +26,11 @@ namespace Fortran::evaluate { // Generalizing packagers: these take operations and expressions of more // specific types and wrap them in Expr<> containers of more abstract types. -// TODO: Would these be better as conversion constructors in the classes? -// TODO: Are the lvalue argument versions still needed? -template Expr> AsExpr(const A &x) { return {x}; } template Expr> AsExpr(A &&x) { return {std::move(x)}; } -template -Expr> AsCategoryExpr(const Expr> &x) { - return {x}; -} - template Expr> AsCategoryExpr(Expr> &&x) { return {std::move(x)}; @@ -54,16 +46,10 @@ Expr> AsCategoryExpr(SomeKindScalar &&x) { x.u); } -template Expr AsGenericExpr(const A &x) { return {x}; } - template Expr AsGenericExpr(A &&x) { return {std::move(x)}; } -template -Expr AsGenericExpr(const Expr> &x) { - return {AsCategoryExpr(x)}; -} template Expr AsGenericExpr(Expr> &&x) { return {AsCategoryExpr(std::move(x))}; @@ -332,6 +318,7 @@ std::optional> Negation( std::optional> Relate(parser::ContextualMessages &, RelationalOperator, Expr &&, Expr &&); +Expr LogicalNegation(Expr &&); Expr BinaryLogicalOperation( LogicalOperator, Expr &&, Expr &&); diff --git a/flang/lib/evaluate/type.h b/flang/lib/evaluate/type.h index ab7e8f327a7d..4e784d9605a7 100644 --- a/flang/lib/evaluate/type.h +++ b/flang/lib/evaluate/type.h @@ -91,12 +91,24 @@ struct Type using Scalar = value::Complex; }; -template -struct Type - : public TypeBase { +template<> +struct Type + : public TypeBase { using Scalar = std::string; }; +template<> +struct Type + : public TypeBase { + using Scalar = std::u16string; +}; + +template<> +struct Type + : public TypeBase { + using Scalar = std::u32string; +}; + template struct Type : public TypeBase { diff --git a/flang/lib/evaluate/variable.h b/flang/lib/evaluate/variable.h index d1a695b9263c..b5e6c164aff0 100644 --- a/flang/lib/evaluate/variable.h +++ b/flang/lib/evaluate/variable.h @@ -185,6 +185,7 @@ public: std::ostream &Dump(std::ostream &) const; private: + // TODO: character kinds > 1 std::variant u_; std::optional first_, last_; }; @@ -296,8 +297,4 @@ using SubroutineRef = ProcedureRef; } // namespace Fortran::evaluate -// This inclusion must follow the definitions in this header due to -// mutual references. -#include "expression.h" - #endif // FORTRAN_EVALUATE_VARIABLE_H_ diff --git a/flang/lib/semantics/expression.cc b/flang/lib/semantics/expression.cc index 18d481095036..6240ca861174 100644 --- a/flang/lib/semantics/expression.cc +++ b/flang/lib/semantics/expression.cc @@ -486,8 +486,20 @@ MaybeExpr ExprAnalyzer::Analyze(const parser::Expr::Negate &x) { return std::nullopt; } -MaybeExpr ExprAnalyzer::Analyze(const parser::Expr::NOT &) { - context.messages.Say("pmk: NOT unimplemented\n"_err_en_US); +MaybeExpr ExprAnalyzer::Analyze(const parser::Expr::NOT &x) { + if (MaybeExpr operand{AnalyzeHelper(*this, *x.v)}) { + return std::visit(common::visitors{[](Expr &&lx) -> MaybeExpr { + return {AsGenericExpr( + LogicalNegation(std::move(lx)))}; + }, + [=](auto &&) -> MaybeExpr { + // TODO pmk: INTEGER operand for bitwise extension? + context.messages.Say( + "Operand of .NOT. must be LOGICAL"_err_en_US); + return std::nullopt; + }}, + std::move(operand->u)); + } return std::nullopt; } @@ -538,8 +550,35 @@ MaybeExpr ExprAnalyzer::Analyze(const parser::Expr::ComplexConstructor &x) { AnalyzeHelper(*this, *std::get<1>(x.t)))); } -MaybeExpr ExprAnalyzer::Analyze(const parser::Expr::Concat &) { - context.messages.Say("pmk: Concat unimplemented\n"_err_en_US); +MaybeExpr ExprAnalyzer::Analyze(const parser::Expr::Concat &x) { + if (auto both{common::AllPresent(AnalyzeHelper(*this, *std::get<0>(x.t)), + AnalyzeHelper(*this, *std::get<1>(x.t)))}) { + return std::visit( + common::visitors{ + [&](Expr &&cx, Expr &&cy) { + return std::visit( + [&](auto &&cxk, auto &&cyk) -> MaybeExpr { + using Ty = ResultType; + if constexpr (std::is_same_v>) { + return {AsGenericExpr(AsCategoryExpr(AsExpr( + Concat{std::move(cxk), std::move(cyk)})))}; + } else { + context.messages.Say( + "Operands of // must be the same kind of CHARACTER"_err_en_US); + return std::nullopt; + } + }, + std::move(cx.u), std::move(cy.u)); + }, + [&](auto &&, auto &&) -> MaybeExpr { + context.messages.Say( + "Operands of // must be CHARACTER"_err_en_US); + return std::nullopt; + }, + }, + std::move(std::get<0>(*both).u), std::move(std::get<1>(*both).u)); + } return std::nullopt; } -- 2.34.1