forked from OSchip/llvm-project
[flang] continue refactoring
Original-commit: flang-compiler/f18@f2b49ba0e2 Reviewed-on: https://github.com/flang-compiler/f18/pull/183 Tree-same-pre-rewrite: false
This commit is contained in:
parent
f38fe515ed
commit
7d042acb9d
|
@ -173,5 +173,12 @@ std::optional<A> MapOptional(std::function<A(B &&, C &&)> &f,
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Move a value from one variant type to another. The types allowed in the
|
||||
// source variant must all be allowed in the destination variant type.
|
||||
template<typename TOV, typename FROMV> TOV MoveVariant(FROMV &&u) {
|
||||
return std::visit(
|
||||
[](auto &&x) -> TOV { return {std::move(x)}; }, std::move(u));
|
||||
}
|
||||
|
||||
} // namespace Fortran::common
|
||||
#endif // FORTRAN_COMMON_IDIOMS_H_
|
||||
|
|
|
@ -27,23 +27,22 @@ namespace Fortran::common {
|
|||
// SearchTypeList<PREDICATE, TYPES...> scans a list of types. The zero-based
|
||||
// index of the first type T in the list for which PREDICATE<T>::value() is
|
||||
// true is returned, or -1 if the predicate is false for every type in the list.
|
||||
template<int N, template<typename> class PREDICATE, typename A,
|
||||
typename... REST>
|
||||
struct SearchTypeListTemplate {
|
||||
template<int N, template<typename> class PREDICATE, typename TUPLE>
|
||||
struct SearchTypeListHelper {
|
||||
static constexpr int value() {
|
||||
if constexpr (PREDICATE<A>::value()) {
|
||||
return N;
|
||||
} else if constexpr (sizeof...(REST) == 0) {
|
||||
if constexpr (N >= std::tuple_size_v<TUPLE>) {
|
||||
return -1;
|
||||
} else if constexpr (PREDICATE<std::tuple_element_t<N, TUPLE>>::value()) {
|
||||
return N;
|
||||
} else {
|
||||
return SearchTypeListTemplate<N + 1, PREDICATE, REST...>::value();
|
||||
return SearchTypeListHelper<N + 1, PREDICATE, TUPLE>::value();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<template<typename> class PREDICATE, typename... TYPES>
|
||||
constexpr int SearchTypeList{
|
||||
SearchTypeListTemplate<0, PREDICATE, TYPES...>::value()};
|
||||
SearchTypeListHelper<0, PREDICATE, std::tuple<TYPES...>>::value()};
|
||||
|
||||
// TypeIndex<A, TYPES...> scans a list of types for simple type equality.
|
||||
// The zero-based index of A in the list is returned, or -1 if A is not present.
|
||||
|
@ -66,17 +65,31 @@ constexpr int TypeIndex{SearchTypeList<MatchType<A>::template Match, TYPES...>};
|
|||
// N.B. It *is* possible to extract the types of the alternatives of a
|
||||
// std::variant discriminated union instantiation and reuse them as a
|
||||
// template parameter pack in another template instantiation. The trick is
|
||||
// to match the std::variant type with a partial specialization.
|
||||
template<template<typename> class PREDICATE, typename V>
|
||||
struct SearchVariantTypeTemplate;
|
||||
template<template<typename> class PREDICATE, typename... Ts>
|
||||
struct SearchVariantTypeTemplate<PREDICATE, std::variant<Ts...>> {
|
||||
static constexpr int index{SearchTypeList<PREDICATE, Ts...>};
|
||||
// to match the std::variant type with a partial specialization. And it
|
||||
// works with tuples, too, of course.
|
||||
template<template<typename...> class, typename> struct OverMembersHelper;
|
||||
template<template<typename...> class T, typename... Ts>
|
||||
struct OverMembersHelper<T, std::variant<Ts...>> {
|
||||
using type = T<Ts...>;
|
||||
};
|
||||
template<template<typename...> class T, typename... Ts>
|
||||
struct OverMembersHelper<T, std::tuple<Ts...>> {
|
||||
using type = T<Ts...>;
|
||||
};
|
||||
|
||||
template<template<typename> class PREDICATE, typename VARIANT>
|
||||
constexpr int SearchVariantType{
|
||||
SearchVariantTypeTemplate<PREDICATE, VARIANT>::index};
|
||||
template<template<typename...> class T, typename TorV>
|
||||
using OverMembers = typename OverMembersHelper<T, TorV>::type;
|
||||
|
||||
template<template<typename> class PREDICATE> struct SearchMembersHelper {
|
||||
template<typename... Ts> struct Scanner {
|
||||
static constexpr int value() { return SearchTypeList<PREDICATE, Ts...>; }
|
||||
};
|
||||
};
|
||||
|
||||
template<template<typename> class PREDICATE, typename TorV>
|
||||
constexpr int SearchMembers{
|
||||
OverMembers<SearchMembersHelper<PREDICATE>::template Scanner,
|
||||
TorV>::value()};
|
||||
|
||||
// CombineTuples takes a list of std::tuple<> template instantiation types
|
||||
// and constructs a new std::tuple type that concatenates all of their member
|
||||
|
@ -93,7 +106,8 @@ template<typename... TUPLES>
|
|||
using CombineTuples = typename CombineTuplesHelper<TUPLES...>::type;
|
||||
|
||||
// CombineVariants takes a list of std::variant<> instantiations and constructs
|
||||
// a new instantiation that holds all of their alternatives.
|
||||
// a new instantiation that holds all of their alternatives, which probably
|
||||
// should be distinct.
|
||||
template<typename> struct VariantToTupleHelper;
|
||||
template<typename... Ts> struct VariantToTupleHelper<std::variant<Ts...>> {
|
||||
using type = std::tuple<Ts...>;
|
||||
|
@ -114,5 +128,23 @@ template<typename... VARIANTS> struct CombineVariantsHelper {
|
|||
template<typename... VARIANTS>
|
||||
using CombineVariants = typename CombineVariantsHelper<VARIANTS...>::type;
|
||||
|
||||
// Given a type function, apply it to each of the types in a tuple or variant,
|
||||
// and collect the results in another tuple or variant.
|
||||
template<template<typename> class, template<typename...> class, typename...>
|
||||
struct MapTemplateHelper;
|
||||
template<template<typename> class F, template<typename...> class TorV,
|
||||
typename... Ts>
|
||||
struct MapTemplateHelper<F, TorV, std::tuple<Ts...>> {
|
||||
using type = TorV<F<Ts>...>;
|
||||
};
|
||||
template<template<typename> class F, template<typename...> class TorV,
|
||||
typename... Ts>
|
||||
struct MapTemplateHelper<F, TorV, std::variant<Ts...>> {
|
||||
using type = TorV<F<Ts>...>;
|
||||
};
|
||||
template<template<typename> class F, template<typename...> class TorV,
|
||||
typename TV>
|
||||
using MapTemplate = typename MapTemplateHelper<F, TorV, TV>::type;
|
||||
|
||||
} // namespace Fortran::common
|
||||
#endif // FORTRAN_COMMON_TEMPLATE_H_
|
||||
|
|
|
@ -191,7 +191,7 @@ auto Expr<SomeType>::Fold(FoldingContext &context)
|
|||
},
|
||||
[&](auto &x) -> std::optional<Scalar<Result>> {
|
||||
if (auto c{x.Fold(context)}) {
|
||||
return {Scalar<Result>{std::move(*c)}};
|
||||
return {common::MoveVariant<Scalar<Result>>(std::move(c->u))};
|
||||
}
|
||||
return std::nullopt;
|
||||
}},
|
||||
|
@ -229,7 +229,7 @@ auto Convert<TO, FROM>::FoldScalar(FoldingContext &context,
|
|||
using Ty = TypeOf<std::decay_t<decltype(x)>>;
|
||||
return Convert<Result, Ty>::FoldScalar(context, x);
|
||||
},
|
||||
c.u.u);
|
||||
c.u);
|
||||
} else if constexpr (Result::category == TypeCategory::Integer) {
|
||||
if constexpr (Operand::category == TypeCategory::Integer) {
|
||||
auto converted{Scalar<Result>::ConvertSigned(c)};
|
||||
|
@ -398,7 +398,7 @@ auto RealToIntPower<A, B>::FoldScalar(FoldingContext &context,
|
|||
RealFlagWarnings(context, power.flags, "raising to INTEGER power");
|
||||
return {std::move(power.value)};
|
||||
},
|
||||
y.u.u);
|
||||
y.u);
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
|
@ -543,9 +543,8 @@ std::ostream &Expr<SomeKind<CAT>>::Dump(std::ostream &o) const {
|
|||
return DumpExpr(o, u.u);
|
||||
}
|
||||
|
||||
template<TypeCategory CAT>
|
||||
std::ostream &Relational<SomeKind<CAT>>::Dump(std::ostream &o) const {
|
||||
return DumpExpr(o, u.u);
|
||||
std::ostream &AnyRelational::Dump(std::ostream &o) const {
|
||||
return DumpExpr(o, u);
|
||||
}
|
||||
|
||||
std::ostream &Expr<SomeType>::Dump(std::ostream &o) const {
|
||||
|
@ -669,7 +668,7 @@ auto Expr<SomeType>::ScalarValue() const -> std::optional<Scalar<Result>> {
|
|||
},
|
||||
[](const auto &x) -> std::optional<Scalar<Result>> {
|
||||
if (auto c{x.ScalarValue()}) {
|
||||
return {Scalar<Result>{std::move(*c)}};
|
||||
return {common::MoveVariant<Scalar<Result>>(std::move(c->u))};
|
||||
}
|
||||
return std::nullopt;
|
||||
}},
|
||||
|
|
|
@ -497,22 +497,16 @@ struct Relational : public Operation<Relational<A>, LogicalResult, A, A> {
|
|||
|
||||
// A generic relation between two operands of the same kind in some intrinsic
|
||||
// type category (except LOGICAL).
|
||||
template<TypeCategory CAT> struct Relational<SomeKind<CAT>> {
|
||||
static constexpr TypeCategory category{CAT};
|
||||
struct AnyRelational {
|
||||
using Result = LogicalResult;
|
||||
using Operand = SomeKind<CAT>;
|
||||
template<TypeCategory C, int K> using KindRelational = Relational<Type<C, K>>;
|
||||
|
||||
CLASS_BOILERPLATE(Relational)
|
||||
template<int KIND>
|
||||
Relational(const KindRelational<category, KIND> &x) : u{x} {}
|
||||
template<int KIND>
|
||||
Relational(KindRelational<category, KIND> &&x) : u{std::move(x)} {}
|
||||
|
||||
template<typename A> AnyRelational(const A &x) : u{x} {}
|
||||
template<typename A>
|
||||
AnyRelational(std::enable_if_t<!std::is_reference_v<A>, A> &&x)
|
||||
: u{std::move(x)} {}
|
||||
std::optional<Scalar<Result>> Fold(FoldingContext &);
|
||||
std::ostream &Dump(std::ostream &) const;
|
||||
|
||||
CategoryUnion<CAT, KindRelational> u;
|
||||
common::MapTemplate<Relational, std::variant, RelationalTypes> u;
|
||||
};
|
||||
|
||||
template<int KIND> class Expr<Type<TypeCategory::Logical, KIND>> {
|
||||
|
@ -544,11 +538,7 @@ private:
|
|||
std::variant<Scalar<Result>, CopyableIndirection<DataRef>,
|
||||
CopyableIndirection<FunctionRef>,
|
||||
// TODO Parentheses<Result>,
|
||||
Not<KIND>, LogicalOperation<KIND>,
|
||||
Relational<SomeKind<TypeCategory::Integer>>,
|
||||
Relational<SomeKind<TypeCategory::Real>>,
|
||||
Relational<SomeKind<TypeCategory::Complex>>,
|
||||
Relational<SomeKind<TypeCategory::Character>>>
|
||||
Not<KIND>, LogicalOperation<KIND>, AnyRelational>
|
||||
u_;
|
||||
};
|
||||
|
||||
|
|
|
@ -67,7 +67,10 @@ ConvertRealOperandsResult ConvertRealOperands(
|
|||
|
||||
Expr<SomeType> GenericScalarToExpr(const Scalar<SomeType> &x) {
|
||||
return std::visit(
|
||||
[&](const auto &c) { return ToGenericExpr(SomeKindScalarToExpr(c)); },
|
||||
[](const auto &c) -> Expr<SomeType> {
|
||||
using Ty = TypeOf<decltype(c)>;
|
||||
return {Expr<SomeKind<Ty::category>>{Expr<Ty>{c}}};
|
||||
},
|
||||
x.u);
|
||||
}
|
||||
|
||||
|
|
|
@ -141,13 +141,6 @@ Expr<SomeKind<CAT>> ToSomeKindExpr(Expr<Type<CAT, KIND>> &&x) {
|
|||
return {std::move(x)};
|
||||
}
|
||||
|
||||
template<TypeCategory CAT>
|
||||
Expr<SomeKind<CAT>> SomeKindScalarToExpr(const SomeKindScalar<CAT> &x) {
|
||||
return std::visit(
|
||||
[](const auto &c) { return ToSomeKindExpr(ScalarConstantToExpr(c)); },
|
||||
x.u.u);
|
||||
}
|
||||
|
||||
Expr<SomeType> GenericScalarToExpr(const Scalar<SomeType> &);
|
||||
|
||||
template<TypeCategory CAT, int KIND>
|
||||
|
|
|
@ -112,6 +112,7 @@ struct Type<TypeCategory::Logical, KIND>
|
|||
|
||||
template<typename T> using Scalar = typename std::decay_t<T>::Scalar;
|
||||
|
||||
// Given a specific type, find the type of the same kind in another category.
|
||||
template<TypeCategory C, typename T>
|
||||
using SameKind = Type<C, std::decay_t<T>::kind>;
|
||||
|
||||
|
@ -194,103 +195,101 @@ struct IntrinsicTypeUnionTemplate {
|
|||
template<template<TypeCategory, int> class A>
|
||||
using IntrinsicTypeUnion = typename IntrinsicTypeUnionTemplate<A>::type;
|
||||
|
||||
// For an intrinsic type category CAT, CategoryTypes<CAT> is an instantiation
|
||||
// of std::tuple<Type<CAT, K>> for every supported kind K in that category.
|
||||
template<TypeCategory CAT, int... KINDS>
|
||||
using CategoryTypesTuple = std::tuple<Type<CAT, KINDS>...>;
|
||||
|
||||
template<TypeCategory CAT> struct CategoryTypesHelper;
|
||||
template<> struct CategoryTypesHelper<TypeCategory::Integer> {
|
||||
using type = CategoryTypesTuple<TypeCategory::Integer, 1, 2, 4, 8, 16>;
|
||||
};
|
||||
template<> struct CategoryTypesHelper<TypeCategory::Real> {
|
||||
using type = CategoryTypesTuple<TypeCategory::Real, 2, 4, 8, 10, 16>;
|
||||
};
|
||||
template<> struct CategoryTypesHelper<TypeCategory::Complex> {
|
||||
using type = CategoryTypesTuple<TypeCategory::Complex, 2, 4, 8, 10, 16>;
|
||||
};
|
||||
template<> struct CategoryTypesHelper<TypeCategory::Character> {
|
||||
using type = CategoryTypesTuple<TypeCategory::Character, 1>; // TODO: 2 & 4
|
||||
};
|
||||
template<> struct CategoryTypesHelper<TypeCategory::Logical> {
|
||||
using type = CategoryTypesTuple<TypeCategory::Logical, 1, 2, 4, 8>;
|
||||
};
|
||||
template<TypeCategory CAT>
|
||||
using CategoryTypes = typename CategoryTypesHelper<CAT>::type;
|
||||
|
||||
using NumericTypes = common::CombineTuples<CategoryTypes<TypeCategory::Integer>,
|
||||
CategoryTypes<TypeCategory::Real>, CategoryTypes<TypeCategory::Complex>>;
|
||||
using RelationalTypes =
|
||||
common::CombineTuples<NumericTypes, CategoryTypes<TypeCategory::Character>>;
|
||||
using AllIntrinsicTypes = common::CombineTuples<RelationalTypes,
|
||||
CategoryTypes<TypeCategory::Logical>>;
|
||||
|
||||
// When Scalar<T> is S, then TypeOf<S> is T.
|
||||
// TypeOf is implemented by scanning all supported types for a match
|
||||
// with Type<T>::Scalar.
|
||||
template<typename CONST> struct TypeOfTemplate {
|
||||
template<typename A>
|
||||
struct InnerPredicate { // A is a specific Type<CAT,KIND>
|
||||
template<typename CONST> struct TypeOfHelper {
|
||||
template<typename T> struct Predicate {
|
||||
static constexpr bool value() {
|
||||
return std::is_same_v<std::decay_t<CONST>,
|
||||
std::decay_t<typename A::Scalar>>;
|
||||
std::decay_t<typename T::Scalar>>;
|
||||
}
|
||||
};
|
||||
template<typename A>
|
||||
struct OuterPredicate { // A is a CategoryUnion<CAT, Type>
|
||||
static constexpr bool value() {
|
||||
return common::SearchVariantType<InnerPredicate, typename A::Variant> >=
|
||||
0;
|
||||
}
|
||||
};
|
||||
using BareTypes = IntrinsicTypeUnion<Type>;
|
||||
static constexpr int CatIndex{
|
||||
common::SearchVariantType<OuterPredicate, typename BareTypes::Variant>};
|
||||
static_assert(
|
||||
CatIndex >= 0 || !"no category found for type of scalar constant");
|
||||
static constexpr TypeCategory category{BareTypes::IndexToKind(CatIndex)};
|
||||
using CatType = BareTypes::template KindType<category>;
|
||||
static constexpr int KindIndex{
|
||||
common::SearchVariantType<InnerPredicate, typename CatType::Variant>};
|
||||
static_assert(KindIndex >= 0 || !"search over category failed when repeated");
|
||||
static constexpr int kind{CatType::IndexToKind(KindIndex)};
|
||||
using type = Type<category, kind>;
|
||||
static constexpr int index{
|
||||
common::SearchMembers<Predicate, AllIntrinsicTypes>};
|
||||
static_assert(index >= 0 || !"No intrinsic type found for constant type");
|
||||
using type = std::tuple_element_t<index, AllIntrinsicTypes>;
|
||||
};
|
||||
|
||||
template<typename CONST> using TypeOf = typename TypeOfTemplate<CONST>::type;
|
||||
template<typename CONST> using TypeOf = typename TypeOfHelper<CONST>::type;
|
||||
|
||||
// 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)
|
||||
// A variant union that can hold a scalar constant of some type in a set.
|
||||
template<typename TYPES> struct SomeScalar {
|
||||
using Types = TYPES;
|
||||
CLASS_BOILERPLATE(SomeScalar)
|
||||
|
||||
template<typename A> SomeKindScalar(const A &x) : u{x} {}
|
||||
template<typename A> SomeScalar(const A &x) : u{x} {}
|
||||
template<typename A>
|
||||
SomeKindScalar(std::enable_if_t<!std::is_reference_v<A>, A> &&x)
|
||||
SomeScalar(std::enable_if_t<!std::is_reference_v<A>, A> &&x)
|
||||
: u{std::move(x)} {}
|
||||
|
||||
std::optional<std::int64_t> ToInt64() const {
|
||||
if constexpr (category == TypeCategory::Integer) {
|
||||
return std::visit(
|
||||
[](const auto &x) { return std::make_optional(x.ToInt64()); }, u.u);
|
||||
}
|
||||
return std::nullopt;
|
||||
auto ToInt64() const {
|
||||
return std::visit(
|
||||
[](const auto &x) -> std::optional<std::int64_t> {
|
||||
if constexpr (TypeOf<decltype(x)>::category ==
|
||||
TypeCategory::Integer) {
|
||||
return {x.ToInt64()};
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
},
|
||||
u);
|
||||
}
|
||||
|
||||
std::optional<std::string> ToString() const {
|
||||
return common::GetIf<std::string>(u.u);
|
||||
auto ToString() const {
|
||||
return std::visit(
|
||||
[](const auto &x) -> std::optional<std::string> {
|
||||
if constexpr (std::is_same_v<std::string,
|
||||
std::decay_t<decltype(x)>>) {
|
||||
return {x};
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
},
|
||||
u);
|
||||
}
|
||||
|
||||
template<TypeCategory C, int K> using KindScalar = Scalar<Type<C, K>>;
|
||||
CategoryUnion<CAT, KindScalar> u;
|
||||
template<typename T> auto GetIf() const {
|
||||
return common::GetIf<Scalar<T>>(u);
|
||||
}
|
||||
|
||||
common::MapTemplate<Scalar, std::variant, Types> u;
|
||||
};
|
||||
|
||||
// Holds a scalar constant of any intrinsic category and size.
|
||||
struct GenericScalar {
|
||||
CLASS_BOILERPLATE(GenericScalar)
|
||||
|
||||
template<TypeCategory CAT, int KIND>
|
||||
GenericScalar(const Scalar<Type<CAT, KIND>> &x) : u{SomeKindScalar<CAT>{x}} {}
|
||||
template<TypeCategory CAT, int KIND>
|
||||
GenericScalar(Scalar<Type<CAT, KIND>> &&x)
|
||||
: u{SomeKindScalar<CAT>{std::move(x)}} {}
|
||||
|
||||
template<typename A> GenericScalar(const A &x) : u{x} {}
|
||||
template<typename A>
|
||||
GenericScalar(std::enable_if_t<!std::is_reference_v<A>, A> &&x)
|
||||
: u{std::move(x)} {}
|
||||
|
||||
std::optional<std::int64_t> ToInt64() const {
|
||||
if (const auto *j{std::get_if<SomeKindScalar<TypeCategory::Integer>>(&u)}) {
|
||||
return j->ToInt64();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::string> ToString() const {
|
||||
if (const auto *c{
|
||||
std::get_if<SomeKindScalar<TypeCategory::Character>>(&u)}) {
|
||||
return c->ToString();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::variant<SomeKindScalar<TypeCategory::Integer>,
|
||||
SomeKindScalar<TypeCategory::Real>, SomeKindScalar<TypeCategory::Complex>,
|
||||
SomeKindScalar<TypeCategory::Character>,
|
||||
SomeKindScalar<TypeCategory::Logical>>
|
||||
u;
|
||||
};
|
||||
template<TypeCategory CAT>
|
||||
using SomeKindScalar = SomeScalar<CategoryTypes<CAT>>;
|
||||
using GenericScalar = SomeScalar<AllIntrinsicTypes>;
|
||||
|
||||
// Represents a type of any supported kind within a particular category.
|
||||
template<TypeCategory CAT> struct SomeKind {
|
||||
|
@ -304,7 +303,7 @@ using SomeComplex = SomeKind<TypeCategory::Complex>;
|
|||
using SomeCharacter = SomeKind<TypeCategory::Character>;
|
||||
using SomeLogical = SomeKind<TypeCategory::Logical>;
|
||||
|
||||
// Represents a completely generic type.
|
||||
// Represents a completely generic intrinsic type.
|
||||
struct SomeType {
|
||||
using Scalar = GenericScalar;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue