error.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #pragma once
  2. #include "object.h"
  3. namespace pkbind {
  4. /// represent a all exception raised by python.
  5. class python_error : public std::exception {
  6. public:
  7. python_error(char* what, object exception) : m_what(what), m_exception(std::move(exception)) {}
  8. const char* what() const noexcept override { return m_what; }
  9. // get the python exception object
  10. object& exception() { return m_exception; }
  11. ~python_error() { py_free(m_what); }
  12. bool match(py_Type type) const { return py_isinstance(m_exception.ptr(), type); }
  13. bool match(class type) const;
  14. private:
  15. char* m_what;
  16. object m_exception;
  17. };
  18. class error_already_set : public std::exception {
  19. public:
  20. bool match(py_Type type) const { return py_matchexc(type); }
  21. bool match(type type) const;
  22. };
  23. template <auto Fn, typename... Args>
  24. inline auto raise_call(Args&&... args) {
  25. auto pc = py_peek(0);
  26. auto result = Fn(std::forward<Args>(args)...);
  27. using type = decltype(result);
  28. if constexpr(std::is_same_v<type, bool>) {
  29. if(result != false) { return result; }
  30. } else if constexpr(std::is_same_v<type, int>) {
  31. if(result != -1) { return result; }
  32. } else {
  33. static_assert(dependent_false<type>, "invalid return type");
  34. }
  35. bool o = py_matchexc(tp_Exception);
  36. object e = object::from_ret();
  37. auto what = py_formatexc();
  38. py_clearexc(pc);
  39. throw python_error(what, std::move(e));
  40. }
  41. class stop_iteration {
  42. public:
  43. stop_iteration() = default;
  44. stop_iteration(object value) : m_value(std::move(value)) {}
  45. object value() const { return m_value; }
  46. private:
  47. object m_value;
  48. };
  49. class cast_error : public std::runtime_error {
  50. using std::runtime_error::runtime_error;
  51. };
  52. class index_error : public std::runtime_error {
  53. using std::runtime_error::runtime_error;
  54. };
  55. class key_error : public std::runtime_error {
  56. using std::runtime_error::runtime_error;
  57. };
  58. class value_error : public std::runtime_error {
  59. using std::runtime_error::runtime_error;
  60. };
  61. class type_error : public std::runtime_error {
  62. using std::runtime_error::runtime_error;
  63. };
  64. class import_error : public std::runtime_error {
  65. using std::runtime_error::runtime_error;
  66. };
  67. class attribute_error : public std::runtime_error {
  68. using std::runtime_error::runtime_error;
  69. };
  70. inline object::operator bool () const { return raise_call<py_bool>(m_ptr); }
  71. #define PKBIND_BINARY_OPERATOR(name, lop, rop) \
  72. inline object operator name (handle lhs, handle rhs) { \
  73. raise_call<py_binaryop>(lhs.ptr(), rhs.ptr(), lop, rop); \
  74. return object::from_ret(); \
  75. }
  76. PKBIND_BINARY_OPERATOR(==, py_name("__eq__"), py_name("__eq__"))
  77. PKBIND_BINARY_OPERATOR(!=, py_name("__ne__"), py_name("__ne__"))
  78. PKBIND_BINARY_OPERATOR(<, py_name("__lt__"), py_name("__gt__"))
  79. PKBIND_BINARY_OPERATOR(<=, py_name("__le__"), py_name("__ge__"))
  80. PKBIND_BINARY_OPERATOR(>, py_name("__gt__"), py_name("__lt__"))
  81. PKBIND_BINARY_OPERATOR(>=, py_name("__ge__"), py_name("__le__"))
  82. PKBIND_BINARY_OPERATOR(+, py_name("__add__"), py_name("__radd__"))
  83. PKBIND_BINARY_OPERATOR(-, py_name("__sub__"), py_name("__rsub__"))
  84. PKBIND_BINARY_OPERATOR(*, py_name("__mul__"), py_name("__rmul__"))
  85. PKBIND_BINARY_OPERATOR(/, py_name("__truediv__"), py_name("__rtruediv__"))
  86. PKBIND_BINARY_OPERATOR(%, py_name("__mod__"), py_name("__rmod__"))
  87. // FIXME: support __rand__ ...
  88. PKBIND_BINARY_OPERATOR(&, py_name("__and__"), nullptr)
  89. PKBIND_BINARY_OPERATOR(|, py_name("__or__"), nullptr)
  90. PKBIND_BINARY_OPERATOR(^, py_name("__xor__"), nullptr)
  91. PKBIND_BINARY_OPERATOR(<<, py_name("__lshift__"), nullptr)
  92. PKBIND_BINARY_OPERATOR(>>, py_name("__rshift__"), nullptr)
  93. #undef PKBIND_BINARY_OPERATOR
  94. } // namespace pkbind