[flang] Extirpate expression-forward.h
authorpeter klausler <pklausler@nvidia.com>
Tue, 14 Aug 2018 21:35:51 +0000 (14:35 -0700)
committerpeter klausler <pklausler@nvidia.com>
Wed, 12 Sep 2018 23:28:47 +0000 (16:28 -0700)
Original-commit: flang-compiler/f18@288acd399304de69c154b7b7bfe3b9d0ccd32a7d
Reviewed-on: https://github.com/flang-compiler/f18/pull/183
Tree-same-pre-rewrite: false

flang/lib/evaluate/expression-forward.h [deleted file]
flang/lib/evaluate/expression.cc
flang/lib/evaluate/expression.h
flang/lib/evaluate/type.h
flang/lib/evaluate/variable.h
flang/lib/semantics/expression.cc
flang/test/evaluate/expression.cc

diff --git a/flang/lib/evaluate/expression-forward.h b/flang/lib/evaluate/expression-forward.h
deleted file mode 100644 (file)
index 69c6dc7..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-// 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.
-
-#ifndef FORTRAN_EVALUATE_EXPRESSION_FORWARD_H_
-#define FORTRAN_EVALUATE_EXPRESSION_FORWARD_H_
-
-// Some forward definitions for expression.h that need to be available
-// in variable.h to resolve cases of mutual references between class
-// definitions.
-
-#include "type.h"
-
-namespace Fortran::evaluate {
-
-// An expression of some specific result type.
-template<typename A> class Expr;
-
-// TODO: pmk: obsolete?
-template<int KIND> using IntegerExpr = Expr<Type<TypeCategory::Integer, KIND>>;
-using DefaultIntegerExpr = Expr<DefaultInteger>;
-template<int KIND> using RealExpr = Expr<Type<TypeCategory::Real, KIND>>;
-template<int KIND> using ComplexExpr = Expr<Type<TypeCategory::Complex, KIND>>;
-template<int KIND>
-using CharacterExpr = Expr<Type<TypeCategory::Character, KIND>>;
-template<int KIND> using LogicalExpr = Expr<Type<TypeCategory::Logical, KIND>>;
-
-// An expression whose result is within one particular type category and
-// of any supported kind.
-using SomeKindIntegerExpr = Expr<SomeKind<TypeCategory::Integer>>;
-using SomeKindRealExpr = Expr<SomeKind<TypeCategory::Real>>;
-using SomeKindComplexExpr = Expr<SomeKind<TypeCategory::Complex>>;
-using SomeKindCharacterExpr = Expr<SomeKind<TypeCategory::Character>>;
-using SomeKindLogicalExpr = Expr<SomeKind<TypeCategory::Logical>>;
-
-}  // namespace Fortran::evaluate
-#endif  // FORTRAN_EVALUATE_EXPRESSION_FORWARD_H_
index 0536083..10a5a6b 100644 (file)
@@ -76,7 +76,8 @@ std::ostream &Binary<CRTP, RESULT, A, B>::Dump(
 }
 
 template<int KIND>
-std::ostream &IntegerExpr<KIND>::Dump(std::ostream &o) const {
+std::ostream &Expr<Type<TypeCategory::Integer, KIND>>::Dump(
+    std::ostream &o) const {
   std::visit(
       common::visitors{[&](const Scalar<Result> &n) { o << n.SignedDecimal(); },
           [&](const CopyableIndirection<DataRef> &d) { d->Dump(o); },
@@ -97,7 +98,9 @@ std::ostream &IntegerExpr<KIND>::Dump(std::ostream &o) const {
   return o;
 }
 
-template<int KIND> std::ostream &RealExpr<KIND>::Dump(std::ostream &o) const {
+template<int KIND>
+std::ostream &Expr<Type<TypeCategory::Real, KIND>>::Dump(
+    std::ostream &o) const {
   std::visit(common::visitors{[&](const Scalar<Result> &n) {
                                 o << n.DumpHexadecimal();
                               },
@@ -124,7 +127,8 @@ template<int KIND> std::ostream &RealExpr<KIND>::Dump(std::ostream &o) const {
 }
 
 template<int KIND>
-std::ostream &ComplexExpr<KIND>::Dump(std::ostream &o) const {
+std::ostream &Expr<Type<TypeCategory::Complex, KIND>>::Dump(
+    std::ostream &o) const {
   std::visit(common::visitors{[&](const Scalar<Result> &n) {
                                 o << n.DumpHexadecimal();
                               },
@@ -144,7 +148,8 @@ std::ostream &ComplexExpr<KIND>::Dump(std::ostream &o) const {
 }
 
 template<int KIND>
-std::ostream &CharacterExpr<KIND>::Dump(std::ostream &o) const {
+std::ostream &Expr<Type<TypeCategory::Character, KIND>>::Dump(
+    std::ostream &o) const {
   std::visit(common::visitors{[&](const Scalar<Result> &s) {
                                 o << parser::QuoteCharacterLiteral(s);
                               },
@@ -164,7 +169,8 @@ template<typename A> std::ostream &Comparison<A>::Dump(std::ostream &o) const {
 }
 
 template<int KIND>
-std::ostream &LogicalExpr<KIND>::Dump(std::ostream &o) const {
+std::ostream &Expr<Type<TypeCategory::Logical, KIND>>::Dump(
+    std::ostream &o) const {
   std::visit(common::visitors{[&](const Scalar<Result> &tf) {
                                 o << (tf.IsTrue() ? ".TRUE." : ".FALSE.");
                               },
@@ -181,7 +187,8 @@ std::ostream &LogicalExpr<KIND>::Dump(std::ostream &o) const {
 }
 
 // LEN()
-template<int KIND> Expr<SubscriptInteger> CharacterExpr<KIND>::LEN() const {
+template<int KIND>
+Expr<SubscriptInteger> Expr<Type<TypeCategory::Character, KIND>>::LEN() const {
   return std::visit(
       common::visitors{[](const Scalar<Result> &c) {
                          // std::string::size_type isn't convertible to uint64_t
@@ -238,7 +245,7 @@ auto Binary<CRTP, RESULT, A, B>::Fold(FoldingContext &context)
 }
 
 template<int KIND>
-auto IntegerExpr<KIND>::ConvertInteger::FoldScalar(
+auto Expr<Type<TypeCategory::Integer, KIND>>::ConvertInteger::FoldScalar(
     FoldingContext &context, const SomeKindScalar<TypeCategory::Integer> &c)
     -> std::optional<Scalar<Result>> {
   return std::visit(
@@ -254,7 +261,7 @@ auto IntegerExpr<KIND>::ConvertInteger::FoldScalar(
 }
 
 template<int KIND>
-auto IntegerExpr<KIND>::ConvertReal::FoldScalar(
+auto Expr<Type<TypeCategory::Integer, KIND>>::ConvertReal::FoldScalar(
     FoldingContext &context, const SomeKindScalar<TypeCategory::Real> &c)
     -> std::optional<Scalar<Result>> {
   return std::visit(
@@ -275,8 +282,9 @@ auto IntegerExpr<KIND>::ConvertReal::FoldScalar(
 }
 
 template<int KIND>
-auto IntegerExpr<KIND>::Negate::FoldScalar(FoldingContext &context,
-    const Scalar<Result> &c) -> std::optional<Scalar<Result>> {
+auto Expr<Type<TypeCategory::Integer, KIND>>::Negate::FoldScalar(
+    FoldingContext &context, const Scalar<Result> &c)
+    -> std::optional<Scalar<Result>> {
   auto negated{c.Negate()};
   if (negated.overflow) {
     context.messages.Say("integer negation overflowed"_en_US);
@@ -286,7 +294,7 @@ auto IntegerExpr<KIND>::Negate::FoldScalar(FoldingContext &context,
 }
 
 template<int KIND>
-auto IntegerExpr<KIND>::Add::FoldScalar(
+auto Expr<Type<TypeCategory::Integer, KIND>>::Add::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   auto sum{a.AddSigned(b)};
@@ -298,7 +306,7 @@ auto IntegerExpr<KIND>::Add::FoldScalar(
 }
 
 template<int KIND>
-auto IntegerExpr<KIND>::Subtract::FoldScalar(
+auto Expr<Type<TypeCategory::Integer, KIND>>::Subtract::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   auto diff{a.SubtractSigned(b)};
@@ -310,7 +318,7 @@ auto IntegerExpr<KIND>::Subtract::FoldScalar(
 }
 
 template<int KIND>
-auto IntegerExpr<KIND>::Multiply::FoldScalar(
+auto Expr<Type<TypeCategory::Integer, KIND>>::Multiply::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   auto product{a.MultiplySigned(b)};
@@ -322,7 +330,7 @@ auto IntegerExpr<KIND>::Multiply::FoldScalar(
 }
 
 template<int KIND>
-auto IntegerExpr<KIND>::Divide::FoldScalar(
+auto Expr<Type<TypeCategory::Integer, KIND>>::Divide::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   auto qr{a.DivideSigned(b)};
@@ -338,7 +346,7 @@ auto IntegerExpr<KIND>::Divide::FoldScalar(
 }
 
 template<int KIND>
-auto IntegerExpr<KIND>::Power::FoldScalar(
+auto Expr<Type<TypeCategory::Integer, KIND>>::Power::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   typename Scalar<Result>::PowerWithErrors power{a.Power(b)};
@@ -358,7 +366,7 @@ auto IntegerExpr<KIND>::Power::FoldScalar(
 }
 
 template<int KIND>
-auto IntegerExpr<KIND>::Max::FoldScalar(
+auto Expr<Type<TypeCategory::Integer, KIND>>::Max::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   if (a.CompareSigned(b) == Ordering::Greater) {
@@ -368,7 +376,7 @@ auto IntegerExpr<KIND>::Max::FoldScalar(
 }
 
 template<int KIND>
-auto IntegerExpr<KIND>::Min::FoldScalar(
+auto Expr<Type<TypeCategory::Integer, KIND>>::Min::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   if (a.CompareSigned(b) == Ordering::Less) {
@@ -378,7 +386,7 @@ auto IntegerExpr<KIND>::Min::FoldScalar(
 }
 
 template<int KIND>
-auto IntegerExpr<KIND>::Fold(FoldingContext &context)
+auto Expr<Type<TypeCategory::Integer, KIND>>::Fold(FoldingContext &context)
     -> std::optional<Scalar<Result>> {
   return std::visit(
       [&](auto &x) -> std::optional<Scalar<Result>> {
@@ -399,7 +407,7 @@ auto IntegerExpr<KIND>::Fold(FoldingContext &context)
 }
 
 template<int KIND>
-auto RealExpr<KIND>::ConvertInteger::FoldScalar(
+auto Expr<Type<TypeCategory::Real, KIND>>::ConvertInteger::FoldScalar(
     FoldingContext &context, const SomeKindScalar<TypeCategory::Integer> &c)
     -> std::optional<Scalar<Result>> {
   return std::visit(
@@ -412,7 +420,7 @@ auto RealExpr<KIND>::ConvertInteger::FoldScalar(
 }
 
 template<int KIND>
-auto RealExpr<KIND>::ConvertReal::FoldScalar(
+auto Expr<Type<TypeCategory::Real, KIND>>::ConvertReal::FoldScalar(
     FoldingContext &context, const SomeKindScalar<TypeCategory::Real> &c)
     -> std::optional<Scalar<Result>> {
   return std::visit(
@@ -425,13 +433,14 @@ auto RealExpr<KIND>::ConvertReal::FoldScalar(
 }
 
 template<int KIND>
-auto RealExpr<KIND>::Negate::FoldScalar(FoldingContext &context,
-    const Scalar<Result> &c) -> std::optional<Scalar<Result>> {
+auto Expr<Type<TypeCategory::Real, KIND>>::Negate::FoldScalar(
+    FoldingContext &context, const Scalar<Result> &c)
+    -> std::optional<Scalar<Result>> {
   return {c.Negate()};
 }
 
 template<int KIND>
-auto RealExpr<KIND>::Add::FoldScalar(
+auto Expr<Type<TypeCategory::Real, KIND>>::Add::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   auto sum{a.Add(b, context.rounding)};
@@ -440,7 +449,7 @@ auto RealExpr<KIND>::Add::FoldScalar(
 }
 
 template<int KIND>
-auto RealExpr<KIND>::Subtract::FoldScalar(
+auto Expr<Type<TypeCategory::Real, KIND>>::Subtract::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   auto difference{a.Subtract(b, context.rounding)};
@@ -449,7 +458,7 @@ auto RealExpr<KIND>::Subtract::FoldScalar(
 }
 
 template<int KIND>
-auto RealExpr<KIND>::Multiply::FoldScalar(
+auto Expr<Type<TypeCategory::Real, KIND>>::Multiply::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   auto product{a.Multiply(b, context.rounding)};
@@ -458,7 +467,7 @@ auto RealExpr<KIND>::Multiply::FoldScalar(
 }
 
 template<int KIND>
-auto RealExpr<KIND>::Divide::FoldScalar(
+auto Expr<Type<TypeCategory::Real, KIND>>::Divide::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   auto quotient{a.Divide(b, context.rounding)};
@@ -467,15 +476,16 @@ auto RealExpr<KIND>::Divide::FoldScalar(
 }
 
 template<int KIND>
-auto RealExpr<KIND>::Power::FoldScalar(
+auto Expr<Type<TypeCategory::Real, KIND>>::Power::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   return std::nullopt;  // TODO
 }
 
 template<int KIND>
-auto RealExpr<KIND>::IntPower::FoldScalar(FoldingContext &context,
-    const Scalar<Result> &a, const SomeKindScalar<TypeCategory::Integer> &b)
+auto Expr<Type<TypeCategory::Real, KIND>>::IntPower::FoldScalar(
+    FoldingContext &context, const Scalar<Result> &a,
+    const SomeKindScalar<TypeCategory::Integer> &b)
     -> std::optional<Scalar<Result>> {
   return std::visit(
       [&](const auto &pow) -> std::optional<Scalar<Result>> {
@@ -487,7 +497,7 @@ auto RealExpr<KIND>::IntPower::FoldScalar(FoldingContext &context,
 }
 
 template<int KIND>
-auto RealExpr<KIND>::Max::FoldScalar(
+auto Expr<Type<TypeCategory::Real, KIND>>::Max::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   if (b.IsNotANumber() || a.Compare(b) == Relation::Less) {
@@ -497,7 +507,7 @@ auto RealExpr<KIND>::Max::FoldScalar(
 }
 
 template<int KIND>
-auto RealExpr<KIND>::Min::FoldScalar(
+auto Expr<Type<TypeCategory::Real, KIND>>::Min::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   if (b.IsNotANumber() || a.Compare(b) == Relation::Greater) {
@@ -507,21 +517,23 @@ auto RealExpr<KIND>::Min::FoldScalar(
 }
 
 template<int KIND>
-auto RealExpr<KIND>::RealPart::FoldScalar(FoldingContext &context,
+auto Expr<Type<TypeCategory::Real, KIND>>::RealPart::FoldScalar(
+    FoldingContext &context,
     const Scalar<SameKind<TypeCategory::Complex, Result>> &z)
     -> std::optional<Scalar<Result>> {
   return {z.REAL()};
 }
 
 template<int KIND>
-auto RealExpr<KIND>::AIMAG::FoldScalar(FoldingContext &context,
+auto Expr<Type<TypeCategory::Real, KIND>>::AIMAG::FoldScalar(
+    FoldingContext &context,
     const Scalar<SameKind<TypeCategory::Complex, Result>> &z)
     -> std::optional<Scalar<Result>> {
   return {z.AIMAG()};
 }
 
 template<int KIND>
-auto RealExpr<KIND>::Fold(FoldingContext &context)
+auto Expr<Type<TypeCategory::Real, KIND>>::Fold(FoldingContext &context)
     -> std::optional<Scalar<Result>> {
   return std::visit(
       [&](auto &x) -> std::optional<Scalar<Result>> {
@@ -545,13 +557,14 @@ auto RealExpr<KIND>::Fold(FoldingContext &context)
 }
 
 template<int KIND>
-auto ComplexExpr<KIND>::Negate::FoldScalar(FoldingContext &context,
-    const Scalar<Result> &c) -> std::optional<Scalar<Result>> {
+auto Expr<Type<TypeCategory::Complex, KIND>>::Negate::FoldScalar(
+    FoldingContext &context, const Scalar<Result> &c)
+    -> std::optional<Scalar<Result>> {
   return {c.Negate()};
 }
 
 template<int KIND>
-auto ComplexExpr<KIND>::Add::FoldScalar(
+auto Expr<Type<TypeCategory::Complex, KIND>>::Add::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   auto sum{a.Add(b, context.rounding)};
@@ -560,7 +573,7 @@ auto ComplexExpr<KIND>::Add::FoldScalar(
 }
 
 template<int KIND>
-auto ComplexExpr<KIND>::Subtract::FoldScalar(
+auto Expr<Type<TypeCategory::Complex, KIND>>::Subtract::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   auto difference{a.Subtract(b, context.rounding)};
@@ -569,7 +582,7 @@ auto ComplexExpr<KIND>::Subtract::FoldScalar(
 }
 
 template<int KIND>
-auto ComplexExpr<KIND>::Multiply::FoldScalar(
+auto Expr<Type<TypeCategory::Complex, KIND>>::Multiply::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   auto product{a.Multiply(b, context.rounding)};
@@ -578,7 +591,7 @@ auto ComplexExpr<KIND>::Multiply::FoldScalar(
 }
 
 template<int KIND>
-auto ComplexExpr<KIND>::Divide::FoldScalar(
+auto Expr<Type<TypeCategory::Complex, KIND>>::Divide::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   auto quotient{a.Divide(b, context.rounding)};
@@ -587,15 +600,16 @@ auto ComplexExpr<KIND>::Divide::FoldScalar(
 }
 
 template<int KIND>
-auto ComplexExpr<KIND>::Power::FoldScalar(
+auto Expr<Type<TypeCategory::Complex, KIND>>::Power::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   return std::nullopt;  // TODO
 }
 
 template<int KIND>
-auto ComplexExpr<KIND>::IntPower::FoldScalar(FoldingContext &context,
-    const Scalar<Result> &a, const SomeKindScalar<TypeCategory::Integer> &b)
+auto Expr<Type<TypeCategory::Complex, KIND>>::IntPower::FoldScalar(
+    FoldingContext &context, const Scalar<Result> &a,
+    const SomeKindScalar<TypeCategory::Integer> &b)
     -> std::optional<Scalar<Result>> {
   return std::visit(
       [&](const auto &pow) -> std::optional<Scalar<Result>> {
@@ -607,7 +621,8 @@ auto ComplexExpr<KIND>::IntPower::FoldScalar(FoldingContext &context,
 }
 
 template<int KIND>
-auto ComplexExpr<KIND>::CMPLX::FoldScalar(FoldingContext &context,
+auto Expr<Type<TypeCategory::Complex, KIND>>::CMPLX::FoldScalar(
+    FoldingContext &context,
     const Scalar<SameKind<TypeCategory::Real, Result>> &a,
     const Scalar<SameKind<TypeCategory::Real, Result>> &b)
     -> std::optional<Scalar<Result>> {
@@ -615,7 +630,7 @@ auto ComplexExpr<KIND>::CMPLX::FoldScalar(FoldingContext &context,
 }
 
 template<int KIND>
-auto ComplexExpr<KIND>::Fold(FoldingContext &context)
+auto Expr<Type<TypeCategory::Complex, KIND>>::Fold(FoldingContext &context)
     -> std::optional<Scalar<Result>> {
   return std::visit(
       [&](auto &x) -> std::optional<Scalar<Result>> {
@@ -639,7 +654,7 @@ auto ComplexExpr<KIND>::Fold(FoldingContext &context)
 }
 
 template<int KIND>
-auto CharacterExpr<KIND>::Concat::FoldScalar(
+auto Expr<Type<TypeCategory::Character, KIND>>::Concat::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   if constexpr (KIND == 1) {
@@ -649,7 +664,7 @@ auto CharacterExpr<KIND>::Concat::FoldScalar(
 }
 
 template<int KIND>
-auto CharacterExpr<KIND>::Max::FoldScalar(
+auto Expr<Type<TypeCategory::Character, KIND>>::Max::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   if (Compare(a, b) == Ordering::Less) {
@@ -659,7 +674,7 @@ auto CharacterExpr<KIND>::Max::FoldScalar(
 }
 
 template<int KIND>
-auto CharacterExpr<KIND>::Min::FoldScalar(
+auto Expr<Type<TypeCategory::Character, KIND>>::Min::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   if (Compare(a, b) == Ordering::Greater) {
@@ -669,7 +684,7 @@ auto CharacterExpr<KIND>::Min::FoldScalar(
 }
 
 template<int KIND>
-auto CharacterExpr<KIND>::Fold(FoldingContext &context)
+auto Expr<Type<TypeCategory::Character, KIND>>::Fold(FoldingContext &context)
     -> std::optional<Scalar<Result>> {
   return std::visit(
       [&](auto &x) -> std::optional<Scalar<Result>> {
@@ -741,41 +756,42 @@ auto Comparison<A>::FoldScalar(FoldingContext &c, const Scalar<Operand> &a,
 }
 
 template<int KIND>
-auto LogicalExpr<KIND>::Not::FoldScalar(FoldingContext &context,
-    const Scalar<Result> &x) -> std::optional<Scalar<Result>> {
+auto Expr<Type<TypeCategory::Logical, KIND>>::Not::FoldScalar(
+    FoldingContext &context, const Scalar<Result> &x)
+    -> std::optional<Scalar<Result>> {
   return {Scalar<Result>{!x.IsTrue()}};
 }
 
 template<int KIND>
-auto LogicalExpr<KIND>::And::FoldScalar(
+auto Expr<Type<TypeCategory::Logical, KIND>>::And::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   return {Scalar<Result>{a.IsTrue() && b.IsTrue()}};
 }
 
 template<int KIND>
-auto LogicalExpr<KIND>::Or::FoldScalar(
+auto Expr<Type<TypeCategory::Logical, KIND>>::Or::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   return {Scalar<Result>{a.IsTrue() || b.IsTrue()}};
 }
 
 template<int KIND>
-auto LogicalExpr<KIND>::Eqv::FoldScalar(
+auto Expr<Type<TypeCategory::Logical, KIND>>::Eqv::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   return {Scalar<Result>{a.IsTrue() == b.IsTrue()}};
 }
 
 template<int KIND>
-auto LogicalExpr<KIND>::Neqv::FoldScalar(
+auto Expr<Type<TypeCategory::Logical, KIND>>::Neqv::FoldScalar(
     FoldingContext &context, const Scalar<Result> &a, const Scalar<Result> &b)
     -> std::optional<Scalar<Result>> {
   return {Scalar<Result>{a.IsTrue() != b.IsTrue()}};
 }
 
 template<int KIND>
-auto LogicalExpr<KIND>::Fold(FoldingContext &context)
+auto Expr<Type<TypeCategory::Logical, KIND>>::Fold(FoldingContext &context)
     -> std::optional<Scalar<Result>> {
   return std::visit(
       [&](auto &x) -> std::optional<Scalar<Result>> {
index 5b5d87f..4a45de1 100644 (file)
@@ -22,7 +22,6 @@
 // and manipulation in place.
 
 #include "common.h"
-#include "expression-forward.h"
 #include "type.h"
 #include "variable.h"
 #include "../lib/common/idioms.h"
 
 namespace Fortran::evaluate {
 
+template<typename A> class Expr;
+
+// An expression whose result is within one particular type category and
+// of any supported kind.
+using SomeKindIntegerExpr = Expr<SomeKind<TypeCategory::Integer>>;
+using SomeKindRealExpr = Expr<SomeKind<TypeCategory::Real>>;
+using SomeKindComplexExpr = Expr<SomeKind<TypeCategory::Complex>>;
+using SomeKindCharacterExpr = Expr<SomeKind<TypeCategory::Character>>;
+using SomeKindLogicalExpr = Expr<SomeKind<TypeCategory::Logical>>;
+
 // Helper base classes for packaging subexpressions.
 template<typename CRTP, typename RESULT, typename A = RESULT> class Unary {
 public:
@@ -160,16 +169,19 @@ public:
   Expr(const SomeKindIntegerExpr &x) : u_{ConvertInteger{x}} {}
   Expr(SomeKindIntegerExpr &&x) : u_{ConvertInteger{std::move(x)}} {}
   template<int K>
-  Expr(const IntegerExpr<K> &x) : u_{ConvertInteger{SomeKindIntegerExpr{x}}} {}
+  Expr(const Expr<Type<TypeCategory::Integer, K>> &x)
+    : u_{ConvertInteger{SomeKindIntegerExpr{x}}} {}
   template<int K>
-  Expr(IntegerExpr<K> &&x)
+  Expr(Expr<Type<TypeCategory::Integer, K>> &&x)
     : u_{ConvertInteger{SomeKindIntegerExpr{std::move(x)}}} {}
   Expr(const SomeKindRealExpr &x) : u_{ConvertReal{x}} {}
   Expr(SomeKindRealExpr &&x) : u_{ConvertReal{std::move(x)}} {}
   template<int K>
-  Expr(const RealExpr<K> &x) : u_{ConvertReal{SomeKindRealExpr{x}}} {}
+  Expr(const Expr<Type<TypeCategory::Real, K>> &x)
+    : u_{ConvertReal{SomeKindRealExpr{x}}} {}
   template<int K>
-  Expr(RealExpr<K> &&x) : u_{ConvertReal{SomeKindRealExpr{std::move(x)}}} {}
+  Expr(Expr<Type<TypeCategory::Real, K>> &&x)
+    : u_{ConvertReal{SomeKindRealExpr{std::move(x)}}} {}
   template<typename A> Expr(const A &x) : u_{x} {}
   template<typename A>
   Expr(std::enable_if_t<!std::is_reference_v<A> &&
@@ -285,16 +297,19 @@ public:
   Expr(const SomeKindIntegerExpr &x) : u_{ConvertInteger{x}} {}
   Expr(SomeKindIntegerExpr &&x) : u_{ConvertInteger{std::move(x)}} {}
   template<int K>
-  Expr(const IntegerExpr<K> &x) : u_{ConvertInteger{SomeKindIntegerExpr{x}}} {}
+  Expr(const Expr<Type<TypeCategory::Integer, K>> &x)
+    : u_{ConvertInteger{SomeKindIntegerExpr{x}}} {}
   template<int K>
-  Expr(IntegerExpr<K> &&x)
+  Expr(Expr<Type<TypeCategory::Integer, K>> &&x)
     : u_{ConvertInteger{SomeKindIntegerExpr{std::move(x)}}} {}
   Expr(const SomeKindRealExpr &x) : u_{ConvertReal{x}} {}
   Expr(SomeKindRealExpr &&x) : u_{ConvertReal{std::move(x)}} {}
   template<int K>
-  Expr(const RealExpr<K> &x) : u_{ConvertReal{SomeKindRealExpr{x}}} {}
+  Expr(const Expr<Type<TypeCategory::Real, K>> &x)
+    : u_{ConvertReal{SomeKindRealExpr{x}}} {}
   template<int K>
-  Expr(RealExpr<K> &&x) : u_{ConvertReal{SomeKindRealExpr{std::move(x)}}} {}
+  Expr(Expr<Type<TypeCategory::Real, K>> &&x)
+    : u_{ConvertReal{SomeKindRealExpr{std::move(x)}}} {}
   template<typename A> Expr(const A &x) : u_{x} {}
   template<typename A>
   Expr(std::enable_if_t<!std::is_reference_v<A>, A> &&x) : u_{std::move(x)} {}
@@ -659,21 +674,21 @@ BINARY(Power, Power)
 #undef BINARY
 
 #define BINARY(FUNC, OP) \
-  template<typename A> LogicalExpr<1> FUNC(const A &x, const A &y) { \
+  template<typename A> Expr<LogicalResult> FUNC(const A &x, const A &y) { \
     return {Comparison<ResultType<A>>{OP, x, y}}; \
   } \
   template<typename A> \
-  std::enable_if_t<!std::is_reference_v<A>, LogicalExpr<1>> FUNC( \
+  std::enable_if_t<!std::is_reference_v<A>, Expr<LogicalResult>> FUNC( \
       const A &x, A &&y) { \
     return {Comparison<ResultType<A>>{OP, x, std::move(y)}}; \
   } \
   template<typename A> \
-  std::enable_if_t<!std::is_reference_v<A>, LogicalExpr<1>> FUNC( \
+  std::enable_if_t<!std::is_reference_v<A>, Expr<LogicalResult>> FUNC( \
       A &&x, const A &y) { \
     return {Comparison<ResultType<A>>{OP, std::move(x), y}}; \
   } \
   template<typename A> \
-  std::enable_if_t<!std::is_reference_v<A>, LogicalExpr<1>> FUNC( \
+  std::enable_if_t<!std::is_reference_v<A>, Expr<LogicalResult>> FUNC( \
       A &&x, A &&y) { \
     return {Comparison<ResultType<A>>{OP, std::move(x), std::move(y)}}; \
   }
index c3816fc..a5f528b 100644 (file)
@@ -238,5 +238,6 @@ template<TypeCategory CAT> struct SomeKind {
   static constexpr TypeCategory category{CAT};
   using Scalar = SomeKindScalar<CAT>;
 };
+
 }  // namespace Fortran::evaluate
 #endif  // FORTRAN_EVALUATE_TYPE_H_
index 535a26c..fa9396f 100644 (file)
@@ -22,8 +22,8 @@
 // that only admissable combinations can be constructed.
 
 #include "common.h"
-#include "expression-forward.h"
 #include "intrinsics.h"
+#include "type.h"
 #include "../common/idioms.h"
 #include "../semantics/symbol.h"
 #include <optional>
@@ -36,6 +36,7 @@ namespace Fortran::evaluate {
 using semantics::Symbol;
 
 // Forward declarations
+template<typename A> class Expr;
 class DataRef;
 class Variable;
 class ActualFunctionArg;
index 4679fb6..de74add 100644 (file)
@@ -23,6 +23,8 @@ using namespace Fortran::parser::literals;
 
 namespace Fortran::semantics {
 
+using common::TypeCategory;
+
 // AnalyzeHelper is a local template function that keeps the API
 // member function ExpressionAnalyzer::Analyze from having to be a
 // many-specialized template itself.
@@ -96,9 +98,11 @@ static std::optional<evaluate::SomeKindCharacterExpr> AnalyzeLiteral(
       ExpressionAnalyzer::KindParam{1})};
   switch (kind) {
 #define CASE(k) \
-  case k: \
+  case k: { \
+    using Ty = evaluate::Type<TypeCategory::Character, k>; \
     return {evaluate::SomeKindCharacterExpr{ \
-        evaluate::CharacterExpr<k>{std::get<std::string>(x.t)}}};
+        evaluate::Expr<Ty>{std::get<std::string>(x.t)}}}; \
+  }
     FOR_EACH_CHARACTER_KIND(CASE, )
 #undef CASE
   default:
@@ -153,7 +157,7 @@ MaybeExpr AnalyzeHelper(
   }
   evaluate::Substring substring{std::move(str), std::move(lb), std::move(ub)};
   evaluate::CopyableIndirection<evaluate::Substring> ind{std::move(substring)};
-  evaluate::CharacterExpr<1> chExpr{std::move(ind)};
+  evaluate::Expr<evaluate::DefaultCharacter> chExpr{std::move(ind)};
   chExpr.Fold(ea.context());
   return {GenericExpr{evaluate::SomeKindCharacterExpr{std::move(chExpr)}}};
 }
@@ -167,7 +171,10 @@ std::optional<evaluate::SomeKindIntegerExpr> IntLiteralConstant(
   auto value{std::get<0>(x.t)};  // std::[u]int64_t
   switch (kind) {
 #define CASE(k) \
-  case k: return {evaluate::ToSomeKindExpr(evaluate::IntegerExpr<k>{value})};
+  case k: { \
+    using Ty = evaluate::Type<TypeCategory::Integer, k>; \
+    return {evaluate::ToSomeKindExpr(evaluate::Expr<Ty>{value})}; \
+  }
     FOR_EACH_INTEGER_KIND(CASE, )
 #undef CASE
   default:
@@ -216,7 +223,7 @@ template<int KIND>
 std::optional<evaluate::SomeKindRealExpr> ReadRealLiteral(
     parser::CharBlock source, evaluate::FoldingContext &context) {
   const char *p{source.begin()};
-  using RealType = evaluate::Type<evaluate::TypeCategory::Real, KIND>;
+  using RealType = evaluate::Type<TypeCategory::Real, KIND>;
   auto valWithFlags{evaluate::Scalar<RealType>::Read(p, context.rounding)};
   CHECK(p == source.end());
   evaluate::RealFlagWarnings(
@@ -333,8 +340,10 @@ static std::optional<evaluate::SomeKindLogicalExpr> AnalyzeLiteral(
   bool value{std::get<bool>(x.t)};
   switch (kind) {
 #define CASE(k) \
-  case k: \
-    return {evaluate::SomeKindLogicalExpr{evaluate::LogicalExpr<k>{value}}};
+  case k: { \
+    using Ty = evaluate::Type<TypeCategory::Logical, k>; \
+    return {evaluate::SomeKindLogicalExpr{evaluate::Expr<Ty>{value}}}; \
+  }
     FOR_EACH_LOGICAL_KIND(CASE, )
 #undef CASE
   default:
@@ -602,8 +611,7 @@ ExpressionAnalyzer::ConstructComplex(MaybeExpr &&real, MaybeExpr &&imaginary) {
     return {std::visit(
         [](auto &&rx, auto &&ix) -> evaluate::SomeKindComplexExpr {
           using realType = evaluate::ResultType<decltype(rx)>;
-          using zType =
-              evaluate::SameKind<evaluate::TypeCategory::Complex, realType>;
+          using zType = evaluate::SameKind<TypeCategory::Complex, realType>;
           using zExpr = evaluate::Expr<zType>;
           return {zExpr{typename zExpr::CMPLX{std::move(rx), std::move(ix)}}};
         },
index 5ed02a3..d4d727f 100644 (file)
@@ -29,6 +29,7 @@ template<typename A> std::string Dump(const A &x) {
 }
 
 int main() {
+  using DefaultIntegerExpr = Expr<DefaultInteger>;
   TEST(DefaultIntegerExpr::Result::Dump() == "Integer(4)");
   MATCH("666", Dump(DefaultIntegerExpr{666}));
   MATCH("(-1)", Dump(-DefaultIntegerExpr{1}));