[flang] Expression formatting
authorpeter klausler <pklausler@nvidia.com>
Wed, 20 Jun 2018 23:50:27 +0000 (16:50 -0700)
committerpeter klausler <pklausler@nvidia.com>
Fri, 22 Jun 2018 21:58:04 +0000 (14:58 -0700)
Original-commit: flang-compiler/f18@3d0977a57e32460ac0cf808a7e4b5bcbdb3d30ba
Reviewed-on: https://github.com/flang-compiler/f18/pull/111
Tree-same-pre-rewrite: false

flang/lib/evaluate/CMakeLists.txt
flang/lib/evaluate/complex.cc
flang/lib/evaluate/complex.h
flang/lib/evaluate/expression.cc
flang/lib/evaluate/expression.h
flang/lib/evaluate/type.cc [new file with mode: 0644]
flang/lib/evaluate/type.h
flang/test/evaluate/expression.cc

index cf43366..af481fb 100644 (file)
@@ -18,6 +18,7 @@ add_library(FortranEvaluate
   integer.cc
   logical.cc
   real.cc
+  type.cc
 )
 
 target_link_libraries(FortranEvaluate
index b67f7dc..4d50634 100644 (file)
@@ -81,4 +81,13 @@ ValueWithRealFlags<Complex<R>> Complex<R>::Divide(const Complex &that) const {
   Part im{im1.Divide(den).AccumulateFlags(flags)};
   return {Complex{re, im}, flags};
 }
+
+template<typename R> std::string Complex<R>::DumpHexadecimal() const {
+  std::string result{'('};
+  result += re_.DumpHexadecimal();
+  result += ',';
+  result += im_.DumpHexadecimal();
+  result += ')';
+  return result;
+}
 }  // namespace Fortran::evaluate::value
index 064554e..9248d62 100644 (file)
@@ -16,6 +16,7 @@
 #define FORTRAN_EVALUATE_COMPLEX_H_
 
 #include "real.h"
+#include <string>
 
 namespace Fortran::evaluate::value {
 
@@ -44,6 +45,7 @@ public:
   ValueWithRealFlags<Complex> Multiply(const Complex &) const;
   ValueWithRealFlags<Complex> Divide(const Complex &) const;
 
+  std::string DumpHexadecimal() const;
   // TODO: (C)ABS once Real::HYPOT is done
   // TODO: unit testing
 
index 63cbc39..3cb94d7 100644 (file)
 #include "../common/idioms.h"
 #include <ostream>
 #include <string>
+#include <type_traits>
 
 namespace Fortran::evaluate {
 
-template<Category C, int KIND>
-void NumericBase<C, KIND>::dump(std::ostream &o) const {}
+template<int KIND> std::ostream &IntExpr<KIND>::Dump(std::ostream &o) const {
+  std::visit(
+      common::visitors{[&](const Constant &n) { o << n.SignedDecimal(); },
+          [&](const Convert &c) {
+            o << "convert(";
+            std::visit(
+                [&](const auto &x) {  // x is IntegerOperand or RealOperand
+                  std::visit(
+                      [&](const auto &y) {  // y is ExprOperand<Type<C,K>>
+                        using Expr =
+                            typename std::remove_reference<decltype(*y)>::type;
+                        using Ty = typename Expr::Result;
+                        y->Dump(o << Ty::Dump() << ' ');
+                      },
+                      x.u);
+                },
+                c.u);
+            o << ')';
+          },
+          [&](const Parentheses &p) { p.x->Dump(o << '(') << ')'; },
+          [&](const Negate &n) { n.x->Dump(o << "(-") << ')'; },
+          [&](const Add &a) { a.y->Dump(a.x->Dump(o << '(') << '+') << ')'; },
+          [&](const Subtract &s) {
+            s.y->Dump(s.x->Dump(o << '(') << '-') << ')';
+          },
+          [&](const Multiply &m) {
+            m.y->Dump(m.x->Dump(o << '(') << '*') << ')';
+          },
+          [&](const Divide &d) {
+            d.y->Dump(d.x->Dump(o << '(') << '/') << ')';
+          },
+          [&](const Power &p) {
+            p.y->Dump(p.x->Dump(o << '(') << "**") << ')';
+          }},
+      u);
+  return o;
+}
+
+template<int KIND> std::ostream &RealExpr<KIND>::Dump(std::ostream &o) const {
+  std::visit(
+      common::visitors{[&](const Constant &n) { o << n.DumpHexadecimal(); },
+          [&](const auto &) { o << "TODO"; }},
+      u);
+  return o;
+}
 
 template<int KIND> typename CharExpr<KIND>::Length CharExpr<KIND>::LEN() const {
   return std::visit(
index 310e112..da28204 100644 (file)
@@ -34,7 +34,7 @@ namespace Fortran::evaluate {
 //   struct Add { Operand x, y; };
 // a data member to hold an instance of one of these structs:
 //   std::variant<> u;
-// and a formatting member function, dump().
+// and a formatting member function, Dump().
 template<typename T> struct Expression;
 
 template<typename T> struct ExprOperand {
@@ -97,8 +97,6 @@ template<Category C, int KIND> struct NumericBase {
   struct Power {
     Operand x, y;
   };
-
-  void dump(std::ostream &) const;
 };
 
 template<int KIND>
@@ -117,8 +115,11 @@ struct Expression<Type<Category::Integer, KIND>>
   using Power = typename Base::Power;
   Expression() = delete;
   Expression(Expression &&) = default;
-  Expression(const typename Base::Constant &x) : u{x} {}
+  Expression(const Constant &x) : u{x} {}
+  Expression(std::int64_t n) : u{Constant{n}} {}
+  Expression(int n) : u{Constant{n}} {}
   template<typename A> Expression(A &&x) : u{std::move(x)} {}
+  std::ostream &Dump(std::ostream &) const;
   std::variant<Constant, Convert, Parentheses, Negate, Add, Subtract, Multiply,
       Divide, Power>
       u;
@@ -160,6 +161,7 @@ struct Expression<Type<Category::Real, KIND>>
   Expression(Expression &&) = default;
   Expression(const Constant &x) : u{x} {}
   template<typename A> Expression(A &&x) : u{std::move(x)} {}
+  std::ostream &Dump(std::ostream &) const;
   std::variant<Constant, Convert, Parentheses, Negate, Add, Subtract, Multiply,
       Divide, Power, IntegerPower, RealPart, AIMAG>
       u;
@@ -186,6 +188,7 @@ struct Expression<Type<Category::Complex, KIND>>
   Expression(Expression &&) = default;
   Expression(const Constant &x) : u{x} {}
   template<typename A> Expression(A &&x) : u{std::move(x)} {}
+  std::ostream &Dump(std::ostream &) const;
   std::variant<Constant, Parentheses, Negate, Add, Subtract, Multiply, Divide,
       Power, IntegerPower, CMPLX>
       u;
@@ -310,6 +313,8 @@ template<> struct Expression<Type<Category::Logical, 1>> {
     return {typename Comparison<T>::GT{std::move(x), std::move(y)}};
   }
 
+  std::ostream &Dump(std::ostream &) const;
+
   std::variant<Constant, Not, And, Or, Eqv, Neqv, IntegerComparison,
       RealComparison, ComplexComparison, CharacterComparison>
       u;
@@ -330,6 +335,7 @@ template<int KIND> struct Expression<Type<Category::Character, KIND>> {
   Expression(Expression &&a, Expression &&b)
     : u{Concat{std::move(a), std::move(b)}} {}
   Length LEN() const;
+  std::ostream &Dump(std::ostream &) const;
   std::variant<Constant, Concat> u;
 };
 
@@ -377,7 +383,10 @@ struct ArbitraryExpression {
       u;
 };
 
-// Convenience operator overloadings for expression construction.
+// Convenience functions and operator overloadings for expression construction.
+template<typename A> Expression<A> Parentheses(Expression<A> &&x) {
+  return {typename Expression<A>::Parentheses{std::move(x)}};
+}
 template<typename A> Expression<A> operator-(Expression<A> &&x) {
   return {typename Expression<A>::Negate{std::move(x)}};
 }
@@ -397,6 +406,11 @@ template<typename A>
 Expression<A> operator/(Expression<A> &&x, Expression<A> &&y) {
   return {typename Expression<A>::Divide{std::move(x), std::move(y)}};
 }
+template<typename A> Expression<A> Power(Expression<A> &&x, Expression<A> &&y) {
+  return {typename Expression<A>::Power{std::move(x), std::move(y)}};
+}
+
+// TODO: comparison generators
 
 extern template struct Expression<Type<Category::Integer, 1>>;
 extern template struct Expression<Type<Category::Integer, 2>>;
diff --git a/flang/lib/evaluate/type.cc b/flang/lib/evaluate/type.cc
new file mode 100644 (file)
index 0000000..3f010ef
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright (c) 2018, NVIDIA CORPORATION.  All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "type.h"
+#include <string>
+
+namespace Fortran::evaluate {
+
+std::string CategoryName(Category c) {
+  switch (c) {
+  case Category::Integer: return "Integer";
+  case Category::Real: return "Real";
+  case Category::Complex: return "Complex";
+  case Category::Logical: return "Logical";
+  case Category::Character: return "Character";
+  case Category::Derived: return "Derived";
+  }
+  return "";  // placate g++
+}
+}  // namespace Fortran::evaluate
index 97748e3..bf9edc7 100644 (file)
 
 namespace Fortran::evaluate {
 
-enum class Category { Integer, Real, Complex, Character, Logical, Derived };
+enum class Category { Integer, Real, Complex, Logical, Character, Derived };
+
+std::string CategoryName(Category);
 
 template<Category C, int KIND> struct TypeBase {
   static constexpr Category category{C};
   static constexpr int kind{KIND};
   static constexpr bool hasLen{false};
+  static std::string Dump() {
+    return CategoryName(category) + '(' + std::to_string(kind) + ')';
+  }
 };
 
 template<Category C, int KIND> struct Type;
index a161fc0..8fefd1b 100644 (file)
 #include "testing.h"
 #include <cstdio>
 #include <cstdlib>
+#include <sstream>
+#include <iostream>  // TODO pmk rm
 
 using namespace Fortran::evaluate;
 
 int main() {
   using Int4 = Type<Category::Integer, 4>;
+  TEST(Int4::Dump() == "Integer(4)");
   using IntEx4 = Expression<Int4>;
-  IntEx4 ie{value::Integer<32>(666)};
-  IntEx4 one{value::Integer<32>(1)};
-  IntEx4 incr{IntEx4::Add{std::move(ie), std::move(one)}};
+  IntEx4 ie{666};
+  std::stringstream ss;
+  ie.Dump(ss);
+  TEST(ss.str() == "666");
+  IntEx4 one{IntEx4::Constant{1}};
+  IntEx4 incr{std::move(ie) + IntEx4{1}};
+incr.Dump(std::cout) << '\n';
   using Log = Expression<Type<Category::Logical, 1>>;
-  IntEx4 two{value::Integer<32>(2)};
-  Log cmp{Log::EQ(std::move(incr), std::move(two))};
+  Log cmp{Log::EQ(std::move(incr), IntEx4{2})};
   return testing::Complete();
 }