error.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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) {
  26. return result;
  27. }
  28. } else if constexpr(std::is_same_v<type, int>) {
  29. if(result != -1) {
  30. return result;
  31. }
  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. class cast_error : public std::runtime_error {
  43. using std::runtime_error::runtime_error;
  44. };
  45. class index_error : public std::runtime_error {
  46. using std::runtime_error::runtime_error;
  47. };
  48. class key_error : public std::runtime_error {
  49. using std::runtime_error::runtime_error;
  50. };
  51. class value_error : public std::runtime_error {
  52. using std::runtime_error::runtime_error;
  53. };
  54. class type_error : public std::runtime_error {
  55. using std::runtime_error::runtime_error;
  56. };
  57. class import_error : public std::runtime_error {
  58. using std::runtime_error::runtime_error;
  59. };
  60. class attribute_error : public std::runtime_error {
  61. using std::runtime_error::runtime_error;
  62. };
  63. inline object::operator bool () const { return raise_call<py_bool>(m_ptr); }
  64. #define PKBIND_BINARY_OPERATOR(name, lop, rop) \
  65. inline object operator name (handle lhs, handle rhs) { \
  66. raise_call<py_binaryop>(lhs.ptr(), rhs.ptr(), lop, rop); \
  67. return object(retv, object::realloc_t{}); \
  68. }
  69. PKBIND_BINARY_OPERATOR(==, __eq__, __eq__)
  70. PKBIND_BINARY_OPERATOR(!=, __ne__, __ne__)
  71. PKBIND_BINARY_OPERATOR(<, __lt__, __gt__)
  72. PKBIND_BINARY_OPERATOR(<=, __le__, __ge__)
  73. PKBIND_BINARY_OPERATOR(>, __gt__, __lt__)
  74. PKBIND_BINARY_OPERATOR(>=, __ge__, __le__)
  75. PKBIND_BINARY_OPERATOR(+, __add__, __radd__)
  76. PKBIND_BINARY_OPERATOR(-, __sub__, __rsub__)
  77. PKBIND_BINARY_OPERATOR(*, __mul__, __rmul__)
  78. PKBIND_BINARY_OPERATOR(/, __truediv__, __rtruediv__)
  79. PKBIND_BINARY_OPERATOR(%, __mod__, __rmod__)
  80. // FIXME: support __rand__ ...
  81. PKBIND_BINARY_OPERATOR(&, __and__, 0)
  82. PKBIND_BINARY_OPERATOR(|, __or__, 0)
  83. PKBIND_BINARY_OPERATOR(^, __xor__, 0)
  84. PKBIND_BINARY_OPERATOR(<<, __lshift__, 0)
  85. PKBIND_BINARY_OPERATOR(>>, __rshift__, 0)
  86. #undef PKBIND_BINARY_OPERATOR
  87. } // namespace pkbind