9 #ifndef MLIR_BINDINGS_PYTHON_PYBINDUTILS_H 10 #define MLIR_BINDINGS_PYTHON_PYBINDUTILS_H 13 #include "llvm/ADT/Optional.h" 14 #include "llvm/ADT/Twine.h" 16 #include <pybind11/pybind11.h> 17 #include <pybind11/stl.h> 26 pybind11::error_already_set
SetPyError(PyObject *excClass,
27 const llvm::Twine &message);
44 template <
typename DerivedTy,
typename T>
66 template <
typename DefaultingTy>
68 PYBIND11_TYPE_CASTER(DefaultingTy, _(DefaultingTy::kTypeDescription));
70 bool load(pybind11::handle src,
bool) {
74 value = DefaultingTy{DefaultingTy::resolve()};
85 pybind11::cast<typename DefaultingTy::ReferrentTy &>(src)};
87 }
catch (std::exception &) {
92 static handle
cast(DefaultingTy src, return_value_policy policy,
94 return pybind11::cast(src, policy);
120 pybind11::str pyPart(part.
data,
122 printAccum->
parts.append(std::move(pyPart));
127 pybind11::str delim(
"", 0);
128 return delim.attr(
"join")(parts);
137 : pyWriteFunction(fileObject.attr(
"write")), binary(binary) {}
143 pybind11::gil_scoped_acquire acquire;
147 pybind11::bytes pyBytes(part.
data, part.
length);
148 accum->pyWriteFunction(pyBytes);
150 pybind11::str pyStr(part.
data,
152 accum->pyWriteFunction(pyStr);
158 pybind11::object pyWriteFunction;
172 assert(!accum->invoked &&
173 "PySinglePartStringAccumulator called back multiple times");
174 accum->invoked =
true;
175 accum->value = pybind11::str(part.
data, part.
length);
180 assert(invoked &&
"PySinglePartStringAccumulator not called back");
181 return std::move(
value);
186 bool invoked =
false;
217 template <
typename Derived,
typename ElementTy>
226 index = length + index;
227 if (index < 0 || index >= length)
234 intptr_t linearIndex = index * step + startIndex;
235 assert(linearIndex >= 0 &&
236 linearIndex < static_cast<Derived *>(
this)->getRawNumElements() &&
237 "linear index out of bounds, the slice is ill-formed");
246 index = wrapIndex(index);
248 PyErr_SetString(PyExc_IndexError,
"index out of range");
252 return pybind11::cast(
253 static_cast<Derived *>(
this)->getRawElement(
linearizeIndex(index)));
259 ssize_t start, stop, extraStep, sliceLength;
260 if (PySlice_GetIndicesEx(slice, length, &start, &stop, &extraStep,
261 &sliceLength) != 0) {
262 PyErr_SetString(PyExc_IndexError,
"index out of range");
265 return pybind11::cast(static_cast<Derived *>(
this)->slice(
266 startIndex + start * step, sliceLength, step * extraStep));
270 explicit Sliceable(intptr_t startIndex, intptr_t length, intptr_t step)
271 : startIndex(startIndex), length(length), step(step) {
272 assert(length >= 0 &&
"expected non-negative slice length");
279 index = wrapIndex(index);
281 throw pybind11::index_error(
"index out of range");
284 return static_cast<Derived *
>(
this)->getRawElement(
linearizeIndex(index));
288 intptr_t
size() {
return length; }
294 std::vector<ElementTy> elements;
295 elements.reserve(length + other.length);
296 for (intptr_t i = 0; i < length; ++i) {
297 elements.push_back(static_cast<Derived *>(
this)->getElement(i));
299 for (intptr_t i = 0; i < other.length; ++i) {
300 elements.push_back(static_cast<Derived *>(&other)->getElement(i));
306 static void bind(pybind11::module &m) {
307 auto clazz = pybind11::class_<Derived>(m, Derived::pyClassName,
308 pybind11::module_local())
310 Derived::bindDerived(clazz);
321 auto heap_type =
reinterpret_cast<PyHeapTypeObject *
>(clazz.ptr());
322 assert(heap_type->ht_type.tp_flags & Py_TPFLAGS_HEAPTYPE &&
323 "must be heap type");
324 heap_type->as_sequence.sq_length = +[](PyObject *rawSelf) -> Py_ssize_t {
325 auto self = pybind11::cast<Derived *>(rawSelf);
330 heap_type->as_sequence.sq_item =
331 +[](PyObject *rawSelf, Py_ssize_t index) -> PyObject * {
332 auto self = pybind11::cast<Derived *>(rawSelf);
333 return self->getItem(index).release().ptr();
336 heap_type->as_mapping.mp_subscript =
337 +[](PyObject *rawSelf, PyObject *rawSubscript) -> PyObject * {
338 auto self = pybind11::cast<Derived *>(rawSelf);
339 Py_ssize_t index = PyNumber_AsSsize_t(rawSubscript, PyExc_IndexError);
340 if (!PyErr_Occurred()) {
342 return self->getItem(index).release().ptr();
347 if (PySlice_Check(rawSubscript)) {
348 return self->getItemSlice(rawSubscript).release().ptr();
351 PyErr_SetString(PyExc_ValueError,
"expected integer or slice");
367 #endif // MLIR_BINDINGS_PYTHON_PYBINDUTILS_H Include the generated interface declarations.
const char * data
Pointer to the first symbol.
intptr_t wrapIndex(intptr_t index)
Transforms index into a legal value to access the underlying sequence.
pybind11::str takeValue()
static constexpr const bool value
PyFileAccumulator(const pybind11::object &fileObject, bool binary)
MlirStringCallback getCallback()
intptr_t linearizeIndex(intptr_t index)
Computes the linear index given the current slice properties.
static void bind(pybind11::module &m)
Binds the indexing and length methods in the Python class.
Defaulting(ReferrentTy &referrent)
pybind11::object getItemSlice(PyObject *slice)
Returns a new instance of the pseudo-container restricted to the given slice.
MlirStringCallback getCallback()
std::vector< ElementTy > dunderAdd(Derived &other)
Returns a new vector (mapped to Python list) containing elements from two slices. ...
pybind11::error_already_set SetPyError(PyObject *excClass, const llvm::Twine &message)
pybind11::class_< Derived > ClassTy
intptr_t size()
Returns the size of slice.
static void bindDerived(ClassTy &)
Hook for derived classes willing to bind more methods.
size_t length
Length of the fragment.
Wrapper around an MlirLocation.
MlirStringCallback getCallback()
Accumulates into a python string from a method that accepts an MlirStringCallback.
A pointer to a sized fragment of a string, not necessarily null-terminated.
A CRTP base class for pseudo-containers willing to support Python-type slicing access on top of index...
Accumulates into a python string from a method that is expected to make one (no more, no less) call to the callback (asserts internally on violation).
Value linearizeIndex(ValueRange indices, ArrayRef< int64_t > strides, int64_t offset, Type integerType, Location loc, OpBuilder &builder)
Generates IR to perform index linearization with the given indices and their corresponding strides...
pybind11::object getItem(intptr_t index)
Returns the element at the given slice index.
void(* MlirStringCallback)(MlirStringRef, void *)
A callback for returning string references.
ReferrentTy * operator->()
ElementTy getElement(intptr_t index)
Returns the index-th element in the slice, supports negative indices.
bool load(pybind11::handle src, bool)
CRTP template for special wrapper types that are allowed to be passed in as 'None' function arguments...
Accumulates int a python file-like object, either writing text (default) or binary.
Sliceable(intptr_t startIndex, intptr_t length, intptr_t step)
Defaulting()=default
Type casters require the type to be default constructible, but using such an instance is illegal...
static handle cast(DefaultingTy src, return_value_policy policy, handle parent)