[pypy-commit] pypy reflex-support: tests of and support for operator overloading
wlav
noreply at buildbot.pypy.org
Wed Jul 13 11:49:55 CEST 2011
Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r45531:25d752656651
Date: 2011-07-13 02:48 -0700
http://bitbucket.org/pypy/pypy/changeset/25d752656651/
Log: tests of and support for operator overloading
diff --git a/pypy/module/cppyy/converter.py b/pypy/module/cppyy/converter.py
--- a/pypy/module/cppyy/converter.py
+++ b/pypy/module/cppyy/converter.py
@@ -288,7 +288,7 @@
libffitype = libffi.types.ulong
def _unwrap_object(self, space, w_obj):
- return space.c_uint_w(w_obj)
+ return space.uint_w(w_obj)
def convert_argument(self, space, w_obj):
arg = self._unwrap_object(space, w_obj)
@@ -376,6 +376,11 @@
x = rffi.str2charp(arg)
return rffi.cast(rffi.VOIDP, x)
+ def from_memory(self, space, w_obj, offset):
+ address = self._get_raw_address(space, w_obj, offset)
+ charpptr = rffi.cast(rffi.CCHARPP, address)
+ return space.wrap(rffi.charp2str(charpptr[0]))
+
class ShortArrayConverter(ArrayTypeConverterMixin, TypeConverter):
_immutable_=True
@@ -566,3 +571,4 @@
_converters["double*"] = DoublePtrConverter
_converters["double[]"] = DoubleArrayConverter
_converters["const char*"] = CStringConverter
+_converters["char*"] = CStringConverter
diff --git a/pypy/module/cppyy/executor.py b/pypy/module/cppyy/executor.py
--- a/pypy/module/cppyy/executor.py
+++ b/pypy/module/cppyy/executor.py
@@ -92,10 +92,10 @@
libffitype = libffi.types.uint
def _wrap_result(self, space, result):
- return space.wrap(result)
+ return space.wrap(rffi.cast(rffi.UINT, result))
def execute(self, space, func, cppthis, num_args, args):
- result = capi.c_call_i(func.cpptype.handle, func.method_index, cppthis, num_args, args)
+ result = capi.c_call_l(func.cpptype.handle, func.method_index, cppthis, num_args, args)
return self._wrap_result(space, result)
class LongExecutor(FunctionExecutor):
@@ -112,6 +112,13 @@
def execute_libffi(self, space, libffifunc, argchain):
return space.wrap(libffifunc.call(argchain, lltype.Signed))
+class UnsignedLongExecutor(LongExecutor):
+ _immutable_ = True
+ libffitype = libffi.types.ulong
+
+ def _wrap_result(self, space, result):
+ return space.wrap(rffi.cast(rffi.ULONG, result))
+
class ConstIntRefExecutor(LongExecutor):
_immutable_ = True
@@ -170,6 +177,10 @@
_immutable_ = True
typecode = 'l'
+class UnsignedLongPtrExecutor(PtrTypeExecutor):
+ _immutable_ = True
+ typecode = 'L'
+
class FloatPtrExecutor(PtrTypeExecutor):
_immutable_ = True
typecode = 'f'
@@ -274,8 +285,8 @@
_executors["unsigned int*"] = UnsignedIntPtrExecutor
_executors["long int"] = LongExecutor
_executors["long int*"] = LongPtrExecutor
-_executors["unsigned long int"] = LongExecutor
-_executors["unsigned long int*"] = LongPtrExecutor
+_executors["unsigned long int"] = UnsignedLongExecutor
+_executors["unsigned long int*"] = UnsignedLongPtrExecutor
_executors["float"] = FloatExecutor
_executors["float*"] = FloatPtrExecutor
_executors["double"] = DoubleExecutor
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
@@ -246,13 +246,22 @@
return self.space.wrap(self.functions[0].executor.name)
@jit.unroll_safe
- def call(self, cppthis, args_w):
+ def call(self, cppinstance, args_w):
+ if cppinstance:
+ cppthis = cppinstance.rawobject
+ else:
+ cppthis = NULL_VOIDP
+
space = self.space
errmsg = 'None of the overloads matched:'
for i in range(len(self.functions)):
cppyyfunc = self.functions[i]
try:
- return cppyyfunc.call(cppthis, args_w)
+ cppresult = cppyyfunc.call(cppthis, args_w)
+ if cppinstance and isinstance(cppresult, W_CPPInstance):
+ if cppresult.rawobject == cppinstance.rawobject:
+ return cppinstance # recycle object to preserve identity
+ return cppresult
except OperationError, e:
if not e.match(space, space.w_TypeError):
raise
@@ -377,7 +386,7 @@
self.space.wrap(str("class %s has no attribute %s" % (self.name, name))))
def invoke(self, overload, args_w):
- return overload.call(NULL_VOIDP, args_w)
+ return overload.call(None, args_w)
W_CPPScope.typedef = TypeDef(
'CPPScope',
@@ -484,7 +493,7 @@
self.space.wrap("%s is abstract" % self.name))
raise
- return overload.call(NULL_VOIDP, args_w)
+ return overload.call(None, args_w)
W_CPPType.typedef = TypeDef(
'CPPType',
@@ -533,7 +542,7 @@
def invoke(self, overload, args_w):
self._nullcheck()
- return overload.call(self.rawobject, args_w)
+ return overload.call(self, args_w)
def destruct(self):
if self.rawobject:
diff --git a/pypy/module/cppyy/test/operators.cxx b/pypy/module/cppyy/test/operators.cxx
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/test/operators.cxx
@@ -0,0 +1,1 @@
+#include "operators.h"
diff --git a/pypy/module/cppyy/test/operators.h b/pypy/module/cppyy/test/operators.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/test/operators.h
@@ -0,0 +1,97 @@
+class number {
+public:
+ number() { m_int = 0; }
+ number(int i) { m_int = i; }
+
+ int AsInt() { return m_int; }
+
+ number operator+(const number& n) const { return number(m_int + n.m_int); }
+ number operator+(int n) const { return number(m_int + n); }
+ number operator-(const number& n) const { return number(m_int - n.m_int); }
+ number operator-(int n) const { return number(m_int - n); }
+ number operator*(const number& n) const { return number(m_int * n.m_int); }
+ number operator*(int n) const { return number(m_int * n); }
+ number operator/(const number& n) const { return number(m_int / n.m_int); }
+ number operator/(int n) const { return number(m_int / n); }
+ number operator%(const number& n) const { return number(m_int % n.m_int); }
+ number operator%(int n) const { return number(m_int % n); }
+
+ number& operator+=(const number& n) { m_int += n.m_int; return *this; }
+ number& operator-=(const number& n) { m_int -= n.m_int; return *this; }
+ number& operator*=(const number& n) { m_int *= n.m_int; return *this; }
+ number& operator/=(const number& n) { m_int /= n.m_int; return *this; }
+ number& operator%=(const number& n) { m_int %= n.m_int; return *this; }
+
+ number operator-() { return number( -m_int ); }
+
+ bool operator<(const number& n) const { return m_int < n.m_int; }
+ bool operator>(const number& n) const { return m_int > n.m_int; }
+ bool operator<=(const number& n) const { return m_int <= n.m_int; }
+ bool operator>=(const number& n) const { return m_int >= n.m_int; }
+ bool operator!=(const number& n) const { return m_int != n.m_int; }
+ bool operator==(const number& n) const { return m_int == n.m_int; }
+
+ operator bool() { return m_int != 0; }
+
+ number operator&(const number& n) const { return number(m_int & n.m_int); }
+ number operator|(const number& n) const { return number(m_int | n.m_int); }
+ number operator^(const number& n) const { return number(m_int ^ n.m_int); }
+
+ number& operator&=(const number& n) { m_int &= n.m_int; return *this; }
+ number& operator|=(const number& n) { m_int |= n.m_int; return *this; }
+ number& operator^=(const number& n) { m_int ^= n.m_int; return *this; }
+
+ number operator<<(int i) const { return number(m_int << i); }
+ number operator>>(int i) const { return number(m_int >> i); }
+
+private:
+ int m_int;
+};
+
+//----------------------------------------------------------------------------
+struct operator_char_star { // for testing user-defined implicit casts
+ operator_char_star() : m_str((char*)"operator_char_star") {}
+ operator char*() { return m_str; }
+ char* m_str;
+};
+
+struct operator_const_char_star {
+ operator_const_char_star() : m_str("operator_const_char_star" ) {}
+ operator const char*() { return m_str; }
+ const char* m_str;
+};
+
+struct operator_int {
+ operator int() { return m_int; }
+ int m_int;
+};
+
+struct operator_long {
+ operator long() { return m_long; }
+ long m_long;
+};
+
+struct operator_double {
+ operator double() { return m_double; }
+ double m_double;
+};
+
+struct operator_short {
+ operator short() { return m_short; }
+ unsigned short m_short;
+};
+
+struct operator_unsigned_int {
+ operator unsigned int() { return m_uint; }
+ unsigned int m_uint;
+};
+
+struct operator_unsigned_long {
+ operator unsigned long() { return m_ulong; }
+ unsigned long m_ulong;
+};
+
+struct operator_float {
+ operator float() { return m_float; }
+ float m_float;
+};
diff --git a/pypy/module/cppyy/test/test_operators.py b/pypy/module/cppyy/test/test_operators.py
new file mode 100755
--- /dev/null
+++ b/pypy/module/cppyy/test/test_operators.py
@@ -0,0 +1,141 @@
+import py, os, sys
+from pypy.conftest import gettestobjspace
+
+
+currpath = py.path.local(__file__).dirpath()
+shared_lib = str(currpath.join("operatorsDict.so"))
+
+space = gettestobjspace(usemodules=['cppyy'])
+
+def setup_module(mod):
+ if sys.platform == 'win32':
+ py.test.skip("win32 not supported so far")
+ err = os.system("cd '%s' && make operatorsDict.so" % currpath)
+ if err:
+ raise OSError("'make' failed (see stderr)")
+
+class AppTestOPERATORS:
+ def setup_class(cls):
+ cls.space = space
+ env = os.environ
+ cls.w_N = space.wrap(5) # should be imported from the dictionary
+ cls.w_shared_lib = space.wrap(shared_lib)
+ cls.w_datatypes = cls.space.appexec([], """():
+ import cppyy
+ return cppyy.load_lib(%r)""" % (shared_lib, ))
+
+ def teardown_method(self, meth):
+ import gc
+ gc.collect()
+
+ def test01_math_operators(self):
+ """Test overloading of math operators"""
+
+ import cppyy
+ number = cppyy.gbl.number
+
+ assert (number(20) + number(10)) == number(30)
+ assert (number(20) + 10 ) == number(30)
+ assert (number(20) - number(10)) == number(10)
+ assert (number(20) - 10 ) == number(10)
+ assert (number(20) / number(10)) == number(2)
+ assert (number(20) / 10 ) == number(2)
+ assert (number(20) * number(10)) == number(200)
+ assert (number(20) * 10 ) == number(200)
+ assert (number(20) % 10 ) == number(0)
+ assert (number(20) % number(10)) == number(0)
+ assert (number(5) & number(14)) == number(4)
+ assert (number(5) | number(14)) == number(15)
+ assert (number(5) ^ number(14)) == number(11)
+ assert (number(5) << 2) == number(20)
+ assert (number(20) >> 2) == number(5)
+
+ def test02_unary_math_operators(self):
+ """Test overloading of unary math operators"""
+
+ import cppyy
+ number = cppyy.gbl.number
+
+ n = number(20)
+ n += number(10)
+ n -= number(10)
+ n *= number(10)
+ n /= number(2)
+ assert n == number(100)
+
+ nn = -n;
+ assert nn == number(-100)
+
+ def test03_comparison_operators(self):
+ """Test overloading of comparison operators"""
+
+ import cppyy
+ number = cppyy.gbl.number
+
+ assert (number(20) > number(10)) == True
+ assert (number(20) < number(10)) == False
+ assert (number(20) >= number(20)) == True
+ assert (number(20) <= number(10)) == False
+ assert (number(20) != number(10)) == True
+ assert (number(20) == number(10)) == False
+
+ def test04_boolean_operator(self):
+ """Test implementation of operator bool"""
+
+ import cppyy
+ number = cppyy.gbl.number
+
+ n = number(20)
+ assert n
+
+ n = number(0)
+ assert not n
+
+ def test05_exact_types(self):
+ """Test converter operators of exact types"""
+
+ import cppyy
+ gbl = cppyy.gbl
+
+ o = gbl.operator_char_star()
+ assert o.m_str == 'operator_char_star'
+ assert str(o) == 'operator_char_star'
+
+ o = gbl.operator_const_char_star()
+ assert o.m_str == 'operator_const_char_star'
+ assert str(o) == 'operator_const_char_star'
+
+ o = gbl.operator_int(); o.m_int = -13
+ assert o.m_int == -13
+ assert int(o) == -13
+
+ o = gbl.operator_long(); o.m_long = 42
+ assert o.m_long == 42
+ assert long(o) == 42
+
+ o = gbl.operator_double(); o.m_double = 3.1415
+ assert o.m_double == 3.1415
+ assert float(o) == 3.1415
+
+ def test06_approximate_types(self):
+ """Test converter operators of approximate types"""
+
+ import cppyy, sys
+ gbl = cppyy.gbl
+
+ o = gbl.operator_short(); o.m_short = 256
+ assert o.m_short == 256
+ assert int(o) == 256
+
+ o = gbl.operator_unsigned_int(); o.m_uint = 2147483647 + 32
+ assert o.m_uint == 2147483647 + 32
+ assert long(o) == 2147483647 + 32
+
+ o = gbl.operator_unsigned_long();
+ o.m_ulong = sys.maxint + 128
+ assert o.m_ulong == sys.maxint + 128
+ assert long(o) == sys.maxint + 128
+
+ o = gbl.operator_float(); o.m_float = 3.14
+ assert round(o.m_float - 3.14, 5) == 0.
+ assert round(float(o) - 3.14, 5) == 0.
More information about the pypy-commit
mailing list