diff --git a/operators.h b/operators.h new file mode 100644 index 00000000..31fdd3aa --- /dev/null +++ b/operators.h @@ -0,0 +1,348 @@ +#ifndef OPERATORS_UK112000_H_ +#define OPERATORS_UK112000_H_ + +#include "functions.h" +#include + +namespace py +{ + +namespace detail +{ + + template <> + struct define_operator<0> + { + template + struct operator_function : Function + { + PyObject* do_call(PyObject* arguments, PyObject* keywords) const + { + PyErr_SetString(PyExc_TypeError, "operator not implemented"); + throw ErrorAlreadySet(); + } + + const char* description() const + { return "__error__"; } + + }; + template + struct roperator_function : Function + { + PyObject* do_call(PyObject* arguments, PyObject* keywords) const + { + PyErr_SetString(PyExc_TypeError, "operator not implemented"); + throw ErrorAlreadySet(); + } + + const char* description() const + { return "__error__"; } + + }; + + static const char * name() { return "__error__"; } + static const char * rname() { return "__error__"; } + }; + +#define py_define_binary_operators(id, oper) \ + template <> \ + struct define_operator \ + { \ + template \ + struct operator_function : Function \ + { \ + PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const \ + { \ + Tuple args(Ptr(arguments, Ptr::new_ref)); \ + \ + return PY_CONVERSION::to_python( \ + PY_CONVERSION::from_python(args[0].get(), py::Type()) oper \ + PY_CONVERSION::from_python(args[1].get(), py::Type())); \ + } \ + \ + const char* description() const \ + { return "__" #id "__"; } \ + \ + }; \ + template \ + struct roperator_function : Function \ + { \ + PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const \ + { \ + Tuple args(Ptr(arguments, Ptr::new_ref)); \ + \ + return PY_CONVERSION::to_python( \ + PY_CONVERSION::from_python(args[1].get(), py::Type()) oper \ + PY_CONVERSION::from_python(args[0].get(), py::Type())); \ + } \ + \ + const char* description() const \ + { return "__r" #id "__"; } \ + \ + }; \ + \ + static const char * name() { return "__" #id "__"; } \ + static const char * rname() { return "__r" #id "__"; } \ + } + +#define py_define_unary_operators(id, oper) \ + template <> \ + struct define_operator \ + { \ + template \ + struct operator_function : Function \ + { \ + PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const \ + { \ + Tuple args(Ptr(arguments, Ptr::new_ref)); \ + \ + return PY_CONVERSION::to_python( \ + oper(PY_CONVERSION::from_python(args[0].get(), py::Type()))); \ + } \ + \ + const char* description() const \ + { return "__" #id "__"; } \ + \ + }; \ + \ + static const char * name() { return "__" #id "__"; } \ + } + +#define py_define_conversion_operators(id, oper) \ + template <> \ + struct define_operator \ + { \ + template \ + struct operator_function : Function \ + { \ + PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const \ + { \ + Tuple args(Ptr(arguments, Ptr::new_ref)); \ + \ + return PY_CONVERSION::to_python( \ + oper(PY_CONVERSION::from_python(args[0].get(), py::Type()))); \ + } \ + \ + const char* description() const \ + { return "__" #id "_"; } \ + \ + }; \ + \ + static const char * name() { return "__" #id "_"; } \ + } + + py_define_binary_operators(add, +); + py_define_binary_operators(sub, -); + py_define_binary_operators(mul, *); + py_define_binary_operators(div, /); + py_define_binary_operators(mod, %); + py_define_binary_operators(lshift, <<); + py_define_binary_operators(rshift, >>); + py_define_binary_operators(and, &); + py_define_binary_operators(xor, ^); + py_define_binary_operators(or, |); + + py_define_unary_operators(neg, -); + py_define_unary_operators(pos, +); + py_define_unary_operators(abs, abs); + py_define_unary_operators(invert, ~); + + py_define_conversion_operators(int, int); + py_define_conversion_operators(long, long); + py_define_conversion_operators(float, double); + +#undef py_define_binary_operators +#undef py_define_unary_operators +#undef py_define_conversion_operators + + template <> + struct define_operator + { + template + struct operator_function : Function + { + PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const + { + Tuple args(Ptr(arguments, Ptr::new_ref)); + + if(args.size() == 3 && args[2]->ob_type != Py_None->ob_type) + { + PyErr_SetString(PyExc_TypeError, "expected 2 arguments, got 3"); + throw ArgumentError(); + } + + return PY_CONVERSION::to_python( + pow(PY_CONVERSION::from_python(args[0].get(), py::Type()), + PY_CONVERSION::from_python(args[1].get(), py::Type()))); + } + + const char* description() const + { return "__pow__"; } + + }; + + template + struct roperator_function : Function + { + PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const + { + Tuple args(Ptr(arguments, Ptr::new_ref)); + + if(args.size() == 3 && args[2]->ob_type != Py_None->ob_type) + { + PyErr_SetString(PyExc_TypeError, "expected 2 arguments, got 3"); + throw ArgumentError(); + } + + return PY_CONVERSION::to_python( + pow(PY_CONVERSION::from_python(args[1].get(), py::Type()), + PY_CONVERSION::from_python(args[0].get(), py::Type()))); + } + + const char* description() const + { return "__rpow__"; } + + }; + + static const char * name() { return "__pow__"; } + static const char * rname() { return "__rpow__"; } + }; + + template <> + struct define_operator + { + template + struct operator_function : Function + { + PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const + { + Tuple args(Ptr(arguments, Ptr::new_ref)); + PyObject * res = PyTuple_New(2); + + PyTuple_SET_ITEM(res, 0, + PY_CONVERSION::to_python( + PY_CONVERSION::from_python(args[0].get(), py::Type()) / + PY_CONVERSION::from_python(args[1].get(), py::Type()))); + PyTuple_SET_ITEM(res, 1, + PY_CONVERSION::to_python( + PY_CONVERSION::from_python(args[0].get(), py::Type()) % + PY_CONVERSION::from_python(args[1].get(), py::Type()))); + + return res; + } + + const char* description() const + { return "__divmod__"; } + + }; + + template + struct roperator_function : Function + { + PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const + { + Tuple args(Ptr(arguments, Ptr::new_ref)); + PyObject * res = PyTuple_New(2); + + PyTuple_SET_ITEM(res, 0, + PY_CONVERSION::to_python( + PY_CONVERSION::from_python(args[1].get(), py::Type()) / + PY_CONVERSION::from_python(args[0].get(), py::Type()))); + PyTuple_SET_ITEM(res, 1, + PY_CONVERSION::to_python( + PY_CONVERSION::from_python(args[1].get(), py::Type()) % + PY_CONVERSION::from_python(args[0].get(), py::Type()))); + + return res; + } + + const char* description() const + { return "__rdivmod__"; } + + }; + + static const char * name() { return "__divmod__"; } + static const char * rname() { return "__rdivmod__"; } + }; + + template <> + struct define_operator + { + template + struct operator_function : Function + { + PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const + { + Tuple args(Ptr(arguments, Ptr::new_ref)); + + return PY_CONVERSION::to_python( + (PY_CONVERSION::from_python(args[0].get(), py::Type()) < + PY_CONVERSION::from_python(args[1].get(), py::Type())) ? + - 1 : + (PY_CONVERSION::from_python(args[1].get(), py::Type()) < + PY_CONVERSION::from_python(args[0].get(), py::Type())) ? + 1 : + 0) ; + } + + const char* description() const + { return "__cmp__"; } + + }; + + template + struct roperator_function : Function + { + PyObject* do_call(PyObject* arguments, PyObject* /* keywords */) const + { + Tuple args(Ptr(arguments, Ptr::new_ref)); + + return PY_CONVERSION::to_python( + (PY_CONVERSION::from_python(args[1].get(), py::Type()) < + PY_CONVERSION::from_python(args[0].get(), py::Type())) ? + - 1 : + (PY_CONVERSION::from_python(args[0].get(), py::Type()) < + PY_CONVERSION::from_python(args[1].get(), py::Type())) ? + 1 : + 0) ; + } + + const char* description() const + { return "__rcmp__"; } + + }; + + static const char * name() { return "__cmp__"; } + static const char * rname() { return "__rcmp__"; } + }; + + template <> + struct define_operator + { + template + struct operator_function : Function + { + PyObject* do_call(PyObject* arguments, PyObject* keywords) const + { + Tuple args(Ptr(arguments, Ptr::new_ref)); + + std::strstream s; + s << PY_CONVERSION::from_python(args[0].get(), py::Type()); + + return PY_CONVERSION::to_python(const_cast(s.str())); + } + + const char* description() const + { return "__str__"; } + + }; + + static const char * name() { return "__str__"; } + }; + + +} // namespace detail + +} // namespace py + +#endif /* OPERATORS_UK112000_H_ */