merge(3p/immer): Subtree merge at 'ad3e3556d' as 'third_party/immer'
Change-Id: I9636a41ad44b4218293833fd3e9456d9b07c731b
This commit is contained in:
commit
1213b086a1
311 changed files with 74223 additions and 0 deletions
46
third_party/immer/extra/python/CMakeLists.txt
vendored
Normal file
46
third_party/immer/extra/python/CMakeLists.txt
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
option(USE_PYBIND "bind with pybind1" off)
|
||||
option(USE_BOOST_PYTHON "bind with boost::python" off)
|
||||
|
||||
if (USE_PYBIND)
|
||||
set(PYBIND11_CPP_STANDARD -std=c++14)
|
||||
find_package(Boost 1.56 REQUIRED)
|
||||
add_subdirectory(lib/pybind11)
|
||||
pybind11_add_module(immer_python_module src/immer-pybind.cpp)
|
||||
target_link_libraries(immer_python_module PUBLIC
|
||||
immer)
|
||||
|
||||
elseif(USE_BOOST_PYTHON)
|
||||
find_package(PythonInterp)
|
||||
find_package(PythonLibs)
|
||||
find_package(Boost 1.56 COMPONENTS python)
|
||||
python_add_module(immer_python_module src/immer-boost.cpp)
|
||||
include_directories(immer_python_module PUBLIC
|
||||
${immer_include_dir}
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${PYTHON_INCLUDE_DIRS})
|
||||
target_link_libraries(immer_python_module PUBLIC
|
||||
immer
|
||||
${Boost_LIBRARIES}
|
||||
${PYTHON_LIBRARIES})
|
||||
|
||||
else()
|
||||
find_package(PythonInterp)
|
||||
find_package(PythonLibs)
|
||||
|
||||
if (NOT PYTHONLIBS_FOUND)
|
||||
message(STATUS "Disabling Python modules")
|
||||
return()
|
||||
endif()
|
||||
|
||||
python_add_module(immer_python_module EXCLUDE_FROM_ALL
|
||||
src/immer-raw.cpp)
|
||||
target_include_directories(immer_python_module PUBLIC
|
||||
${PYTHON_INCLUDE_DIRS})
|
||||
target_link_libraries(immer_python_module PUBLIC
|
||||
immer
|
||||
${PYTHON_LIBRARIES})
|
||||
|
||||
endif()
|
||||
|
||||
add_custom_target(python DEPENDS immer_python_module)
|
||||
42
third_party/immer/extra/python/README.rst
vendored
Normal file
42
third_party/immer/extra/python/README.rst
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
|
||||
Python bindings
|
||||
===============
|
||||
|
||||
This library includes experimental bindings bring efficient immutable
|
||||
vectors for the Python language. They were developed as part of the
|
||||
research for the `ICFP'17 paper`_. The interface is quite
|
||||
**incomplete**, yet you can already do some things like:
|
||||
|
||||
.. literalinclude:: ../extra/python/example.py
|
||||
:language: python
|
||||
:start-after: intro/start
|
||||
:end-before: intro/end
|
||||
..
|
||||
|
||||
**Do you want to help** making these bindings complete and production
|
||||
ready? Drop a line at `immer@sinusoid.al
|
||||
<mailto:immer@sinusoid.al>`_ or `open an issue on Github
|
||||
<https://github.com/arximboldi/immer>`_
|
||||
|
||||
Installation
|
||||
------------
|
||||
::
|
||||
|
||||
pip install --user git+https://github.com/arximboldi/immer.git
|
||||
|
||||
Benchmarks
|
||||
----------
|
||||
|
||||
The library includes a set of benchmarks that compare it to
|
||||
`pyrsistent <https://github.com/tobgu/pyrsistent>`_. You can see the
|
||||
results in the `ICFP'17 paper`_. If you want to run them yourself,
|
||||
you need to install some dependencies::
|
||||
|
||||
pip install --user pytest-benchmark pyrsistent
|
||||
|
||||
Then you need to clone the `project repository
|
||||
<https://github.com/arximboldi/immer>`_ and from its root, run::
|
||||
|
||||
pytest extra/python/benchmark
|
||||
|
||||
.. _ICFP'17 paper: https://public.sinusoid.es/misc/immer/immer-icfp17.pdf
|
||||
45
third_party/immer/extra/python/benchmark/test_benchmarks.py
vendored
Normal file
45
third_party/immer/extra/python/benchmark/test_benchmarks.py
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
# immer: immutable data structures for C++
|
||||
# Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
|
||||
#
|
||||
# This software is distributed under the Boost Software License, Version 1.0.
|
||||
# See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
|
||||
|
||||
##
|
||||
|
||||
import immer
|
||||
import pyrsistent
|
||||
|
||||
BENCHMARK_SIZE = 1000
|
||||
|
||||
def push(v, n=BENCHMARK_SIZE):
|
||||
for x in xrange(n):
|
||||
v = v.append(x)
|
||||
return v
|
||||
|
||||
def assoc(v):
|
||||
for i in xrange(len(v)):
|
||||
v = v.set(i, i+1)
|
||||
return v
|
||||
|
||||
def index(v):
|
||||
for i in xrange(len(v)):
|
||||
v[i]
|
||||
|
||||
def test_push_immer(benchmark):
|
||||
benchmark(push, immer.Vector())
|
||||
|
||||
def test_push_pyrsistent(benchmark):
|
||||
benchmark(push, pyrsistent.pvector())
|
||||
|
||||
def test_assoc_immer(benchmark):
|
||||
benchmark(assoc, push(immer.Vector()))
|
||||
|
||||
def test_assoc_pyrsistent(benchmark):
|
||||
benchmark(assoc, push(pyrsistent.pvector()))
|
||||
|
||||
def test_index_immer(benchmark):
|
||||
benchmark(index, push(immer.Vector()))
|
||||
|
||||
def test_index_pyrsistent(benchmark):
|
||||
benchmark(index, push(pyrsistent.pvector()))
|
||||
21
third_party/immer/extra/python/example.py
vendored
Executable file
21
third_party/immer/extra/python/example.py
vendored
Executable file
|
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/env python##
|
||||
|
||||
# immer: immutable data structures for C++
|
||||
# Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
|
||||
#
|
||||
# This software is distributed under the Boost Software License, Version 1.0.
|
||||
# See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
|
||||
|
||||
|
||||
# include:intro/start
|
||||
import immer
|
||||
|
||||
v0 = immer.Vector().append(13).append(42)
|
||||
assert v0[0] == 13
|
||||
assert v0[1] == 42
|
||||
assert len(v0) == 2
|
||||
|
||||
v1 = v0.set(0, 12)
|
||||
assert v0.tolist() == [13, 42]
|
||||
assert v1.tolist() == [12, 42]
|
||||
# include:intro/end
|
||||
2
third_party/immer/extra/python/immer/__init__.py
vendored
Normal file
2
third_party/immer/extra/python/immer/__init__.py
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
from immer_python_module import *
|
||||
1
third_party/immer/extra/python/lib/pybind11
vendored
Submodule
1
third_party/immer/extra/python/lib/pybind11
vendored
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 1eaacd19f6de9a053570c21de6d173efc2304bc2
|
||||
80
third_party/immer/extra/python/src/immer-boost.cpp
vendored
Normal file
80
third_party/immer/extra/python/src/immer-boost.cpp
vendored
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
//
|
||||
// immer: immutable data structures for C++
|
||||
// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
|
||||
//
|
||||
// This software is distributed under the Boost Software License, Version 1.0.
|
||||
// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
|
||||
#include <boost/python.hpp>
|
||||
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
|
||||
|
||||
#include <immer/vector.hpp>
|
||||
#include <immer/refcount/unsafe_refcount_policy.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
struct heap_t
|
||||
{
|
||||
template <typename ...Tags>
|
||||
static void* allocate(std::size_t size, Tags...)
|
||||
{
|
||||
return PyMem_Malloc(size);
|
||||
}
|
||||
|
||||
template <typename ...Tags>
|
||||
static void deallocate(std::size_t, void* obj, Tags...)
|
||||
{
|
||||
PyMem_Free(obj);
|
||||
}
|
||||
};
|
||||
|
||||
using memory_t = immer::memory_policy<
|
||||
immer::unsafe_free_list_heap_policy<heap_t>,
|
||||
immer::unsafe_refcount_policy>;
|
||||
|
||||
template <typename Vector>
|
||||
struct immer_vector_indexing_suite : boost::python::vector_indexing_suite<
|
||||
Vector, true, immer_vector_indexing_suite<Vector>>
|
||||
{
|
||||
using value_t = typename Vector::value_type;
|
||||
using index_t = typename Vector::size_type;
|
||||
using object_t = boost::python::object;
|
||||
|
||||
static void forbidden() { throw std::runtime_error{"immutable!"}; }
|
||||
static void todo() { throw std::runtime_error{"TODO!"}; }
|
||||
|
||||
static const value_t& get_item(const Vector& v, index_t i) { return v[i]; }
|
||||
static object_t get_slice(const Vector&, index_t, index_t) { todo(); }
|
||||
|
||||
static void set_item(const Vector&, index_t, const value_t&) { forbidden(); }
|
||||
static void delete_item(const Vector&, index_t) { forbidden(); }
|
||||
static void set_slice(const Vector&, index_t, index_t, const value_t&) { forbidden(); }
|
||||
static void delete_slice(const Vector&, index_t, index_t) { forbidden(); }
|
||||
template <typename Iter>
|
||||
static void set_slice(const Vector&, index_t, index_t, Iter, Iter) { forbidden(); }
|
||||
template <class Iter>
|
||||
static void extend(const Vector& container, Iter, Iter) { forbidden(); }
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
BOOST_PYTHON_MODULE(immer_python_module)
|
||||
{
|
||||
using namespace boost::python;
|
||||
|
||||
using vector_t = immer::vector<object, memory_t>;
|
||||
|
||||
class_<vector_t>("Vector")
|
||||
.def(immer_vector_indexing_suite<vector_t>())
|
||||
.def("append",
|
||||
+[] (const vector_t& v, object x) {
|
||||
return v.push_back(std::move(x));
|
||||
})
|
||||
.def("set",
|
||||
+[] (const vector_t& v, std::size_t i, object x) {
|
||||
return v.set(i, std::move(x));
|
||||
})
|
||||
;
|
||||
}
|
||||
77
third_party/immer/extra/python/src/immer-pybind.cpp
vendored
Normal file
77
third_party/immer/extra/python/src/immer-pybind.cpp
vendored
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
//
|
||||
// immer: immutable data structures for C++
|
||||
// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
|
||||
//
|
||||
// This software is distributed under the Boost Software License, Version 1.0.
|
||||
// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
|
||||
#include <pybind11/pybind11.h>
|
||||
|
||||
#include <immer/vector.hpp>
|
||||
#include <immer/refcount/unsafe_refcount_policy.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
struct heap_t
|
||||
{
|
||||
template <typename ...Tags>
|
||||
static void* allocate(std::size_t size, Tags...)
|
||||
{
|
||||
return PyMem_Malloc(size);
|
||||
}
|
||||
|
||||
template <typename ...Tags>
|
||||
static void deallocate(std::size_t, void* obj, Tags...)
|
||||
{
|
||||
PyMem_Free(obj);
|
||||
}
|
||||
};
|
||||
|
||||
using memory_t = immer::memory_policy<
|
||||
immer::unsafe_free_list_heap_policy<heap_t>,
|
||||
immer::unsafe_refcount_policy>;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
PYBIND11_PLUGIN(immer_python_module)
|
||||
{
|
||||
py::module m("immer", R"pbdoc(
|
||||
Immer
|
||||
-----
|
||||
.. currentmodule:: immer
|
||||
.. autosummary::
|
||||
:toctree: _generate
|
||||
Vector
|
||||
)pbdoc");
|
||||
|
||||
using vector_t = immer::vector<py::object, memory_t>;
|
||||
|
||||
py::class_<vector_t>(m, "Vector")
|
||||
.def(py::init<>())
|
||||
.def("__len__", &vector_t::size)
|
||||
.def("__getitem__",
|
||||
[] (const vector_t& v, std::size_t i) {
|
||||
if (i > v.size())
|
||||
throw py::index_error{"Index out of range"};
|
||||
return v[i];
|
||||
})
|
||||
.def("append",
|
||||
[] (const vector_t& v, py::object x) {
|
||||
return v.push_back(std::move(x));
|
||||
})
|
||||
.def("set",
|
||||
[] (const vector_t& v, std::size_t i, py::object x) {
|
||||
return v.set(i, std::move(x));
|
||||
});
|
||||
|
||||
#ifdef VERSION_INFO
|
||||
m.attr("__version__") = py::str(VERSION_INFO);
|
||||
#else
|
||||
m.attr("__version__") = py::str("dev");
|
||||
#endif
|
||||
|
||||
return m.ptr();
|
||||
}
|
||||
402
third_party/immer/extra/python/src/immer-raw.cpp
vendored
Normal file
402
third_party/immer/extra/python/src/immer-raw.cpp
vendored
Normal file
|
|
@ -0,0 +1,402 @@
|
|||
//
|
||||
// immer: immutable data structures for C++
|
||||
// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
|
||||
//
|
||||
// This software is distributed under the Boost Software License, Version 1.0.
|
||||
// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
|
||||
extern "C" {
|
||||
#include <Python.h>
|
||||
#include <structmember.h>
|
||||
}
|
||||
|
||||
#include <immer/vector.hpp>
|
||||
#include <immer/algorithm.hpp>
|
||||
#include <immer/refcount/unsafe_refcount_policy.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace {
|
||||
|
||||
struct heap_t
|
||||
{
|
||||
template <typename ...Tags>
|
||||
static void* allocate(std::size_t size, Tags...)
|
||||
{
|
||||
return PyMem_Malloc(size);
|
||||
}
|
||||
|
||||
template <typename ...Tags>
|
||||
static void deallocate(std::size_t, void* obj, Tags...)
|
||||
{
|
||||
PyMem_Free(obj);
|
||||
}
|
||||
};
|
||||
|
||||
struct object_t
|
||||
{
|
||||
struct wrap_t {};
|
||||
struct adopt_t {};
|
||||
|
||||
PyObject* ptr_ = nullptr;
|
||||
|
||||
object_t() = delete;
|
||||
~object_t() { Py_XDECREF(ptr_); }
|
||||
|
||||
explicit object_t(PyObject* p, wrap_t) : ptr_{p} {}
|
||||
explicit object_t(PyObject* p, adopt_t) : ptr_{p}
|
||||
{
|
||||
assert(p);
|
||||
Py_INCREF(p);
|
||||
}
|
||||
|
||||
static object_t wrap(PyObject* p) { return object_t{p, wrap_t{}}; }
|
||||
static object_t adopt(PyObject* p) { return object_t{p, adopt_t{}}; }
|
||||
|
||||
object_t(const object_t& o) : ptr_(o.ptr_) { Py_INCREF(ptr_); }
|
||||
object_t(object_t&& o) { std::swap(ptr_, o.ptr_); }
|
||||
|
||||
object_t& operator=(const object_t& o)
|
||||
{
|
||||
Py_XINCREF(o.ptr_);
|
||||
Py_XDECREF(ptr_);
|
||||
ptr_ = o.ptr_;
|
||||
return *this;
|
||||
}
|
||||
object_t& operator=(object_t&& o)
|
||||
{
|
||||
std::swap(ptr_, o.ptr_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PyObject* release()
|
||||
{
|
||||
auto p = ptr_;
|
||||
ptr_ = nullptr;
|
||||
return p;
|
||||
}
|
||||
|
||||
PyObject* get() const { return ptr_; }
|
||||
};
|
||||
|
||||
using memory_t = immer::memory_policy<
|
||||
immer::unsafe_free_list_heap_policy<heap_t>,
|
||||
immer::unsafe_refcount_policy>;
|
||||
|
||||
using vector_impl_t = immer::vector<object_t, memory_t>;
|
||||
|
||||
struct vector_t
|
||||
{
|
||||
PyObject_HEAD
|
||||
vector_impl_t impl;
|
||||
PyObject* in_weakreflist;
|
||||
|
||||
static PyTypeObject type;
|
||||
};
|
||||
|
||||
vector_t* empty_vector = nullptr;
|
||||
|
||||
vector_t* make_vector()
|
||||
{
|
||||
auto* v = PyObject_GC_New(vector_t, &vector_t::type);
|
||||
new (&v->impl) vector_impl_t{};
|
||||
v->in_weakreflist = nullptr;
|
||||
PyObject_GC_Track((PyObject*)v);
|
||||
return v;
|
||||
}
|
||||
|
||||
vector_t* make_vector(vector_impl_t&& impl)
|
||||
{
|
||||
auto v = PyObject_GC_New(vector_t, &vector_t::type);
|
||||
new (&v->impl) vector_impl_t{std::move(impl)};
|
||||
v->in_weakreflist = nullptr;
|
||||
PyObject_GC_Track((PyObject*)v);
|
||||
return v;
|
||||
}
|
||||
|
||||
auto todo()
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, "immer: todo!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void vector_dealloc(vector_t* self)
|
||||
{
|
||||
if (self->in_weakreflist != nullptr)
|
||||
PyObject_ClearWeakRefs((PyObject*)self);
|
||||
|
||||
PyObject_GC_UnTrack((PyObject*)self);
|
||||
Py_TRASHCAN_SAFE_BEGIN(self);
|
||||
|
||||
self->impl.~vector_impl_t();
|
||||
|
||||
PyObject_GC_Del(self);
|
||||
Py_TRASHCAN_SAFE_END(self);
|
||||
}
|
||||
|
||||
PyObject* vector_to_list(vector_t* self)
|
||||
{
|
||||
auto list = PyList_New(self->impl.size());
|
||||
auto idx = 0;
|
||||
immer::for_each(self->impl, [&] (auto&& obj) {
|
||||
auto o = obj.get();
|
||||
Py_INCREF(o);
|
||||
PyList_SET_ITEM(list, idx, o);
|
||||
++idx;
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
PyObject* vector_repr(vector_t *self)
|
||||
{
|
||||
auto list = vector_to_list(self);
|
||||
auto list_repr = PyObject_Repr(list);
|
||||
Py_DECREF(list);
|
||||
|
||||
if (!list_repr) return nullptr;
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
auto s = PyUnicode_FromFormat("%s%U%s", "immer.vector(", list_repr, ")");
|
||||
Py_DECREF(list_repr);
|
||||
#else
|
||||
auto s = PyString_FromString("immer.vector(");
|
||||
PyString_ConcatAndDel(&s, list_repr);
|
||||
PyString_ConcatAndDel(&s, PyString_FromString(")"));
|
||||
#endif
|
||||
return s;
|
||||
}
|
||||
|
||||
Py_ssize_t vector_len(vector_t* self)
|
||||
{
|
||||
return self->impl.size();
|
||||
}
|
||||
|
||||
PyObject* vector_extend(vector_t* self, PyObject* iterable)
|
||||
{
|
||||
return todo();
|
||||
}
|
||||
|
||||
vector_t* vector_append(vector_t* self, PyObject *obj)
|
||||
{
|
||||
assert(obj != nullptr);
|
||||
return make_vector(self->impl.push_back(object_t::adopt(obj)));
|
||||
}
|
||||
|
||||
vector_t* vector_set(vector_t* self, PyObject* args)
|
||||
{
|
||||
PyObject* obj = nullptr;
|
||||
Py_ssize_t pos;
|
||||
// the n parses for size, the O parses for a Python object
|
||||
if(!PyArg_ParseTuple(args, "nO", &pos, &obj)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (pos < 0)
|
||||
pos += self->impl.size();
|
||||
if (pos < 0 || pos > (Py_ssize_t)self->impl.size()) {
|
||||
PyErr_Format(PyExc_IndexError, "Index out of range: %zi", pos);
|
||||
return nullptr;
|
||||
}
|
||||
return make_vector(self->impl.set(pos, object_t::adopt(obj)));
|
||||
}
|
||||
|
||||
PyObject* vector_new(PyTypeObject* subtype, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
Py_INCREF(empty_vector);
|
||||
return (PyObject*)empty_vector;
|
||||
}
|
||||
|
||||
long vector_hash(vector_t* self)
|
||||
{
|
||||
todo();
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject* vector_get_item(vector_t* self, Py_ssize_t pos)
|
||||
{
|
||||
if (pos < 0)
|
||||
pos += self->impl.size();
|
||||
if (pos < 0 || pos >= (Py_ssize_t)self->impl.size()) {
|
||||
PyErr_Format(PyExc_IndexError, "Index out of range: %zi", pos);
|
||||
return nullptr;
|
||||
}
|
||||
auto r = self->impl[pos];
|
||||
return r.release();
|
||||
}
|
||||
|
||||
PyObject* vector_subscript(vector_t* self, PyObject* item)
|
||||
{
|
||||
if (PyIndex_Check(item)) {
|
||||
auto i = PyNumber_AsSsize_t(item, PyExc_IndexError);
|
||||
if (i == -1 && PyErr_Occurred())
|
||||
return nullptr;
|
||||
return vector_get_item(self, i);
|
||||
} else if (PySlice_Check(item)) {
|
||||
return todo();
|
||||
} else {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"vector indices must be integers, not %.200s",
|
||||
Py_TYPE(item)->tp_name);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* vector_repeat(vector_t* self, Py_ssize_t n)
|
||||
{
|
||||
return todo();
|
||||
}
|
||||
|
||||
int vector_traverse(vector_t* self, visitproc visit, void* arg)
|
||||
{
|
||||
auto result = 0;
|
||||
immer::all_of(self->impl, [&] (auto&& o) {
|
||||
return 0 == (result = [&] {
|
||||
Py_VISIT(o.get());
|
||||
return 0;
|
||||
}());
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
PyObject* vector_richcompare(PyObject* v, PyObject* w, int op)
|
||||
{
|
||||
return todo();
|
||||
}
|
||||
|
||||
PyObject* vector_iter(PyObject* self)
|
||||
{
|
||||
return todo();
|
||||
}
|
||||
|
||||
PyMethodDef vector_methods[] =
|
||||
{
|
||||
{"append", (PyCFunction)vector_append, METH_O, "Appends an element"},
|
||||
{"set", (PyCFunction)vector_set, METH_VARARGS, "Inserts an element at the specified position"},
|
||||
{"extend", (PyCFunction)vector_extend, METH_O|METH_COEXIST, "Extend"},
|
||||
{"tolist", (PyCFunction)vector_to_list, METH_NOARGS, "Convert to list"},
|
||||
{0}
|
||||
};
|
||||
|
||||
PyMemberDef vector_members[] =
|
||||
{
|
||||
{0} /* sentinel */
|
||||
};
|
||||
|
||||
PySequenceMethods vector_sequence_methods =
|
||||
{
|
||||
(lenfunc)vector_len, /* sq_length */
|
||||
(binaryfunc)vector_extend, /* sq_concat */
|
||||
(ssizeargfunc)vector_repeat, /* sq_repeat */
|
||||
(ssizeargfunc)vector_get_item, /* sq_item */
|
||||
0, /* sq_slice */
|
||||
0, /* sq_ass_item */
|
||||
0, /* sq_ass_slice */
|
||||
0, /* sq_contains */
|
||||
0, /* sq_inplace_concat */
|
||||
0, /* sq_inplace_repeat */
|
||||
};
|
||||
|
||||
PyMappingMethods vector_mapping_methods =
|
||||
{
|
||||
(lenfunc)vector_len,
|
||||
(binaryfunc)vector_subscript,
|
||||
0
|
||||
};
|
||||
|
||||
PyTypeObject vector_t::type =
|
||||
{
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"immer.Vector", /* tp_name */
|
||||
sizeof(vector_t), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
(destructor)vector_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_compare */
|
||||
(reprfunc)vector_repr, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
&vector_sequence_methods, /* tp_as_sequence */
|
||||
&vector_mapping_methods, /* tp_as_mapping */
|
||||
(hashfunc)vector_hash, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
||||
"", /* tp_doc */
|
||||
(traverseproc)vector_traverse, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
vector_richcompare, /* tp_richcompare */
|
||||
offsetof(vector_t, in_weakreflist), /* tp_weaklistoffset */
|
||||
vector_iter, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
vector_methods, /* tp_methods */
|
||||
vector_members, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
0, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
vector_new, /* tp_new */
|
||||
};
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
struct PyModuleDef module_def =
|
||||
{
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"immer_python_module", /* m_name */
|
||||
"", /* m_doc */
|
||||
-1, /* m_size */
|
||||
/module_methods, /* m_methods */
|
||||
0, /* m_reload */
|
||||
0, /* m_traverse */
|
||||
0, /* m_clear */
|
||||
0, /* m_free */
|
||||
};
|
||||
#endif
|
||||
|
||||
PyMethodDef module_methods[] = {
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
PyObject* module_init()
|
||||
{
|
||||
if (PyType_Ready(&vector_t::type) < 0)
|
||||
return nullptr;
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
auto m = PyModule_Create(&module_def);
|
||||
#else
|
||||
auto m = Py_InitModule3("immer_python_module", module_methods, "");
|
||||
#endif
|
||||
if (!m)
|
||||
return nullptr;
|
||||
|
||||
if (!empty_vector)
|
||||
empty_vector = make_vector();
|
||||
|
||||
Py_INCREF(&vector_t::type);
|
||||
PyModule_AddObject(m, "Vector", (PyObject*) &vector_t::type);
|
||||
return m;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
extern "C" {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyMODINIT_FUNC PyInit_immer_python_module()
|
||||
{
|
||||
return module_init();
|
||||
}
|
||||
#else
|
||||
PyMODINIT_FUNC initimmer_python_module()
|
||||
{
|
||||
module_init();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue