|
12 | 12 |
|
13 | 13 | namespace Fortran::evaluate {
|
14 | 14 |
|
| 15 | +// Given a collection of ConstantSubscripts values, package them as a Constant. |
| 16 | +// Return scalar value if asScalar == true and shape-dim array otherwise. |
| 17 | +template <typename T> |
| 18 | +Expr<T> PackageConstantBounds( |
| 19 | + const ConstantSubscripts &&bounds, bool asScalar = false) { |
| 20 | + if (asScalar) { |
| 21 | + return Expr<T>{Constant<T>{bounds.at(0)}}; |
| 22 | + } else { |
| 23 | + // As rank-dim array |
| 24 | + const int rank{GetRank(bounds)}; |
| 25 | + std::vector<Scalar<T>> packed(rank); |
| 26 | + std::transform(bounds.begin(), bounds.end(), packed.begin(), |
| 27 | + [](ConstantSubscript x) { return Scalar<T>(x); }); |
| 28 | + return Expr<T>{Constant<T>{std::move(packed), ConstantSubscripts{rank}}}; |
| 29 | + } |
| 30 | +} |
| 31 | + |
15 | 32 | // Class to retrieve the constant lower bound of an expression which is an
|
16 | 33 | // array that devolves to a type of Constant<T>
|
17 | 34 | class GetConstantArrayLboundHelper {
|
18 | 35 | public:
|
19 |
| - GetConstantArrayLboundHelper(ConstantSubscript dim) : dim_{dim} {} |
| 36 | + GetConstantArrayLboundHelper(std::optional<ConstantSubscript> dim) |
| 37 | + : dim_{dim} {} |
20 | 38 |
|
21 |
| - template <typename T> ConstantSubscript GetLbound(const T &) { |
| 39 | + template <typename T> ConstantSubscripts GetLbound(const T &) { |
22 | 40 | // The method is needed for template expansion, but we should never get
|
23 | 41 | // here in practice.
|
24 | 42 | CHECK(false);
|
25 |
| - return 0; |
| 43 | + return {0}; |
26 | 44 | }
|
27 | 45 |
|
28 |
| - template <typename T> ConstantSubscript GetLbound(const Constant<T> &x) { |
| 46 | + template <typename T> ConstantSubscripts GetLbound(const Constant<T> &x) { |
29 | 47 | // Return the lower bound
|
30 |
| - return x.lbounds()[dim_]; |
| 48 | + if (dim_) { |
| 49 | + return {x.lbounds().at(*dim_)}; |
| 50 | + } else { |
| 51 | + return x.lbounds(); |
| 52 | + } |
31 | 53 | }
|
32 | 54 |
|
33 |
| - template <typename T> ConstantSubscript GetLbound(const Parentheses<T> &x) { |
| 55 | + template <typename T> ConstantSubscripts GetLbound(const Parentheses<T> &x) { |
34 | 56 | // Strip off the parentheses
|
35 | 57 | return GetLbound(x.left());
|
36 | 58 | }
|
37 | 59 |
|
38 |
| - template <typename T> ConstantSubscript GetLbound(const Expr<T> &x) { |
| 60 | + template <typename T> ConstantSubscripts GetLbound(const Expr<T> &x) { |
39 | 61 | // recurse through Expr<T>'a until we hit a constant
|
40 | 62 | return common::visit([&](const auto &inner) { return GetLbound(inner); },
|
41 | 63 | // [&](const auto &) { return 0; },
|
42 | 64 | x.u);
|
43 | 65 | }
|
44 | 66 |
|
45 | 67 | private:
|
46 |
| - ConstantSubscript dim_; |
| 68 | + std::optional<ConstantSubscript> dim_; |
47 | 69 | };
|
48 | 70 |
|
49 | 71 | template <int KIND>
|
@@ -89,16 +111,13 @@ Expr<Type<TypeCategory::Integer, KIND>> LBOUND(FoldingContext &context,
|
89 | 111 | }
|
90 | 112 | }
|
91 | 113 | if (IsActuallyConstant(*array)) {
|
92 |
| - return Expr<T>{GetConstantArrayLboundHelper{*dim}.GetLbound(*array)}; |
| 114 | + const ConstantSubscripts bounds{ |
| 115 | + GetConstantArrayLboundHelper{dim}.GetLbound(*array)}; |
| 116 | + return PackageConstantBounds<T>(std::move(bounds), dim.has_value()); |
93 | 117 | }
|
94 | 118 | if (lowerBoundsAreOne) {
|
95 |
| - if (dim) { |
96 |
| - return Expr<T>{1}; |
97 |
| - } else { |
98 |
| - std::vector<Scalar<T>> ones(rank, Scalar<T>{1}); |
99 |
| - return Expr<T>{ |
100 |
| - Constant<T>{std::move(ones), ConstantSubscripts{rank}}}; |
101 |
| - } |
| 119 | + ConstantSubscripts ones(rank, ConstantSubscript{1}); |
| 120 | + return PackageConstantBounds<T>(std::move(ones), dim.has_value()); |
102 | 121 | }
|
103 | 122 | }
|
104 | 123 | }
|
|
0 commit comments