[flang] Add AsFortran() for types
authorTim Keith <tkeith@nvidia.com>
Sat, 22 Jun 2019 17:16:13 +0000 (10:16 -0700)
committerTim Keith <tkeith@nvidia.com>
Sun, 23 Jun 2019 01:14:14 +0000 (18:14 -0700)
Add an `AsFortran()` member function to `DeclTypeSpec` and related
classes to convert types to a Fortran representation. This allows
error messages to mention types. It also fixes `.mod` file writing
where it previous used `operator<<` to convert types to Fortran.

Original-commit: flang-compiler/f18@eb16f8b5dd1b8c3631690afce03c3b26b26d0f6f
Reviewed-on: https://github.com/flang-compiler/f18/pull/521
Tree-same-pre-rewrite: false

flang/lib/semantics/mod-file.cc
flang/lib/semantics/type.cc
flang/lib/semantics/type.h

index a50d2ce..21b7c08 100644 (file)
@@ -573,9 +573,7 @@ std::ostream &PutLower(std::ostream &os, const Symbol &symbol) {
 }
 
 std::ostream &PutLower(std::ostream &os, const DeclTypeSpec &type) {
-  std::stringstream s;
-  s << type;
-  return PutLower(os, s.str());
+  return PutLower(os, type.AsFortran());
 }
 
 std::ostream &PutLower(std::ostream &os, const std::string &str) {
index b11836d..1dd5de6 100644 (file)
@@ -174,22 +174,27 @@ Scope &DerivedTypeSpec::Instantiate(
   return newScope;
 }
 
-std::ostream &operator<<(std::ostream &o, const DerivedTypeSpec &x) {
-  o << x.typeSymbol().name().ToString();
-  if (!x.parameters_.empty()) {
-    o << '(';
+std::string DerivedTypeSpec::AsFortran() const {
+  std::stringstream ss;
+  ss << typeSymbol_.name().ToString();
+  if (!parameters_.empty()) {
+    ss << '(';
     bool first = true;
-    for (const auto &[name, value] : x.parameters_) {
+    for (const auto &[name, value] : parameters_) {
       if (first) {
         first = false;
       } else {
-        o << ',';
+        ss << ',';
       }
-      o << name.ToString() << '=' << value;
+      ss << name.ToString() << '=' << value.AsFortran();
     }
-    o << ')';
+    ss << ')';
   }
-  return o;
+  return ss.str();
+}
+
+std::ostream &operator<<(std::ostream &o, const DerivedTypeSpec &x) {
+  return o << x.AsFortran();
 }
 
 Bound::Bound(int bound) : expr_{bound} {}
@@ -255,17 +260,24 @@ void ParamValue::SetExplicit(SomeIntExpr &&x) {
   expr_ = std::move(x);
 }
 
-std::ostream &operator<<(std::ostream &o, const ParamValue &x) {
-  if (x.isAssumed()) {
-    o << '*';
-  } else if (x.isDeferred()) {
-    o << ':';
-  } else if (!x.GetExplicit()) {
-    o << "<no-expr>";
-  } else {
-    o << x.GetExplicit();
+std::string ParamValue::AsFortran() const {
+  switch (category_) {
+  case Category::Assumed: return "*";
+  case Category::Deferred: return ":";
+  case Category::Explicit:
+    if (expr_) {
+      std::stringstream ss;
+      expr_->AsFortran(ss);
+      return ss.str();
+    } else {
+      return "";
+    }
+  default: CRASH_NO_CASE;
   }
-  return o;
+}
+
+std::ostream &operator<<(std::ostream &o, const ParamValue &x) {
+  return o << x.AsFortran();
 }
 
 IntrinsicTypeSpec::IntrinsicTypeSpec(TypeCategory category, KindExpr &&kind)
@@ -273,22 +285,31 @@ IntrinsicTypeSpec::IntrinsicTypeSpec(TypeCategory category, KindExpr &&kind)
   CHECK(category != TypeCategory::Derived);
 }
 
-std::ostream &operator<<(std::ostream &os, const IntrinsicTypeSpec &x) {
-  os << parser::ToUpperCaseLetters(common::EnumToString(x.category()));
-  if (auto k{evaluate::ToInt64(x.kind())}) {
-    return os << '(' << *k << ')';  // emit unsuffixed kind code
+static std::string KindAsFortran(const KindExpr &kind) {
+  std::stringstream ss;
+  if (auto k{evaluate::ToInt64(kind)}) {
+    ss << *k;  // emit unsuffixed kind code
   } else {
-    return os << '(' << x.kind() << ')';
+    kind.AsFortran(ss);
   }
+  return ss.str();
+}
+
+std::string IntrinsicTypeSpec::AsFortran() const {
+  return parser::ToUpperCaseLetters(common::EnumToString(category_)) + '(' +
+      KindAsFortran(kind_) + ')';
+}
+
+std::ostream &operator<<(std::ostream &os, const IntrinsicTypeSpec &x) {
+  return os << x.AsFortran();
+}
+
+std::string CharacterTypeSpec::AsFortran() const {
+  return "CHARACTER(" + length_.AsFortran() + ',' + KindAsFortran(kind()) + ')';
 }
 
 std::ostream &operator<<(std::ostream &os, const CharacterTypeSpec &x) {
-  os << "CHARACTER(" << x.length() << ',';
-  if (auto k{evaluate::ToInt64(x.kind())}) {
-    return os << *k << ')';  // emit unsuffixed kind code
-  } else {
-    return os << x.kind() << ')';
-  }
+  return os << x.AsFortran();
 }
 
 DeclTypeSpec::DeclTypeSpec(NumericTypeSpec &&typeSpec)
@@ -329,21 +350,23 @@ bool DeclTypeSpec::operator==(const DeclTypeSpec &that) const {
   return category_ == that.category_ && typeSpec_ == that.typeSpec_;
 }
 
-std::ostream &operator<<(std::ostream &o, const DeclTypeSpec &x) {
-  switch (x.category()) {
-  case DeclTypeSpec::Numeric: return o << x.numericTypeSpec();
-  case DeclTypeSpec::Logical: return o << x.logicalTypeSpec();
-  case DeclTypeSpec::Character: return o << x.characterTypeSpec();
-  case DeclTypeSpec::TypeDerived:
-    return o << "TYPE(" << x.derivedTypeSpec() << ')';
-  case DeclTypeSpec::ClassDerived:
-    return o << "CLASS(" << x.derivedTypeSpec() << ')';
-  case DeclTypeSpec::TypeStar: return o << "TYPE(*)";
-  case DeclTypeSpec::ClassStar: return o << "CLASS(*)";
-  default: CRASH_NO_CASE; return o;
+std::string DeclTypeSpec::AsFortran() const {
+  switch (category_) {
+  case Numeric: return numericTypeSpec().AsFortran();
+  case Logical: return logicalTypeSpec().AsFortran();
+  case Character: return characterTypeSpec().AsFortran();
+  case TypeDerived: return "TYPE(" + derivedTypeSpec().AsFortran() + ')';
+  case ClassDerived: return "CLASS(" + derivedTypeSpec().AsFortran() + ')';
+  case TypeStar: return "TYPE(*)";
+  case ClassStar: return "CLASS(*)";
+  default: CRASH_NO_CASE;
   }
 }
 
+std::ostream &operator<<(std::ostream &o, const DeclTypeSpec &x) {
+  return o << x.AsFortran();
+}
+
 void ProcInterface::set_symbol(const Symbol &symbol) {
   CHECK(!type_);
   symbol_ = &symbol;
index 82dca1b..698f43c 100644 (file)
@@ -104,6 +104,7 @@ public:
   bool operator==(const ParamValue &that) const {
     return category_ == that.category_ && expr_ == that.expr_;
   }
+  std::string AsFortran() const;
 
 private:
   enum class Category { Explicit, Deferred, Assumed };
@@ -121,6 +122,7 @@ public:
     return category_ == x.category_ && kind_ == x.kind_;
   }
   bool operator!=(const IntrinsicTypeSpec &x) const { return !operator==(x); }
+  std::string AsFortran() const;
 
 protected:
   IntrinsicTypeSpec(TypeCategory, KindExpr &&);
@@ -151,6 +153,7 @@ public:
     : IntrinsicTypeSpec(TypeCategory::Character, std::move(kind)),
       length_{std::move(length)} {}
   const ParamValue &length() const { return length_; }
+  std::string AsFortran() const;
 
 private:
   ParamValue length_;
@@ -244,6 +247,7 @@ public:
   bool operator==(const DerivedTypeSpec &that) const {
     return &typeSymbol_ == &that.typeSymbol_ && parameters_ == that.parameters_;
   }
+  std::string AsFortran() const;
 
 private:
   const Symbol &typeSymbol_;
@@ -315,6 +319,8 @@ public:
     }
   }
 
+  std::string AsFortran() const;
+
 private:
   Category category_;
   std::variant<std::monostate, NumericTypeSpec, LogicalTypeSpec,