From b35f4a98e2d80b5f7a1f400f7f38393752680f1c Mon Sep 17 00:00:00 2001 From: peter klausler Date: Mon, 1 Apr 2019 10:54:22 -0700 Subject: [PATCH] [flang] work in progress Original-commit: flang-compiler/f18@33ea8e506a114350d4c587ed14c6f5dacbd5379a Reviewed-on: https://github.com/flang-compiler/f18/pull/371 Tree-same-pre-rewrite: false --- flang/lib/evaluate/formatting.cc | 204 +++++++++++++++++++++++++++-- flang/lib/evaluate/variable.cc | 168 +----------------------- flang/lib/evaluate/variable.h | 5 + flang/test/evaluate/expression.cc | 6 +- flang/test/semantics/modfile13.f90 | 6 +- flang/test/semantics/modfile17.f90 | 6 +- 6 files changed, 207 insertions(+), 188 deletions(-) diff --git a/flang/lib/evaluate/formatting.cc b/flang/lib/evaluate/formatting.cc index c638578e1d2e..dff43d253cf6 100644 --- a/flang/lib/evaluate/formatting.cc +++ b/flang/lib/evaluate/formatting.cc @@ -16,6 +16,7 @@ #include "call.h" #include "constant.h" #include "expression.h" +#include "tools.h" #include "../parser/characters.h" #include "../semantics/symbol.h" @@ -134,6 +135,7 @@ std::ostream &ProcedureRef::AsFortran(std::ostream &o) const { enum class Precedence { Primary, // don't parenthesize + Constant, // parenthesize if negative integer/real operand Parenthesize, // (x), (real, imaginary) DefinedUnary, Negate, @@ -147,7 +149,7 @@ enum class Precedence { }; template constexpr Precedence ToPrecedence{Precedence::Primary}; - +template constexpr Precedence ToPrecedence>{Precedence::Constant}; template constexpr Precedence ToPrecedence>{Precedence::Parenthesize}; template @@ -218,6 +220,14 @@ std::ostream &Operation::AsFortran(std::ostream &o) const { static constexpr Precedence thisPrec{ToPrecedence}; bool lhsParens{lhsPrec == Precedence::Parenthesize || lhsPrec > thisPrec || (lhsPrec == thisPrec && lhsPrec == Precedence::Power)}; + if constexpr (lhsPrec == Precedence::Constant && thisPrec != Precedence::Additive) { + static constexpr TypeCategory cat{Operand<0>::Result::category}; + if constexpr (cat == TypeCategory::Integer || cat == TypeCategory::Real) { + const auto *p{UnwrapExpr>>(left())}; + CHECK(p != nullptr); + lhsParens |= p->size() == 1 && (*p)->IsNegative(); + } + } if (lhsParens) { o << '('; } @@ -226,7 +236,15 @@ std::ostream &Operation::AsFortran(std::ostream &o) const { o << ')'; } static constexpr Precedence rhsPrec{ToPrecedence>}; - bool rhsParens{rhsPrec == Precedence::Parenthesize || rhsPrec > thisPrec}; + bool rhsParens{rhsPrec == Precedence::Parenthesize || rhsPrec == Precedence::Negate || rhsPrec > thisPrec}; + if constexpr (rhsPrec == Precedence::Constant) { + static constexpr TypeCategory cat{Operand<1>::Result::category}; + if constexpr (cat == TypeCategory::Integer || cat == TypeCategory::Real) { + const auto *p{UnwrapExpr>>(right())}; + CHECK(p != nullptr); + rhsParens |= p->size() == 1 && (*p)->IsNegative(); + } + } if (rhsParens) { o << '('; } @@ -284,18 +302,18 @@ template const char *LogicalOperation::Infix() const { } template -std::ostream &Emit( +std::ostream &EmitArray( std::ostream &o, const common::CopyableIndirection> &expr) { return expr.value().AsFortran(o); } template -std::ostream &Emit(std::ostream &, const ArrayConstructorValues &); +std::ostream &EmitArray(std::ostream &, const ArrayConstructorValues &); template -std::ostream &Emit(std::ostream &o, const ImpliedDo &implDo) { +std::ostream &EmitArray(std::ostream &o, const ImpliedDo &implDo) { o << '('; - Emit(o, implDo.values()); + EmitArray(o, implDo.values()); o << ',' << ImpliedDoIndex::Result::AsFortran() << "::" << implDo.name().ToString() << '='; implDo.lower().AsFortran(o) << ','; @@ -305,11 +323,11 @@ std::ostream &Emit(std::ostream &o, const ImpliedDo &implDo) { } template -std::ostream &Emit(std::ostream &o, const ArrayConstructorValues &values) { +std::ostream &EmitArray(std::ostream &o, const ArrayConstructorValues &values) { const char *sep{""}; for (const auto &value : values.values()) { o << sep; - std::visit([&](const auto &x) { Emit(o, x); }, value.u); + std::visit([&](const auto &x) { EmitArray(o, x); }, value.u); sep = ","; } return o; @@ -318,7 +336,7 @@ std::ostream &Emit(std::ostream &o, const ArrayConstructorValues &values) { template std::ostream &ArrayConstructor::AsFortran(std::ostream &o) const { o << '[' << GetType().AsFortran() << "::"; - Emit(o, *this); + EmitArray(o, *this); return o << ']'; } @@ -328,13 +346,13 @@ std::ostream &ArrayConstructor>::AsFortran( std::stringstream len; LEN().AsFortran(len); o << '[' << GetType().AsFortran(len.str()) << "::"; - Emit(o, *this); + EmitArray(o, *this); return o << ']'; } std::ostream &ArrayConstructor::AsFortran(std::ostream &o) const { o << '[' << GetType().AsFortran() << "::"; - Emit(o, *this); + EmitArray(o, *this); return o << ']'; } @@ -384,7 +402,169 @@ std::ostream &DerivedTypeSpecAsFortran( return o; } +std::ostream &EmitVar(std::ostream &o, const Symbol &symbol) { + return o << symbol.name().ToString(); +} + +std::ostream &EmitVar(std::ostream &o, const std::string &lit) { + return o << parser::QuoteCharacterLiteral(lit); +} + +std::ostream &EmitVar(std::ostream &o, const std::u16string &lit) { + return o << parser::QuoteCharacterLiteral(lit); +} + +std::ostream &EmitVar(std::ostream &o, const std::u32string &lit) { + return o << parser::QuoteCharacterLiteral(lit); +} + +template std::ostream &EmitVar(std::ostream &o, const A &x) { + return x.AsFortran(o); +} + +template +std::ostream &EmitVar(std::ostream &o, const A *p, const char *kw = nullptr) { + if (p != nullptr) { + if (kw != nullptr) { + o << kw; + } + EmitVar(o, *p); + } + return o; +} + +template +std::ostream &EmitVar( + std::ostream &o, const std::optional &x, const char *kw = nullptr) { + if (x.has_value()) { + if (kw != nullptr) { + o << kw; + } + EmitVar(o, *x); + } + return o; +} + +template +std::ostream &EmitVar(std::ostream &o, const common::Indirection &p, + const char *kw = nullptr) { + if (kw != nullptr) { + o << kw; + } + EmitVar(o, p.value()); + return o; +} + +template +std::ostream &EmitVar(std::ostream &o, const std::shared_ptr &p) { + CHECK(p != nullptr); + return EmitVar(o, *p); +} + +template +std::ostream &EmitVar(std::ostream &o, const std::variant &u) { + std::visit([&](const auto &x) { EmitVar(o, x); }, u); + return o; +} + +std::ostream &BaseObject::AsFortran(std::ostream &o) const { + return EmitVar(o, u); +} + +template +std::ostream &TypeParamInquiry::AsFortran(std::ostream &o) const { + std::visit( + common::visitors{ + [&](const Symbol *sym) { + if (sym != nullptr) { + EmitVar(o, *sym) << '%'; + } + }, + [&](const Component &comp) { EmitVar(o, comp) << '%'; }, + }, + base_); + return EmitVar(o, *parameter_); +} + +std::ostream &Component::AsFortran(std::ostream &o) const { + base_.value().AsFortran(o); + return EmitVar(o << '%', *symbol_); +} + +std::ostream &Triplet::AsFortran(std::ostream &o) const { + EmitVar(o, lower_) << ':'; + EmitVar(o, upper_); + EmitVar(o << ':', stride_.value()); + return o; +} + +std::ostream &Subscript::AsFortran(std::ostream &o) const { return EmitVar(o, u); } + +std::ostream &ArrayRef::AsFortran(std::ostream &o) const { + EmitVar(o, base_); + char separator{'('}; + for (const Subscript &ss : subscript_) { + ss.AsFortran(o << separator); + separator = ','; + } + return o << ')'; +} + +std::ostream &CoarrayRef::AsFortran(std::ostream &o) const { + for (const Symbol *sym : base_) { + EmitVar(o, *sym); + } + char separator{'('}; + for (const auto &ss : subscript_) { + EmitVar(o << separator, ss); + separator = ','; + } + if (separator == ',') { + o << ')'; + } + separator = '['; + for (const auto &css : cosubscript_) { + EmitVar(o << separator, css); + separator = ','; + } + if (stat_.has_value()) { + EmitVar(o << separator, stat_, "STAT="); + separator = ','; + } + if (team_.has_value()) { + EmitVar(o << separator, team_, teamIsTeamNumber_ ? "TEAM_NUMBER=" : "TEAM="); + } + return o << ']'; +} + +std::ostream &DataRef::AsFortran(std::ostream &o) const { return EmitVar(o, u); } + +std::ostream &Substring::AsFortran(std::ostream &o) const { + EmitVar(o, parent_) << '('; + EmitVar(o, lower_) << ':'; + return EmitVar(o, upper_); +} + +std::ostream &ComplexPart::AsFortran(std::ostream &o) const { + return complex_.AsFortran(o) << '%' << EnumToString(part_); +} + +std::ostream &ProcedureDesignator::AsFortran(std::ostream &o) const { + return EmitVar(o, u); +} + +template +std::ostream &Designator::AsFortran(std::ostream &o) const { + std::visit( + common::visitors{ + [&](const Symbol *sym) { EmitVar(o, *sym); }, + [&](const auto &x) { x.AsFortran(o); }, + }, + u); + return o; +} + INSTANTIATE_CONSTANT_TEMPLATES INSTANTIATE_EXPRESSION_TEMPLATES -// TODO variable templates and call templates? +INSTANTIATE_VARIABLE_TEMPLATES } diff --git a/flang/lib/evaluate/variable.cc b/flang/lib/evaluate/variable.cc index 8fa75e93d5df..7ec3b815925a 100644 --- a/flang/lib/evaluate/variable.cc +++ b/flang/lib/evaluate/variable.cc @@ -213,170 +213,6 @@ std::optional> Substring::Fold(FoldingContext &context) { return std::nullopt; } -// Variable formatting - -std::ostream &Emit(std::ostream &o, const Symbol &symbol) { - return o << symbol.name().ToString(); -} - -std::ostream &Emit(std::ostream &o, const std::string &lit) { - return o << parser::QuoteCharacterLiteral(lit); -} - -std::ostream &Emit(std::ostream &o, const std::u16string &lit) { - return o << parser::QuoteCharacterLiteral(lit); -} - -std::ostream &Emit(std::ostream &o, const std::u32string &lit) { - return o << parser::QuoteCharacterLiteral(lit); -} - -template std::ostream &Emit(std::ostream &o, const A &x) { - return x.AsFortran(o); -} - -template -std::ostream &Emit(std::ostream &o, const A *p, const char *kw = nullptr) { - if (p != nullptr) { - if (kw != nullptr) { - o << kw; - } - Emit(o, *p); - } - return o; -} - -template -std::ostream &Emit( - std::ostream &o, const std::optional &x, const char *kw = nullptr) { - if (x.has_value()) { - if (kw != nullptr) { - o << kw; - } - Emit(o, *x); - } - return o; -} - -template -std::ostream &Emit(std::ostream &o, const common::Indirection &p, - const char *kw = nullptr) { - if (kw != nullptr) { - o << kw; - } - Emit(o, p.value()); - return o; -} - -template -std::ostream &Emit(std::ostream &o, const std::shared_ptr &p) { - CHECK(p != nullptr); - return Emit(o, *p); -} - -template -std::ostream &Emit(std::ostream &o, const std::variant &u) { - std::visit([&](const auto &x) { Emit(o, x); }, u); - return o; -} - -std::ostream &BaseObject::AsFortran(std::ostream &o) const { - return Emit(o, u); -} - -template -std::ostream &TypeParamInquiry::AsFortran(std::ostream &o) const { - std::visit( - common::visitors{ - [&](const Symbol *sym) { - if (sym != nullptr) { - Emit(o, *sym) << '%'; - } - }, - [&](const Component &comp) { Emit(o, comp) << '%'; }, - }, - base_); - return Emit(o, *parameter_); -} - -std::ostream &Component::AsFortran(std::ostream &o) const { - base_.value().AsFortran(o); - return Emit(o << '%', *symbol_); -} - -std::ostream &Triplet::AsFortran(std::ostream &o) const { - Emit(o, lower_) << ':'; - Emit(o, upper_); - Emit(o << ':', stride_.value()); - return o; -} - -std::ostream &Subscript::AsFortran(std::ostream &o) const { return Emit(o, u); } - -std::ostream &ArrayRef::AsFortran(std::ostream &o) const { - Emit(o, base_); - char separator{'('}; - for (const Subscript &ss : subscript_) { - ss.AsFortran(o << separator); - separator = ','; - } - return o << ')'; -} - -std::ostream &CoarrayRef::AsFortran(std::ostream &o) const { - for (const Symbol *sym : base_) { - Emit(o, *sym); - } - char separator{'('}; - for (const auto &ss : subscript_) { - Emit(o << separator, ss); - separator = ','; - } - if (separator == ',') { - o << ')'; - } - separator = '['; - for (const auto &css : cosubscript_) { - Emit(o << separator, css); - separator = ','; - } - if (stat_.has_value()) { - Emit(o << separator, stat_, "STAT="); - separator = ','; - } - if (team_.has_value()) { - Emit(o << separator, team_, teamIsTeamNumber_ ? "TEAM_NUMBER=" : "TEAM="); - } - return o << ']'; -} - -std::ostream &DataRef::AsFortran(std::ostream &o) const { return Emit(o, u); } - -std::ostream &Substring::AsFortran(std::ostream &o) const { - Emit(o, parent_) << '('; - Emit(o, lower_) << ':'; - return Emit(o, upper_); -} - -std::ostream &ComplexPart::AsFortran(std::ostream &o) const { - return complex_.AsFortran(o) << '%' << EnumToString(part_); -} - -std::ostream &ProcedureDesignator::AsFortran(std::ostream &o) const { - return Emit(o, u); -} - -template -std::ostream &Designator::AsFortran(std::ostream &o) const { - std::visit( - common::visitors{ - [&](const Symbol *sym) { Emit(o, *sym); }, - [&](const auto &x) { x.AsFortran(o); }, - }, - u); - return o; -} - // LEN() static Expr SymbolLEN(const Symbol &sym) { return AsExpr(Constant{0}); // TODO @@ -683,7 +519,5 @@ bool ProcedureRef::operator==(const ProcedureRef &that) const { return proc_ == that.proc_ && arguments_ == that.arguments_; } -EXPAND_FOR_EACH_INTEGER_KIND( - TEMPLATE_INSTANTIATION, template class TypeParamInquiry, ) -FOR_EACH_SPECIFIC_TYPE(template class Designator, ) +INSTANTIATE_VARIABLE_TEMPLATES } diff --git a/flang/lib/evaluate/variable.h b/flang/lib/evaluate/variable.h index 8a946e8c0adf..75f4672e596b 100644 --- a/flang/lib/evaluate/variable.h +++ b/flang/lib/evaluate/variable.h @@ -374,5 +374,10 @@ template struct Variable { } std::variant, FunctionRef> u; }; + +#define INSTANTIATE_VARIABLE_TEMPLATES \ + EXPAND_FOR_EACH_INTEGER_KIND( \ + TEMPLATE_INSTANTIATION, template class TypeParamInquiry, ) \ + FOR_EACH_SPECIFIC_TYPE(template class Designator, ) } #endif // FORTRAN_EVALUATE_VARIABLE_H_ diff --git a/flang/test/evaluate/expression.cc b/flang/test/evaluate/expression.cc index fd0ef32e5ad5..de28e6725cfe 100644 --- a/flang/test/evaluate/expression.cc +++ b/flang/test/evaluate/expression.cc @@ -34,16 +34,16 @@ int main() { using DefaultIntegerExpr = Expr>; TEST(DefaultIntegerExpr::Result::AsFortran() == "Integer(4)"); MATCH("666_4", AsFortran(DefaultIntegerExpr{666})); - MATCH("(-1_4)", AsFortran(-DefaultIntegerExpr{1})); + MATCH("-1_4", AsFortran(-DefaultIntegerExpr{1})); auto ex1{ DefaultIntegerExpr{2} + DefaultIntegerExpr{3} * -DefaultIntegerExpr{4}}; - MATCH("(2_4+(3_4*(-4_4)))", AsFortran(ex1)); + MATCH("2_4+3_4*(-4_4))", AsFortran(ex1)); Fortran::parser::CharBlock src; Fortran::parser::ContextualMessages messages{src, nullptr}; FoldingContext context{messages}; ex1 = Fold(context, std::move(ex1)); MATCH("-10_4", AsFortran(ex1)); - MATCH("(1_4/2_4)", AsFortran(DefaultIntegerExpr{1} / DefaultIntegerExpr{2})); + MATCH("1_4/2_4", AsFortran(DefaultIntegerExpr{1} / DefaultIntegerExpr{2})); DefaultIntegerExpr a{1}; DefaultIntegerExpr b{2}; MATCH("1_4", AsFortran(a)); diff --git a/flang/test/semantics/modfile13.f90 b/flang/test/semantics/modfile13.f90 index 006bf3c35677..16348c686c19 100644 --- a/flang/test/semantics/modfile13.f90 +++ b/flang/test/semantics/modfile13.f90 @@ -38,9 +38,9 @@ end !contains ! subroutine s(n,a,b,c,d) ! integer(4)::n -! character((n+1_4),1)::a -! character((n+2_4),2)::b -! character((n+3_4),1)::c +! character(n+1_4,1)::a +! character(n+2_4,2)::b +! character(n+3_4,1)::c ! character(*,1)::d ! end !end diff --git a/flang/test/semantics/modfile17.f90 b/flang/test/semantics/modfile17.f90 index 3583e701f651..855d1ac096d5 100644 --- a/flang/test/semantics/modfile17.f90 +++ b/flang/test/semantics/modfile17.f90 @@ -111,9 +111,9 @@ end module !end type !type::defaulted(n1,n2,n4,n8) !integer(1),kind::n1=1_4 -!integer(2),kind::n2=(int(n1,kind=4)*2_4) -!integer(4),kind::n4=(2_4*int(n2,kind=4)) -!integer(8),kind::n8=(12_4-n4) +!integer(2),kind::n2=int(n1,kind=4)*2_4 +!integer(4),kind::n4=2_4*int(n2,kind=4) +!integer(8),kind::n8=12_4-n4 !type(capture(k1=n1,k2=n2,k4=n4,k8=n8))::cap !end type !type,extends(defaulted)::extension(k5)