[pypy-commit] pypy reflex-support: overloading based on "argument priority" and associated tests

wlav noreply at buildbot.pypy.org
Mon Mar 25 23:44:31 CET 2013


Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r62768:43726e21a664
Date: 2013-03-25 15:43 -0700
http://bitbucket.org/pypy/pypy/changeset/43726e21a664/

Log:	overloading based on "argument priority" and associated tests

diff --git a/pypy/module/cppyy/capi/cint_capi.py b/pypy/module/cppyy/capi/cint_capi.py
--- a/pypy/module/cppyy/capi/cint_capi.py
+++ b/pypy/module/cppyy/capi/cint_capi.py
@@ -120,7 +120,7 @@
             classname = space.str_w(args_w[1])
             addr_idx  = 2
             w_address = args_w[addr_idx]
-        except OperationError:
+        except (OperationError, TypeError):
             addr_idx  = 1
             w_address = args_w[addr_idx]
 
@@ -140,11 +140,12 @@
         branch_class = interp_cppyy.scope_byname(space, "TBranch")
         w_branch = interp_cppyy.wrap_cppobject(space, vbranch, branch_class)
         return w_branch
-    except (OperationError, TypeError, IndexError), e:
+    except (OperationError, TypeError, IndexError):
         pass
 
     # return control back to the original, unpythonized overload
-    return tree_class.get_overload("Branch").call(w_self, args_w)
+    ol = tree_class.get_overload("Branch")
+    return ol.call(w_self, args_w)
 
 def activate_branch(space, w_branch):
     w_branches = space.call_method(w_branch, "GetListOfBranches")
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
@@ -16,6 +16,17 @@
 class FastCallNotPossible(Exception):
     pass
 
+# overload priorities: lower is preferred
+priority = { 'void*'  : 100,
+             'void**' : 100,
+             'float'  :  30,
+             'double' :  10, }
+
+from rpython.rlib.listsort import make_timsort_class
+CPPMethodBaseTimSort = make_timsort_class()
+class CPPMethodSort(CPPMethodBaseTimSort):
+    def lt(self, a, b):
+        return a.priority() < b.priority()
 
 @unwrap_spec(name=str)
 def load_dictionary(space, name):
@@ -224,7 +235,8 @@
     def _setup(self, cppthis):
         self.converters = [converter.get_converter(self.space, arg_type, arg_dflt)
                                for arg_type, arg_dflt in self.arg_defs]
-        self.executor = executor.get_executor(self.space, capi.c_method_result_type(self.scope, self.index))
+        self.executor = executor.get_executor(
+            self.space, capi.c_method_result_type(self.scope, self.index))
 
         for conv in self.converters:
             if conv.uses_local:
@@ -350,6 +362,12 @@
     def signature(self):
         return capi.c_method_signature(self.scope, self.index)
 
+    def priority(self):
+        total_arg_priority = 0
+        for p in [priority.get(arg_type, 0) for arg_type, arg_dflt in self.arg_defs]:
+            total_arg_priority += p
+        return total_arg_priority
+
     def __del__(self):
         if self.cif_descr:
             lltype.free(self.cif_descr.atypes, flavor='raw')
@@ -373,7 +391,7 @@
         return "CPPFunction: %s" % self.signature()
 
 
-class CPPTemplatedCall(CPPMethod): # TODO: unnecessary derivation to make rtyper happy
+class CPPTemplatedCall(CPPMethod):
     """Method dispatcher that first needs to resolve the template instance.
     Note that the derivation is from object: the CPPMethod is a data member."""
 
@@ -384,7 +402,7 @@
         self.space = space
         self.templ_args = templ_args
         # TODO: might have to specialize for CPPTemplatedCall on CPPMethod/CPPFunction here
-        self.method = CPPMethod(space, containing_scope, method_index, arg_defs, args_required)
+        CPPMethod.__init__(self, space, containing_scope, method_index, arg_defs, args_required)
 
     def call(self, cppthis, args_w):
         assert lltype.typeOf(cppthis) == capi.C_OBJECT
@@ -397,10 +415,10 @@
             if s != self.templ_args[i]:
                 raise OperationError(self.space.w_TypeError, self.space.wrap(
                     "non-matching template (got %s where %s expected" % (s, self.templ_args[i])))
-        return W_CPPBoundMethod(cppthis, self.method)
+        return W_CPPBoundMethod(cppthis, self)
 
-    def signature(self):
-        return self.method.signature()
+    def bound_call(self, cppthis, args_w):
+        return CPPMethod.call(self, cppthis, args_w)
 
     def __repr__(self):
         return "CPPTemplatedCall: %s" % self.signature()
@@ -541,7 +559,7 @@
         self.method = method
 
     def __call__(self, args_w):
-        return self.method.call(self.cppthis, args_w)
+        return self.method.bound_call(self.cppthis, args_w)
 
 W_CPPBoundMethod.typedef = TypeDef(
     'CPPBoundMethod',
@@ -662,6 +680,7 @@
 
         # create the overload methods from the method sets
         for pyname, methods in methods_temp.iteritems():
+            CPPMethodSort(methods).sort()
             overload = W_CPPOverload(self.space, self, methods[:])
             self.methods[pyname] = overload
 
diff --git a/pypy/module/cppyy/test/test_cint.py b/pypy/module/cppyy/test/test_cint.py
--- a/pypy/module/cppyy/test/test_cint.py
+++ b/pypy/module/cppyy/test/test_cint.py
@@ -329,20 +329,20 @@
         mytree._python_owns = False
 
         import array
-        ba = array.array('c', [chr(0)])
-        ia = array.array('i', [0])
-        da = array.array('d', [0.])
+        mytree.ba = array.array('c', [chr(0)])
+        mytree.ia = array.array('i', [0])
+        mytree.da = array.array('d', [0.])
 
-        mytree.Branch("my_bool",   ba, "my_bool/O")
-        mytree.Branch("my_int",    ia, "my_int/I")
-        mytree.Branch("my_int2",   ia, "my_int2/I")
-        mytree.Branch("my_double", da, "my_double/D")
+        mytree.Branch("my_bool",   mytree.ba, "my_bool/O")
+        mytree.Branch("my_int",    mytree.ia, "my_int/I")
+        mytree.Branch("my_int2",   mytree.ia, "my_int2/I")
+        mytree.Branch("my_double", mytree.da, "my_double/D")
 
         for i in range(self.N):
             # make sure value is different from default (0)
-            ba[0] = i%2 and chr(0) or chr(1)
-            ia[0] = i+1
-            da[0] = (i+1)/2.
+            mytree.ba[0] = i%2 and chr(0) or chr(1)
+            mytree.ia[0] = i+1
+            mytree.da[0] = (i+1)/2.
             mytree.Fill()
         f.Write()
         f.Close()
diff --git a/pypy/module/cppyy/test/test_overloads.py b/pypy/module/cppyy/test/test_overloads.py
--- a/pypy/module/cppyy/test/test_overloads.py
+++ b/pypy/module/cppyy/test/test_overloads.py
@@ -62,7 +62,7 @@
         assert c.__dispatch__('get_int', 'b_overload*')(b_overload()) == 13
 
         assert c_overload().__dispatch__('get_int', 'a_overload*')(a_overload())  == 42
-#        assert c_overload.__dispatch__('get_int', 'b_overload*')(c, b_overload()) == 13
+        # TODO: #assert c_overload.__dispatch__('get_int', 'b_overload*')(c, b_overload()) == 13
 
         d = d_overload()
         assert d.__dispatch__('get_int', 'a_overload*')(a_overload()) == 42
@@ -105,11 +105,9 @@
     def test05_array_overloads(self):
         """Test functions overloaded on different arrays"""
 
-        # TODO: buffer to pointer interface
-        return
-
         import cppyy
         c_overload = cppyy.gbl.c_overload
+        d_overload = cppyy.gbl.d_overload
 
         from array import array
 
@@ -127,8 +125,8 @@
         import cppyy
         more_overloads = cppyy.gbl.more_overloads
 
-#        assert more_overloads().call(1)   == "int"
-#        assert more_overloads().call(1.)  == "double"
+        assert more_overloads().call(1)   == "int"
+        assert more_overloads().call(1.)  == "double"
         assert more_overloads().call1(1)  == "int"
         assert more_overloads().call1(1.) == "double"
 
@@ -143,4 +141,4 @@
 
         for l in ['f', 'd', 'i', 'h', 'l']:
             a = array.array(l, numbers)
-            assert(round(cmean(len(a), a) - mean, 8), 0)
+            assert round(cmean(len(a), a) - mean, 8) == 0


More information about the pypy-commit mailing list