diff --git a/imperative/python/src/ops.cpp b/imperative/python/src/ops.cpp index c1790eade59ebdc35ffad0cfbb076f72d7df08d0..06100741e50698827c3e9df4e9333c98b38ec9c9 100644 --- a/imperative/python/src/ops.cpp +++ b/imperative/python/src/ops.cpp @@ -33,6 +33,18 @@ auto normalize_enum(const std::string& in) { } } // anonymous namespace +#define CATCH_ALL(RETVAL) \ + catch(py::error_already_set& e) { \ + e.restore(); \ + return RETVAL; \ + } catch(py::builtin_exception& e) { \ + e.set_error(); \ + return RETVAL; \ + } catch(std::exception& e) { \ + PyErr_SetString(PyExc_RuntimeError, e.what()); \ + return RETVAL; \ + } \ + namespace { #define PyOp(name) Py##name #define PyOpType(name) PyOp(name)::py_type @@ -99,14 +111,6 @@ PyObject* py_get_generic_impl(PyObject* obj, void* /* closure */) { #define py_get_generic(name, attr) \ py_get_generic_impl().attr), &name::attr> -template -PyObject* py_get_scope_impl(PyObject* obj, void* /* closure */) { - // T: PyOpXXX inst(): return XXX in opdef.h.inl - auto& op = reinterpret_cast(obj)->inst(); - return pyobj_convert_generic::to(op.scope()); -} -#define py_get_scope(class) py_get_scope_impl - template int py_set_generic_impl(PyObject* obj, PyObject* value, void* /* closure */) { if (value == NULL) { @@ -116,51 +120,46 @@ int py_set_generic_impl(PyObject* obj, PyObject* value, void* /* closure */) { auto& op = reinterpret_cast(obj)->inst(); try { op.*attr = pyobj_convert_generic::from(value); - return 0; - } catch(py::error_already_set& e) { - e.restore(); - } catch(py::builtin_exception& e) { - e.set_error(); - } catch(...) { - PyErr_SetString(PyExc_RuntimeError, "Unknown Error"); - } - return -1; + } CATCH_ALL(-1) + return 0; } #define py_set_generic(name, attr) \ py_set_generic_impl().attr), &name::attr> -template -int py_set_scope_impl(PyObject* obj, PyObject* value, void* /* closure */) { - if (value == NULL) { - PyErr_SetString(PyExc_TypeError, "Cannot delete the attribute"); - return -1; - } - auto& op = reinterpret_cast(obj)->inst(); - try { - op.set_scope(pyobj_convert_generic::from(value)); - return 0; - } catch(py::error_already_set& e) { - e.restore(); - } catch(py::builtin_exception& e) { - e.set_error(); - } catch(...) { - PyErr_SetString(PyExc_RuntimeError, "Unknown Error"); - } - return -1; -} -#define py_set_scope(class) py_set_scope_impl - struct PyOpDef { PyObject_HEAD std::shared_ptr op; static PyTypeObject py_type; static std::unordered_map ctype2pytype; + static PyGetSetDef py_getsetters[]; static Py_hash_t tp_hash(PyObject *obj); static PyObject* tp_richcompare(PyObject *self, PyObject *other, int op); }; PyTypeObject PyOpType(OpDef); std::unordered_map PyOp(OpDef)::ctype2pytype; +PyObject* py_get_scope(PyObject* obj, void* /* closure */) { + return pyobj_convert_generic::to( + reinterpret_cast(obj)->op->scope()); +} + +int py_set_scope(PyObject* obj, PyObject* value, void* /* closure */) { + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, "Cannot delete the attribute"); + return -1; + } + try { + reinterpret_cast(obj)->op + ->set_scope(pyobj_convert_generic::from(value)); + } CATCH_ALL(-1) + return 0; +} + +PyGetSetDef PyOp(OpDef)::py_getsetters[] = { + {const_cast("scope"), py_get_scope, py_set_scope, "scope", NULL}, + {NULL} +}; + Py_hash_t PyOp(OpDef)::tp_hash(PyObject *obj) { return static_cast( reinterpret_cast(obj)->op->hash()); @@ -225,6 +224,7 @@ struct pyobj_convert_generic= 0); m.add_object("OpDef", reinterpret_cast(&py_type)); } @@ -309,6 +310,8 @@ void _init_py_op_base(py::module m) { // auto generated opdefs #include "opdef.cpy.inl" +#undef CATCH_ALL + } // anonymous namespace namespace PYBIND11_NAMESPACE { diff --git a/imperative/tablegen/autogen.cpp b/imperative/tablegen/autogen.cpp index eec1a5ec21cc2880b03205d77279beb96989882c..5e2b137a1c7050e0487783a49d08b4bcccd4b260 100644 --- a/imperative/tablegen/autogen.cpp +++ b/imperative/tablegen/autogen.cpp @@ -485,52 +485,44 @@ EnumWrapper<{0}::{1}>::type2str = {{ className, i.name)); } - getsetters.push_back(formatv( - "{{\"scope\", py_get_scope({0}), py_set_scope({0}), \"scope\", NULL},", - className)); - // generate tp_init std::string initBody; if (!op.getMgbAttributes().empty()) { initBody += "static const char* kwlist[] = {"; + + std::vector attr_name_list; llvm::for_each(op.getMgbAttributes(), [&](auto&& attr) { - initBody += formatv("\"{0}\", ", attr.name); + attr_name_list.push_back(attr.name); + }); + attr_name_list.push_back("scope"); + + llvm::for_each(attr_name_list, [&](auto&& attr) { + initBody += formatv("\"{0}\", ", attr); }); - initBody += "\"scope\", "; initBody += "NULL};\n"; initBody += " PyObject "; - std::vector attrs; - llvm::for_each(op.getMgbAttributes(), [&](auto&& attr) { - attrs.push_back(formatv("*{0} = NULL", attr.name)); + std::vector attr_init; + llvm::for_each(attr_name_list, [&](auto&& attr) { + attr_init.push_back(formatv("*{0} = NULL", attr)); }); - initBody += llvm::join(attrs, ", ") + ";\n"; - initBody += " PyObject *scope = NULL;\n"; + initBody += llvm::join(attr_init, ", ") + ";\n"; initBody += " if (!PyArg_ParseTupleAndKeywords(args, kwds, \"|"; // an extra slot created for name - initBody += std::string(op.getMgbAttributes().size() + 1, 'O'); + initBody += std::string(attr_name_list.size(), 'O'); initBody += "\", const_cast(kwlist)"; - llvm::for_each(op.getMgbAttributes(), [&](auto&& attr) { - initBody += formatv(", &{0}", attr.name); + llvm::for_each(attr_name_list, [&](auto&& attr) { + initBody += formatv(", &{0}", attr); }); - initBody += ", &scope"; initBody += "))\n"; initBody += " return -1;\n"; + llvm::for_each(op.getMgbAttributes(), [&](auto&& attr) { initBody += formatv(R"( if ({1}) {{ try {{ reinterpret_cast(self)->inst().{1} = pyobj_convert_generic::from({1}); - } catch(py::error_already_set& e) {{ - e.restore(); - return -1; - } catch(py::builtin_exception& e) {{ - e.set_error(); - return -1; - } catch(...) {{ - PyErr_SetString(PyExc_RuntimeError, "Unknown Error"); - return -1; - } + } CATCH_ALL(-1) } )", className, attr.name); }); @@ -538,18 +530,9 @@ EnumWrapper<{0}::{1}>::type2str = {{ initBody += formatv(R"( if (scope) {{ try {{ - reinterpret_cast(self)->inst().set_scope( - pyobj_convert_generic::from(scope)); - } catch(py::error_already_set& e) {{ - e.restore(); - return -1; - } catch(py::builtin_exception& e) {{ - e.set_error(); - return -1; - } catch(...) {{ - PyErr_SetString(PyExc_RuntimeError, "Unknown Error"); - return -1; - } + reinterpret_cast(self)->op + ->set_scope(pyobj_convert_generic::from(scope)); + } CATCH_ALL(-1) } )", className);