[flang] work in progress

Original-commit: flang-compiler/f18@33ea8e506a
Reviewed-on: https://github.com/flang-compiler/f18/pull/371
Tree-same-pre-rewrite: false
This commit is contained in:
peter klausler 2019-04-01 10:54:22 -07:00
parent 95b4e65ecf
commit b35f4a98e2
6 changed files with 207 additions and 188 deletions

View File

@ -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<typename A> constexpr Precedence ToPrecedence{Precedence::Primary};
template<typename T> constexpr Precedence ToPrecedence<Constant<T>>{Precedence::Constant};
template<typename T>
constexpr Precedence ToPrecedence<Parentheses<T>>{Precedence::Parenthesize};
template<int KIND>
@ -218,6 +220,14 @@ std::ostream &Operation<D, R, O...>::AsFortran(std::ostream &o) const {
static constexpr Precedence thisPrec{ToPrecedence<D>};
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<Constant<Operand<0>>>(left())};
CHECK(p != nullptr);
lhsParens |= p->size() == 1 && (*p)->IsNegative();
}
}
if (lhsParens) {
o << '(';
}
@ -226,7 +236,15 @@ std::ostream &Operation<D, R, O...>::AsFortran(std::ostream &o) const {
o << ')';
}
static constexpr Precedence rhsPrec{ToPrecedence<Operand<1>>};
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<Constant<Operand<1>>>(right())};
CHECK(p != nullptr);
rhsParens |= p->size() == 1 && (*p)->IsNegative();
}
}
if (rhsParens) {
o << '(';
}
@ -284,18 +302,18 @@ template<int KIND> const char *LogicalOperation<KIND>::Infix() const {
}
template<typename T>
std::ostream &Emit(
std::ostream &EmitArray(
std::ostream &o, const common::CopyableIndirection<Expr<T>> &expr) {
return expr.value().AsFortran(o);
}
template<typename T>
std::ostream &Emit(std::ostream &, const ArrayConstructorValues<T> &);
std::ostream &EmitArray(std::ostream &, const ArrayConstructorValues<T> &);
template<typename T>
std::ostream &Emit(std::ostream &o, const ImpliedDo<T> &implDo) {
std::ostream &EmitArray(std::ostream &o, const ImpliedDo<T> &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<T> &implDo) {
}
template<typename T>
std::ostream &Emit(std::ostream &o, const ArrayConstructorValues<T> &values) {
std::ostream &EmitArray(std::ostream &o, const ArrayConstructorValues<T> &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<T> &values) {
template<typename T>
std::ostream &ArrayConstructor<T>::AsFortran(std::ostream &o) const {
o << '[' << GetType().AsFortran() << "::";
Emit(o, *this);
EmitArray(o, *this);
return o << ']';
}
@ -328,13 +346,13 @@ std::ostream &ArrayConstructor<Type<TypeCategory::Character, KIND>>::AsFortran(
std::stringstream len;
LEN().AsFortran(len);
o << '[' << GetType().AsFortran(len.str()) << "::";
Emit(o, *this);
EmitArray(o, *this);
return o << ']';
}
std::ostream &ArrayConstructor<SomeDerived>::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<typename A> std::ostream &EmitVar(std::ostream &o, const A &x) {
return x.AsFortran(o);
}
template<typename A>
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<typename A>
std::ostream &EmitVar(
std::ostream &o, const std::optional<A> &x, const char *kw = nullptr) {
if (x.has_value()) {
if (kw != nullptr) {
o << kw;
}
EmitVar(o, *x);
}
return o;
}
template<typename A, bool COPY>
std::ostream &EmitVar(std::ostream &o, const common::Indirection<A, COPY> &p,
const char *kw = nullptr) {
if (kw != nullptr) {
o << kw;
}
EmitVar(o, p.value());
return o;
}
template<typename A>
std::ostream &EmitVar(std::ostream &o, const std::shared_ptr<A> &p) {
CHECK(p != nullptr);
return EmitVar(o, *p);
}
template<typename... A>
std::ostream &EmitVar(std::ostream &o, const std::variant<A...> &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<int KIND>
std::ostream &TypeParamInquiry<KIND>::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<typename T>
std::ostream &Designator<T>::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
}

View File

@ -213,170 +213,6 @@ std::optional<Expr<SomeCharacter>> 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<typename A> std::ostream &Emit(std::ostream &o, const A &x) {
return x.AsFortran(o);
}
template<typename A>
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<typename A>
std::ostream &Emit(
std::ostream &o, const std::optional<A> &x, const char *kw = nullptr) {
if (x.has_value()) {
if (kw != nullptr) {
o << kw;
}
Emit(o, *x);
}
return o;
}
template<typename A, bool COPY>
std::ostream &Emit(std::ostream &o, const common::Indirection<A, COPY> &p,
const char *kw = nullptr) {
if (kw != nullptr) {
o << kw;
}
Emit(o, p.value());
return o;
}
template<typename A>
std::ostream &Emit(std::ostream &o, const std::shared_ptr<A> &p) {
CHECK(p != nullptr);
return Emit(o, *p);
}
template<typename... A>
std::ostream &Emit(std::ostream &o, const std::variant<A...> &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<int KIND>
std::ostream &TypeParamInquiry<KIND>::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<typename T>
std::ostream &Designator<T>::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<SubscriptInteger> SymbolLEN(const Symbol &sym) {
return AsExpr(Constant<SubscriptInteger>{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
}

View File

@ -374,5 +374,10 @@ template<typename T> struct Variable {
}
std::variant<Designator<Result>, FunctionRef<Result>> 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_

View File

@ -34,16 +34,16 @@ int main() {
using DefaultIntegerExpr = Expr<Type<TypeCategory::Integer, 4>>;
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));

View File

@ -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

View File

@ -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)