8#ifndef FORTRAN_EVALUATE_MATCH_H_
9#define FORTRAN_EVALUATE_MATCH_H_
11#include "flang/Common/Fortran-consts.h"
12#include "flang/Common/visit.h"
13#include "flang/Evaluate/expression.h"
14#include "flang/Support/Fortran.h"
15#include "llvm/ADT/STLExtras.h"
25template <
typename,
typename =
void>
27 static constexpr bool value{
false};
32 static constexpr bool value{
true};
37constexpr bool is_operation_v{detail::IsOperation<T>::value};
39template <common::TypeCategory C,
int K>
41 if (
auto *parens{std::get_if<Parentheses<Type<C, K>>>(&x.u)}) {
42 return deparen(parens->template operand<0>());
48template <common::TypeCategory C>
49const evaluate::Expr<SomeKind<C>> &deparen(
50 const evaluate::Expr<SomeKind<C>> &x) {
59const evaluate::Expr<SomeType> &deparen(
60 const evaluate::Expr<SomeType> &) =
delete;
76 using MatchType = llvm::remove_cvref_t<T>;
78 template <
typename U>
bool match(
const U &input)
const {
79 if constexpr (std::is_same_v<MatchType, U>) {
87 mutable const MatchType *ref{
nullptr};
98template <
typename... Patterns>
struct AnyOfPattern {
99 static_assert(
sizeof...(Patterns) != 0);
102 using PatternTuple = std::tuple<Patterns...>;
105 using Pattern =
typename std::tuple_element<I, PatternTuple>::type;
107 template <
size_t... Is,
typename... Ops>
108 AnyOfPattern(std::index_sequence<Is...>,
const Ops &...ops)
109 : patterns(std::make_tuple(Pattern<Is>(ops...)...)) {}
111 template <
typename P,
typename U>
112 bool matchOne(
const P &pattern,
const U &input)
const {
113 if (pattern.match(input)) {
120 template <
typename U,
size_t... Is>
121 bool matchImpl(
const U &input, std::index_sequence<Is...>)
const {
122 return (matchOne(std::get<Is>(patterns), input) || ...);
125 PatternTuple patterns;
128 using Indexes = std::index_sequence_for<Patterns...>;
129 using MatchTypes = std::tuple<
typename Patterns::MatchType...>;
131 template <
typename... Ops>
132 AnyOfPattern(
const Ops &...ops) : AnyOfPattern(Indexes{}, ops...) {}
134 template <
typename U>
bool match(
const U &input)
const {
135 return matchImpl(input, Indexes{});
138 mutable std::variant<
const Patterns *..., std::monostate> ref{
148template <
typename OpType,
typename... Ops>
151 using Indexes = std::index_sequence_for<Ops...>;
153 template <
typename S,
size_t... Is>
154 bool matchImpl(
const S &op, std::index_sequence<Is...>)
const {
155 using TypeS = llvm::remove_cvref_t<S>;
156 if constexpr (is_operation_v<TypeS>) {
157 if constexpr (TypeS::operands == Indexes::size()) {
158 return TypePattern<OpType>::match(op) &&
159 (std::get<Is>(operands).match(op.template operand<Is>()) && ...);
165 std::tuple<
const Ops &...> operands;
168 using MatchType = OpType;
170 OperationPattern(
const Ops &...ops, llvm::type_identity<OpType> = {})
171 : operands(ops...) {}
174 return common::visit(
175 [&](
auto &&s) {
return matchImpl(s, Indexes{}); }, deparen(input).u);
178 template <
typename U>
bool match(
const U &input)
const {
184template <
typename OpType,
typename... Ops>
190template <common::LogicalOperator Operator,
typename ValType,
typename... Ops>
191struct LogicalOperationPattern
192 :
public OperationPattern<LogicalOperation<ValType::kind>, Ops...> {
193 using Base = OperationPattern<LogicalOperation<ValType::kind>, Ops...>;
194 static constexpr common::LogicalOperator opCode{Operator};
198 if constexpr (ValType::kind == K) {
199 return op.logicalOperator == opCode;
203 template <
typename U>
bool matchOp(
const U &)
const {
return false; }
206 LogicalOperationPattern(
const Ops &...ops, llvm::type_identity<ValType> = {})
215 if (common::visit([&](
auto &&s) {
return matchOp(s); }, deparen(input).u)) {
216 return Base::match(input);
222 template <
typename U>
bool match(
const U &input)
const {
234template <
typename OpType,
typename... Ops>
237template <common::LogicalOperator Operator,
typename ValType,
typename... Ops>
240template <common::LogicalOperator Operator,
typename Type,
typename Op0,
242LogicalOp<Operator, Type, Op0, Op1> logical(
const Op0 &op0,
const Op1 &op1) {
243 return LogicalOp<Operator, Type, Op0, Op1>(op0, op1);
246template <
typename Pattern,
typename Input>
247bool match(
const Pattern &pattern,
const Input &input) {
248 return pattern.match(input);
254template <
typename Type,
typename Op0,
typename Op1>
255struct Add :
public Op<evaluate::Add<Type>, Op0, Op1> {
256 using Base = Op<evaluate::Add<Type>, Op0, Op1>;
258 Add(
const Op0 &op0,
const Op1 &op1) : Base(op0, op1) {}
261template <
typename Type,
typename Op0,
typename Op1>
267template <
typename Type,
typename Op0,
typename Op1>
268struct Mul :
public Op<evaluate::Multiply<Type>, Op0, Op1> {
269 using Base = Op<evaluate::Multiply<Type>, Op0, Op1>;
271 Mul(
const Op0 &op0,
const Op1 &op1) : Base(op0, op1) {}
274template <
typename Type,
typename Op0,
typename Op1>
Definition expression.h:379
Matches evaluate::Expr<T> that contains evaluate::Opreration<OpType>.
Definition match.h:149