[pypy-commit] pypy reflex-support: o) on demand lookup of global operator== (only for CINT backend for now)

wlav noreply at buildbot.pypy.org
Tue Jun 26 21:15:52 CEST 2012


Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r55838:3b63338d1a80
Date: 2012-06-25 15:19 -0700
http://bitbucket.org/pypy/pypy/changeset/3b63338d1a80/

Log:	o) on demand lookup of global operator== (only for CINT backend for
	now) o) reworking of method indexing to give more flexibility to
	backend

diff --git a/pypy/module/cppyy/capi/__init__.py b/pypy/module/cppyy/capi/__init__.py
--- a/pypy/module/cppyy/capi/__init__.py
+++ b/pypy/module/cppyy/capi/__init__.py
@@ -23,6 +23,8 @@
 C_NULL_OBJECT = rffi.cast(C_OBJECT, _C_OPAQUE_NULL)
 
 C_METHOD = _C_OPAQUE_PTR
+C_INDEX = rffi.LONG
+WLAVC_INDEX = rffi.LONG
 
 C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP)
 C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER)
@@ -148,23 +150,22 @@
     [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], lltype.Void,
     threadsafe=ts_call,
     compilation_info=backend.eci)
-
 _c_call_o = rffi.llexternal(
     "cppyy_call_o",
     [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP, C_TYPE], rffi.LONG,
     threadsafe=ts_call,
     compilation_info=backend.eci)
-def c_call_o(method_index, cppobj, nargs, args, cppclass):
-    return _c_call_o(method_index, cppobj, nargs, args, cppclass.handle)
+def c_call_o(method, cppobj, nargs, args, cppclass):
+    return _c_call_o(method, cppobj, nargs, args, cppclass.handle)
 
 _c_get_methptr_getter = rffi.llexternal(
     "cppyy_get_methptr_getter",
-    [C_SCOPE, rffi.INT], C_METHPTRGETTER_PTR,
+    [C_SCOPE, C_INDEX], C_METHPTRGETTER_PTR,
     threadsafe=ts_reflect,
     compilation_info=backend.eci,
     elidable_function=True)
-def c_get_methptr_getter(cppscope, method_index):
-    return _c_get_methptr_getter(cppscope.handle, method_index)
+def c_get_methptr_getter(cppscope, index):
+    return _c_get_methptr_getter(cppscope.handle, index)
 
 # handling of function argument buffer ---------------------------------------
 c_allocate_function_args = rffi.llexternal(
@@ -236,7 +237,6 @@
     compilation_info=backend.eci)
 def c_base_name(cppclass, base_index):
     return charp2str_free(_c_base_name(cppclass.handle, base_index))
-
 _c_is_subtype = rffi.llexternal(
     "cppyy_is_subtype",
     [C_TYPE, C_TYPE], rffi.INT,
@@ -269,87 +269,102 @@
     compilation_info=backend.eci)
 def c_num_methods(cppscope):
     return _c_num_methods(cppscope.handle)
+_c_method_index_at = rffi.llexternal(
+    "cppyy_method_index_at",
+    [C_SCOPE, rffi.INT], C_INDEX,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_method_index_at(cppscope, imethod):
+    return _c_method_index_at(cppscope.handle, imethod)
+_c_method_index_from_name = rffi.llexternal(
+    "cppyy_method_index_from_name",
+    [C_SCOPE, rffi.CCHARP], C_INDEX,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+def c_method_index_from_name(cppscope, name):
+    return _c_method_index_from_name(cppscope.handle, name)
+
 _c_method_name = rffi.llexternal(
     "cppyy_method_name",
-    [C_SCOPE, rffi.INT], rffi.CCHARP,
+    [C_SCOPE, C_INDEX], rffi.CCHARP,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_method_name(cppscope, method_index):
-    return charp2str_free(_c_method_name(cppscope.handle, method_index))
+def c_method_name(cppscope, index):
+    return charp2str_free(_c_method_name(cppscope.handle, index))
 _c_method_result_type = rffi.llexternal(
     "cppyy_method_result_type",
-    [C_SCOPE, rffi.INT], rffi.CCHARP,
+    [C_SCOPE, C_INDEX], rffi.CCHARP,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_method_result_type(cppscope, method_index):
-    return charp2str_free(_c_method_result_type(cppscope.handle, method_index))
+def c_method_result_type(cppscope, index):
+    return charp2str_free(_c_method_result_type(cppscope.handle, index))
 _c_method_num_args = rffi.llexternal(
     "cppyy_method_num_args",
-    [C_SCOPE, rffi.INT], rffi.INT,
+    [C_SCOPE, C_INDEX], rffi.INT,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_method_num_args(cppscope, method_index):
-    return _c_method_num_args(cppscope.handle, method_index)
+def c_method_num_args(cppscope, index):
+    return _c_method_num_args(cppscope.handle, index)
 _c_method_req_args = rffi.llexternal(
     "cppyy_method_req_args",
-    [C_SCOPE, rffi.INT], rffi.INT,
+    [C_SCOPE, C_INDEX], rffi.INT,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_method_req_args(cppscope, method_index):
-    return _c_method_req_args(cppscope.handle, method_index)
+def c_method_req_args(cppscope, index):
+    return _c_method_req_args(cppscope.handle, index)
 _c_method_arg_type = rffi.llexternal(
     "cppyy_method_arg_type",
-    [C_SCOPE, rffi.INT, rffi.INT], rffi.CCHARP,
+    [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_method_arg_type(cppscope, method_index, arg_index):
-    return charp2str_free(_c_method_arg_type(cppscope.handle, method_index, arg_index))
+def c_method_arg_type(cppscope, index, arg_index):
+    return charp2str_free(_c_method_arg_type(cppscope.handle, index, arg_index))
 _c_method_arg_default = rffi.llexternal(
     "cppyy_method_arg_default",
-    [C_SCOPE, rffi.INT, rffi.INT], rffi.CCHARP,
+    [C_SCOPE, C_INDEX, rffi.INT], rffi.CCHARP,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_method_arg_default(cppscope, method_index, arg_index):
-    return charp2str_free(_c_method_arg_default(cppscope.handle, method_index, arg_index))
+def c_method_arg_default(cppscope, index, arg_index):
+    return charp2str_free(_c_method_arg_default(cppscope.handle, index, arg_index))
 _c_method_signature = rffi.llexternal(
     "cppyy_method_signature",
-    [C_SCOPE, rffi.INT], rffi.CCHARP,
+    [C_SCOPE, C_INDEX], rffi.CCHARP,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_method_signature(cppscope, method_index):
-    return charp2str_free(_c_method_signature(cppscope.handle, method_index))
-
-_c_method_index = rffi.llexternal(
-    "cppyy_method_index",
-    [C_SCOPE, rffi.CCHARP], rffi.INT,
-    threadsafe=ts_reflect,
-    compilation_info=backend.eci)
-def c_method_index(cppscope, name):
-    return _c_method_index(cppscope.handle, name)
+def c_method_signature(cppscope, index):
+    return charp2str_free(_c_method_signature(cppscope.handle, index))
 
 _c_get_method = rffi.llexternal(
     "cppyy_get_method",
-    [C_SCOPE, rffi.INT], C_METHOD,
+    [C_SCOPE, C_INDEX], C_METHOD,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_get_method(cppscope, method_index):
-    return _c_get_method(cppscope.handle, method_index)
+def c_get_method(cppscope, index):
+    return _c_get_method(cppscope.handle, index)
+_c_get_global_operator = rffi.llexternal(
+    "cppyy_get_global_operator",
+    [C_SCOPE, C_SCOPE, rffi.CCHARP], WLAVC_INDEX,
+    threadsafe=ts_reflect,
+    compilation_info=backend.eci)
+ at jit.elidable_promote()                      # TODO: this is debatable
+def c_get_global_operator(lc, rc, op):
+    return _c_get_global_operator(lc.handle, rc.handle, op)
 
 # method properties ----------------------------------------------------------
 _c_is_constructor = rffi.llexternal(
     "cppyy_is_constructor",
-    [C_TYPE, rffi.INT], rffi.INT,
+    [C_TYPE, C_INDEX], rffi.INT,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_is_constructor(cppclass, method_index):
-    return _c_is_constructor(cppclass.handle, method_index)
+def c_is_constructor(cppclass, index):
+    return _c_is_constructor(cppclass.handle, index)
 _c_is_staticmethod = rffi.llexternal(
     "cppyy_is_staticmethod",
-    [C_TYPE, rffi.INT], rffi.INT,
+    [C_TYPE, C_INDEX], rffi.INT,
     threadsafe=ts_reflect,
     compilation_info=backend.eci)
-def c_is_staticmethod(cppclass, method_index):
-    return _c_is_staticmethod(cppclass.handle, method_index)
+def c_is_staticmethod(cppclass, index):
+    return _c_is_staticmethod(cppclass.handle, index)
 
 # data member reflection information -----------------------------------------
 _c_num_datamembers = rffi.llexternal(
diff --git a/pypy/module/cppyy/include/capi.h b/pypy/module/cppyy/include/capi.h
--- a/pypy/module/cppyy/include/capi.h
+++ b/pypy/module/cppyy/include/capi.h
@@ -11,6 +11,7 @@
     typedef cppyy_scope_t cppyy_type_t;
     typedef long cppyy_object_t;
     typedef long cppyy_method_t;
+    typedef long cppyy_index_t;
     typedef void* (*cppyy_methptrgetter_t)(cppyy_object_t);
 
     /* name to opaque C++ scope representation -------------------------------- */
@@ -41,7 +42,7 @@
     void cppyy_constructor(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
     cppyy_object_t cppyy_call_o(cppyy_method_t method, cppyy_object_t self, int nargs, void* args, cppyy_type_t result_type);
 
-    cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_scope_t scope, int method_index);
+    cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_scope_t scope, cppyy_index_t idx);
 
     /* handling of function argument buffer ----------------------------------- */
     void*  cppyy_allocate_function_args(size_t nargs);
@@ -66,21 +67,23 @@
 
     /* method/function reflection information --------------------------------- */
     int cppyy_num_methods(cppyy_scope_t scope);
-    char* cppyy_method_name(cppyy_scope_t scope, int method_index);
-    char* cppyy_method_result_type(cppyy_scope_t scope, int method_index);
-    int cppyy_method_num_args(cppyy_scope_t scope, int method_index);
-    int cppyy_method_req_args(cppyy_scope_t scope, int method_index);
-    char* cppyy_method_arg_type(cppyy_scope_t scope, int method_index, int arg_index);
-    char* cppyy_method_arg_default(cppyy_scope_t scope, int method_index, int arg_index);
-    char* cppyy_method_signature(cppyy_scope_t scope, int method_index);
+    cppyy_index_t cppyy_method_index_at(cppyy_scope_t scope, int imeth);
+    cppyy_index_t cppyy_method_index_from_name(cppyy_scope_t scope, const char* name);
 
-    int cppyy_method_index(cppyy_scope_t scope, const char* name);
+    char* cppyy_method_name(cppyy_scope_t scope, cppyy_index_t idx);
+    char* cppyy_method_result_type(cppyy_scope_t scope, cppyy_index_t idx);
+    int cppyy_method_num_args(cppyy_scope_t scope, cppyy_index_t idx);
+    int cppyy_method_req_args(cppyy_scope_t scope, cppyy_index_t idx);
+    char* cppyy_method_arg_type(cppyy_scope_t scope, cppyy_index_t idx, int arg_index);
+    char* cppyy_method_arg_default(cppyy_scope_t scope, cppyy_index_t idx, int arg_index);
+    char* cppyy_method_signature(cppyy_scope_t scope, cppyy_index_t idx);
 
-    cppyy_method_t cppyy_get_method(cppyy_scope_t scope, int method_index);
+    cppyy_method_t cppyy_get_method(cppyy_scope_t scope, cppyy_index_t idx);
+    cppyy_index_t cppyy_get_global_operator(cppyy_scope_t lc, cppyy_scope_t rc, const char* op);
 
     /* method properties -----------------------------------------------------  */
-    int cppyy_is_constructor(cppyy_type_t type, int method_index);
-    int cppyy_is_staticmethod(cppyy_type_t type, int method_index);
+    int cppyy_is_constructor(cppyy_type_t type, cppyy_index_t idx);
+    int cppyy_is_staticmethod(cppyy_type_t type, cppyy_index_t idx);
 
     /* data member reflection information ------------------------------------  */
     int cppyy_num_datamembers(cppyy_scope_t scope);
@@ -95,9 +98,9 @@
     int cppyy_is_staticdata(cppyy_type_t type, int datamember_index);
 
     /* misc helpers ----------------------------------------------------------- */
-    void cppyy_free(void* ptr);
     long long cppyy_strtoll(const char* str);
     unsigned long long cppyy_strtuoll(const char* str);
+    void cppyy_free(void* ptr);
 
     cppyy_object_t cppyy_charp2stdstring(const char* str);
     cppyy_object_t cppyy_stdstring2stdstring(cppyy_object_t ptr);
diff --git a/pypy/module/cppyy/interp_cppyy.py b/pypy/module/cppyy/interp_cppyy.py
--- a/pypy/module/cppyy/interp_cppyy.py
+++ b/pypy/module/cppyy/interp_cppyy.py
@@ -59,7 +59,7 @@
             cppscope = W_CPPClass(space, final_name, opaque_handle)
         state.cppscope_cache[name] = cppscope
 
-        cppscope._find_methods()
+        cppscope._build_methods()
         cppscope._find_datamembers()
         return cppscope
 
@@ -412,29 +412,29 @@
         assert lltype.typeOf(opaque_handle) == capi.C_SCOPE
         self.handle = opaque_handle
         self.methods = {}
-        # Do not call "self._find_methods()" here, so that a distinction can
+        # Do not call "self._build_methods()" here, so that a distinction can
         #  be made between testing for existence (i.e. existence in the cache
         #  of classes) and actual use. Point being that a class can use itself,
         #  e.g. as a return type or an argument to one of its methods.
 
         self.datamembers = {}
-        # Idem self.methods: a type could hold itself by pointer.
+        # Idem as for self.methods: a type could hold itself by pointer.
 
-    def _find_methods(self):
-        num_methods = capi.c_num_methods(self)
-        args_temp = {}
-        for i in range(num_methods):
-            method_name = capi.c_method_name(self, i)
-            pymethod_name = helper.map_operator_name(
-                    method_name, capi.c_method_num_args(self, i),
-                    capi.c_method_result_type(self, i))
-            if not pymethod_name in self.methods:
-                cppfunction = self._make_cppfunction(i)
-                overload = args_temp.setdefault(pymethod_name, [])
-                overload.append(cppfunction)
-        for name, functions in args_temp.iteritems():
-            overload = W_CPPOverload(self.space, self, functions[:])
-            self.methods[name] = overload
+    def _build_methods(self):
+        assert len(self.methods) == 0
+        methods_temp = {}
+        N = capi.c_num_methods(self)
+        for i in range(N):
+            idx = capi.c_method_index_at(self, i)
+            pyname = helper.map_operator_name(
+                capi.c_method_name(self, idx),
+                capi.c_method_num_args(self, idx),
+                capi.c_method_result_type(self, idx))
+            cppmethod = self._make_cppfunction(idx)
+            methods_temp.setdefault(pyname, []).append(cppmethod)
+        for pyname, methods in methods_temp.iteritems():
+            overload = W_CPPOverload(self.space, self, methods[:])
+            self.methods[pyname] = overload
 
     def get_method_names(self):
         return self.space.newlist([self.space.wrap(name) for name in self.methods])
@@ -488,15 +488,15 @@
     _immutable_ = True
     kind = "namespace"
 
-    def _make_cppfunction(self, method_index):
-        num_args = capi.c_method_num_args(self, method_index)
-        args_required = capi.c_method_req_args(self, method_index)
+    def _make_cppfunction(self, index):
+        num_args = capi.c_method_num_args(self, index)
+        args_required = capi.c_method_req_args(self, index)
         arg_defs = []
         for i in range(num_args):
-            arg_type = capi.c_method_arg_type(self, method_index, i)
-            arg_dflt = capi.c_method_arg_default(self, method_index, i)
+            arg_type = capi.c_method_arg_type(self, index, i)
+            arg_dflt = capi.c_method_arg_default(self, index, i)
             arg_defs.append((arg_type, arg_dflt))
-        return CPPFunction(self.space, self, method_index, arg_defs, args_required)
+        return CPPFunction(self.space, self, index, arg_defs, args_required)
 
     def _make_datamember(self, dm_name, dm_idx):
         type_name = capi.c_datamember_type(self, dm_idx)
@@ -516,8 +516,8 @@
 
     def find_overload(self, meth_name):
         # TODO: collect all overloads, not just the non-overloaded version
-        meth_idx = capi.c_method_index(self, meth_name)
-        if meth_idx < 0:
+        meth_idx = capi.c_method_index_from_name(self, meth_name)
+        if meth_idx == -1:
             raise self.missing_attribute_error(meth_name)
         cppfunction = self._make_cppfunction(meth_idx)
         overload = W_CPPOverload(self.space, self, [cppfunction])
@@ -548,21 +548,21 @@
     _immutable_ = True
     kind = "class"
 
-    def _make_cppfunction(self, method_index):
-        num_args = capi.c_method_num_args(self, method_index)
-        args_required = capi.c_method_req_args(self, method_index)
+    def _make_cppfunction(self, index):
+        num_args = capi.c_method_num_args(self, index)
+        args_required = capi.c_method_req_args(self, index)
         arg_defs = []
         for i in range(num_args):
-            arg_type = capi.c_method_arg_type(self, method_index, i)
-            arg_dflt = capi.c_method_arg_default(self, method_index, i)
+            arg_type = capi.c_method_arg_type(self, index, i)
+            arg_dflt = capi.c_method_arg_default(self, index, i)
             arg_defs.append((arg_type, arg_dflt))
-        if capi.c_is_constructor(self, method_index):
+        if capi.c_is_constructor(self, index):
             cls = CPPConstructor
-        elif capi.c_is_staticmethod(self, method_index):
+        elif capi.c_is_staticmethod(self, index):
             cls = CPPFunction
         else:
             cls = CPPMethod
-        return cls(self.space, self, method_index, arg_defs, args_required)
+        return cls(self.space, self, index, arg_defs, args_required)
 
     def _find_datamembers(self):
         num_datamembers = capi.c_num_datamembers(self)
@@ -693,7 +693,18 @@
 
     def instance__eq__(self, w_other):
         other = self.space.interp_w(W_CPPInstance, w_other, can_be_None=False)
-        iseq = self._rawobject == other._rawobject
+        # get here if no class-specific overloaded operator is available
+        meth_idx = capi.c_get_global_operator(self.cppclass, other.cppclass, "==")
+        if meth_idx != -1:
+            gbl = scope_byname(self.space, "")
+            f = gbl._make_cppfunction(meth_idx)
+            ol = W_CPPOverload(self.space, scope_byname(self.space, ""), [f])
+            # TODO: cache this operator (currently cached by JIT in capi/__init__.py)
+            return ol.call(self, (self, w_other))
+        
+        # fallback: direct pointer comparison (the class comparison is needed since the
+        # first data member in a struct and the struct have the same address)
+        iseq = (self._rawobject == other._rawobject) and (self.cppclass == other.cppclass)
         return self.space.wrap(iseq)
 
     def instance__ne__(self, w_other):
@@ -774,7 +785,7 @@
 
 def wrap_cppobject_nocast(space, w_pycppclass, cppclass, rawobject, isref, python_owns):
     obj = memory_regulator.retrieve(rawobject)
-    if obj and obj.cppclass == cppclass:
+    if not (obj is None) and obj.cppclass is cppclass:
         return obj
     return wrap_new_cppobject_nocast(space, w_pycppclass, cppclass, rawobject, isref, python_owns)
 
diff --git a/pypy/module/cppyy/pythonify.py b/pypy/module/cppyy/pythonify.py
--- a/pypy/module/cppyy/pythonify.py
+++ b/pypy/module/cppyy/pythonify.py
@@ -329,10 +329,9 @@
 
     # map begin()/end() protocol to iter protocol
     if hasattr(pyclass, 'begin') and hasattr(pyclass, 'end'):
-        # TODO: make gnu-independent
         def __iter__(self):
             iter = self.begin()
-            while gbl.__gnu_cxx.__ne__(iter, self.end()):
+            while iter != self.end():
                 yield iter.__deref__()
                 iter.__preinc__()
             iter.destruct()
diff --git a/pypy/module/cppyy/src/cintcwrapper.cxx b/pypy/module/cppyy/src/cintcwrapper.cxx
--- a/pypy/module/cppyy/src/cintcwrapper.cxx
+++ b/pypy/module/cppyy/src/cintcwrapper.cxx
@@ -141,6 +141,13 @@
 
 
 /* local helpers ---------------------------------------------------------- */
+static inline const std::string resolve_typedef(const std::string& tname) {
+    G__TypeInfo ti(tname.c_str());
+    if (!ti.IsValid())
+        return tname;
+    return TClassEdit::ShortType(TClassEdit::CleanType(ti.TrueName(), 1).c_str(), 3);
+}
+
 static inline char* cppstring_to_cstring(const std::string& name) {
     char* name_char = (char*)malloc(name.size() + 1);
     strcpy(name_char, name.c_str());
@@ -154,17 +161,17 @@
 }
 
 static inline TClassRef type_from_handle(cppyy_type_t handle) {
+    assert((ClassRefs_t::size_type)handle < g_classrefs.size());
     return g_classrefs[(ClassRefs_t::size_type)handle];
 }
 
-static inline TFunction* type_get_method(cppyy_type_t handle, int method_index) {
+static inline TFunction* type_get_method(cppyy_type_t handle, cppyy_index_t idx) {
     TClassRef cr = type_from_handle(handle);
     if (cr.GetClass())
-        return (TFunction*)cr->GetListOfMethods()->At(method_index);
-    return &g_globalfuncs[method_index];
+        return (TFunction*)cr->GetListOfMethods()->At(idx);
+    return (TFunction*)idx;
 }
 
-
 static inline void fixup_args(G__param* libp) {
     for (int i = 0; i < libp->paran; ++i) {
         libp->para[i].ref = libp->para[i].obj.i;
@@ -194,7 +201,6 @@
             libp->para[i].ref = (long)&libp->para[i].obj.i;
             libp->para[i].type = 'd';
             break;
-
         }
         }
     }
@@ -261,6 +267,7 @@
     return klass;
 }
 
+
 /* memory management ------------------------------------------------------ */
 cppyy_object_t cppyy_allocate(cppyy_type_t handle) {
     TClassRef cr = type_from_handle(handle);
@@ -387,7 +394,7 @@
     return G__int(result);
 }
 
-cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_type_t /*handle*/, int /*method_index*/) {
+cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_type_t /*handle*/, cppyy_index_t /*idx*/) {
     return (cppyy_methptrgetter_t)NULL;
 }
 
@@ -533,47 +540,75 @@
     return 0;
 }
 
-char* cppyy_method_name(cppyy_scope_t handle, int method_index) {
-    TFunction* f = type_get_method(handle, method_index);
+cppyy_index_t cppyy_method_index_at(cppyy_scope_t handle, int imeth) {
+    TClassRef cr = type_from_handle(handle);
+    if (cr.GetClass())
+        return (cppyy_index_t)imeth;
+    return (cppyy_index_t)&g_globalfuncs[imeth];
+}
+
+cppyy_index_t cppyy_method_index_from_name(cppyy_scope_t handle, const char* name) {
+    TClassRef cr = type_from_handle(handle);
+    if (cr.GetClass()) {
+        gInterpreter->UpdateListOfMethods(cr.GetClass());
+        int imeth = 0;
+        TFunction* func;
+        TIter next(cr->GetListOfMethods());
+        while ((func = (TFunction*)next())) {
+            if (strcmp(name, func->GetName()) == 0) {
+                if (func->Property() & G__BIT_ISPUBLIC)
+                    return (cppyy_index_t)imeth;
+                return (cppyy_index_t)-1;
+            }
+            ++imeth;
+        }
+    }
+    TFunction* func = gROOT->GetGlobalFunction(name, NULL, kTRUE);
+    if (!func)
+        return (cppyy_index_t)-1;  // (void*)-1 is in kernel space, so invalid
+    int idx = g_globalfuncs.size();
+    g_globalfuncs.push_back(*func);
+    return (cppyy_index_t)func;
+}
+
+
+char* cppyy_method_name(cppyy_scope_t handle, cppyy_index_t idx) {
+    TFunction* f = type_get_method(handle, idx);
     return cppstring_to_cstring(f->GetName());
 }
 
-char* cppyy_method_result_type(cppyy_scope_t handle, int method_index) {
-    TFunction* f = 0;
+char* cppyy_method_result_type(cppyy_scope_t handle, cppyy_index_t idx) {
     TClassRef cr = type_from_handle(handle);
-    if (cr.GetClass()) {
-        if (cppyy_is_constructor(handle, method_index))
-            return cppstring_to_cstring("constructor");
-        f = (TFunction*)cr->GetListOfMethods()->At(method_index);
-    } else
-        f = &g_globalfuncs[method_index];
+    if (cr.GetClass() && cppyy_is_constructor(handle, idx))
+        return cppstring_to_cstring("constructor");
+    TFunction* f = type_get_method(handle, idx);
     return type_cppstring_to_cstring(f->GetReturnTypeName());
 }
 
-int cppyy_method_num_args(cppyy_scope_t handle, int method_index) {
-    TFunction* f = type_get_method(handle, method_index);
+int cppyy_method_num_args(cppyy_scope_t handle, cppyy_index_t idx) {
+    TFunction* f = type_get_method(handle, idx);
     return f->GetNargs();
 }
 
-int cppyy_method_req_args(cppyy_scope_t handle, int method_index) {
-    TFunction* f = type_get_method(handle, method_index);
+int cppyy_method_req_args(cppyy_scope_t handle, cppyy_index_t idx) {
+    TFunction* f = type_get_method(handle, idx);
     return f->GetNargs() - f->GetNargsOpt();
 }
 
-char* cppyy_method_arg_type(cppyy_scope_t handle, int method_index, int arg_index) {
-    TFunction* f = type_get_method(handle, method_index);
+char* cppyy_method_arg_type(cppyy_scope_t handle, cppyy_index_t idx, int arg_index) {
+    TFunction* f = type_get_method(handle, idx);
     TMethodArg* arg = (TMethodArg*)f->GetListOfMethodArgs()->At(arg_index);
     return type_cppstring_to_cstring(arg->GetFullTypeName());
 }
 
-char* cppyy_method_arg_default(cppyy_scope_t, int, int) {
+char* cppyy_method_arg_default(cppyy_scope_t /*handle*/, cppyy_index_t /*idx*/, int /*arg_index*/) {
     /* unused: libffi does not work with CINT back-end */
     return cppstring_to_cstring("");
 }
 
-char* cppyy_method_signature(cppyy_scope_t handle, int method_index) {
-    TFunction* f = type_get_method(handle, method_index);
+char* cppyy_method_signature(cppyy_scope_t handle, cppyy_index_t idx) {
     TClassRef cr = type_from_handle(handle);
+    TFunction* f = type_get_method(handle, idx);
     std::ostringstream sig;
     if (cr.GetClass() && cr->GetClassInfo()
         && strcmp(f->GetName(), ((G__ClassInfo*)cr->GetClassInfo())->Name()) != 0)
@@ -589,46 +624,53 @@
     return cppstring_to_cstring(sig.str());
 }
 
-int cppyy_method_index(cppyy_scope_t handle, const char* name) {
-    TClassRef cr = type_from_handle(handle);
-    if (cr.GetClass()) {
-        gInterpreter->UpdateListOfMethods(cr.GetClass());
-        int imeth = 0;
-        TFunction* func;
-        TIter next(cr->GetListOfMethods());
-        while ((func = (TFunction*)next())) {
-            if (strcmp(name, func->GetName()) == 0) {
-                if (func->Property() & G__BIT_ISPUBLIC)
-                    return imeth;
-                return -1;
-            }
-            ++imeth;
-        }
-    }
-    TFunction* func = gROOT->GetGlobalFunction(name, NULL, kTRUE);
-    if (!func)
-        return -1;
-    int idx = g_globalfuncs.size();
-    g_globalfuncs.push_back(*func);
-    return idx;
-}
 
-cppyy_method_t cppyy_get_method(cppyy_scope_t handle, int method_index) {
-    TFunction* f = type_get_method(handle, method_index);
+cppyy_method_t cppyy_get_method(cppyy_scope_t handle, cppyy_index_t idx) {
+    TFunction* f = type_get_method(handle, idx);
     return (cppyy_method_t)f->InterfaceMethod();
 }
 
+cppyy_index_t cppyy_get_global_operator(cppyy_scope_t lc, cppyy_scope_t rc, const char* op) {
+    TClassRef lccr = type_from_handle(lc);
+    if (!lccr.GetClass()) 
+        return (cppyy_index_t)-1;  // (void*)-1 is in kernel space, so invalid as a method handle
+    std::string lcname = lccr->GetName();
+
+    TClassRef rccr = type_from_handle(lc);
+    if (!rccr.GetClass())
+        return (cppyy_index_t)-1;
+    std::string rcname = rccr->GetName();
+
+    std::string opname = "operator";
+    opname += op;
+
+    for (int idx = 0; idx < (int)g_globalfuncs.size(); ++idx) {
+        TFunction* func = &g_globalfuncs[idx];
+        if (func->GetListOfMethodArgs()->GetSize() != 2)
+            continue;
+
+        if (func->GetName() == opname) {
+            if (lcname == resolve_typedef(((TMethodArg*)func->GetListOfMethodArgs()->At(0))->GetTypeName()) &&
+                rcname == resolve_typedef(((TMethodArg*)func->GetListOfMethodArgs()->At(1))->GetTypeName())) {
+                return (cppyy_index_t)func;
+            }
+        }
+    }
+
+    return (cppyy_index_t)-1;
+}
+
 
 /* method properties -----------------------------------------------------  */
-int cppyy_is_constructor(cppyy_type_t handle, int method_index) {
+int cppyy_is_constructor(cppyy_type_t handle, cppyy_index_t idx) {
     TClassRef cr = type_from_handle(handle);
-    TMethod* m = (TMethod*)cr->GetListOfMethods()->At(method_index);
+    TMethod* m = (TMethod*)cr->GetListOfMethods()->At(idx);
     return strcmp(m->GetName(), ((G__ClassInfo*)cr->GetClassInfo())->Name()) == 0;
 }
 
-int cppyy_is_staticmethod(cppyy_type_t handle, int method_index) {
+int cppyy_is_staticmethod(cppyy_type_t handle, cppyy_index_t idx) {
     TClassRef cr = type_from_handle(handle);
-    TMethod* m = (TMethod*)cr->GetListOfMethods()->At(method_index);
+    TMethod* m = (TMethod*)cr->GetListOfMethods()->At(idx);
     return m->Property() & G__BIT_ISSTATIC;
 }
 
@@ -769,13 +811,14 @@
     return (cppyy_object_t)new std::string(*(std::string*)ptr);
 }
 
+void cppyy_assign2stdstring(cppyy_object_t ptr, const char* str) {
+   *((std::string*)ptr) = str;
+}
+
 void cppyy_free_stdstring(cppyy_object_t ptr) {
     delete (std::string*)ptr;
 }
 
-void cppyy_assign2stdstring(cppyy_object_t ptr, const char* str) {
-   *((std::string*)ptr) = str;
-}
 
 void* cppyy_load_dictionary(const char* lib_name) {
     if (0 <= gSystem->Load(lib_name))
diff --git a/pypy/module/cppyy/src/reflexcwrapper.cxx b/pypy/module/cppyy/src/reflexcwrapper.cxx
--- a/pypy/module/cppyy/src/reflexcwrapper.cxx
+++ b/pypy/module/cppyy/src/reflexcwrapper.cxx
@@ -188,7 +188,7 @@
     return 0;
 }
 
-cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_type_t handle, int method_index) {
+cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_type_t handle, cppyy_index_t method_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     return get_methptr_getter(m);
@@ -332,7 +332,28 @@
     return s.FunctionMemberSize();
 }
 
-char* cppyy_method_name(cppyy_scope_t handle, int method_index) {
+cppyy_index_t cppyy_method_index_at(cppyy_scope_t scope, int imeth) {
+    return (cppyy_index_t)imeth;
+}
+
+cppyy_index_t cppyy_method_index_from_name(cppyy_scope_t handle, const char* name) {
+    Reflex::Scope s = scope_from_handle(handle);
+    // the following appears dumb, but the internal storage for Reflex is an
+    // unsorted std::vector anyway, so there's no gain to be had in using the
+    // Scope::FunctionMemberByName() function
+    int num_meth = s.FunctionMemberSize();
+    for (int imeth = 0; imeth < num_meth; ++imeth) {
+        Reflex::Member m = s.FunctionMemberAt(imeth);
+        if (m.Name() == name) {
+            if (m.IsPublic())
+               return (cppyy_index_t)imeth;
+            return (cppyy_index_t)-1;
+        }
+    }
+    return (cppyy_index_t)-1;
+}
+
+char* cppyy_method_name(cppyy_scope_t handle, cppyy_index_t method_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     std::string name;
@@ -343,7 +364,7 @@
     return cppstring_to_cstring(name);
 }
 
-char* cppyy_method_result_type(cppyy_scope_t handle, int method_index) {
+char* cppyy_method_result_type(cppyy_scope_t handle, cppyy_index_t method_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     if (m.IsConstructor())
@@ -353,19 +374,19 @@
     return cppstring_to_cstring(name);
 }
 
-int cppyy_method_num_args(cppyy_scope_t handle, int method_index) {
+int cppyy_method_num_args(cppyy_scope_t handle, cppyy_index_t method_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     return m.FunctionParameterSize();
 }
 
-int cppyy_method_req_args(cppyy_scope_t handle, int method_index) {
+int cppyy_method_req_args(cppyy_scope_t handle, cppyy_index_t method_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     return m.FunctionParameterSize(true);
 }
 
-char* cppyy_method_arg_type(cppyy_scope_t handle, int method_index, int arg_index) {
+char* cppyy_method_arg_type(cppyy_scope_t handle, cppyy_index_t method_index, int arg_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     Reflex::Type at = m.TypeOf().FunctionParameterAt(arg_index);
@@ -373,14 +394,14 @@
     return cppstring_to_cstring(name);
 }
 
-char* cppyy_method_arg_default(cppyy_scope_t handle, int method_index, int arg_index) {
+char* cppyy_method_arg_default(cppyy_scope_t handle, cppyy_index_t method_index, int arg_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     std::string dflt = m.FunctionParameterDefaultAt(arg_index);
     return cppstring_to_cstring(dflt);
 }
 
-char* cppyy_method_signature(cppyy_scope_t handle, int method_index) {
+char* cppyy_method_signature(cppyy_scope_t handle, cppyy_index_t method_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     Reflex::Type mt = m.TypeOf();
@@ -398,39 +419,26 @@
     return cppstring_to_cstring(sig.str());
 }
 
-int cppyy_method_index(cppyy_scope_t handle, const char* name) {
-    Reflex::Scope s = scope_from_handle(handle);
-    // the following appears dumb, but the internal storage for Reflex is an
-    // unsorted std::vector anyway, so there's no gain to be had in using the
-    // Scope::FunctionMemberByName() function
-    int num_meth = s.FunctionMemberSize();
-    for (int imeth = 0; imeth < num_meth; ++imeth) {
-        Reflex::Member m = s.FunctionMemberAt(imeth);
-        if (m.Name() == name) {
-            if (m.IsPublic())
-                return imeth;
-            return -1;
-        }
-    }
-    return -1;
-}
-
-cppyy_method_t cppyy_get_method(cppyy_scope_t handle, int method_index) {
+cppyy_method_t cppyy_get_method(cppyy_scope_t handle, cppyy_index_t method_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     assert(m.IsFunctionMember());
     return (cppyy_method_t)m.Stubfunction();
 }
 
+cppyy_index_t cppyy_get_global_operator(cppyy_scope_t lc, cppyy_scope_t rc, const char* op) {
+    return (cppyy_index_t)-1; /* not needed yet; covered in pythonify.py */
+}
+
 
 /* method properties -----------------------------------------------------  */
-int cppyy_is_constructor(cppyy_type_t handle, int method_index) {
+int cppyy_is_constructor(cppyy_type_t handle, cppyy_index_t method_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     return m.IsConstructor();
 }
 
-int cppyy_is_staticmethod(cppyy_type_t handle, int method_index) {
+int cppyy_is_staticmethod(cppyy_type_t handle, cppyy_index_t method_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.FunctionMemberAt(method_index);
     return m.IsStatic();
diff --git a/pypy/module/cppyy/test/test_stltypes.py b/pypy/module/cppyy/test/test_stltypes.py
--- a/pypy/module/cppyy/test/test_stltypes.py
+++ b/pypy/module/cppyy/test/test_stltypes.py
@@ -43,16 +43,14 @@
 
         #-----
         v = tv1(self.N)
-        # TODO: get the following in order
-        #assert v.begin().__eq__(v.begin())
-        #assert v.begin() == v.begin()
-        #assert v.end() == v.end()
-        #assert v.begin() != v.end()
-        #assert v.end() != v.begin()
+        assert v.begin().__eq__(v.begin())
+        assert v.begin() == v.begin()
+        assert v.end() == v.end()
+        assert v.begin() != v.end()
+        assert v.end() != v.begin()
 
         #-----
         for i in range(self.N):
-          # TODO:
           #  v[i] = i
           #  assert v[i] == i
           #  assert v.at(i) == i


More information about the pypy-commit mailing list