aboutsummaryrefslogtreecommitdiffstats
path: root/common/pycontainers.h
diff options
context:
space:
mode:
Diffstat (limited to 'common/pycontainers.h')
-rw-r--r--common/pycontainers.h39
1 files changed, 26 insertions, 13 deletions
diff --git a/common/pycontainers.h b/common/pycontainers.h
index 917f49e9..e1a73d75 100644
--- a/common/pycontainers.h
+++ b/common/pycontainers.h
@@ -28,6 +28,7 @@
#include <type_traits>
#include <utility>
#include "nextpnr.h"
+#include "pywrappers.h"
NEXTPNR_NAMESPACE_BEGIN
@@ -37,18 +38,22 @@ inline void KeyError() { PyErr_SetString(PyExc_KeyError, "Key not found"); }
/*
A wrapper for a Pythonised nextpnr Iterator. The actual class wrapped is a
-pair<Iterator, Iterator> containing (current, end)
+pair<Iterator, Iterator> containing (current, end), wrapped in a ContextualWrapper
+
*/
-template <typename T, typename P> struct iterator_wrapper
+template <typename T, typename P, typename value_conv = PythonConversion::pass_through<T>> struct iterator_wrapper
{
typedef decltype(*(std::declval<T>())) value_t;
- static value_t next(std::pair<T, T> &iter)
+ typedef PythonConversion::ContextualWrapper<std::pair<T, T>> wrapped_iter_t;
+ using return_t = typename value_conv::ret_type;
+
+ static return_t next(wrapped_iter_t &iter)
{
- if (iter.first != iter.second) {
- value_t val = *iter.first;
- ++iter.first;
+ if (iter.base.first != iter.base.second) {
+ return_t val = value_conv()(iter.ctx, *iter.base.first);
+ ++iter.base.first;
return val;
} else {
PyErr_SetString(PyExc_StopIteration, "End of range reached");
@@ -61,7 +66,7 @@ template <typename T, typename P> struct iterator_wrapper
static void wrap(const char *python_name)
{
- class_<std::pair<T, T>>(python_name, no_init).def("__next__", next, P());
+ class_<wrapped_iter_t>(python_name, no_init).def("__next__", next, P());
}
};
@@ -71,22 +76,29 @@ and end() which return iterator-like objects supporting ++, * and !=
Full STL iterator semantics are not required, unlike the standard Boost wrappers
*/
-template <typename T, typename P = return_value_policy<return_by_value>> struct range_wrapper
+template <typename T, typename P = return_value_policy<return_by_value>,
+ typename value_conv = PythonConversion::pass_through<T>>
+struct range_wrapper
{
typedef decltype(std::declval<T>().begin()) iterator_t;
-
- static std::pair<iterator_t, iterator_t> iter(T &range) { return std::make_pair(range.begin(), range.end()); }
+ typedef typename PythonConversion::ContextualWrapper<T> wrapped_range;
+ typedef typename PythonConversion::ContextualWrapper<std::pair<iterator_t, iterator_t>> wrapped_pair;
+ static wrapped_pair iter(wrapped_range &range)
+ {
+ return wrapped_pair(range.ctx, std::make_pair(range.base.begin(), range.base.end()));
+ }
static void wrap(const char *range_name, const char *iter_name)
{
- class_<T>(range_name, no_init).def("__iter__", iter);
- iterator_wrapper<iterator_t, P>().wrap(iter_name);
+ class_<wrapped_range>(range_name, no_init).def("__iter__", iter);
+ iterator_wrapper<iterator_t, P, value_conv>().wrap(iter_name);
}
typedef iterator_wrapper<iterator_t, P> iter_wrap;
};
-#define WRAP_RANGE(t) range_wrapper<t##Range>().wrap(#t "Range", #t "Iterator")
+#define WRAP_RANGE(t, conv) \
+ range_wrapper<t##Range, return_value_policy<return_by_value>, conv>().wrap(#t "Range", #t "Iterator")
/*
Wrapper for a pair, allows accessing either using C++-style members (.first and
@@ -259,6 +271,7 @@ template <typename T1, typename T2> struct map_pair_wrapper_uptr
{
typedef std::pair<T1, T2> T;
typedef typename T::second_type::element_type V;
+
struct pair_iterator_wrapper
{
static object next(std::pair<T &, int> &iter)