[flang] Make all Expr<> instances derived from ExpressionBase

Original-commit: flang-compiler/f18@f7d1a21532
Reviewed-on: https://github.com/flang-compiler/f18/pull/225
Tree-same-pre-rewrite: false
This commit is contained in:
peter klausler 2018-10-30 12:44:09 -07:00
parent 03618fd5e3
commit 59c1233036
6 changed files with 39 additions and 71 deletions

View File

@ -110,11 +110,6 @@ std::ostream &ExpressionBase<RESULT>::Dump(std::ostream &o) const {
return o;
}
std::ostream &Expr<SomeDerived>::Dump(std::ostream &o) const {
std::visit([&](const auto &x) { x.Dump(o); }, u);
return o;
}
template<int KIND>
Expr<SubscriptInteger> Expr<Type<TypeCategory::Character, KIND>>::LEN() const {
return std::visit(
@ -154,10 +149,6 @@ std::optional<DynamicType> ExpressionBase<A>::GetType() const {
}
}
std::optional<DynamicType> Expr<SomeDerived>::GetType() const {
return std::visit([](const auto &x) { return x.GetType(); }, u);
}
template<typename A> int ExpressionBase<A>::Rank() const {
return std::visit(
[](const auto &x) {
@ -171,10 +162,6 @@ template<typename A> int ExpressionBase<A>::Rank() const {
derived().u);
}
int Expr<SomeDerived>::Rank() const {
return std::visit([](const auto &x) { return x.Rank(); }, u);
}
// Template instantiations to resolve the "extern template" declarations
// that appear in expression.h.
@ -184,8 +171,7 @@ FOR_EACH_INTEGER_KIND(template struct Relational)
FOR_EACH_REAL_KIND(template struct Relational)
FOR_EACH_CHARACTER_KIND(template struct Relational)
template struct Relational<SomeType>;
FOR_EACH_INTRINSIC_KIND(template struct ExpressionBase)
FOR_EACH_CATEGORY_TYPE(template struct ExpressionBase)
FOR_EACH_TYPE_AND_KIND(template class ExpressionBase)
}
// For reclamation of analyzed expressions to which owning pointers have

View File

@ -54,18 +54,42 @@ using common::RelationalOperator;
// - Expr<SomeType> is a union of Expr<SomeKind<CATEGORY>> over the five
// intrinsic type categories of Fortran. It represents any valid expression.
//
// Every Expr specialization supports at least these interfaces:
// using Result = ...; // type of a result of this expression
// DynamicType GetType() const;
// int Rank() const;
// std::ostream &Dump(std::ostream &) const;
// Everything that can appear in, or as, a valid Fortran expression must be
// represented with an instance of some class containing a Result typedef that
// maps to some instantiation of Type<CATEGORY, KIND>, SomeKind<CATEGORY>,
// or SomeType.
template<typename A> using ResultType = typename std::decay_t<A>::Result;
// Common Expr<> behaviors: every Expr<T> derives from ExpressionBase<T>.
template<typename RESULT> class ExpressionBase {
public:
using Result = RESULT;
private:
using Derived = Expr<Result>;
Derived &derived() { return *static_cast<Derived *>(this); }
const Derived &derived() const { return *static_cast<const Derived *>(this); }
public:
template<typename A> Derived &operator=(const A &x) {
Derived &d{derived()};
d.u = x;
return d;
}
template<typename A>
Derived &operator=(std::enable_if_t<!std::is_reference_v<A>, A> &&x) {
Derived &d{derived()};
d.u = std::move(x);
return d;
}
std::optional<DynamicType> GetType() const;
int Rank() const;
std::ostream &Dump(std::ostream &) const;
static Derived Rewrite(FoldingContext &, Derived &&);
};
// BOZ literal "typeless" constants must be wide enough to hold a numeric
// value of any supported kind of INTEGER or REAL. They must also be
// distinguishable from other integer constants, since they are permitted
@ -356,32 +380,6 @@ struct LogicalOperation
// Per-category expression representations
// Common Expr<> behaviors
template<typename RESULT> struct ExpressionBase {
using Result = RESULT;
using Derived = Expr<Result>;
Derived &derived() { return *static_cast<Derived *>(this); }
const Derived &derived() const { return *static_cast<const Derived *>(this); }
template<typename A> Derived &operator=(const A &x) {
Derived &d{derived()};
d.u = x;
return d;
}
template<typename A>
Derived &operator=(std::enable_if_t<!std::is_reference_v<A>, A> &&x) {
Derived &d{derived()};
d.u = std::move(x);
return d;
}
std::optional<DynamicType> GetType() const;
int Rank() const;
std::ostream &Dump(std::ostream &) const;
};
template<int KIND>
class Expr<Type<TypeCategory::Integer, KIND>>
: public ExpressionBase<Type<TypeCategory::Integer, KIND>> {
@ -564,18 +562,11 @@ public:
common::MapTemplate<Expr, CategoryTypes<CAT>> u;
};
// Note that Expr<SomeDerived> does not inherit from ExpressionBase
// since Constant<SomeDerived> and Scalar<SomeDerived> are not defined
// for derived types.
template<> class Expr<SomeDerived> {
// An expression whose result has a derived type.
template<> class Expr<SomeDerived> : public ExpressionBase<SomeDerived> {
public:
using Result = SomeDerived;
EVALUATE_UNION_CLASS_BOILERPLATE(Expr)
std::optional<DynamicType> GetType() const;
int Rank() const;
std::ostream &Dump(std::ostream &) const;
std::variant<Designator<Result>, FunctionRef<Result>> u;
};
@ -627,6 +618,6 @@ struct GenericExprWrapper {
};
FOR_EACH_CATEGORY_TYPE(extern template class Expr)
FOR_EACH_TYPE_AND_KIND(extern template struct ExpressionBase)
FOR_EACH_TYPE_AND_KIND(extern template class ExpressionBase)
}
#endif // FORTRAN_EVALUATE_EXPRESSION_H_

View File

@ -422,7 +422,7 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldOperation(
// end per-operation folding functions
template<typename T>
Expr<T> FoldHelper<T>::FoldExpr(FoldingContext &context, Expr<T> &&expr) {
Expr<T> ExpressionBase<T>::Rewrite(FoldingContext &context, Expr<T> &&expr) {
return std::visit(
[&](auto &&x) -> Expr<T> {
if constexpr (T::isSpecificIntrinsicType) {
@ -439,7 +439,7 @@ Expr<T> FoldHelper<T>::FoldExpr(FoldingContext &context, Expr<T> &&expr) {
std::move(expr.u));
}
FOR_EACH_TYPE_AND_KIND(template struct FoldHelper)
FOR_EACH_TYPE_AND_KIND(template class ExpressionBase)
template<typename T>
std::optional<Constant<T>>

View File

@ -29,14 +29,9 @@ using namespace Fortran::parser::literals;
// Fold() rewrites an expression and returns it. When the rewritten expression
// is a constant, GetScalarConstantValue() below will be able to extract it.
// Note the rvalue reference argument: the rewrites are performed in place
// for efficiency. The implementation is wrapped in a helper template class so
// that all the per-type template instantiations can be made once in fold.cc.
template<typename T> struct FoldHelper {
static Expr<T> FoldExpr(FoldingContext &, Expr<T> &&);
};
// for efficiency.
template<typename T> Expr<T> Fold(FoldingContext &context, Expr<T> &&expr) {
return FoldHelper<T>::FoldExpr(context, std::move(expr));
return Expr<T>::Rewrite(context, std::move(expr));
}
template<typename T>
@ -49,8 +44,6 @@ std::optional<Expr<T>> Fold(
}
}
FOR_EACH_TYPE_AND_KIND(extern template struct FoldHelper)
// GetScalarConstantValue() extracts the constant value of an expression,
// when it has one, even if it is parenthesized or optional.
template<typename T> struct GetScalarConstantValueHelper {

View File

@ -127,8 +127,6 @@ std::optional<std::int64_t> ToInt64(const std::optional<A> &x) {
}
}
// TODO: GetSymbol and Rank and GetType here, too
// Generalizing packagers: these take operations and expressions of more
// specific types and wrap them in Expr<> containers of more abstract types.

View File

@ -239,7 +239,7 @@ template<TypeCategory CATEGORY> struct SomeKind {
template<> class SomeKind<TypeCategory::Derived> {
public:
static constexpr bool isSpecificIntrinsicType{true};
static constexpr bool isSpecificIntrinsicType{false};
static constexpr TypeCategory category{TypeCategory::Derived};
CLASS_BOILERPLATE(SomeKind)