[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:
parent
8b9efa289c
commit
94540975f3
|
@ -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};
|
||||
}
|
||||
|
|
|
@ -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>>;
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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))};
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue