types.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. #pragma once
  2. #include "error.h"
  3. namespace pkbind {
  4. #define PKBIND_TYPE_IMPL(parent, child, expr) \
  5. \
  6. private: \
  7. friend class type; \
  8. static auto type_or_check() { return expr; } \
  9. \
  10. public: \
  11. using parent::parent; \
  12. using parent::operator=; \
  13. child(const object& o) : parent(type::isinstance<child>(o) ? o : type::of<child>()(o)) {} \
  14. child(object&& o) : \
  15. parent(type::isinstance<child>(o) ? std::move(o) : type::of<child>()(std::move(o))) {}
  16. class type : public object {
  17. protected:
  18. template <typename T>
  19. constexpr inline static bool is_check_v =
  20. std::is_invocable_r_v<bool, decltype(T::type_or_check()), handle>;
  21. static auto type_or_check() { return tp_type; }
  22. public:
  23. using object ::object;
  24. using object ::operator=;
  25. inline static std::unordered_map<std::type_index, py_Type> m_type_map;
  26. // note: type is global instance, so we use ref_t.
  27. explicit type(py_Type type) : object(py_tpobject(type), ref_t{}) {}
  28. py_Type index() const { return py_totype(ptr()); }
  29. const char* name() const { return py_tpname(index()); }
  30. static type of(handle h) { return type(py_typeof(h.ptr())); }
  31. template <typename T>
  32. static type of();
  33. template <typename T>
  34. static bool isinstance(handle obj);
  35. };
  36. class none : public object {
  37. PKBIND_TYPE_IMPL(object, none, tp_NoneType);
  38. // note: none is global instance, so we use ref_t.
  39. none() : object(py_None(), ref_t{}) {}
  40. };
  41. class bool_ : public object {
  42. PKBIND_TYPE_IMPL(object, bool_, tp_bool);
  43. // same as none, bool is a singleton.
  44. bool_(bool value) : object(value ? py_True() : py_False(), ref_t{}) {}
  45. explicit operator bool () { return py_tobool(ptr()); }
  46. };
  47. class int_ : public object {
  48. PKBIND_TYPE_IMPL(object, int_, tp_int);
  49. int_(py_i64 value) : object(alloc_t{}) { py_newint(m_ptr, value); }
  50. explicit operator py_i64 () { return py_toint(ptr()); }
  51. };
  52. class float_ : public object {
  53. PKBIND_TYPE_IMPL(object, float_, tp_float);
  54. float_(py_f64 value) : object(alloc_t{}) { py_newfloat(m_ptr, value); }
  55. explicit operator py_f64 () { return py_tofloat(ptr()); }
  56. };
  57. bool hasattr(handle obj, name name);
  58. class iterable : public object {
  59. PKBIND_TYPE_IMPL(object, iterable, [](handle h) {
  60. return hasattr(h, "__iter__");
  61. });
  62. };
  63. class iterator : public object {
  64. template <typename Dervied>
  65. friend class interface;
  66. iterator() : object(), m_value() {}
  67. iterator(handle h) : object(h, realloc_t{}), m_value() { operator++ (); }
  68. public:
  69. PKBIND_TYPE_IMPL(object, iterator, [](handle h) {
  70. return hasattr(h, "__iter__") && hasattr(h, "__next__");
  71. });
  72. iterator& operator++ () {
  73. int result = raise_call<py_next>(m_ptr);
  74. if(result == 1) {
  75. m_value = object::from_ret();
  76. } else if(result == 0) {
  77. m_value = object();
  78. }
  79. return *this;
  80. }
  81. object operator* () const { return m_value; }
  82. friend bool operator== (const iterator& lhs, const iterator& rhs) {
  83. return lhs.m_value.ptr() == rhs.m_value.ptr();
  84. }
  85. friend bool operator!= (const iterator& lhs, const iterator& rhs) { return !(lhs == rhs); }
  86. static iterator sentinel() { return iterator(); }
  87. private:
  88. object m_value;
  89. };
  90. template <typename Dervied>
  91. iterator interface<Dervied>::begin() const {
  92. raise_call<py_iter>(ptr());
  93. return iterator(py_retval());
  94. }
  95. template <typename Dervied>
  96. iterator interface<Dervied>::end() const {
  97. return iterator::sentinel();
  98. }
  99. class str : public object {
  100. PKBIND_TYPE_IMPL(object, str, tp_str);
  101. str(const char* data, int size) : object(alloc_t{}) { py_newstrv(m_ptr, {data, size}); }
  102. str(const char* data) : str(data, static_cast<int>(strlen(data))) {}
  103. str(std::string_view s) : str(s.data(), static_cast<int>(s.size())) {}
  104. template <typename... Args>
  105. object format(Args&&... args);
  106. };
  107. class tuple : public object {
  108. PKBIND_TYPE_IMPL(object, tuple, tp_tuple);
  109. tuple(int size) : object(alloc_t{}) { py_newtuple(m_ptr, size); }
  110. tuple(std::initializer_list<handle> args) : tuple(static_cast<int>(args.size())) {
  111. int index = 0;
  112. for(auto& arg: args) {
  113. py_tuple_setitem(m_ptr, index++, arg.ptr());
  114. }
  115. }
  116. tuple_accessor operator[] (int index) const;
  117. int size() const { return py_tuple_len(m_ptr); }
  118. bool empty() const { return size() == 0; }
  119. class iterator {
  120. friend tuple;
  121. iterator(py_Ref ptr, int index) : ptr(ptr), index(index) {}
  122. public:
  123. bool operator== (const iterator& other) const { return index == other.index; }
  124. bool operator!= (const iterator& other) const { return index != other.index; }
  125. iterator& operator++ () {
  126. index++;
  127. return *this;
  128. }
  129. object operator* () const { return borrow(py_tuple_getitem(ptr, index)); }
  130. private:
  131. py_Ref ptr;
  132. int index;
  133. };
  134. iterator begin() const { return iterator(m_ptr, 0); }
  135. iterator end() const { return iterator(m_ptr, size()); }
  136. };
  137. class list : public object {
  138. PKBIND_TYPE_IMPL(object, list, tp_list);
  139. list() : object(alloc_t{}) { py_newlist(m_ptr); }
  140. list(int size) : object(alloc_t{}) { py_newlistn(m_ptr, size); }
  141. list(std::initializer_list<handle> args) : list(static_cast<int>(args.size())) {
  142. int index = 0;
  143. for(auto& arg: args) {
  144. py_list_setitem(m_ptr, index++, arg.ptr());
  145. }
  146. }
  147. list_accessor operator[] (int index) const;
  148. int size() const { return py_list_len(m_ptr); }
  149. bool empty() const { return size() == 0; }
  150. void swap(int i, int j) { py_list_swap(m_ptr, i, j); }
  151. void append(handle item) { py_list_append(m_ptr, item.ptr()); }
  152. void insert(int index, handle item) { py_list_insert(m_ptr, index, item.ptr()); }
  153. void remove(int index) { py_list_delitem(m_ptr, index); }
  154. void clear() { py_list_clear(m_ptr); }
  155. class iterator {
  156. friend list;
  157. iterator(py_Ref ptr, int index) : ptr(ptr), index(index) {}
  158. public:
  159. iterator(const iterator&) = default;
  160. bool operator== (const iterator& other) const { return index == other.index; }
  161. bool operator!= (const iterator& other) const { return index != other.index; }
  162. iterator operator++ () {
  163. index++;
  164. return *this;
  165. }
  166. object operator* () const { return borrow(py_list_getitem(ptr, index)); }
  167. private:
  168. py_Ref ptr;
  169. int index;
  170. };
  171. iterator begin() const { return iterator(m_ptr, 0); }
  172. iterator end() const { return iterator(m_ptr, size()); }
  173. };
  174. class dict : public object {
  175. PKBIND_TYPE_IMPL(object, dict, tp_dict);
  176. dict() : object(alloc_t{}) { py_newdict(m_ptr); }
  177. dict(std::initializer_list<arg_with_default> args);
  178. dict_accessor<int> operator[] (int key) const;
  179. dict_accessor<name> operator[] (name key) const;
  180. dict_accessor<handle> operator[] (handle key) const;
  181. int size() const { return py_dict_len(m_ptr); }
  182. bool empty() const { return size() == 0; }
  183. template <typename Fn>
  184. void apply(Fn&& fn) {
  185. static_assert(std::is_invocable_v<Fn, py_Ref, py_Ref>);
  186. using ret = std::invoke_result_t<Fn, py_Ref, py_Ref>;
  187. auto callback = +[](py_Ref key, py_Ref value, void* data) -> bool {
  188. auto fn = reinterpret_cast<Fn*>(data);
  189. if constexpr(std::is_same_v<ret, void>) {
  190. (*fn)(key, value);
  191. return true;
  192. } else {
  193. return (*fn)(key, value);
  194. }
  195. };
  196. raise_call<py_dict_apply>(m_ptr, callback, &fn);
  197. }
  198. class iterator {
  199. friend dict;
  200. iterator() : iter(pkbind::iterator::sentinel()) {}
  201. iterator(handle ptr);
  202. public:
  203. iterator(const iterator&) = default;
  204. bool operator== (const iterator& other) const { return iter == other.iter; }
  205. bool operator!= (const iterator& other) const { return !(*this == other); }
  206. iterator operator++ () {
  207. ++iter;
  208. return *this;
  209. }
  210. std::pair<object, object> operator* () const;
  211. private:
  212. object items;
  213. pkbind::iterator iter;
  214. };
  215. iterator begin() const { return iterator(m_ptr); }
  216. iterator end() const { return iterator(); }
  217. };
  218. class slice : public object {
  219. PKBIND_TYPE_IMPL(object, slice, tp_slice);
  220. };
  221. class set : public object {};
  222. class args : public tuple {
  223. PKBIND_TYPE_IMPL(tuple, args, tp_tuple);
  224. };
  225. class kwargs : public dict {
  226. PKBIND_TYPE_IMPL(dict, kwargs, tp_dict);
  227. };
  228. // TODO:
  229. class capsule : public object {
  230. PKBIND_TYPE_IMPL(object, capsule, *tp_capsule);
  231. struct capsule_impl {
  232. void* data;
  233. void (*destructor)(void*);
  234. };
  235. inline static lazy<py_Type> tp_capsule = +[](py_Type& type) {
  236. type = py_newtype("capsule", tp_object, nullptr, [](void* data) {
  237. auto impl = static_cast<capsule_impl*>(data);
  238. if(impl->data && impl->destructor) { impl->destructor(impl->data); }
  239. });
  240. };
  241. capsule(void* data, void (*destructor)(void*) = nullptr) : object(alloc_t{}) {
  242. void* impl = py_newobject(m_ptr, tp_capsule, 0, sizeof(capsule_impl));
  243. new (impl) capsule_impl{data, destructor};
  244. }
  245. void* data() { return static_cast<capsule_impl*>(py_touserdata(m_ptr))->data; }
  246. template <typename T>
  247. T& cast() {
  248. return *static_cast<T*>(data());
  249. }
  250. };
  251. } // namespace pkbind