[flang] clean up naming in expressions and types

Original-commit: flang-compiler/f18@ab17ef4d4b
Reviewed-on: https://github.com/flang-compiler/f18/pull/183
Tree-same-pre-rewrite: false
This commit is contained in:
peter klausler 2018-08-13 17:05:15 -07:00
parent 8b9efa289c
commit 94540975f3
9 changed files with 126 additions and 117 deletions

View 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};
}

View 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>>;

View 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};

View 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

View 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
// category.
template<TypeCategory CAT> struct ScalarConstant {
static constexpr TypeCategory category{CAT};
CLASS_BOILERPLATE(ScalarConstant)
template<typename CONST>
using ScalarValueType = typename GetTypeOfScalarValue<CONST>::type;
template<int KIND> using KindScalar = typename Type<CAT, KIND>::Value;
template<typename A> ScalarConstant(const A &x) : u{x} {}
// Holds a scalar value of any kind within a particular intrinsic type
// category.
template<TypeCategory CAT> struct SomeKindScalar {
static constexpr TypeCategory category{CAT};
CLASS_BOILERPLATE(SomeKindScalar)
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_

View 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));

View 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))};

View 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());

View file

@ -21,13 +21,13 @@
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 {