1
0

error.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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() { std::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. using error_already_set = python_error;
  19. template <auto Fn, typename... Args>
  20. inline auto raise_call(Args&&... args) {
  21. auto pc = py_peek(0);
  22. auto result = Fn(std::forward<Args>(args)...);
  23. using type = decltype(result);
  24. if constexpr(std::is_same_v<type, bool>) {
  25. if(result != false) { return result; }
  26. } else if constexpr(std::is_same_v<type, int>) {
  27. if(result != -1) { return result; }
  28. } else {
  29. static_assert(dependent_false<type>, "invalid return type");
  30. }
  31. bool o = py_matchexc(tp_Exception);
  32. object e = object::from_ret();
  33. auto what = py_formatexc();
  34. py_clearexc(pc);
  35. throw python_error(what, std::move(e));
  36. }
  37. class stop_iteration {};
  38. class cast_error : public std::runtime_error {
  39. using std::runtime_error::runtime_error;
  40. };
  41. class index_error : public std::runtime_error {
  42. using std::runtime_error::runtime_error;
  43. };
  44. class key_error : public std::runtime_error {
  45. using std::runtime_error::runtime_error;
  46. };
  47. class value_error : public std::runtime_error {
  48. using std::runtime_error::runtime_error;
  49. };
  50. class type_error : public std::runtime_error {
  51. using std::runtime_error::runtime_error;
  52. };
  53. class import_error : public std::runtime_error {
  54. using std::runtime_error::runtime_error;
  55. };
  56. class attribute_error : public std::runtime_error {
  57. using std::runtime_error::runtime_error;
  58. };
  59. inline object::operator bool () const { return raise_call<py_bool>(m_ptr); }
  60. #define PKBIND_BINARY_OPERATOR(name, lop, rop) \
  61. inline object operator name (handle lhs, handle rhs) { \
  62. raise_call<py_binaryop>(lhs.ptr(), rhs.ptr(), lop, rop); \
  63. return object::from_ret(); \
  64. }
  65. PKBIND_BINARY_OPERATOR(==, __eq__, __eq__)
  66. PKBIND_BINARY_OPERATOR(!=, __ne__, __ne__)
  67. PKBIND_BINARY_OPERATOR(<, __lt__, __gt__)
  68. PKBIND_BINARY_OPERATOR(<=, __le__, __ge__)
  69. PKBIND_BINARY_OPERATOR(>, __gt__, __lt__)
  70. PKBIND_BINARY_OPERATOR(>=, __ge__, __le__)
  71. PKBIND_BINARY_OPERATOR(+, __add__, __radd__)
  72. PKBIND_BINARY_OPERATOR(-, __sub__, __rsub__)
  73. PKBIND_BINARY_OPERATOR(*, __mul__, __rmul__)
  74. PKBIND_BINARY_OPERATOR(/, __truediv__, __rtruediv__)
  75. PKBIND_BINARY_OPERATOR(%, __mod__, __rmod__)
  76. // FIXME: support __rand__ ...
  77. PKBIND_BINARY_OPERATOR(&, __and__, 0)
  78. PKBIND_BINARY_OPERATOR(|, __or__, 0)
  79. PKBIND_BINARY_OPERATOR(^, __xor__, 0)
  80. PKBIND_BINARY_OPERATOR(<<, __lshift__, 0)
  81. PKBIND_BINARY_OPERATOR(>>, __rshift__, 0)
  82. #undef PKBIND_BINARY_OPERATOR
  83. } // namespace pkbind