10 #ifndef MLIR_BINDINGS_PYTHON_PYBINDUTILS_H 
   11 #define MLIR_BINDINGS_PYTHON_PYBINDUTILS_H 
   15 #include "llvm/ADT/STLExtras.h" 
   16 #include "llvm/ADT/StringRef.h" 
   17 #include "llvm/ADT/Twine.h" 
   18 #include "llvm/Support/DataTypes.h" 
   19 #include "llvm/Support/raw_ostream.h" 
   25 struct std::iterator_traits<
nanobind::detail::fast_iterator> {
 
   51 template <
typename DerivedTy, 
typename T>
 
   73 template <
typename DefaultingTy>
 
   75   NB_TYPE_CASTER(DefaultingTy, const_name(DefaultingTy::kTypeDescription))
 
   77   bool 
from_python(handle src, uint8_t flags, cleanup_list *cleanup) {
 
   81       value = DefaultingTy{DefaultingTy::resolve()};
 
   92           nanobind::cast<typename DefaultingTy::ReferrentTy &>(src)};
 
   94     } 
catch (std::exception &) {
 
   99   static handle 
from_cpp(DefaultingTy src, rv_policy policy,
 
  100                          cleanup_list *cleanup) noexcept {
 
  101     return nanobind::cast(src, policy);
 
  124       nanobind::str pyPart(part.
data,
 
  126       printAccum->
parts.append(std::move(pyPart));
 
  131     nanobind::str delim(
"", 0);
 
  132     return nanobind::cast<nanobind::str>(delim.attr(
"join")(
parts));
 
  142     std::string filePath;
 
  143     if (nanobind::try_cast<std::string>(fileOrStringObject, filePath)) {
 
  145       writeTarget.emplace<llvm::raw_fd_ostream>(filePath, ec);
 
  147         throw nanobind::value_error(
 
  148             (std::string(
"Unable to open file for writing: ") + ec.message())
 
  152       writeTarget.emplace<nanobind::object>(fileOrStringObject.attr(
"write"));
 
  157     return writeTarget.index() == 0 ? getPyWriteCallback()
 
  158                                     : getOstreamCallback();
 
  166       nanobind::gil_scoped_acquire acquire;
 
  170         nanobind::bytes pyBytes(part.
data, part.
length);
 
  171         std::get<nanobind::object>(accum->writeTarget)(pyBytes);
 
  173         nanobind::str pyStr(part.
data,
 
  175         std::get<nanobind::object>(accum->writeTarget)(pyStr);
 
  183       std::get<llvm::raw_fd_ostream>(accum->writeTarget)
 
  188   std::variant<nanobind::object, llvm::raw_fd_ostream> writeTarget;
 
  202       assert(!accum->invoked &&
 
  203              "PySinglePartStringAccumulator called back multiple times");
 
  204       accum->invoked = 
true;
 
  205       accum->value = nanobind::str(part.
data, part.
length);
 
  210     assert(invoked && 
"PySinglePartStringAccumulator not called back");
 
  211     return std::move(value);
 
  216   bool invoked = 
false;
 
  247 template <
typename Derived, 
typename ElementTy>
 
  256       index = length + index;
 
  257     if (index < 0 || index >= length)
 
  264     intptr_t linearIndex = index * step + startIndex;
 
  265     assert(linearIndex >= 0 &&
 
  266            linearIndex < 
static_cast<Derived *
>(
this)->getRawNumElements() &&
 
  267            "linear index out of bounds, the slice is ill-formed");
 
  273   template <
typename T, 
typename... Args>
 
  283       PyErr_SetString(PyExc_IndexError, 
"index out of range");
 
  287     if constexpr (llvm::is_detected<has_maybe_downcast, ElementTy>::value)
 
  288       return static_cast<Derived *
>(
this)
 
  292       return nanobind::cast(
 
  293           static_cast<Derived *
>(
this)->getRawElement(
linearizeIndex(index)));
 
  299     ssize_t start, stop, extraStep, sliceLength;
 
  300     if (PySlice_GetIndicesEx(slice, length, &start, &stop, &extraStep,
 
  301                              &sliceLength) != 0) {
 
  302       PyErr_SetString(PyExc_IndexError, 
"index out of range");
 
  305     return nanobind::cast(
static_cast<Derived *
>(
this)->slice(
 
  306         startIndex + start * step, sliceLength, step * extraStep));
 
  310   explicit Sliceable(intptr_t startIndex, intptr_t length, intptr_t step)
 
  311       : startIndex(startIndex), length(length), step(step) {
 
  312     assert(length >= 0 && 
"expected non-negative slice length");
 
  321       throw nanobind::index_error(
"index out of range");
 
  324     return static_cast<Derived *
>(
this)->getRawElement(
linearizeIndex(index));
 
  328   intptr_t 
size() { 
return length; }
 
  334     std::vector<ElementTy> elements;
 
  335     elements.reserve(length + other.length);
 
  336     for (intptr_t i = 0; i < length; ++i) {
 
  337       elements.push_back(
static_cast<Derived *
>(
this)->
getElement(i));
 
  339     for (intptr_t i = 0; i < other.length; ++i) {
 
  340       elements.push_back(
static_cast<Derived *
>(&other)->
getElement(i));
 
  346   static void bind(nanobind::module_ &m) {
 
  347     auto clazz = nanobind::class_<Derived>(m, Derived::pyClassName)
 
  349     Derived::bindDerived(clazz);
 
  360     auto heap_type = 
reinterpret_cast<PyHeapTypeObject *
>(clazz.ptr());
 
  361     assert(heap_type->ht_type.tp_flags & Py_TPFLAGS_HEAPTYPE &&
 
  362            "must be heap type");
 
  363     heap_type->as_sequence.sq_length = +[](PyObject *rawSelf) -> Py_ssize_t {
 
  364       auto self = nanobind::cast<Derived *>(nanobind::handle(rawSelf));
 
  369     heap_type->as_sequence.sq_item =
 
  370         +[](PyObject *rawSelf, Py_ssize_t index) -> PyObject * {
 
  371       auto self = nanobind::cast<Derived *>(nanobind::handle(rawSelf));
 
  372       return self->getItem(index).release().ptr();
 
  375     heap_type->as_mapping.mp_subscript =
 
  376         +[](PyObject *rawSelf, PyObject *rawSubscript) -> PyObject * {
 
  377       auto self = nanobind::cast<Derived *>(nanobind::handle(rawSelf));
 
  378       Py_ssize_t index = PyNumber_AsSsize_t(rawSubscript, PyExc_IndexError);
 
  379       if (!PyErr_Occurred()) {
 
  381         return self->getItem(index).release().ptr();
 
  386       if (PySlice_Check(rawSubscript)) {
 
  387         return self->getItemSlice(rawSubscript).release().ptr();
 
  390       PyErr_SetString(PyExc_ValueError, 
"expected integer or slice");
 
  421   static inline bool isEqual(
const MlirTypeID &lhs, 
const MlirTypeID &rhs) {
 
Accumulates into a file, either writing text (default) or binary.
PyFileAccumulator(const nanobind::object &fileOrStringObject, bool binary)
MlirStringCallback getCallback()
A CRTP base class for pseudo-containers willing to support Python-type slicing access on top of index...
intptr_t linearizeIndex(intptr_t index)
Computes the linear index given the current slice properties.
static void bind(nanobind::module_ &m)
Binds the indexing and length methods in the Python class.
ElementTy getElement(intptr_t index)
Returns the index-th element in the slice, supports negative indices.
nanobind::object getItemSlice(PyObject *slice)
Returns a new instance of the pseudo-container restricted to the given slice.
nanobind::class_< Derived > ClassTy
std::vector< ElementTy > dunderAdd(Derived &other)
Returns a new vector (mapped to Python list) containing elements from two slices.
static void bindDerived(ClassTy &)
Hook for derived classes willing to bind more methods.
Sliceable(intptr_t startIndex, intptr_t length, intptr_t step)
decltype(&T::maybeDownCast) has_maybe_downcast
Trait to check if T provides a maybeDownCast method.
intptr_t wrapIndex(intptr_t index)
Transforms index into a legal value to access the underlying sequence.
nanobind::object getItem(intptr_t index)
Returns the element at the given slice index.
intptr_t size()
Returns the size of slice.
CRTP template for special wrapper types that are allowed to be passed in as 'None' function arguments...
ReferrentTy * get() const
Defaulting(ReferrentTy &referrent)
Defaulting()=default
Type casters require the type to be default constructible, but using such an instance is illegal.
ReferrentTy * operator->()
MLIR_CAPI_EXPORTED MlirTypeID mlirTypeIDCreate(const void *ptr)
ptr must be 8 byte aligned and unique to a type valid for the duration of the returned type id's usag...
MLIR_CAPI_EXPORTED size_t mlirTypeIDHashValue(MlirTypeID typeID)
Returns the hash value of the type id.
MLIR_CAPI_EXPORTED bool mlirTypeIDEqual(MlirTypeID typeID1, MlirTypeID typeID2)
Checks if two type ids are equal.
void(* MlirStringCallback)(MlirStringRef, void *)
A callback for returning string references.
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Include the generated interface declarations.
A pointer to a sized fragment of a string, not necessarily null-terminated.
const char * data
Pointer to the first symbol.
size_t length
Length of the fragment.
static MlirTypeID getTombstoneKey()
static MlirTypeID getEmptyKey()
static bool isEqual(const MlirTypeID &lhs, const MlirTypeID &rhs)
static unsigned getHashValue(const MlirTypeID &val)
Accumulates into a python string from a method that accepts an MlirStringCallback.
MlirStringCallback getCallback()
Accumulates into a python string from a method that is expected to make one (no more,...
nanobind::str takeValue()
MlirStringCallback getCallback()
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup)
static handle from_cpp(DefaultingTy src, rv_policy policy, cleanup_list *cleanup) noexcept
const value_type reference
std::ptrdiff_t difference_type
std::forward_iterator_tag iterator_category
nanobind::handle value_type