[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