bool isElemental) const {
const auto &len{that.LEN()};
if (!type_.IsTypeCompatibleWith(that.type_)) {
- std::stringstream lenstr;
- if (len) {
- len->AsFortran(lenstr);
- }
messages.Say(
"%1$s type '%2$s' is not compatible with %3$s type '%4$s'"_err_en_US,
- thatIs, that.type_.AsFortran(lenstr.str()), thisIs, type_.AsFortran());
+ thatIs, that.type_.AsFortran(len ? len->AsFortran() : ""), thisIs,
+ type_.AsFortran());
return false;
}
return isElemental ||
}
std::ostream &TypeAndShape::Dump(std::ostream &o) const {
- std::stringstream LENstr;
- if (LEN_) {
- LEN_->AsFortran(LENstr);
- }
- o << type_.AsFortran(LENstr.str());
+ o << type_.AsFortran(LEN_ ? LEN_->AsFortran() : "");
attrs_.Dump(o, EnumToString);
if (!shape_.empty()) {
o << " dimension(";
std::optional<DynamicType> GetType() const;
int Rank() const;
+ std::string AsFortran() const;
std::ostream &AsFortran(std::ostream &) const;
static Derived Rewrite(FoldingContext &, Derived &&);
};
#include <complex>
#include <cstdio>
#include <optional>
-#include <sstream>
#include <type_traits>
#include <variant>
}
mutableObject->set_init(std::nullopt);
} else {
- std::stringstream ss;
- unwrapped->AsFortran(ss);
context_.messages().Say(symbol.name(),
"Initialization expression for PARAMETER '%s' (%s) cannot be computed as a constant value"_err_en_US,
- symbol.name(), ss.str());
+ symbol.name(), unwrapped->AsFortran());
}
} else {
- std::stringstream ss;
- init->AsFortran(ss);
context_.messages().Say(symbol.name(),
"Initialization expression for PARAMETER '%s' (%s) cannot be converted to its type (%s)"_err_en_US,
- symbol.name(), ss.str(), dyType->AsFortran());
+ symbol.name(), init->AsFortran(), dyType->AsFortran());
}
}
}
#include "tools.h"
#include "../parser/characters.h"
#include "../semantics/symbol.h"
+#include <sstream>
namespace Fortran::evaluate {
Precedence thisPrec{ToPrecedence(derived())};
if constexpr (operands == 1) {
if (thisPrec != Precedence::Top && lhsPrec < thisPrec) {
- o << '(' << left() << ')';
+ left().AsFortran(o << '(') << ')';
} else {
- o << left();
+ left().AsFortran(o);
}
} else {
if (thisPrec != Precedence::Top &&
(lhsPrec < thisPrec ||
(lhsPrec == Precedence::Power && thisPrec == Precedence::Power))) {
- o << '(' << left() << ')';
+ left().AsFortran(o << '(') << ')';
} else {
- o << left();
+ left().AsFortran(o);
}
o << spelling.infix;
Precedence rhsPrec{ToPrecedence(right())};
if (thisPrec != Precedence::Top && rhsPrec < thisPrec) {
- o << '(' << right() << ')';
+ right().AsFortran(o << '(') << ')';
} else {
- o << right();
+ right().AsFortran(o);
}
}
return o << spelling.suffix;
template<int KIND>
std::ostream &ArrayConstructor<Type<TypeCategory::Character, KIND>>::AsFortran(
std::ostream &o) const {
- std::stringstream len;
- LEN().AsFortran(len);
- o << '[' << GetType().AsFortran(len.str()) << "::";
+ o << '[' << GetType().AsFortran(LEN().AsFortran()) << "::";
EmitArray(o, *this);
return o << ']';
}
}
template<typename RESULT>
+std::string ExpressionBase<RESULT>::AsFortran() const {
+ std::ostringstream ss;
+ AsFortran(ss);
+ return ss.str();
+}
+
+template<typename RESULT>
std::ostream &ExpressionBase<RESULT>::AsFortran(std::ostream &o) const {
std::visit(
common::visitors{
} else if (charLength_->isDeferred()) {
result += ':';
} else if (const auto &length{charLength_->GetExplicit()}) {
- std::stringstream ss;
- length->AsFortran(ss);
- result += ss.str();
+ result += length->AsFortran();
}
return result + ')';
} else if (IsUnlimitedPolymorphic()) {
"dummy argument", "actual argument");
}
} else {
- std::stringstream lenStr;
- if (const auto &len{actualType.LEN()}) {
- len->AsFortran(lenStr);
- }
+ const auto &len{actualType.LEN()};
messages.Say(
"Actual argument type '%s' is not compatible with dummy argument type '%s'"_err_en_US,
- actualType.type().AsFortran(lenStr.str()),
+ actualType.type().AsFortran(len ? len->AsFortran() : ""),
dummy.type.type().AsFortran());
}
#include "semantics.h"
#include "tools.h"
#include "../common/idioms.h"
+#include "../evaluate/expression.h"
#include <ostream>
#include <string>
os << ' ' << label << ':' << *x;
}
}
+template<typename T>
+static void DumpExpr(std::ostream &os, const char *label,
+ const std::optional<evaluate::Expr<T>> &x) {
+ if (x) {
+ x->AsFortran(os << ' ' << label << ':');
+ }
+}
static void DumpBool(std::ostream &os, const char *label, bool x) {
if (x) {
std::ostream &operator<<(std::ostream &os, const SubprogramDetails &x) {
DumpBool(os, "isInterface", x.isInterface_);
- DumpOptional(os, "bindName", x.bindName_);
+ DumpExpr(os, "bindName", x.bindName_);
if (x.result_) {
os << " result:" << x.result_->name();
if (!x.result_->attrs().empty()) {
if (x.type()) {
os << " type: " << *x.type();
}
- DumpOptional(os, "bindName", x.bindName_);
+ DumpExpr(os, "bindName", x.bindName_);
return os;
}
os << *static_cast<const EntityDetails *>(&x);
DumpList(os, "shape", x.shape());
DumpList(os, "coshape", x.coshape());
- DumpOptional(os, "init", x.init_);
+ DumpExpr(os, "init", x.init_);
return os;
}
std::ostream &operator<<(std::ostream &os, const AssocEntityDetails &x) {
os << *static_cast<const EntityDetails *>(&x);
- DumpOptional(os, "expr", x.expr());
+ DumpExpr(os, "expr", x.expr());
return os;
}
} else {
DumpType(os, x.interface_.type());
}
- DumpOptional(os, "bindName", x.bindName());
+ DumpExpr(os, "bindName", x.bindName());
DumpOptional(os, "passName", x.passName());
if (x.init()) {
if (const Symbol * target{*x.init()}) {
os << dummy->name();
}
os << ')';
- DumpOptional(os, "bindName", x.bindName());
+ DumpExpr(os, "bindName", x.bindName());
if (x.isFunction()) {
os << " result(";
DumpType(os, x.result());
[&](const TypeParamDetails &x) {
DumpOptional(os, "type", x.type());
os << ' ' << common::EnumToString(x.attr());
- DumpOptional(os, "init", x.init());
+ DumpExpr(os, "init", x.init());
},
[&](const MiscDetails &x) {
os << ' ' << MiscDetails::EnumToString(x.kind());
continue;
}
}
- std::stringstream fortran;
- expr->AsFortran(fortran);
evaluate::SayWithDeclaration(messages, symbol,
"Value of type parameter '%s' (%s) is not convertible to its type"_err_en_US,
- name, fortran.str());
+ name, expr->AsFortran());
}
}
}
if (expr->Rank() == 0 &&
maybeDynamicType->category() == TypeCategory::Integer) {
if (!evaluate::ToInt64(*expr)) {
- std::stringstream fortran;
- fortran << *expr;
if (auto *msg{foldingContext.messages().Say(
"Value of kind type parameter '%s' (%s) is not "
"a scalar INTEGER constant"_err_en_US,
- name, fortran.str())}) {
+ name, expr->AsFortran())}) {
msg->Attach(name, "declared here"_en_US);
}
}
} else if (x.isDeferred()) {
o << ':';
} else if (x.expr_) {
- o << x.expr_;
+ x.expr_->AsFortran(o);
} else {
o << "<no-expr>";
}
#include "../../lib/parser/message.h"
#include <cstdio>
#include <cstdlib>
-#include <sstream>
#include <string>
using namespace Fortran::evaluate;
-template<typename A> std::string AsFortran(const A &x) {
- std::stringstream ss;
- ss << x;
- return ss.str();
-}
-
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("666_4", DefaultIntegerExpr{666}.AsFortran());
+ MATCH("-1_4", (-DefaultIntegerExpr{1}).AsFortran());
auto ex1{
DefaultIntegerExpr{2} + DefaultIntegerExpr{3} * -DefaultIntegerExpr{4}};
- MATCH("2_4+3_4*(-4_4)", AsFortran(ex1));
+ MATCH("2_4+3_4*(-4_4)", ex1.AsFortran());
Fortran::common::IntrinsicTypeDefaultKinds defaults;
auto intrinsics{Fortran::evaluate::IntrinsicProcTable::Configure(defaults)};
FoldingContext context{
Fortran::parser::ContextualMessages{nullptr}, defaults, intrinsics};
ex1 = Fold(context, std::move(ex1));
- MATCH("-10_4", AsFortran(ex1));
- MATCH("1_4/2_4", AsFortran(DefaultIntegerExpr{1} / DefaultIntegerExpr{2}));
+ MATCH("-10_4", ex1.AsFortran());
+ MATCH("1_4/2_4", (DefaultIntegerExpr{1} / DefaultIntegerExpr{2}).AsFortran());
DefaultIntegerExpr a{1};
DefaultIntegerExpr b{2};
- MATCH("1_4", AsFortran(a));
+ MATCH("1_4", a.AsFortran());
a = b;
- MATCH("2_4", AsFortran(a));
- MATCH("2_4", AsFortran(b));
+ MATCH("2_4", a.AsFortran());
+ MATCH("2_4", b.AsFortran());
return testing::Complete();
}