Expr<SomeType> v;
};
-// When an Expr holds something that is a Variable (i.e., a Designator
-// or pointer-valued FunctionRef), return a copy of its contents in
-// a Variable.
-template<typename A>
-std::optional<Variable<A>> AsVariable(const Expr<A> &expr) {
- using Variant = decltype(Variable<A>::u);
- return std::visit(
- [](const auto &x) -> std::optional<Variable<A>> {
- if constexpr (common::HasMember<std::decay_t<decltype(x)>, Variant>) {
- return std::make_optional<Variable<A>>(x);
- }
- return std::nullopt;
- },
- expr.u);
-}
-
-// Predicate: true when an expression is a variable reference
-template<typename A> bool IsVariable(const Expr<A> &expr) {
- return AsVariable(expr).has_value();
-}
-
-template<TypeCategory CATEGORY>
-bool IsVariable(const Expr<SomeKind<CATEGORY>> &expr) {
- return std::visit([](const auto &x) { return IsVariable(x); }, expr.u);
-}
-
-template<> inline bool IsVariable(const Expr<SomeDerived> &) { return true; }
-
-template<> inline bool IsVariable(const Expr<SomeType> &expr) {
- return std::visit(
- [](const auto &x) {
- if constexpr (!std::is_same_v<BOZLiteralConstant,
- std::decay_t<decltype(x)>>) {
- return IsVariable(x);
- }
- return false;
- },
- expr.u);
-}
-
FOR_EACH_CATEGORY_TYPE(extern template class Expr)
FOR_EACH_TYPE_AND_KIND(extern template struct ExpressionBase)
}
namespace Fortran::evaluate {
+// Some expression predicates and extractors.
+
+// When an Expr holds something that is a Variable (i.e., a Designator
+// or pointer-valued FunctionRef), return a copy of its contents in
+// a Variable.
+template<typename A>
+std::optional<Variable<A>> AsVariable(const Expr<A> &expr) {
+ using Variant = decltype(Variable<A>::u);
+ return std::visit(
+ [](const auto &x) -> std::optional<Variable<A>> {
+ if constexpr (common::HasMember<std::decay_t<decltype(x)>, Variant>) {
+ return std::make_optional<Variable<A>>(x);
+ }
+ return std::nullopt;
+ },
+ expr.u);
+}
+
+// Predicate: true when an expression is a variable reference
+template<typename A> bool IsVariable(const A &) { return false; }
+template<typename A> bool IsVariable(const Designator<A> &) { return true; }
+template<typename A> bool IsVariable(const FunctionRef<A> &) { return true; }
+template<typename A> bool IsVariable(const Expr<A> &expr) {
+ return std::visit([](const auto &x) { return IsVariable(x); }, expr.u);
+}
+
+// Predicate: true when an expression is a constant value
+template<typename A> bool IsConstant(const A &) { return false; }
+template<typename A> bool IsConstant(const Constant<A> &) { return true; }
+template<typename A> bool IsConstant(const Expr<A> &expr) {
+ return std::visit([](const auto &x) { return IsConstant(x); }, expr.u);
+}
+
// Generalizing packagers: these take operations and expressions of more
// specific types and wrap them in Expr<> containers of more abstract types.
FOR_EACH_SPECIFIC_TYPE(PREFIX) \
FOR_EACH_CATEGORY_TYPE(PREFIX)
-// Wraps a constant value in a class with its resolved type.
+// Wraps a constant scalar value of a specific intrinsic type
+// in a class with its resolved type.
+// N.B. Array constants are represented as array constructors
+// and derived type constants are structure constructors; generic
+// constants are generic expressions wrapping these constants.
template<typename T> struct Constant {
+ // TODO: static_assert(T::isSpecificIntrinsicType);
using Result = T;
using Value = Scalar<Result>;
CLASS_BOILERPLATE(Constant)
return value.GetType();
}
}
- int Rank() const { return 0; } // TODO: array constants
+ int Rank() const { return 0; }
std::ostream &Dump(std::ostream &) const;
Value value;
};