[flang] clean up naming in expressions and types
authorpeter klausler <pklausler@nvidia.com>
Tue, 14 Aug 2018 00:05:15 +0000 (17:05 -0700)
committerpeter klausler <pklausler@nvidia.com>
Wed, 12 Sep 2018 23:28:46 +0000 (16:28 -0700)
Original-commit: flang-compiler/f18@ab17ef4d4bc7e5ab8fae2dbe43edd47f25f9ba5a
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/type.cc
flang/lib/evaluate/type.h
flang/lib/parser/basic-parsers.h
flang/lib/semantics/expression.cc
flang/test/evaluate/logical.cc
flang/test/evaluate/real.cc

index 717e401..338f564 100644 (file)
@@ -236,7 +236,7 @@ auto Binary<CRTP, RESULT, A, B>::Fold(FoldingContext &context)
 
 template<int KIND>
 auto IntegerExpr<KIND>::ConvertInteger::FoldScalar(FoldingContext &context,
-    const ScalarConstant<TypeCategory::Integer> &c) -> std::optional<Scalar> {
+    const SomeKindScalar<TypeCategory::Integer> &c) -> std::optional<Scalar> {
   return std::visit(
       [&](auto &x) -> std::optional<Scalar> {
         auto converted{Scalar::ConvertSigned(x)};
@@ -251,7 +251,7 @@ auto IntegerExpr<KIND>::ConvertInteger::FoldScalar(FoldingContext &context,
 
 template<int KIND>
 auto IntegerExpr<KIND>::ConvertReal::FoldScalar(FoldingContext &context,
-    const ScalarConstant<TypeCategory::Real> &c) -> std::optional<Scalar> {
+    const SomeKindScalar<TypeCategory::Real> &c) -> std::optional<Scalar> {
   return std::visit(
       [&](auto &x) -> std::optional<Scalar> {
         auto converted{x.template ToInteger<Scalar>()};
@@ -369,7 +369,7 @@ template<int KIND>
 auto IntegerExpr<KIND>::Fold(FoldingContext &context) -> std::optional<Scalar> {
   return std::visit(
       [&](auto &x) -> std::optional<Scalar> {
-        using Ty = typename std::decay<decltype(x)>::type;
+        using Ty = std::decay_t<decltype(x)>;
         if constexpr (std::is_same_v<Ty, Scalar>) {
           return {x};
         }
@@ -387,7 +387,7 @@ auto IntegerExpr<KIND>::Fold(FoldingContext &context) -> std::optional<Scalar> {
 
 template<int KIND>
 auto RealExpr<KIND>::ConvertInteger::FoldScalar(FoldingContext &context,
-    const ScalarConstant<TypeCategory::Integer> &c) -> std::optional<Scalar> {
+    const SomeKindScalar<TypeCategory::Integer> &c) -> std::optional<Scalar> {
   return std::visit(
       [&](auto &x) -> std::optional<Scalar> {
         auto converted{Scalar::FromInteger(x)};
@@ -399,7 +399,7 @@ auto RealExpr<KIND>::ConvertInteger::FoldScalar(FoldingContext &context,
 
 template<int KIND>
 auto RealExpr<KIND>::ConvertReal::FoldScalar(FoldingContext &context,
-    const ScalarConstant<TypeCategory::Real> &c) -> std::optional<Scalar> {
+    const SomeKindScalar<TypeCategory::Real> &c) -> std::optional<Scalar> {
   return std::visit(
       [&](auto &x) -> std::optional<Scalar> {
         auto converted{Scalar::Convert(x)};
@@ -455,7 +455,7 @@ auto RealExpr<KIND>::Power::FoldScalar(FoldingContext &context, const Scalar &a,
 
 template<int KIND>
 auto RealExpr<KIND>::IntPower::FoldScalar(FoldingContext &context,
-    const Scalar &a, const ScalarConstant<TypeCategory::Integer> &b)
+    const Scalar &a, const SomeKindScalar<TypeCategory::Integer> &b)
     -> std::optional<Scalar> {
   return std::visit(
       [&](const auto &pow) -> std::optional<Scalar> {
@@ -486,13 +486,13 @@ auto RealExpr<KIND>::Min::FoldScalar(FoldingContext &context, const Scalar &a,
 
 template<int KIND>
 auto RealExpr<KIND>::RealPart::FoldScalar(FoldingContext &context,
-    const SameKindComplexScalar &z) -> std::optional<Scalar> {
+    const evaluate::Scalar<Complex> &z) -> std::optional<Scalar> {
   return {z.REAL()};
 }
 
 template<int KIND>
 auto RealExpr<KIND>::AIMAG::FoldScalar(FoldingContext &context,
-    const SameKindComplexScalar &z) -> std::optional<Scalar> {
+    const evaluate::Scalar<Complex> &z) -> std::optional<Scalar> {
   return {z.AIMAG()};
 }
 
@@ -500,7 +500,7 @@ template<int KIND>
 auto RealExpr<KIND>::Fold(FoldingContext &context) -> std::optional<Scalar> {
   return std::visit(
       [&](auto &x) -> std::optional<Scalar> {
-        using Ty = typename std::decay<decltype(x)>::type;
+        using Ty = std::decay_t<decltype(x)>;
         if constexpr (std::is_same_v<Ty, Scalar>) {
           return {x};
         }
@@ -565,7 +565,7 @@ auto ComplexExpr<KIND>::Power::FoldScalar(FoldingContext &context,
 
 template<int KIND>
 auto ComplexExpr<KIND>::IntPower::FoldScalar(FoldingContext &context,
-    const Scalar &a, const ScalarConstant<TypeCategory::Integer> &b)
+    const Scalar &a, const SomeKindScalar<TypeCategory::Integer> &b)
     -> std::optional<Scalar> {
   return std::visit(
       [&](const auto &pow) -> std::optional<Scalar> {
@@ -578,7 +578,7 @@ auto ComplexExpr<KIND>::IntPower::FoldScalar(FoldingContext &context,
 
 template<int KIND>
 auto ComplexExpr<KIND>::CMPLX::FoldScalar(FoldingContext &context,
-    const SameKindRealScalar &a, const SameKindRealScalar &b)
+    const evaluate::Scalar<Part> &a, const evaluate::Scalar<Part> &b)
     -> std::optional<Scalar> {
   return {Scalar{a, b}};
 }
@@ -587,7 +587,7 @@ template<int KIND>
 auto ComplexExpr<KIND>::Fold(FoldingContext &context) -> std::optional<Scalar> {
   return std::visit(
       [&](auto &x) -> std::optional<Scalar> {
-        using Ty = typename std::decay<decltype(x)>::type;
+        using Ty = std::decay_t<decltype(x)>;
         if constexpr (std::is_same_v<Ty, Scalar>) {
           return {x};
         }
@@ -638,7 +638,7 @@ auto CharacterExpr<KIND>::Fold(FoldingContext &context)
     -> std::optional<Scalar> {
   return std::visit(
       [&](auto &x) -> std::optional<Scalar> {
-        using Ty = typename std::decay<decltype(x)>::type;
+        using Ty = std::decay_t<decltype(x)>;
         if constexpr (std::is_same_v<Ty, Scalar>) {
           return {x};
         }
@@ -740,7 +740,7 @@ template<int KIND>
 auto LogicalExpr<KIND>::Fold(FoldingContext &context) -> std::optional<Scalar> {
   return std::visit(
       [&](auto &x) -> std::optional<Scalar> {
-        using Ty = typename std::decay<decltype(x)>::type;
+        using Ty = std::decay_t<decltype(x)>;
         if constexpr (std::is_same_v<Ty, Scalar>) {
           return {x};
         }
index 0b0f3cc..c8ab9a9 100644 (file)
@@ -38,11 +38,11 @@ template<typename CRTP, typename RESULT, typename A = RESULT> class Unary {
 protected:
   using OperandType = A;
   using Operand = Expr<OperandType>;
-  using OperandScalarConstant = typename OperandType::Value;
+  using OperandScalarConstant = Scalar<OperandType>;
 
 public:
   using Result = RESULT;
-  using Scalar = typename Result::Value;
+  using Scalar = Scalar<Result>;
   using FoldableTrait = std::true_type;
   CLASS_BOILERPLATE(Unary)
   Unary(const Operand &a) : operand_{a} {}
@@ -62,14 +62,14 @@ class Binary {
 protected:
   using LeftType = A;
   using Left = Expr<LeftType>;
-  using LeftScalar = typename LeftType::Value;
+  using LeftScalar = Scalar<LeftType>;
   using RightType = B;
   using Right = Expr<RightType>;
-  using RightScalar = typename RightType::Value;
+  using RightScalar = Scalar<RightType>;
 
 public:
   using Result = RESULT;
-  using Scalar = typename Result::Value;
+  using Scalar = Scalar<Result>;
   using FoldableTrait = std::true_type;
   CLASS_BOILERPLATE(Binary)
   Binary(const Left &a, const Right &b) : left_{a}, right_{b} {}
@@ -96,21 +96,21 @@ private:
 template<int KIND> class Expr<Type<TypeCategory::Integer, KIND>> {
 public:
   using Result = Type<TypeCategory::Integer, KIND>;
-  using Scalar = typename Result::Value;
+  using Scalar = Scalar<Result>;
   using FoldableTrait = std::true_type;
 
   struct ConvertInteger
     : public Unary<ConvertInteger, Result, SomeKind<TypeCategory::Integer>> {
     using Unary<ConvertInteger, Result, SomeKind<TypeCategory::Integer>>::Unary;
     static std::optional<Scalar> FoldScalar(
-        FoldingContext &, const ScalarConstant<TypeCategory::Integer> &);
+        FoldingContext &, const SomeKindScalar<TypeCategory::Integer> &);
   };
 
   struct ConvertReal
     : public Unary<ConvertReal, Result, SomeKind<TypeCategory::Real>> {
     using Unary<ConvertReal, Result, SomeKind<TypeCategory::Real>>::Unary;
     static std::optional<Scalar> FoldScalar(
-        FoldingContext &, const ScalarConstant<TypeCategory::Real> &);
+        FoldingContext &, const SomeKindScalar<TypeCategory::Real> &);
   };
 
   template<typename CRTP> using Un = Unary<CRTP, Result>;
@@ -203,8 +203,9 @@ private:
 template<int KIND> class Expr<Type<TypeCategory::Real, KIND>> {
 public:
   using Result = Type<TypeCategory::Real, KIND>;
-  using Scalar = typename Result::Value;
+  using Scalar = Scalar<Result>;
   using FoldableTrait = std::true_type;
+  using Complex = typename Result::Complex;
 
   // N.B. Real->Complex and Complex->Real conversions are done with CMPLX
   // and part access operations (resp.).  Conversions between kinds of
@@ -213,13 +214,13 @@ public:
     : public Unary<ConvertInteger, Result, SomeKind<TypeCategory::Integer>> {
     using Unary<ConvertInteger, Result, SomeKind<TypeCategory::Integer>>::Unary;
     static std::optional<Scalar> FoldScalar(
-        FoldingContext &, const ScalarConstant<TypeCategory::Integer> &);
+        FoldingContext &, const SomeKindScalar<TypeCategory::Integer> &);
   };
   struct ConvertReal
     : public Unary<ConvertReal, Result, SomeKind<TypeCategory::Real>> {
     using Unary<ConvertReal, Result, SomeKind<TypeCategory::Real>>::Unary;
     static std::optional<Scalar> FoldScalar(
-        FoldingContext &, const ScalarConstant<TypeCategory::Real> &);
+        FoldingContext &, const SomeKindScalar<TypeCategory::Real> &);
   };
   template<typename CRTP> using Un = Unary<CRTP, Result>;
   template<typename CRTP> using Bin = Binary<CRTP, Result>;
@@ -263,7 +264,7 @@ public:
     using Binary<IntPower, Result, Result,
         SomeKind<TypeCategory::Integer>>::Binary;
     static std::optional<Scalar> FoldScalar(FoldingContext &, const Scalar &,
-        const ScalarConstant<TypeCategory::Integer> &);
+        const SomeKindScalar<TypeCategory::Integer> &);
   };
   struct Max : public Bin<Max> {
     using Bin<Max>::Bin;
@@ -275,19 +276,16 @@ public:
     static std::optional<Scalar> FoldScalar(
         FoldingContext &, const Scalar &, const Scalar &);
   };
-  using SameKindComplex = Type<TypeCategory::Complex, KIND>;
-  using SameKindComplexScalar = typename SameKindComplex::Value;
-  template<typename CRTP>
-  using SameKindComplexUn = Unary<CRTP, Result, SameKindComplex>;
-  struct RealPart : public SameKindComplexUn<RealPart> {
-    using SameKindComplexUn<RealPart>::SameKindComplexUn;
+  template<typename CRTP> using ComplexUn = Unary<CRTP, Result, Complex>;
+  struct RealPart : public ComplexUn<RealPart> {
+    using ComplexUn<RealPart>::ComplexUn;
     static std::optional<Scalar> FoldScalar(
-        FoldingContext &, const SameKindComplexScalar &);
+        FoldingContext &, const evaluate::Scalar<Complex> &);
   };
-  struct AIMAG : public SameKindComplexUn<AIMAG> {
-    using SameKindComplexUn<AIMAG>::SameKindComplexUn;
+  struct AIMAG : public ComplexUn<AIMAG> {
+    using ComplexUn<AIMAG>::ComplexUn;
     static std::optional<Scalar> FoldScalar(
-        FoldingContext &, const SameKindComplexScalar &);
+        FoldingContext &, const evaluate::Scalar<Complex> &);
   };
 
   CLASS_BOILERPLATE(Expr)
@@ -326,8 +324,10 @@ private:
 template<int KIND> class Expr<Type<TypeCategory::Complex, KIND>> {
 public:
   using Result = Type<TypeCategory::Complex, KIND>;
-  using Scalar = typename Result::Value;
+  using Scalar = Scalar<Result>;
+  using Part = typename Result::Part;
   using FoldableTrait = std::true_type;
+
   template<typename CRTP> using Un = Unary<CRTP, Result>;
   template<typename CRTP> using Bin = Binary<CRTP, Result>;
   struct Parentheses : public Un<Parentheses> {
@@ -370,14 +370,12 @@ public:
     using Binary<IntPower, Result, Result,
         SomeKind<TypeCategory::Integer>>::Binary;
     static std::optional<Scalar> FoldScalar(FoldingContext &, const Scalar &,
-        const ScalarConstant<TypeCategory::Integer> &);
+        const SomeKindScalar<TypeCategory::Integer> &);
   };
-  using SameKindReal = Type<TypeCategory::Real, KIND>;
-  using SameKindRealScalar = typename SameKindReal::Value;
-  struct CMPLX : public Binary<CMPLX, Result, SameKindReal> {
-    using Binary<CMPLX, Result, SameKindReal>::Binary;
+  struct CMPLX : public Binary<CMPLX, Result, Part> {
+    using Binary<CMPLX, Result, Part>::Binary;
     static std::optional<Scalar> FoldScalar(FoldingContext &,
-        const SameKindRealScalar &, const SameKindRealScalar &);
+        const evaluate::Scalar<Part> &, const evaluate::Scalar<Part> &);
   };
 
   CLASS_BOILERPLATE(Expr)
@@ -402,7 +400,7 @@ private:
 template<int KIND> class Expr<Type<TypeCategory::Character, KIND>> {
 public:
   using Result = Type<TypeCategory::Character, KIND>;
-  using Scalar = typename Result::Value;
+  using Scalar = Scalar<Result>;
   using FoldableTrait = std::true_type;
   template<typename CRTP> using Bin = Binary<CRTP, Result>;
   struct Concat : public Bin<Concat> {
@@ -483,7 +481,7 @@ extern template struct Comparison<Type<TypeCategory::Character, 1>>;
 // Dynamically polymorphic comparisons whose operands are expressions of
 // the same supported kind of a particular type category.
 template<TypeCategory CAT> struct CategoryComparison {
-  using Scalar = typename Type<TypeCategory::Logical, 1>::Value;
+  using Scalar = Scalar<Type<TypeCategory::Logical, 1>>;
   CLASS_BOILERPLATE(CategoryComparison)
   template<int KIND> using KindComparison = Comparison<Type<CAT, KIND>>;
   template<int KIND> CategoryComparison(const KindComparison<KIND> &x) : u{x} {}
@@ -496,7 +494,7 @@ template<TypeCategory CAT> struct CategoryComparison {
 template<int KIND> class Expr<Type<TypeCategory::Logical, KIND>> {
 public:
   using Result = Type<TypeCategory::Logical, KIND>;
-  using Scalar = typename Result::Value;
+  using Scalar = Scalar<Result>;
   using FoldableTrait = std::true_type;
   struct Not : Unary<Not, Result> {
     using Unary<Not, Result>::Unary;
@@ -578,7 +576,7 @@ extern template class Expr<Type<TypeCategory::Logical, 8>>;
 template<TypeCategory CAT> class Expr<SomeKind<CAT>> {
 public:
   using Result = SomeKind<CAT>;
-  using Scalar = typename Result::Value;
+  using Scalar = Scalar<Result>;
   using FoldableTrait = std::true_type;
   CLASS_BOILERPLATE(Expr)
   template<int KIND> using KindExpr = Expr<Type<CAT, KIND>>;
index 44a12dd..2da628f 100644 (file)
@@ -35,8 +35,8 @@ SomeKindRealExpr ConvertToTypeOf(
 static void ConvertToSameRealKind(SomeKindRealExpr &x, SomeKindRealExpr &y) {
   std::visit(
       [&](auto &xk, auto &yk) {
-        using xt = typename std::decay<decltype(xk)>::type;
-        using yt = typename std::decay<decltype(yk)>::type;
+        using xt = std::decay_t<decltype(xk)>;
+        using yt = std::decay_t<decltype(yk)>;
         constexpr int kindDiff{xt::Result::kind - yt::Result::kind};
         if constexpr (kindDiff < 0) {
           x.u = yt{xk};
index aae0fec..c61048c 100644 (file)
@@ -22,7 +22,7 @@
 namespace Fortran::evaluate {
 
 std::optional<std::int64_t> GenericScalar::ToInt64() const {
-  if (const auto *j{std::get_if<ScalarConstant<TypeCategory::Integer>>(&u)}) {
+  if (const auto *j{std::get_if<SomeKindScalar<TypeCategory::Integer>>(&u)}) {
     return std::visit(
         [](const auto &k) { return std::optional<std::int64_t>{k.ToInt64()}; },
         j->u);
@@ -31,7 +31,7 @@ std::optional<std::int64_t> GenericScalar::ToInt64() const {
 }
 
 std::optional<std::string> GenericScalar::ToString() const {
-  if (const auto *c{std::get_if<ScalarConstant<TypeCategory::Character>>(&u)}) {
+  if (const auto *c{std::get_if<SomeKindScalar<TypeCategory::Character>>(&u)}) {
     if (const std::string * s{std::get_if<std::string>(&c->u)}) {
       return std::optional<std::string>{*s};
     }
@@ -39,25 +39,33 @@ std::optional<std::string> GenericScalar::ToString() const {
   return std::nullopt;
 }
 
-// There's some opaque type-fu going on below.  Given a GenericScalar, we
-// figure out its intrinsic type category, and then (for each category),
-// we figure out its kind from the type of the constant.  Then, given
-// the category, kind, and constant, we construct a GenericExpr around
-// the constant.
+// TODO pmk: maybe transplant these templates to type.h/expression.h?
+
+// There's some admittedly opaque type-fu going on below.
+// Given a GenericScalar value, we want to be able to (re-)wrap it as
+// a GenericExpr.  So we extract its value, then build up an expression
+// around it.  The subtle magic is in the first template, whose result
+// is a specific expression whose Fortran type category and kind are inferred
+// from the type of the scalar constant.
+template<typename A> Expr<ScalarValueType<A>> ScalarConstantToExpr(const A &x) {
+  return {x};
+}
+
+template<typename A>
+Expr<SomeKind<A::category>> ToSomeKindExpr(const Expr<A> &x) {
+  return {x};
+}
+
+template<TypeCategory CAT>
+Expr<SomeKind<CAT>> SomeKindScalarToExpr(const SomeKindScalar<CAT> &x) {
+  return std::visit(
+      [](const auto &c) { return ToSomeKindExpr(ScalarConstantToExpr(c)); },
+      x.u);
+}
+
 GenericExpr GenericScalar::ToGenericExpr() const {
   return std::visit(
-      [](const auto &c) -> GenericExpr {
-        using cType = typename std::decay<decltype(c)>::type;
-        constexpr TypeCategory cat{cType::category};
-        return {std::visit(
-            [&](const auto &value) -> Expr<SomeKind<cat>> {
-              using valueType = typename std::decay<decltype(value)>::type;
-              using Ty = typename TypeOfScalarValue<valueType>::type;
-              return {Expr<Ty>{value}};
-            },
-            c.u)};
-      },
-      u);
+      [&](const auto &c) { return GenericExpr{SomeKindScalarToExpr(c)}; }, u);
 }
 
 }  // namespace Fortran::evaluate
index 4220425..049d20a 100644 (file)
@@ -39,6 +39,7 @@ struct GenericExpr;
 
 template<TypeCategory C, int KIND> struct TypeBase {
   static constexpr TypeCategory category{C};
+  static constexpr TypeCategory GetCategory() { return C; };
   static constexpr int kind{KIND};
   static constexpr bool hasLen{false};
   static std::string Dump() {
@@ -46,43 +47,44 @@ template<TypeCategory C, int KIND> struct TypeBase {
   }
 };
 
+template<typename T> using Scalar = typename T::Scalar;
+
 template<TypeCategory C, int KIND> struct Type;
 
 template<int KIND>
 struct Type<TypeCategory::Integer, KIND>
   : public TypeBase<TypeCategory::Integer, KIND> {
-  using Value = value::Integer<8 * KIND>;
+  using Scalar = value::Integer<8 * KIND>;
 };
 
 template<>
 struct Type<TypeCategory::Real, 2> : public TypeBase<TypeCategory::Real, 2> {
-  using Value = value::Real<typename Type<TypeCategory::Integer, 2>::Value, 11>;
+  using Scalar = value::Real<Scalar<Type<TypeCategory::Integer, 2>>, 11>;
   using Complex = Type<TypeCategory::Complex, 2>;
 };
 
 template<>
 struct Type<TypeCategory::Real, 4> : public TypeBase<TypeCategory::Real, 4> {
-  using Value = value::Real<typename Type<TypeCategory::Integer, 4>::Value, 24>;
-  using Complex = Type<TypeCategory::Complex, 2>;
+  using Scalar = value::Real<Scalar<Type<TypeCategory::Integer, 4>>, 24>;
+  using Complex = Type<TypeCategory::Complex, 4>;
 };
 
 template<>
 struct Type<TypeCategory::Real, 8> : public TypeBase<TypeCategory::Real, 8> {
-  using Value = value::Real<typename Type<TypeCategory::Integer, 8>::Value, 53>;
-  using Complex = Type<TypeCategory::Complex, 2>;
+  using Scalar = value::Real<Scalar<Type<TypeCategory::Integer, 8>>, 53>;
+  using Complex = Type<TypeCategory::Complex, 8>;
 };
 
 template<>
 struct Type<TypeCategory::Real, 10> : public TypeBase<TypeCategory::Real, 10> {
-  using Value = value::Real<value::Integer<80>, 64, false>;
-  using Complex = Type<TypeCategory::Complex, 2>;
+  using Scalar = value::Real<value::Integer<80>, 64, false>;
+  using Complex = Type<TypeCategory::Complex, 10>;
 };
 
 template<>
 struct Type<TypeCategory::Real, 16> : public TypeBase<TypeCategory::Real, 16> {
-  using Value =
-      value::Real<typename Type<TypeCategory::Integer, 16>::Value, 112>;
-  using Complex = Type<TypeCategory::Complex, 2>;
+  using Scalar = value::Real<value::Integer<128>, 112>;
+  using Complex = Type<TypeCategory::Complex, 16>;
 };
 
 // The KIND type parameter on COMPLEX is the kind of each of its components.
@@ -90,14 +92,14 @@ template<int KIND>
 struct Type<TypeCategory::Complex, KIND>
   : public TypeBase<TypeCategory::Complex, KIND> {
   using Part = Type<TypeCategory::Real, KIND>;
-  using Value = value::Complex<typename Part::Value>;
+  using Scalar = value::Complex<Scalar<Part>>;
 };
 
 template<int KIND> struct Type<TypeCategory::Character, KIND> {
   static constexpr TypeCategory category{TypeCategory::Character};
   static constexpr int kind{KIND};
   static constexpr bool hasLen{true};
-  using Value = std::string;
+  using Scalar = std::string;
   static std::string Dump() {
     return EnumToString(category) + '(' + std::to_string(kind) + ')';
   }
@@ -106,7 +108,7 @@ template<int KIND> struct Type<TypeCategory::Character, KIND> {
 template<int KIND>
 struct Type<TypeCategory::Logical, KIND>
   : public TypeBase<TypeCategory::Logical, KIND> {
-  using Value = value::Logical<8 * KIND>;
+  using Scalar = value::Logical<8 * KIND>;
 };
 
 // Convenience type aliases:
@@ -139,8 +141,7 @@ using SubscriptInteger = Type<TypeCategory::Integer, 8>;
 
 #define FOR_EACH_CATEGORY(M) \
   M(Integer, INTEGER) \
-  M(Real, REAL) M(Complex, COMPLEX) M(Character, CHARACTER) \
-      M(Logical, LOGICAL)
+  M(Real, REAL) M(Complex, COMPLEX) M(Character, CHARACTER) M(Logical, LOGICAL)
 
 // These macros and template create instances of std::variant<> that can contain
 // applications of some class template to all of the supported kinds of
@@ -155,13 +156,13 @@ FOR_EACH_CATEGORY(MAKE)
 #undef MAKE
 #undef TKIND
 
-// Map scalar constant value types back to their Fortran types.
-// For every type T = Type<CAT, KIND>, TypeOfScalarValue<T::Value>::type == T.
+// Map scalar value types back to their Fortran types.
+// For every type T = Type<CAT, KIND>, TypeOfScalarValue<T>> == T.
 // E.g., TypeOfScalarValue<Integer<32>> is Type<TypeCategory::Integer, 4>.
-template<typename CONST> struct TypeOfScalarValue;
+template<typename CONST> struct GetTypeOfScalarValue;
 #define TOSV(cat, kind) \
   template<> \
-  struct TypeOfScalarValue<typename Type<TypeCategory::cat, kind>::Value> { \
+  struct GetTypeOfScalarValue<Scalar<Type<TypeCategory::cat, kind>>> { \
     using type = Type<TypeCategory::cat, kind>; \
   };
 #define M(k) TOSV(Integer, k)
@@ -181,16 +182,19 @@ FOR_EACH_LOGICAL_KIND(M, )
 #undef M
 #undef TOSV
 
-// Holds a scalar constant of any kind within a particular intrinsic type
+template<typename CONST>
+using ScalarValueType = typename GetTypeOfScalarValue<CONST>::type;
+
+// Holds a scalar value of any kind within a particular intrinsic type
 // category.
-template<TypeCategory CAT> struct ScalarConstant {
+template<TypeCategory CAT> struct SomeKindScalar {
   static constexpr TypeCategory category{CAT};
-  CLASS_BOILERPLATE(ScalarConstant)
+  CLASS_BOILERPLATE(SomeKindScalar)
 
-  template<int KIND> using KindScalar = typename Type<CAT, KIND>::Value;
-  template<typename A> ScalarConstant(const A &x) : u{x} {}
+  template<int KIND> using KindScalar = Scalar<Type<CAT, KIND>>;
+  template<typename A> SomeKindScalar(const A &x) : u{x} {}
   template<typename A>
-  ScalarConstant(std::enable_if_t<!std::is_reference_v<A>, A> &&x)
+  SomeKindScalar(std::enable_if_t<!std::is_reference_v<A>, A> &&x)
     : u{std::move(x)} {}
 
   typename KindsVariant<CAT, KindScalar>::type u;
@@ -201,11 +205,10 @@ struct GenericScalar {
   CLASS_BOILERPLATE(GenericScalar)
 
   template<TypeCategory CAT, int KIND>
-  GenericScalar(const typename Type<CAT, KIND>::Value &x)
-    : u{ScalarConstant<CAT>{x}} {}
+  GenericScalar(const Scalar<Type<CAT, KIND>> &x) : u{SomeKindScalar<CAT>{x}} {}
   template<TypeCategory CAT, int KIND>
-  GenericScalar(typename Type<CAT, KIND>::Value &&x)
-    : u{ScalarConstant<CAT>{std::move(x)}} {}
+  GenericScalar(Scalar<Type<CAT, KIND>> &&x)
+    : u{SomeKindScalar<CAT>{std::move(x)}} {}
 
   template<typename A> GenericScalar(const A &x) : u{x} {}
   template<typename A>
@@ -216,17 +219,17 @@ struct GenericScalar {
   std::optional<std::string> ToString() const;
   GenericExpr ToGenericExpr() const;
 
-  std::variant<ScalarConstant<TypeCategory::Integer>,
-      ScalarConstant<TypeCategory::Real>, ScalarConstant<TypeCategory::Complex>,
-      ScalarConstant<TypeCategory::Character>,
-      ScalarConstant<TypeCategory::Logical>>
+  std::variant<SomeKindScalar<TypeCategory::Integer>,
+      SomeKindScalar<TypeCategory::Real>, SomeKindScalar<TypeCategory::Complex>,
+      SomeKindScalar<TypeCategory::Character>,
+      SomeKindScalar<TypeCategory::Logical>>
       u;
 };
 
 // Represents a type of any supported kind within a particular category.
 template<TypeCategory CAT> struct SomeKind {
   static constexpr TypeCategory category{CAT};
-  using Value = ScalarConstant<CAT>;
+  using Scalar = SomeKindScalar<CAT>;
 };
 }  // namespace Fortran::evaluate
 #endif  // FORTRAN_EVALUATE_TYPE_H_
index 6c25d1b..47790df 100644 (file)
@@ -311,7 +311,7 @@ private:
       state = backtrack;
       const auto &parser{std::get<J>(ps_)};
       static_assert(std::is_same_v<resultType,
-          typename std::decay<decltype(parser)>::type::resultType>);
+          typename std::decay_t<decltype(parser)>::resultType>);
       result = parser.Parse(state);
       if (!result.has_value()) {
         state.CombineFailedParses(std::move(prevState));
index f3ee629..5105f7d 100644 (file)
@@ -269,7 +269,7 @@ static std::optional<evaluate::SomeKindRealExpr> AnalyzeLiteral(
       if (sign == parser::Sign::Negative) {
         std::visit(
             [](auto &rk) {
-              using t = typename std::decay<decltype(rk)>::type;
+              using t = std::decay_t<decltype(rk)>;
               rk = typename t::Negate{rk};
             },
             result->u);
@@ -600,8 +600,8 @@ ExpressionAnalyzer::ConstructComplex(MaybeExpr &&real, MaybeExpr &&imaginary) {
   if (auto joined{common::JoinOptionals(std::move(converted))}) {
     return {std::visit(
         [](auto &&rx, auto &&ix) -> evaluate::SomeKindComplexExpr {
-          using realExpr = typename std::decay<decltype(rx)>::type;
-          using zExpr = evaluate::Expr<typename realExpr::SameKindComplex>;
+          using realExpr = std::decay_t<decltype(rx)>;
+          using zExpr = evaluate::Expr<typename realExpr::Complex>;
           return {zExpr{typename zExpr::CMPLX{std::move(rx), std::move(ix)}}};
         },
         std::move(joined->first.u), std::move(joined->second.u))};
index 7c81dc9..5b92b79 100644 (file)
@@ -22,7 +22,7 @@ template<int KIND> void testKind() {
   TEST(Type::category == Fortran::common::TypeCategory::Logical);
   TEST(Type::kind == KIND);
   TEST(!Type::hasLen);
-  using Value = typename Type::Value;
+  using Value = Fortran::evaluate::Scalar<Type>;
   MATCH(8 * KIND, Value::bits);
   TEST(!Value{}.IsTrue());
   TEST(!Value{false}.IsTrue());
index 7e8f86e..e14c3c2 100644 (file)
 using namespace Fortran::evaluate;
 using namespace Fortran::common;
 
-using Real2 = typename Type<TypeCategory::Real, 2>::Value;
-using Real4 = typename Type<TypeCategory::Real, 4>::Value;
-using Real8 = typename Type<TypeCategory::Real, 8>::Value;
-using Real10 = typename Type<TypeCategory::Real, 10>::Value;
-using Real16 = typename Type<TypeCategory::Real, 16>::Value;
-using Integer4 = typename Type<TypeCategory::Integer, 4>::Value;
-using Integer8 = typename Type<TypeCategory::Integer, 8>::Value;
+using Real2 = Scalar<Type<TypeCategory::Real, 2>>;
+using Real4 = Scalar<Type<TypeCategory::Real, 4>>;
+using Real8 = Scalar<Type<TypeCategory::Real, 8>>;
+using Real10 = Scalar<Type<TypeCategory::Real, 10>>;
+using Real16 = Scalar<Type<TypeCategory::Real, 16>>;
+using Integer4 = Scalar<Type<TypeCategory::Integer, 4>>;
+using Integer8 = Scalar<Type<TypeCategory::Integer, 8>>;
 
 void dumpTest() {
   struct {