12#ifndef FORTRAN_EVALUATE_SHAPE_H_
13#define FORTRAN_EVALUATE_SHAPE_H_
15#include "expression.h"
18#include "flang/Evaluate/type.h"
29using ExtentType = SubscriptInteger;
31using MaybeExtentExpr = std::optional<ExtentExpr>;
32using Shape = std::vector<MaybeExtentExpr>;
34inline constexpr int ExtentIntKind = Fortran::evaluate::SubscriptIntegerKind;
38 ExtentIntKind, Scalar<ExtentType>{ExtentIntKind, v}};
43 ExtentIntKind, Scalar<ExtentType>{ExtentIntKind, v}};
46inline ExtentExpr MakeExtentExpr(int64_t v) {
47 return ExtentExpr{MakeExtentConstant(v)};
51 return ExtentExpr{MakeExtentConstant(v)};
54bool IsImpliedShape(
const Symbol &);
55bool IsExplicitShape(
const Symbol &);
58std::optional<ExtentExpr> AsExtentArrayExpr(
const Shape &);
60std::optional<Constant<ExtentType>> AsConstantShape(
67std::optional<ConstantSubscripts> AsConstantExtents(
69inline std::optional<ConstantSubscripts> AsConstantExtents(
70 FoldingContext &foldingContext,
const std::optional<Shape> &maybeShape) {
72 return AsConstantExtents(foldingContext, *maybeShape);
77Shape AsShape(
const ConstantSubscripts &);
78std::optional<Shape> AsShape(
const std::optional<ConstantSubscripts> &);
80inline int GetRank(
const Shape &s) {
return static_cast<int>(s.size()); }
83std::optional<Shape> Fold(
FoldingContext &, std::optional<Shape> &&);
89std::optional<Shape> GetShape(
92std::optional<Shape> GetShape(
95std::optional<Shape> GetShape(
const A &,
bool invariantOnly =
true);
107ExtentExpr GetRawLowerBound(
108 const NamedEntity &,
int dimension,
bool invariantOnly =
true);
110 int dimension,
bool invariantOnly =
true);
111MaybeExtentExpr GetLBOUND(
112 const NamedEntity &,
int dimension,
bool invariantOnly =
true);
114 bool invariantOnly =
true);
115MaybeExtentExpr GetRawUpperBound(
116 const NamedEntity &,
int dimension,
bool invariantOnly =
true);
118 int dimension,
bool invariantOnly =
true);
119MaybeExtentExpr GetUBOUND(
120 const NamedEntity &,
int dimension,
bool invariantOnly =
true);
122 bool invariantOnly =
true);
123MaybeExtentExpr ComputeUpperBound(ExtentExpr &&lower, MaybeExtentExpr &&extent);
124MaybeExtentExpr ComputeUpperBound(
126Shape GetRawLowerBounds(
const NamedEntity &,
bool invariantOnly =
true);
127Shape GetRawLowerBounds(
129Shape GetLBOUNDs(
const NamedEntity &,
bool invariantOnly =
true);
132Shape GetUBOUNDs(
const NamedEntity &,
bool invariantOnly =
true);
135MaybeExtentExpr GetExtent(
136 const NamedEntity &,
int dimension,
bool invariantOnly =
true);
138 bool invariantOnly =
true);
140 bool invariantOnly =
true);
142 const NamedEntity &,
int dimension,
bool invariantOnly =
true);
145MaybeExtentExpr GetLCOBOUND(
146 const Symbol &,
int dimension,
bool invariantOnly =
true);
147MaybeExtentExpr GetUCOBOUND(
148 const Symbol &,
int dimension,
bool invariantOnly =
true);
149Shape GetLCOBOUNDs(
const Symbol &,
bool invariantOnly =
true);
150Shape GetUCOBOUNDs(
const Symbol &,
bool invariantOnly =
true);
153ExtentExpr CountTrips(
154 ExtentExpr &&lower, ExtentExpr &&upper, ExtentExpr &&stride);
155ExtentExpr CountTrips(
156 const ExtentExpr &lower,
const ExtentExpr &upper,
const ExtentExpr &stride);
157MaybeExtentExpr CountTrips(
158 MaybeExtentExpr &&lower, MaybeExtentExpr &&upper, MaybeExtentExpr &&stride);
161MaybeExtentExpr GetSize(Shape &&);
162ConstantSubscript GetSize(
const ConstantSubscripts &);
163inline MaybeExtentExpr GetSize(
const std::optional<Shape> &maybeShape) {
165 return GetSize(Shape(*maybeShape));
171bool ContainsAnyImpliedDoIndex(
const ExtentExpr &);
177template <
typename T>
bool ContainsUntaggedRankOneBoundElement(
const Expr<T> &);
178extern template bool ContainsUntaggedRankOneBoundElement(
180extern template bool ContainsUntaggedRankOneBoundElement(
182extern template bool ContainsUntaggedRankOneBoundElement(
188 :
public AnyTraverse<GetShapeHelper, std::optional<Shape>> {
190 using Result = std::optional<Shape>;
191 using Base = AnyTraverse<GetShapeHelper, Result>;
192 using Base::operator();
194 : Base{*
this}, context_{context}, invariantOnly_{invariantOnly} {}
196 Result operator()(
const ImpliedDoIndex &)
const {
return ScalarShape(); }
200 Result operator()(
const BOZLiteralConstant &)
const {
return ScalarShape(); }
201 Result operator()(
const StaticDataObject::Pointer &)
const {
202 return ScalarShape();
205 return ScalarShape();
208 template <
typename T> Result operator()(
const Constant<T> &c)
const {
209 return ConstantShape(c.SHAPE());
212 Result operator()(
const Symbol &)
const;
213 Result operator()(
const Component &)
const;
214 Result operator()(
const ArrayRef &)
const;
216 Result operator()(
const Substring &)
const;
220 template <
typename T>
222 return Shape{GetArrayConstructorExtent(aconst)};
224 template <
typename T>
228 int rank{conditional.thenValue().Rank()};
229 Result thenShape{(*this)(conditional.thenValue())};
231 return Shape(rank, std::nullopt);
233 Result elseShape{(*this)(conditional.elseValue())};
234 if (thenShape != elseShape) {
235 return Shape(rank, std::nullopt);
239 template <
typename D,
typename R,
typename LO,
typename RO>
241 if (
int rr{operation.right().Rank()}; rr > 0) {
242 if (
int lr{operation.left().Rank()}; lr == 0 || lr == rr) {
243 return (*
this)(operation.right());
248 return (*
this)(operation.left());
253 static Result ScalarShape() {
return Shape{}; }
255 Result AsShapeResult(ExtentExpr &&)
const;
258 template <
typename T>
259 MaybeExtentExpr GetArrayConstructorValueExtent(
261 return common::visit(
263 [&](
const Expr<T> &x) -> MaybeExtentExpr {
264 if (
auto xShape{(*this)(x)}) {
266 return GetSize(std::move(*xShape));
274 if (!ContainsAnyImpliedDoIndex(ido.lower()) &&
275 !ContainsAnyImpliedDoIndex(ido.upper()) &&
276 !ContainsAnyImpliedDoIndex(ido.stride())) {
277 if (
auto nValues{GetArrayConstructorExtent(ido.values())}) {
278 if (!ContainsAnyImpliedDoIndex(*nValues)) {
279 return std::move(*nValues) *
280 CountTrips(ido.lower(), ido.upper(), ido.stride());
290 template <
typename T>
291 MaybeExtentExpr GetArrayConstructorExtent(
293 ExtentExpr result{MakeExtentConstant(0)};
294 for (
const auto &value : values) {
295 if (MaybeExtentExpr n{GetArrayConstructorValueExtent(value)}) {
296 AccumulateExtent(result, std::move(*n));
305 void AccumulateExtent(ExtentExpr &, ExtentExpr &&)
const;
308 mutable bool useResultSymbolShape_{
true};
311 bool invariantOnly_{
true};
315std::optional<Shape> GetShape(
319 return Fold(*context, std::move(shape));
329std::optional<Shape> GetShape(
331 return GetShape(&context, x, invariantOnly);
335std::optional<Shape> GetShape(
const A &x,
bool invariantOnly) {
336 return GetShape(
nullptr, x, invariantOnly);
340std::optional<Constant<ExtentType>> GetConstantShape(
342 if (
auto shape{GetShape(context, x,
true)}) {
343 return AsConstantShape(context, *shape);
351std::optional<ConstantSubscripts> GetConstantExtents(
353 if (
auto shape{GetShape(context, x,
true)}) {
354 if (
auto extents{AsConstantExtents(context, *shape)}) {
355 if (!HasNegativeExtent(*extents)) {
368std::optional<Shape> GetContextFreeShape(
FoldingContext &context,
const A &x) {
384 LeftScalarExpandable = 1,
385 RightScalarExpandable = 2,
386 LeftIsDeferredShape = 4,
387 RightIsDeferredShape = 8,
388 EitherScalarExpandable = LeftScalarExpandable | RightScalarExpandable,
389 BothDeferredShape = LeftIsDeferredShape | RightIsDeferredShape,
390 RightIsExpandableDeferred = RightScalarExpandable | RightIsDeferredShape,
394 const Shape &left,
const Shape &right,
395 CheckConformanceFlags::Flags flags = CheckConformanceFlags::None,
396 const char *leftIs =
"left operand",
const char *rightIs =
"right operand");
402bool IncrementSubscripts(
403 ConstantSubscripts &,
const ConstantSubscripts &extents);
Definition expression.h:509
Definition expression.h:537
Definition variable.h:210
Definition variable.h:248
Definition expression.h:412
Definition constant.h:191
Definition variable.h:450
Definition expression.h:475
Definition variable.h:101
Definition expression.h:114
Definition variable.h:484
Definition expression.h:849
Definition variable.h:309
Definition variable.h:136
Definition integer-value.h:35
Definition check-expression.h:19
Definition expression.h:503
Definition expression.h:461
Definition variable.h:196