| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- #pragma once
- #include "object.h"
- namespace pkbind {
- /// represent a all exception raised by python.
- class python_error : public std::exception {
- public:
- python_error(char* what, object exception) : m_what(what), m_exception(std::move(exception)) {}
- const char* what() const noexcept override { return m_what; }
- // get the python exception object
- object& exception() { return m_exception; }
- ~python_error() { std::free(m_what); }
- bool match(py_Type type) const { return py_isinstance(m_exception.ptr(), type); }
- bool match(class type) const;
- private:
- char* m_what;
- object m_exception;
- };
- using error_already_set = python_error;
- template <auto Fn, typename... Args>
- inline auto raise_call(Args&&... args) {
- auto pc = py_peek(0);
- auto result = Fn(std::forward<Args>(args)...);
- using type = decltype(result);
- if constexpr(std::is_same_v<type, bool>) {
- if(result != false) { return result; }
- } else if constexpr(std::is_same_v<type, int>) {
- if(result != -1) { return result; }
- } else {
- static_assert(dependent_false<type>, "invalid return type");
- }
- bool o = py_matchexc(tp_Exception);
- object e = object::from_ret();
- auto what = py_formatexc();
- py_clearexc(pc);
- throw python_error(what, std::move(e));
- }
- class stop_iteration {};
- class cast_error : public std::runtime_error {
- using std::runtime_error::runtime_error;
- };
- class index_error : public std::runtime_error {
- using std::runtime_error::runtime_error;
- };
- class key_error : public std::runtime_error {
- using std::runtime_error::runtime_error;
- };
- class value_error : public std::runtime_error {
- using std::runtime_error::runtime_error;
- };
- class type_error : public std::runtime_error {
- using std::runtime_error::runtime_error;
- };
- class import_error : public std::runtime_error {
- using std::runtime_error::runtime_error;
- };
- class attribute_error : public std::runtime_error {
- using std::runtime_error::runtime_error;
- };
- inline object::operator bool () const { return raise_call<py_bool>(m_ptr); }
- #define PKBIND_BINARY_OPERATOR(name, lop, rop) \
- inline object operator name (handle lhs, handle rhs) { \
- raise_call<py_binaryop>(lhs.ptr(), rhs.ptr(), lop, rop); \
- return object::from_ret(); \
- }
- PKBIND_BINARY_OPERATOR(==, __eq__, __eq__)
- PKBIND_BINARY_OPERATOR(!=, __ne__, __ne__)
- PKBIND_BINARY_OPERATOR(<, __lt__, __gt__)
- PKBIND_BINARY_OPERATOR(<=, __le__, __ge__)
- PKBIND_BINARY_OPERATOR(>, __gt__, __lt__)
- PKBIND_BINARY_OPERATOR(>=, __ge__, __le__)
- PKBIND_BINARY_OPERATOR(+, __add__, __radd__)
- PKBIND_BINARY_OPERATOR(-, __sub__, __rsub__)
- PKBIND_BINARY_OPERATOR(*, __mul__, __rmul__)
- PKBIND_BINARY_OPERATOR(/, __truediv__, __rtruediv__)
- PKBIND_BINARY_OPERATOR(%, __mod__, __rmod__)
- // FIXME: support __rand__ ...
- PKBIND_BINARY_OPERATOR(&, __and__, 0)
- PKBIND_BINARY_OPERATOR(|, __or__, 0)
- PKBIND_BINARY_OPERATOR(^, __xor__, 0)
- PKBIND_BINARY_OPERATOR(<<, __lshift__, 0)
- PKBIND_BINARY_OPERATOR(>>, __rshift__, 0)
- #undef PKBIND_BINARY_OPERATOR
- } // namespace pkbind
|