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#include <variant>
21
22namespace Fortran::evaluate::characteristics {
23class TypeAndShape;
24}
25
26namespace Fortran::evaluate {
27
28using namespace Fortran::parser::literals;
29
30// Fold() rewrites an expression and returns it. When the rewritten expression
31// is a constant, UnwrapConstantValue() and GetScalarConstantValue() below will
32// be able to extract it.
33// Note the rvalue reference argument: the rewrites are performed in place
34// for efficiency.
35template <typename T> Expr<T> Fold(FoldingContext &context, Expr<T> &&expr) {
36 return Expr<T>::Rewrite(context, std::move(expr));
37}
38
40 FoldingContext &, characteristics::TypeAndShape &&);
41
42template <typename A>
43std::optional<A> Fold(FoldingContext &context, std::optional<A> &&x) {
44 if (x) {
45 return Fold(context, std::move(*x));
46 } else {
47 return std::nullopt;
48 }
49}
50
51// UnwrapConstantValue() isolates the known constant value of
52// an expression, if it has one. It returns a pointer, which is
53// const-qualified when the expression is so. The value can be
54// parenthesized.
55template <typename T, typename EXPR>
56auto UnwrapConstantValue(EXPR &expr) -> common::Constify<Constant<T>, EXPR> * {
57 if (auto *c{UnwrapExpr<Constant<T>>(expr)}) {
58 return c;
59 } else {
60 if (auto *parens{UnwrapExpr<Parentheses<T>>(expr)}) {
61 return UnwrapConstantValue<T>(parens->left());
62 }
63 return nullptr;
64 }
65}
66
67// GetScalarConstantValue() extracts the known scalar constant value of
68// an expression, if it has one. The value can be parenthesized.
69template <typename T, typename EXPR>
70constexpr auto GetScalarConstantValue(const EXPR &expr)
71 -> std::optional<Scalar<T>> {
72 if (const Constant<T> *constant{UnwrapConstantValue<T>(expr)}) {
73 return constant->GetScalarValue();
74 } else {
75 return std::nullopt;
76 }
77}
78
79// When an expression is a constant integer, ToInt64() extracts its value.
80// Ensure that the expression has been folded beforehand when folding might
81// be required.
82template <int KIND>
83constexpr std::optional<std::int64_t> ToInt64(
84 const Expr<Type<TypeCategory::Integer, KIND>> &expr) {
85 if (auto scalar{
86 GetScalarConstantValue<Type<TypeCategory::Integer, KIND>>(expr)}) {
87 return scalar->ToInt64();
88 } else {
89 return std::nullopt;
90 }
91}
92template <int KIND>
93constexpr std::optional<std::int64_t> ToInt64(
94 const Expr<Type<TypeCategory::Unsigned, KIND>> &expr) {
95 if (auto scalar{
96 GetScalarConstantValue<Type<TypeCategory::Unsigned, KIND>>(expr)}) {
97 return scalar->ToInt64();
98 } else {
99 return std::nullopt;
100 }
101}
102
103std::optional<std::int64_t> ToInt64(const Expr<SomeInteger> &);
104std::optional<std::int64_t> ToInt64(const Expr<SomeUnsigned> &);
105std::optional<std::int64_t> ToInt64(const Expr<SomeType> &);
106std::optional<std::int64_t> ToInt64(const ActualArgument &);
107
108template <typename A>
109std::optional<std::int64_t> ToInt64(const std::optional<A> &x) {
110 if (x) {
111 return ToInt64(*x);
112 } else {
113 return std::nullopt;
114 }
115}
116
117template <typename A> std::optional<std::int64_t> ToInt64(A *p) {
118 if (p) {
119 return ToInt64(std::as_const(*p));
120 } else {
121 return std::nullopt;
122 }
123}
124
125} // namespace Fortran::evaluate
126#endif // FORTRAN_EVALUATE_FOLD_H_
Definition: characteristics.h:61
Definition: call.h:34
Definition: parse-tree.h:300
Definition: parse-tree.h:1700