[flang] cleaning up TODOs
authorpeter klausler <pklausler@nvidia.com>
Fri, 7 Sep 2018 23:54:33 +0000 (16:54 -0700)
committerpeter klausler <pklausler@nvidia.com>
Wed, 12 Sep 2018 23:29:18 +0000 (16:29 -0700)
Original-commit: flang-compiler/f18@cfd67de3cdda968e01928bdab4a9767dd30ab869
Reviewed-on: https://github.com/flang-compiler/f18/pull/183
Tree-same-pre-rewrite: false

flang/lib/evaluate/expression.cc
flang/lib/evaluate/expression.h
flang/lib/evaluate/tools.cc
flang/lib/evaluate/tools.h
flang/lib/evaluate/type.h
flang/lib/evaluate/variable.h
flang/lib/semantics/expression.cc

index 4bf30433aeff47f60ebb80732a22c84f8c51dc8c..a40027e6e2b23a9f8204a16916762acee1ec4061 100644 (file)
@@ -438,12 +438,17 @@ std::ostream &LogicalOperation<KIND>::Infix(std::ostream &o) const {
 
 template<typename T> std::ostream &Constant<T>::Dump(std::ostream &o) const {
   if constexpr (T::category == TypeCategory::Integer) {
-    return o << value.SignedDecimal() << '_' << Result::kind;
+    return o << value.SignedDecimal() << '_' << T::kind;
   } else if constexpr (T::category == TypeCategory::Real ||
       T::category == TypeCategory::Complex) {
-    return o << value.DumpHexadecimal() << '_' << Result::kind;
+    return o << value.DumpHexadecimal() << '_' << T::kind;
   } else if constexpr (T::category == TypeCategory::Character) {
-    return o << Result::kind << '_' << parser::QuoteCharacterLiteral(value);
+    if constexpr (T::kind == 1) {
+      return o << T::kind << '_' << parser::QuoteCharacterLiteral(value);
+    } else {
+      return o << T::kind
+               << "_'(wide character dumping unimplemented)'";  // TODO
+    }
   } else if constexpr (T::category == TypeCategory::Logical) {
     if (value.IsTrue()) {
       o << ".TRUE.";
@@ -555,7 +560,9 @@ template class Expr<Type<TypeCategory::Complex, 4>>;
 template class Expr<Type<TypeCategory::Complex, 8>>;
 template class Expr<Type<TypeCategory::Complex, 10>>;
 template class Expr<Type<TypeCategory::Complex, 16>>;
-template class Expr<Type<TypeCategory::Character, 1>>;  // TODO others
+template class Expr<Type<TypeCategory::Character, 1>>;
+template class Expr<Type<TypeCategory::Character, 2>>;
+template class Expr<Type<TypeCategory::Character, 4>>;
 template class Expr<Type<TypeCategory::Logical, 1>>;
 template class Expr<Type<TypeCategory::Logical, 2>>;
 template class Expr<Type<TypeCategory::Logical, 4>>;
@@ -577,7 +584,9 @@ template struct Relational<Type<TypeCategory::Real, 4>>;
 template struct Relational<Type<TypeCategory::Real, 8>>;
 template struct Relational<Type<TypeCategory::Real, 10>>;
 template struct Relational<Type<TypeCategory::Real, 16>>;
-template struct Relational<Type<TypeCategory::Character, 1>>;  // TODO others
+template struct Relational<Type<TypeCategory::Character, 1>>;
+template struct Relational<Type<TypeCategory::Character, 2>>;
+template struct Relational<Type<TypeCategory::Character, 4>>;
 template struct Relational<SomeType>;
 
 template struct ExpressionBase<Type<TypeCategory::Integer, 1>>;
index 1b80d523fb13d2b2ba2bcdf586eea50f77b6e53a..3d9050d1318eee6633895fb635484216edcb47e5 100644 (file)
@@ -551,7 +551,9 @@ public:
       u;
 };
 
-extern template class Expr<Type<TypeCategory::Character, 1>>;  // TODO more
+extern template class Expr<Type<TypeCategory::Character, 1>>;
+extern template class Expr<Type<TypeCategory::Character, 2>>;
+extern template class Expr<Type<TypeCategory::Character, 4>>;
 
 // The Relational class template is a helper for constructing logical
 // expressions with polymorphism over the cross product of the possible
@@ -581,7 +583,7 @@ struct Relational : public Operation<Relational<A>, LogicalResult, A, A> {
 };
 
 template<> class Relational<SomeType> {
-  // COMPLEX data is compared piecewise.
+  // COMPLEX data are compared piecewise.
   using DirectlyComparableTypes =
       common::CombineTuples<IntegerTypes, RealTypes, CharacterTypes>;
 
@@ -606,8 +608,9 @@ extern template struct Relational<Type<TypeCategory::Real, 4>>;
 extern template struct Relational<Type<TypeCategory::Real, 8>>;
 extern template struct Relational<Type<TypeCategory::Real, 10>>;
 extern template struct Relational<Type<TypeCategory::Real, 16>>;
-extern template struct Relational<Type<TypeCategory::Character, 1>>;  // TODO
-                                                                      // more
+extern template struct Relational<Type<TypeCategory::Character, 1>>;
+extern template struct Relational<Type<TypeCategory::Character, 2>>;
+extern template struct Relational<Type<TypeCategory::Character, 4>>;
 extern template struct Relational<SomeType>;
 
 template<int KIND>
index a89c27c028974ad02a671bd02bddf4d383696ff3..fb85185be2a85e29df100bab3b5c73cfe388d67a 100644 (file)
@@ -344,6 +344,15 @@ std::optional<Expr<SomeType>> Negation(
       std::move(x.u));
 }
 
+Expr<SomeLogical> LogicalNegation(Expr<SomeLogical> &&x) {
+  return std::visit(
+      [](auto &&xk) {
+        return AsCategoryExpr(
+            AsExpr(Not<ResultType<decltype(xk)>::kind>{std::move(xk)}));
+      },
+      std::move(x.u));
+}
+
 template<typename T>
 Expr<LogicalResult> PackageRelation(
     RelationalOperator opr, Expr<T> &&x, Expr<T> &&y) {
index 161c70ed8e4037ac22b70a257f9160fd1e9c7efd..d3bf4a925c74dc9b7da42ebdd398d098a93b9236 100644 (file)
@@ -26,19 +26,11 @@ namespace Fortran::evaluate {
 
 // Generalizing packagers: these take operations and expressions of more
 // specific types and wrap them in Expr<> containers of more abstract types.
-// TODO: Would these be better as conversion constructors in the classes?
-// TODO: Are the lvalue argument versions still needed?
 
-template<typename A> Expr<ResultType<A>> AsExpr(const A &x) { return {x}; }
 template<typename A> Expr<ResultType<A>> AsExpr(A &&x) {
   return {std::move(x)};
 }
 
-template<TypeCategory CAT, int KIND>
-Expr<SomeKind<CAT>> AsCategoryExpr(const Expr<Type<CAT, KIND>> &x) {
-  return {x};
-}
-
 template<TypeCategory CAT, int KIND>
 Expr<SomeKind<CAT>> AsCategoryExpr(Expr<Type<CAT, KIND>> &&x) {
   return {std::move(x)};
@@ -54,16 +46,10 @@ Expr<SomeKind<CAT>> AsCategoryExpr(SomeKindScalar<CAT> &&x) {
       x.u);
 }
 
-template<typename A> Expr<SomeType> AsGenericExpr(const A &x) { return {x}; }
-
 template<typename A> Expr<SomeType> AsGenericExpr(A &&x) {
   return {std::move(x)};
 }
 
-template<TypeCategory CAT, int KIND>
-Expr<SomeType> AsGenericExpr(const Expr<Type<CAT, KIND>> &x) {
-  return {AsCategoryExpr(x)};
-}
 template<TypeCategory CAT, int KIND>
 Expr<SomeType> AsGenericExpr(Expr<Type<CAT, KIND>> &&x) {
   return {AsCategoryExpr(std::move(x))};
@@ -332,6 +318,7 @@ std::optional<Expr<SomeType>> Negation(
 std::optional<Expr<LogicalResult>> Relate(parser::ContextualMessages &,
     RelationalOperator, Expr<SomeType> &&, Expr<SomeType> &&);
 
+Expr<SomeLogical> LogicalNegation(Expr<SomeLogical> &&);
 Expr<SomeLogical> BinaryLogicalOperation(
     LogicalOperator, Expr<SomeLogical> &&, Expr<SomeLogical> &&);
 
index ab7e8f327a7d3b058762abda8b6707ec3d05a12c..4e784d9605a76407baec8ee0e53b2efb3744a16b 100644 (file)
@@ -91,12 +91,24 @@ struct Type<TypeCategory::Complex, KIND>
   using Scalar = value::Complex<typename Part::Scalar>;
 };
 
-template<int KIND>
-struct Type<TypeCategory::Character, KIND>
-  : public TypeBase<TypeCategory::Character, KIND> {
+template<>
+struct Type<TypeCategory::Character, 1>
+  : public TypeBase<TypeCategory::Character, 1> {
   using Scalar = std::string;
 };
 
+template<>
+struct Type<TypeCategory::Character, 2>
+  : public TypeBase<TypeCategory::Character, 2> {
+  using Scalar = std::u16string;
+};
+
+template<>
+struct Type<TypeCategory::Character, 4>
+  : public TypeBase<TypeCategory::Character, 4> {
+  using Scalar = std::u32string;
+};
+
 template<int KIND>
 struct Type<TypeCategory::Logical, KIND>
   : public TypeBase<TypeCategory::Logical, KIND> {
index d1a695b9263c0511c31a0faa3f6cd6a5fbf45270..b5e6c164aff02055a985b6657541ba2ca76e6da9 100644 (file)
@@ -185,6 +185,7 @@ public:
   std::ostream &Dump(std::ostream &) const;
 
 private:
+  // TODO: character kinds > 1
   std::variant<DataRef, std::string> u_;
   std::optional<IndirectSubscriptIntegerExpr> first_, last_;
 };
@@ -296,8 +297,4 @@ using SubroutineRef = ProcedureRef<ActualSubroutineArg>;
 
 }  // namespace Fortran::evaluate
 
-// This inclusion must follow the definitions in this header due to
-// mutual references.
-#include "expression.h"
-
 #endif  // FORTRAN_EVALUATE_VARIABLE_H_
index 18d4810950362a147f51379d52fa2769e0cc7e7b..6240ca861174ea60f1f5bab34b8e65a517845583 100644 (file)
@@ -486,8 +486,20 @@ MaybeExpr ExprAnalyzer::Analyze(const parser::Expr::Negate &x) {
   return std::nullopt;
 }
 
-MaybeExpr ExprAnalyzer::Analyze(const parser::Expr::NOT &) {
-  context.messages.Say("pmk: NOT unimplemented\n"_err_en_US);
+MaybeExpr ExprAnalyzer::Analyze(const parser::Expr::NOT &x) {
+  if (MaybeExpr operand{AnalyzeHelper(*this, *x.v)}) {
+    return std::visit(common::visitors{[](Expr<SomeLogical> &&lx) -> MaybeExpr {
+                                         return {AsGenericExpr(
+                                             LogicalNegation(std::move(lx)))};
+                                       },
+                          [=](auto &&) -> MaybeExpr {
+                            // TODO pmk: INTEGER operand for bitwise extension?
+                            context.messages.Say(
+                                "Operand of .NOT. must be LOGICAL"_err_en_US);
+                            return std::nullopt;
+                          }},
+        std::move(operand->u));
+  }
   return std::nullopt;
 }
 
@@ -538,8 +550,35 @@ MaybeExpr ExprAnalyzer::Analyze(const parser::Expr::ComplexConstructor &x) {
       AnalyzeHelper(*this, *std::get<1>(x.t))));
 }
 
-MaybeExpr ExprAnalyzer::Analyze(const parser::Expr::Concat &) {
-  context.messages.Say("pmk: Concat unimplemented\n"_err_en_US);
+MaybeExpr ExprAnalyzer::Analyze(const parser::Expr::Concat &x) {
+  if (auto both{common::AllPresent(AnalyzeHelper(*this, *std::get<0>(x.t)),
+          AnalyzeHelper(*this, *std::get<1>(x.t)))}) {
+    return std::visit(
+        common::visitors{
+            [&](Expr<SomeCharacter> &&cx, Expr<SomeCharacter> &&cy) {
+              return std::visit(
+                  [&](auto &&cxk, auto &&cyk) -> MaybeExpr {
+                    using Ty = ResultType<decltype(cxk)>;
+                    if constexpr (std::is_same_v<Ty,
+                                      ResultType<decltype(cyk)>>) {
+                      return {AsGenericExpr(AsCategoryExpr(AsExpr(
+                          Concat<Ty::kind>{std::move(cxk), std::move(cyk)})))};
+                    } else {
+                      context.messages.Say(
+                          "Operands of // must be the same kind of CHARACTER"_err_en_US);
+                      return std::nullopt;
+                    }
+                  },
+                  std::move(cx.u), std::move(cy.u));
+            },
+            [&](auto &&, auto &&) -> MaybeExpr {
+              context.messages.Say(
+                  "Operands of // must be CHARACTER"_err_en_US);
+              return std::nullopt;
+            },
+        },
+        std::move(std::get<0>(*both).u), std::move(std::get<1>(*both).u));
+  }
   return std::nullopt;
 }