| //===- Functional.h - Helpers for functional-style Combinators --*- C++ -*-===// |
| // |
| // Copyright 2019 The MLIR Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // ============================================================================= |
| |
| #ifndef MLIR_SUPPORT_FUNCTIONAL_H_ |
| #define MLIR_SUPPORT_FUNCTIONAL_H_ |
| |
| #include "llvm/ADT/STLExtras.h" |
| #include "llvm/Support/Casting.h" |
| |
| /// This file provides some simple template functional-style sugar to operate |
| /// on **value** types. Make sure when using that the stored type is cheap to |
| /// copy! |
| /// |
| /// TODO(ntv): add some static_assert but we need proper traits for this. |
| |
| namespace mlir { |
| namespace functional { |
| |
| /// Map with iterators. |
| template <typename Fn, typename IterType> |
| auto map(Fn fun, IterType begin, IterType end) |
| -> llvm::SmallVector<typename std::result_of<Fn(decltype(*begin))>::type, |
| 8> { |
| using R = typename std::result_of<Fn(decltype(*begin))>::type; |
| llvm::SmallVector<R, 8> res; |
| // auto i works with both pointer types and value types with an operator*. |
| // auto *i only works for pointer types. |
| for (auto i = begin; i != end; ++i) { |
| res.push_back(fun(*i)); |
| } |
| return res; |
| } |
| |
| /// Map with templated container. |
| template <typename Fn, typename ContainerType> |
| auto map(Fn fun, ContainerType input) |
| -> decltype(map(fun, std::begin(input), std::end(input))) { |
| return map(fun, std::begin(input), std::end(input)); |
| } |
| |
| /// Zip map with 2 templated container, iterates to the min of the sizes of |
| /// the 2 containers. |
| /// TODO(ntv): make variadic when needed. |
| template <typename Fn, typename ContainerType1, typename ContainerType2> |
| auto zipMap(Fn fun, ContainerType1 input1, ContainerType2 input2) |
| -> llvm::SmallVector< |
| typename std::result_of<Fn(decltype(*input1.begin()), |
| decltype(*input2.begin()))>::type, |
| 8> { |
| using R = typename std::result_of<Fn(decltype(*input1.begin()), |
| decltype(*input2.begin()))>::type; |
| llvm::SmallVector<R, 8> res; |
| auto zipIter = llvm::zip(input1, input2); |
| for (auto it : zipIter) { |
| res.push_back(fun(std::get<0>(it), std::get<1>(it))); |
| } |
| return res; |
| } |
| |
| /// Apply with iterators. |
| template <typename Fn, typename IterType> |
| void apply(Fn fun, IterType begin, IterType end) { |
| // auto i works with both pointer types and value types with an operator*. |
| // auto *i only works for pointer types. |
| for (auto i = begin; i != end; ++i) { |
| fun(*i); |
| } |
| } |
| |
| /// Apply with templated container. |
| template <typename Fn, typename ContainerType> |
| void apply(Fn fun, ContainerType input) { |
| return apply(fun, std::begin(input), std::end(input)); |
| } |
| |
| /// Zip apply with 2 templated container, iterates to the min of the sizes of |
| /// the 2 containers. |
| /// TODO(ntv): make variadic when needed. |
| template <typename Fn, typename ContainerType1, typename ContainerType2> |
| void zipApply(Fn fun, ContainerType1 input1, ContainerType2 input2) { |
| auto zipIter = llvm::zip(input1, input2); |
| for (auto it : zipIter) { |
| fun(std::get<0>(it), std::get<1>(it)); |
| } |
| } |
| |
| /// Unwraps a pointer type to another type (possibly the same). |
| /// Used in particular to allow easier compositions of |
| /// Operation::operand_range types. |
| template <typename T, typename ToType = T> |
| inline std::function<ToType *(T *)> makePtrDynCaster() { |
| return [](T *val) { return llvm::dyn_cast<ToType>(val); }; |
| } |
| |
| /// Simple ScopeGuard. |
| struct ScopeGuard { |
| explicit ScopeGuard(std::function<void(void)> destruct) |
| : destruct(destruct) {} |
| ~ScopeGuard() { destruct(); } |
| |
| private: |
| std::function<void(void)> destruct; |
| }; |
| |
| } // namespace functional |
| } // namespace mlir |
| |
| #endif // MLIR_SUPPORT_FUNCTIONAL_H_ |