FLANG
fold.h
1//===-- include/flang/Evaluate/fold.h ---------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef FORTRAN_EVALUATE_FOLD_H_
10#define FORTRAN_EVALUATE_FOLD_H_
11
12// Implements expression tree rewriting, particularly constant expression
13// and designator reference evaluation.
14
15#include "common.h"
16#include "constant.h"
17#include "expression.h"
18#include "tools.h"
19#include "type.h"
20
21namespace Fortran::evaluate::characteristics {
22class TypeAndShape;
23}
24
25namespace Fortran::evaluate {
26
27using namespace Fortran::parser::literals;
28
29// Fold() rewrites an expression and returns it. When the rewritten expression
30// is a constant, UnwrapConstantValue() and GetScalarConstantValue() below will
31// be able to extract it.
32// Note the rvalue reference argument: the rewrites are performed in place
33// for efficiency.
34template <typename T> Expr<T> Fold(FoldingContext &context, Expr<T> &&expr) {
35 return Expr<T>::Rewrite(context, std::move(expr));
36}
37
40
41template <typename A>
42std::optional<A> Fold(FoldingContext &context, std::optional<A> &&x) {
43 if (x) {
44 return Fold(context, std::move(*x));
45 } else {
46 return std::nullopt;
47 }
48}
49
50// UnwrapConstantValue() isolates the known constant value of
51// an expression, if it has one. It returns a pointer, which is
52// const-qualified when the expression is so. The value can be
53// parenthesized.
54template <typename T, typename EXPR>
55auto UnwrapConstantValue(EXPR &expr) -> common::Constify<Constant<T>, EXPR> * {
56 if (auto *c{UnwrapExpr<Constant<T>>(expr)}) {
57 return c;
58 } else {
59 if (auto *parens{UnwrapExpr<Parentheses<T>>(expr)}) {
60 return UnwrapConstantValue<T>(parens->left());
61 }
62 return nullptr;
63 }
64}
65
66// GetScalarConstantValue() extracts the known scalar constant value of
67// an expression, if it has one. The value can be parenthesized.
68template <typename T, typename EXPR>
69constexpr auto GetScalarConstantValue(const EXPR &expr)
70 -> std::optional<Scalar<T>> {
71 if (const Constant<T> *constant{UnwrapConstantValue<T>(expr)}) {
72 return constant->GetScalarValue();
73 } else {
74 return std::nullopt;
75 }
76}
77
78// When an expression is a constant integer, ToInt64() extracts its value.
79// Ensure that the expression has been folded beforehand when folding might
80// be required.
81template <int KIND>
82constexpr std::optional<std::int64_t> ToInt64(
84 if (auto scalar{
85 GetScalarConstantValue<Type<TypeCategory::Integer, KIND>>(expr)}) {
86 return scalar->ToInt64();
87 } else {
88 return std::nullopt;
89 }
90}
91template <int KIND>
92constexpr std::optional<std::int64_t> ToInt64(
94 if (auto scalar{
95 GetScalarConstantValue<Type<TypeCategory::Unsigned, KIND>>(expr)}) {
96 return scalar->ToInt64();
97 } else {
98 return std::nullopt;
99 }
100}
101
102std::optional<std::int64_t> ToInt64(const Expr<SomeInteger> &);
103std::optional<std::int64_t> ToInt64(const Expr<SomeUnsigned> &);
104std::optional<std::int64_t> ToInt64(const Expr<SomeType> &);
105std::optional<std::int64_t> ToInt64(const ActualArgument &);
106
107// When an expression is a constant logical scalar, ToLogical() extracts its
108// value.
109inline std::optional<bool> ToLogical(const Expr<LogicalResult> &expr) {
110 if (auto val{GetScalarConstantValue<LogicalResult>(expr)}) {
111 return val->IsTrue();
112 }
113 return std::nullopt;
114}
115
116template <typename A>
117std::optional<std::int64_t> ToInt64(const std::optional<A> &x) {
118 if (x) {
119 return ToInt64(*x);
120 } else {
121 return std::nullopt;
122 }
123}
124
125template <typename A> std::optional<std::int64_t> ToInt64(A *p) {
126 if (p) {
127 return ToInt64(std::as_const(*p));
128 } else {
129 return std::nullopt;
130 }
131}
132
133} // namespace Fortran::evaluate
134#endif // FORTRAN_EVALUATE_FOLD_H_
Definition constant.h:147
Definition common.h:215
Definition common.h:217
Definition type.h:56
Definition call.h:34