From 66e2b2932545b6b90333e8ef00d7d8dff605266f Mon Sep 17 00:00:00 2001 From: zwimer Date: Fri, 7 Oct 2022 18:34:55 -0700 Subject: [PATCH 1/7] Fix unary operators + rename post/pre inc/decrement operators --- source/function.cpp | 88 +++++++++++++++++++++++++------------------ test/T12.operator.hpp | 4 ++ test/T12.operator.ref | 5 ++- 3 files changed, 60 insertions(+), 37 deletions(-) diff --git a/source/function.cpp b/source/function.cpp index 6d158a41..a773fa5e 100644 --- a/source/function.cpp +++ b/source/function.cpp @@ -40,40 +40,54 @@ using namespace fmt::literals; namespace binder { -static std::map const cpp_python_operator_map{ - {"operator+", "__add__"}, // - {"operator-", "__sub__"}, // - {"operator*", "__mul__"}, // - {"operator/", "__truediv__"}, // - {"operator%", "__mod__"}, // - {"operator~", "__invert__"}, // - {"operator|", "__or__"}, // - {"operator&", "__and__"}, // - {"operator^", "__xor__"}, // - {"operator<<", "__lshift__"}, // - {"operator>>", "__rshift__"}, // - - {"operator+=", "__iadd__"}, // - {"operator-=", "__isub__"}, // - {"operator*=", "__imul__"}, // - {"operator/=", "__itruediv__"}, // - {"operator%=", "__imod__"}, // - {"operator|=", "__ior__"}, // - {"operator&=", "__iand__"}, // - {"operator^=", "__ixor__"}, // - {"operator<<=", "__ilshift__"}, // - {"operator>>=", "__irshift__"}, // - - {"operator()", "__call__"}, // - {"operator==", "__eq__"}, // - {"operator!=", "__ne__"}, // - {"operator[]", "__getitem__"}, // - {"operator=", "assign"}, // - {"operator++", "plus_plus"}, // - {"operator--", "minus_minus"}, // - - {"operator->", "arrow"}, // -}; +// Return the python operator that maps to the C++ operator; returns "" if no mapping exists +string cpp_python_operator(const FunctionDecl & F) { + static std::map> const m { + {"operator+", {"__pos__", "__add__"}}, // + {"operator-", {"__neg__", "__sub__"}}, // + {"operator*", {"dereference", "__mul__"}}, // + {"operator/", {"__truediv__"}}, // + {"operator%", {"__mod__"}}, // + {"operator~", {"__invert__"}}, // + {"operator|", {"__or__"}}, // + {"operator&", {"__and__"}}, // + {"operator^", {"__xor__"}}, // + {"operator<<", {"__lshift__"}}, // + {"operator>>", {"__rshift__"}}, // + + {"operator+=", {"__iadd__"}}, // + {"operator-=", {"__isub__"}}, // + {"operator*=", {"__imul__"}}, // + {"operator/=", {"__itruediv__"}}, // + {"operator%=", {"__imod__"}}, // + {"operator|=", {"__ior__"}}, // + {"operator&=", {"__iand__"}}, // + {"operator^=", {"__ixor__"}}, // + {"operator<<=", {"__ilshift__"}}, // + {"operator>>=", {"__irshift__"}}, // + + {"operator()", {"__call__"}}, // + {"operator==", {"__eq__"}}, // + {"operator!=", {"__ne__"}}, // + {"operator[]", {"__getitem__"}}, // + {"operator=", {"assign"}}, // + {"operator++", {"pre_increment", "pre_increment"}}, // + {"operator--", {"pre_decrement", "post_decrement"}}, // + + {"operator->", {"arrow"}} // + }; + const auto & found = m.find(F.getNameAsString()); + if (found != m.end()) { + const auto & vec { found->second }; + if (vec.size() == 1) { return vec[0]; } + const auto n = F.getNumParams(); + if (vec.size() > n) { + return vec[n]; + } + } + return {}; +} + // Generate function argument list separate by comma: int, bool, std::string string function_arguments(clang::FunctionDecl const *record) @@ -211,7 +225,9 @@ string template_specialization(FunctionDecl const *F) // generate string represetiong class name that could be used in python string python_function_name(FunctionDecl const *F) { - if( F->isOverloadedOperator() ) return cpp_python_operator_map.at(F->getNameAsString()); + if( F->isOverloadedOperator() ) { + return cpp_python_operator(*F); + } else { // if( auto m = dyn_cast(F) ) { // } @@ -481,7 +497,7 @@ bool is_bindable_raw(FunctionDecl const *F) if( F->isOverloadedOperator() ) { // outs() << "Operator: " << F->getNameAsString() << '\n'; - if( !isa(F) or !cpp_python_operator_map.count(F->getNameAsString()) ) return false; + if( !isa(F) or (cpp_python_operator(*F).size() == 0) ) return false; } r &= F->getTemplatedKind() != FunctionDecl::TK_FunctionTemplate /*and !F->isOverloadedOperator()*/ and !isa(F) and !F->isDeleted(); diff --git a/test/T12.operator.hpp b/test/T12.operator.hpp index 5d185b49..59fd4235 100644 --- a/test/T12.operator.hpp +++ b/test/T12.operator.hpp @@ -16,6 +16,10 @@ struct T { T &operator~() { return *this; } + T &operator+() { return *this; } + T &operator-() { return *this; } + T &operator*() { return *this; } + T &operator+(int) { return *this; } T &operator-(int) { return *this; } T &operator*(int) { return *this; } diff --git a/test/T12.operator.ref b/test/T12.operator.ref index 94a03923..0bba291c 100644 --- a/test/T12.operator.ref +++ b/test/T12.operator.ref @@ -19,6 +19,9 @@ void bind_T12_operator(std::function< pybind11::module &(std::string const &name pybind11::class_> cl(M(""), "T", ""); cl.def( pybind11::init( [](){ return new T(); } ) ); cl.def("__invert__", (struct T & (T::*)()) &T::operator~, "C++: T::operator~() --> struct T &", pybind11::return_value_policy::automatic); + cl.def("__pos__", (struct T & (T::*)()) &T::operator+, "C++: T::operator+() --> struct T &", pybind11::return_value_policy::automatic); + cl.def("__neg__", (struct T & (T::*)()) &T::operator-, "C++: T::operator-() --> struct T &", pybind11::return_value_policy::automatic); + cl.def("dereference", (struct T & (T::*)()) &T::operator*, "C++: T::operator*() --> struct T &", pybind11::return_value_policy::automatic); cl.def("__add__", (struct T & (T::*)(int)) &T::operator+, "C++: T::operator+(int) --> struct T &", pybind11::return_value_policy::automatic, pybind11::arg("")); cl.def("__sub__", (struct T & (T::*)(int)) &T::operator-, "C++: T::operator-(int) --> struct T &", pybind11::return_value_policy::automatic, pybind11::arg("")); cl.def("__mul__", (struct T & (T::*)(int)) &T::operator*, "C++: T::operator*(int) --> struct T &", pybind11::return_value_policy::automatic, pybind11::arg("")); @@ -100,4 +103,4 @@ PYBIND11_MODULE(T12_operator, root_module) { // T12_operator.cpp // Modules list file: TEST/T12_operator.modules -// +// From 90c8b2ea14a5b20e9cdb2bcba715e8acc1a223e2 Mon Sep 17 00:00:00 2001 From: zwimer Date: Tue, 11 Oct 2022 17:41:57 -0700 Subject: [PATCH 2/7] No pre/post increment changes --- source/function.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/function.cpp b/source/function.cpp index a773fa5e..610a33c0 100644 --- a/source/function.cpp +++ b/source/function.cpp @@ -71,8 +71,8 @@ string cpp_python_operator(const FunctionDecl & F) { {"operator!=", {"__ne__"}}, // {"operator[]", {"__getitem__"}}, // {"operator=", {"assign"}}, // - {"operator++", {"pre_increment", "pre_increment"}}, // - {"operator--", {"pre_decrement", "post_decrement"}}, // + {"operator++", {"plus_plus"}}, // + {"operator--", {"minus_minus"}}, // {"operator->", {"arrow"}} // }; From d1744f3d247788209d7d9d055c951de0e0684844 Mon Sep 17 00:00:00 2001 From: zwimer Date: Tue, 11 Oct 2022 17:42:57 -0700 Subject: [PATCH 3/7] Documentation update --- documentation/limitations.rst | 8 -------- 1 file changed, 8 deletions(-) diff --git a/documentation/limitations.rst b/documentation/limitations.rst index f9125461..9d973cd6 100644 --- a/documentation/limitations.rst +++ b/documentation/limitations.rst @@ -77,11 +77,3 @@ Miscellaneous 1. The pre/post increment operators both map to ``plus_plus`, with the pre-increment operator being invoked via ``a.plus_plus()`` and post-increment via ``.plus_plus(0)``; just as the operators are technically defined in C++. The same is true for the pre/post decrement operators, both called ``minus_minus``. 2. User defined literals ``operator"" _foo`` end up being named as ``operator_foo``. - ----------- -Known Bugs ----------- - -1. The unary ``operator+`` and unary ``operator-`` currently map to ``__add__`` and ``__sub__`` rather than ``__pos__`` and ``__neg__``. - -2. The unary ``operator*`` (dereference operator) will currently map to ``__mul__``. From 78c7711300ad3163ec4c6734bf4ea13a3fd25b95 Mon Sep 17 00:00:00 2001 From: zwimer Date: Tue, 11 Oct 2022 17:52:17 -0700 Subject: [PATCH 4/7] post/pre increment ops changed --- source/function.cpp | 4 ++-- test/T12.operator.hpp | 2 ++ test/T12.operator.ref | 6 ++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/source/function.cpp b/source/function.cpp index 610a33c0..a773fa5e 100644 --- a/source/function.cpp +++ b/source/function.cpp @@ -71,8 +71,8 @@ string cpp_python_operator(const FunctionDecl & F) { {"operator!=", {"__ne__"}}, // {"operator[]", {"__getitem__"}}, // {"operator=", {"assign"}}, // - {"operator++", {"plus_plus"}}, // - {"operator--", {"minus_minus"}}, // + {"operator++", {"pre_increment", "pre_increment"}}, // + {"operator--", {"pre_decrement", "post_decrement"}}, // {"operator->", {"arrow"}} // }; diff --git a/test/T12.operator.hpp b/test/T12.operator.hpp index 59fd4235..2a5ad949 100644 --- a/test/T12.operator.hpp +++ b/test/T12.operator.hpp @@ -51,4 +51,6 @@ struct T T &operator=(const T &) { return *this; } T &operator++() { return *this; } T &operator--() { return *this; } + T &operator++(int) { return *this; } + T &operator--(int) { return *this; } }; diff --git a/test/T12.operator.ref b/test/T12.operator.ref index 0bba291c..8a2ed9e7 100644 --- a/test/T12.operator.ref +++ b/test/T12.operator.ref @@ -47,8 +47,10 @@ void bind_T12_operator(std::function< pybind11::module &(std::string const &name cl.def("__ne__", (bool (T::*)(const struct T &)) &T::operator!=, "C++: T::operator!=(const struct T &) --> bool", pybind11::arg("")); cl.def("__getitem__", (bool (T::*)(int)) &T::operator[], "C++: T::operator[](int) --> bool", pybind11::arg("")); cl.def("assign", (struct T & (T::*)(const struct T &)) &T::operator=, "C++: T::operator=(const struct T &) --> struct T &", pybind11::return_value_policy::automatic, pybind11::arg("")); - cl.def("plus_plus", (struct T & (T::*)()) &T::operator++, "C++: T::operator++() --> struct T &", pybind11::return_value_policy::automatic); - cl.def("minus_minus", (struct T & (T::*)()) &T::operator--, "C++: T::operator--() --> struct T &", pybind11::return_value_policy::automatic); + cl.def("pre_increment", (struct T & (T::*)()) &T::operator++, "C++: T::operator++() --> struct T &", pybind11::return_value_policy::automatic); + cl.def("pre_decrement", (struct T & (T::*)()) &T::operator--, "C++: T::operator--() --> struct T &", pybind11::return_value_policy::automatic); + cl.def("post_increment", (struct T & (T::*)(int)) &T::operator++, "C++: T::operator++(int) --> struct T &", pybind11::return_value_policy::automatic, pybind11::arg("")); + cl.def("post_decrement", (struct T & (T::*)(int)) &T::operator--, "C++: T::operator--(int) --> struct T &", pybind11::return_value_policy::automatic, pybind11::arg("")); } } From 75af95198e9fe57425fea3172a46ddae0f971e9b Mon Sep 17 00:00:00 2001 From: zwimer Date: Tue, 11 Oct 2022 17:52:50 -0700 Subject: [PATCH 5/7] Documentation update --- documentation/limitations.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/documentation/limitations.rst b/documentation/limitations.rst index 9d973cd6..b14cd956 100644 --- a/documentation/limitations.rst +++ b/documentation/limitations.rst @@ -74,6 +74,4 @@ The following operators will be ignored by binder: Miscellaneous ------------- -1. The pre/post increment operators both map to ``plus_plus`, with the pre-increment operator being invoked via ``a.plus_plus()`` and post-increment via ``.plus_plus(0)``; just as the operators are technically defined in C++. The same is true for the pre/post decrement operators, both called ``minus_minus``. - -2. User defined literals ``operator"" _foo`` end up being named as ``operator_foo``. +1. User defined literals ``operator"" _foo`` end up being named as ``operator_foo``. From 00ab10d5f1d418bfb5b6852aeda109752d97058d Mon Sep 17 00:00:00 2001 From: zwimer Date: Wed, 12 Oct 2022 17:52:39 -0700 Subject: [PATCH 6/7] whitespace --- source/function.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/source/function.cpp b/source/function.cpp index f34554bb..a4fcd6c6 100644 --- a/source/function.cpp +++ b/source/function.cpp @@ -73,7 +73,6 @@ string cpp_python_operator(const FunctionDecl & F) { {"operator!=", {"__ne__"}}, // {"operator[]", {"__getitem__"}}, // {"operator=", {"assign"}}, // - {"operator++", {"pre_increment", "pre_increment"}}, // {"operator--", {"pre_decrement", "post_decrement"}}, // From c3bb141d76577629a0fd03a41499bc12276a3135 Mon Sep 17 00:00:00 2001 From: zwimer Date: Tue, 13 Dec 2022 14:54:13 -0700 Subject: [PATCH 7/7] Fix typo --- source/function.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/function.cpp b/source/function.cpp index a4fcd6c6..43e3bc7e 100644 --- a/source/function.cpp +++ b/source/function.cpp @@ -73,7 +73,7 @@ string cpp_python_operator(const FunctionDecl & F) { {"operator!=", {"__ne__"}}, // {"operator[]", {"__getitem__"}}, // {"operator=", {"assign"}}, // - {"operator++", {"pre_increment", "pre_increment"}}, // + {"operator++", {"pre_increment", "post_increment"}}, // {"operator--", {"pre_decrement", "post_decrement"}}, // {"operator->", {"arrow"}} //