FLANG
rewrite.h
1//===-- include/flang/Evaluate/rewrite.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#ifndef FORTRAN_EVALUATE_REWRITE_H_
9#define FORTRAN_EVALUATE_REWRITE_H_
10
11#include "flang/Common/visit.h"
12#include "flang/Evaluate/expression.h"
13#include "llvm/ADT/STLExtras.h"
14
15#include <tuple>
16#include <type_traits>
17#include <utility>
18#include <variant>
19
20namespace Fortran::evaluate {
21namespace rewrite {
22namespace detail {
23template <typename, typename = void> //
25 static constexpr bool value{false};
26};
27
28template <typename T>
29struct IsOperation<T, std::void_t<decltype(T::operands)>> {
30 static constexpr bool value{true};
31};
32} // namespace detail
33
34template <typename T>
35constexpr bool is_operation_v{detail::IsOperation<T>::value};
36
40struct Identity {
41 template <typename T, typename U>
42 Expr<T> operator()(Expr<T> &&x, const U &op) {
43 return std::move(x);
44 }
45};
46
60template <typename Rewriter> struct Mutator {
61 Mutator(Rewriter &rewriter) : rewriter_(rewriter) {}
62
63 template <typename T, typename U = llvm::remove_cvref_t<T>>
64 U operator()(T &&x) {
65 if constexpr (std::is_lvalue_reference_v<T>) {
66 return Mutate(U(x));
67 } else {
68 return Mutate(std::move(x));
69 }
70 }
71
72private:
73 template <typename T> struct LambdaWithRvalueCapture {
74 LambdaWithRvalueCapture(Rewriter &r, Expr<T> &&c)
75 : rewriter_(r), capture_(std::move(c)) {}
76 template <typename S> Expr<T> operator()(const S &s) {
77 return rewriter_(std::move(capture_), s);
78 }
79
80 private:
81 Rewriter &rewriter_;
82 Expr<T> &&capture_;
83 };
84
85 template <typename T, typename = std::enable_if_t<!is_operation_v<T>>>
86 T Mutate(T &&x) const {
87 return std::move(x);
88 }
89
90 template <typename D, typename = std::enable_if_t<is_operation_v<D>>>
91 D Mutate(D &&op, std::make_index_sequence<D::operands> t = {}) const {
92 return MutateOp(std::move(op), t);
93 }
94
95 template <typename T> //
96 Expr<T> Mutate(Expr<T> &&x) const {
97 // First construct the new expression with the rewritten op.
98 Expr<T> n{common::visit(
99 [&](auto &&s) { //
100 return Expr<T>(Mutate(std::move(s)));
101 },
102 std::move(x.u))};
103 // Return the rewritten expression. The second visit is to make sure
104 // that the second argument in the call to the rewriter is a part of
105 // the Expr<T> passed to it.
106 return common::visit(
107 LambdaWithRvalueCapture<T>(rewriter_, std::move(n)), std::move(n.u));
108 }
109
110 template <typename... Ts>
111 std::variant<Ts...> Mutate(std::variant<Ts...> &&u) const {
112 return common::visit(
113 [this](auto &&s) { return Mutate(std::move(s)); }, std::move(u));
114 }
115
116 template <typename... Ts>
117 std::tuple<Ts...> Mutate(std::tuple<Ts...> &&t) const {
118 return MutateTuple(std::move(t), std::index_sequence_for<Ts...>{});
119 }
120
121 template <typename... Ts, size_t... Is>
122 std::tuple<Ts...> MutateTuple(
123 std::tuple<Ts...> &&t, std::index_sequence<Is...>) const {
124 return std::make_tuple(Mutate(std::move(std::get<Is>(t))...));
125 }
126
127 template <typename D, size_t... Is>
128 D MutateOp(D &&op, std::index_sequence<Is...>) const {
129 return D(Mutate(std::move(op.template operand<Is>()))...);
130 }
131
132 template <typename T, size_t... Is>
133 Extremum<T> MutateOp(Extremum<T> &&op, std::index_sequence<Is...>) const {
134 return Extremum<T>(
135 op.ordering, Mutate(std::move(op.template operand<Is>()))...);
136 }
137
138 template <int K, size_t... Is>
139 ComplexComponent<K> MutateOp(
140 ComplexComponent<K> &&op, std::index_sequence<Is...>) const {
141 return ComplexComponent<K>(
142 op.isImaginaryPart, Mutate(std::move(op.template operand<Is>()))...);
143 }
144
145 template <int K, size_t... Is>
146 LogicalOperation<K> MutateOp(
147 LogicalOperation<K> &&op, std::index_sequence<Is...>) const {
148 return LogicalOperation<K>(
149 op.logicalOperator, Mutate(std::move(op.template operand<Is>()))...);
150 }
151
152 Rewriter &rewriter_;
153};
154
155template <typename Rewriter> Mutator(Rewriter &) -> Mutator<Rewriter>;
156} // namespace rewrite
157} // namespace Fortran::evaluate
158
159#endif // FORTRAN_EVALUATE_REWRITE_H_
Definition common.h:215
Definition call.h:34
Definition expression.h:256
Definition expression.h:339
Definition expression.h:378