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>;
34bool IsImpliedShape(
const Symbol &);
35bool IsExplicitShape(
const Symbol &);
38std::optional<ExtentExpr> AsExtentArrayExpr(
const Shape &);
40std::optional<Constant<ExtentType>> AsConstantShape(
47std::optional<ConstantSubscripts> AsConstantExtents(
49inline std::optional<ConstantSubscripts> AsConstantExtents(
50 FoldingContext &foldingContext,
const std::optional<Shape> &maybeShape) {
52 return AsConstantExtents(foldingContext, *maybeShape);
57Shape AsShape(
const ConstantSubscripts &);
58std::optional<Shape> AsShape(
const std::optional<ConstantSubscripts> &);
60inline int GetRank(
const Shape &s) {
return static_cast<int>(s.size()); }
63std::optional<Shape> Fold(
FoldingContext &, std::optional<Shape> &&);
69std::optional<Shape> GetShape(
72std::optional<Shape> GetShape(
75std::optional<Shape> GetShape(
const A &,
bool invariantOnly =
true);
87ExtentExpr GetRawLowerBound(
88 const NamedEntity &,
int dimension,
bool invariantOnly =
true);
90 int dimension,
bool invariantOnly =
true);
91MaybeExtentExpr GetLBOUND(
92 const NamedEntity &,
int dimension,
bool invariantOnly =
true);
94 bool invariantOnly =
true);
95MaybeExtentExpr GetRawUpperBound(
96 const NamedEntity &,
int dimension,
bool invariantOnly =
true);
98 int dimension,
bool invariantOnly =
true);
99MaybeExtentExpr GetUBOUND(
100 const NamedEntity &,
int dimension,
bool invariantOnly =
true);
102 bool invariantOnly =
true);
103MaybeExtentExpr ComputeUpperBound(ExtentExpr &&lower, MaybeExtentExpr &&extent);
104MaybeExtentExpr ComputeUpperBound(
106Shape GetRawLowerBounds(
const NamedEntity &,
bool invariantOnly =
true);
107Shape GetRawLowerBounds(
109Shape GetLBOUNDs(
const NamedEntity &,
bool invariantOnly =
true);
112Shape GetUBOUNDs(
const NamedEntity &,
bool invariantOnly =
true);
115MaybeExtentExpr GetExtent(
116 const NamedEntity &,
int dimension,
bool invariantOnly =
true);
118 bool invariantOnly =
true);
120 bool invariantOnly =
true);
122 const NamedEntity &,
int dimension,
bool invariantOnly =
true);
125MaybeExtentExpr GetLCOBOUND(
126 const Symbol &,
int dimension,
bool invariantOnly =
true);
127MaybeExtentExpr GetUCOBOUND(
128 const Symbol &,
int dimension,
bool invariantOnly =
true);
129Shape GetLCOBOUNDs(
const Symbol &,
bool invariantOnly =
true);
130Shape GetUCOBOUNDs(
const Symbol &,
bool invariantOnly =
true);
133ExtentExpr CountTrips(
134 ExtentExpr &&lower, ExtentExpr &&upper, ExtentExpr &&stride);
135ExtentExpr CountTrips(
136 const ExtentExpr &lower,
const ExtentExpr &upper,
const ExtentExpr &stride);
137MaybeExtentExpr CountTrips(
138 MaybeExtentExpr &&lower, MaybeExtentExpr &&upper, MaybeExtentExpr &&stride);
141MaybeExtentExpr GetSize(Shape &&);
142ConstantSubscript GetSize(
const ConstantSubscripts &);
143inline MaybeExtentExpr GetSize(
const std::optional<Shape> &maybeShape) {
145 return GetSize(Shape(*maybeShape));
151bool ContainsAnyImpliedDoIndex(
const ExtentExpr &);
156 :
public AnyTraverse<GetShapeHelper, std::optional<Shape>> {
158 using Result = std::optional<Shape>;
159 using Base = AnyTraverse<GetShapeHelper, Result>;
160 using Base::operator();
162 : Base{*
this}, context_{context}, invariantOnly_{invariantOnly} {}
164 Result operator()(
const ImpliedDoIndex &)
const {
return ScalarShape(); }
167 Result operator()(
const BOZLiteralConstant &)
const {
return ScalarShape(); }
168 Result operator()(
const StaticDataObject::Pointer &)
const {
169 return ScalarShape();
172 return ScalarShape();
175 template <
typename T> Result operator()(
const Constant<T> &c)
const {
176 return ConstantShape(c.SHAPE());
179 Result operator()(
const Symbol &)
const;
180 Result operator()(
const Component &)
const;
181 Result operator()(
const ArrayRef &)
const;
183 Result operator()(
const Substring &)
const;
187 template <
typename T>
189 return Shape{GetArrayConstructorExtent(aconst)};
191 template <
typename T>
195 int rank{conditional.thenValue().Rank()};
196 Result thenShape{(*this)(conditional.thenValue())};
198 return Shape(rank, std::nullopt);
200 Result elseShape{(*this)(conditional.elseValue())};
201 if (thenShape != elseShape) {
202 return Shape(rank, std::nullopt);
206 template <
typename D,
typename R,
typename LO,
typename RO>
208 if (
int rr{operation.right().Rank()}; rr > 0) {
209 if (
int lr{operation.left().Rank()}; lr == 0 || lr == rr) {
210 return (*
this)(operation.right());
215 return (*
this)(operation.left());
220 static Result ScalarShape() {
return Shape{}; }
222 Result AsShapeResult(ExtentExpr &&)
const;
225 template <
typename T>
226 MaybeExtentExpr GetArrayConstructorValueExtent(
228 return common::visit(
230 [&](
const Expr<T> &x) -> MaybeExtentExpr {
231 if (
auto xShape{(*this)(x)}) {
233 return GetSize(std::move(*xShape));
241 if (!ContainsAnyImpliedDoIndex(ido.lower()) &&
242 !ContainsAnyImpliedDoIndex(ido.upper()) &&
243 !ContainsAnyImpliedDoIndex(ido.stride())) {
244 if (
auto nValues{GetArrayConstructorExtent(ido.values())}) {
245 if (!ContainsAnyImpliedDoIndex(*nValues)) {
246 return std::move(*nValues) *
247 CountTrips(ido.lower(), ido.upper(), ido.stride());
257 template <
typename T>
258 MaybeExtentExpr GetArrayConstructorExtent(
260 ExtentExpr result{0};
261 for (
const auto &value : values) {
262 if (MaybeExtentExpr n{GetArrayConstructorValueExtent(value)}) {
263 AccumulateExtent(result, std::move(*n));
272 void AccumulateExtent(ExtentExpr &, ExtentExpr &&)
const;
275 mutable bool useResultSymbolShape_{
true};
278 bool invariantOnly_{
true};
282std::optional<Shape> GetShape(
286 return Fold(*context, std::move(shape));
296std::optional<Shape> GetShape(
298 return GetShape(&context, x, invariantOnly);
302std::optional<Shape> GetShape(
const A &x,
bool invariantOnly) {
303 return GetShape(
nullptr, x, invariantOnly);
307std::optional<Constant<ExtentType>> GetConstantShape(
309 if (
auto shape{GetShape(context, x,
true)}) {
310 return AsConstantShape(context, *shape);
318std::optional<ConstantSubscripts> GetConstantExtents(
320 if (
auto shape{GetShape(context, x,
true)}) {
321 if (
auto extents{AsConstantExtents(context, *shape)}) {
322 if (!HasNegativeExtent(*extents)) {
335std::optional<Shape> GetContextFreeShape(
FoldingContext &context,
const A &x) {
351 LeftScalarExpandable = 1,
352 RightScalarExpandable = 2,
353 LeftIsDeferredShape = 4,
354 RightIsDeferredShape = 8,
355 EitherScalarExpandable = LeftScalarExpandable | RightScalarExpandable,
356 BothDeferredShape = LeftIsDeferredShape | RightIsDeferredShape,
357 RightIsExpandableDeferred = RightScalarExpandable | RightIsDeferredShape,
361 const Shape &left,
const Shape &right,
362 CheckConformanceFlags::Flags flags = CheckConformanceFlags::None,
363 const char *leftIs =
"left operand",
const char *rightIs =
"right operand");
369bool IncrementSubscripts(
370 ConstantSubscripts &,
const ConstantSubscripts &extents);
Definition expression.h:478
Definition expression.h:506
Definition variable.h:205
Definition variable.h:243
Definition expression.h:394
Definition constant.h:147
Definition variable.h:413
Definition expression.h:444
Definition variable.h:101
Definition expression.h:113
Definition expression.h:781
Definition variable.h:304
Definition variable.h:136
Definition check-expression.h:19
Definition expression.h:472
Definition expression.h:436
Definition variable.h:191