Author: Armin Rigo <ar...@tunes.org> Branch: ffi-backend Changeset: r55747:f49f7a936634 Date: 2012-06-20 18:35 +0200 http://bitbucket.org/pypy/pypy/changeset/f49f7a936634/
Log: Next test. diff --git a/pypy/module/_ffi_backend/cdataobj.py b/pypy/module/_ffi_backend/cdataobj.py --- a/pypy/module/_ffi_backend/cdataobj.py +++ b/pypy/module/_ffi_backend/cdataobj.py @@ -24,6 +24,9 @@ def repr(self): return self.space.wrap("<cdata '%s'>" % self.ctype.name) + def nonzero(self): + return self.space.wrap(bool(self.cdata)) + def int(self): w_result = self.ctype.int(self.cdata) keepalive_until_here(self) @@ -36,6 +39,11 @@ w_result = space.newlong(space.int_w(w_result)) return w_result + def float(self): + w_result = self.ctype.float(self.cdata) + keepalive_until_here(self) + return w_result + def read_raw_signed_data(self): result = misc.read_raw_signed_data(self.cdata, self.ctype.size) keepalive_until_here(self) @@ -50,6 +58,15 @@ misc.write_raw_integer_data(self.cdata, source, self.ctype.size) keepalive_until_here(self) + def read_raw_float_data(self): + result = misc.read_raw_float_data(self.cdata, self.ctype.size) + keepalive_until_here(self) + return result + + def write_raw_float_data(self, source): + misc.write_raw_float_data(self.cdata, source, self.ctype.size) + keepalive_until_here(self) + def convert_to_object(self): w_obj = self.ctype.convert_to_object(self.cdata) keepalive_until_here(self) @@ -70,8 +87,10 @@ W_CData.typedef = TypeDef( '_ffi_backend.CData', __repr__ = interp2app(W_CData.repr), + __nonzero__ = interp2app(W_CData.nonzero), __int__ = interp2app(W_CData.int), __long__ = interp2app(W_CData.long), + __float__ = interp2app(W_CData.float), ) W_CData.acceptable_as_base_class = False diff --git a/pypy/module/_ffi_backend/ctypeobj.py b/pypy/module/_ffi_backend/ctypeobj.py --- a/pypy/module/_ffi_backend/ctypeobj.py +++ b/pypy/module/_ffi_backend/ctypeobj.py @@ -28,6 +28,11 @@ raise operationerrfmt(space.w_TypeError, "int() not supported on cdata '%s'", self.name) + def float(self, cdata): + space = self.space + raise operationerrfmt(space.w_TypeError, + "float() not supported on cdata '%s'", self.name) + def convert_to_object(self, cdata): raise NotImplementedError @@ -88,6 +93,34 @@ return self.space.wrap(value) # r_ulonglong => 'long' object +class W_CTypePrimitiveFloat(W_CTypePrimitive): + + def cast(self, w_ob): + space = self.space + if cdataobj.check_cdata(space, w_ob): + xxx + elif space.isinstance_w(w_ob, space.w_str): + xxx + elif space.is_w(w_ob, space.w_None): + value = 0.0 + else: + value = space.float_w(w_ob) + w_cdata = cdataobj.W_CDataOwn(space, self.size, self) + w_cdata.write_raw_float_data(value) + return w_cdata + + def int(self, cdata): + w_value = self.float(cdata) + return self.space.int(w_value) + + def float(self, cdata): + return self.convert_to_object(cdata) + + def convert_to_object(self, cdata): + value = misc.read_raw_float_data(cdata, self.size) + return self.space.wrap(value) + + W_CType.typedef = TypeDef( '_ffi_backend.CTypeDescr', __repr__ = interp2app(W_CType.repr), diff --git a/pypy/module/_ffi_backend/misc.py b/pypy/module/_ffi_backend/misc.py --- a/pypy/module/_ffi_backend/misc.py +++ b/pypy/module/_ffi_backend/misc.py @@ -1,3 +1,4 @@ +from pypy.interpreter.error import OperationError, operationerrfmt from pypy.rpython.lltypesystem import lltype, rffi from pypy.rlib.rarithmetic import r_ulonglong from pypy.rlib.unroll import unrolling_iterable @@ -18,18 +19,28 @@ (rffi.ULONG, rffi.ULONGP), (rffi.ULONGLONG, rffi.ULONGLONGP)]) +_prim_float_types = unrolling_iterable([ + (rffi.FLOAT, rffi.FLOATP), + (rffi.DOUBLE, rffi.DOUBLEP)]) + def read_raw_signed_data(target, size): for TP, TPP in _prim_signed_types: if size == rffi.sizeof(TP): - return rffi.cast(rffi.LONGLONG, rffi.cast(TPP, target)[0]) + return rffi.cast(lltype.SignedLongLong, rffi.cast(TPP, target)[0]) raise NotImplementedError("bad integer size") def read_raw_unsigned_data(target, size): for TP, TPP in _prim_unsigned_types: if size == rffi.sizeof(TP): - return rffi.cast(rffi.ULONGLONG, rffi.cast(TPP, target)[0]) + return rffi.cast(lltype.UnsignedLongLong, rffi.cast(TPP,target)[0]) raise NotImplementedError("bad integer size") +def read_raw_float_data(target, size): + for TP, TPP in _prim_float_types: + if size == rffi.sizeof(TP): + return rffi.cast(lltype.Float, rffi.cast(TPP, target)[0]) + raise NotImplementedError("bad float size") + def write_raw_integer_data(target, source, size): for TP, TPP in _prim_unsigned_types: if size == rffi.sizeof(TP): @@ -37,6 +48,13 @@ return raise NotImplementedError("bad integer size") +def write_raw_float_data(target, source, size): + for TP, TPP in _prim_float_types: + if size == rffi.sizeof(TP): + rffi.cast(TPP, target)[0] = rffi.cast(TP, source) + return + raise NotImplementedError("bad float size") + # ____________________________________________________________ @@ -91,8 +109,8 @@ def as_unsigned_long_long(space, w_ob, strict): # (possibly) convert and cast a Python object to an unsigned long long. # This accepts a Python int too, and does convertions from other types of - # objects. If 'overflow', complains with OverflowError; if 'not overflow', - # mask the result. + # objects. If 'strict', complains with OverflowError; if 'not strict', + # mask the result and round floats. if space.is_w(space.type(w_ob), space.w_int): # shortcut value = space.int_w(w_ob) if strict and value < 0: diff --git a/pypy/module/_ffi_backend/newtype.py b/pypy/module/_ffi_backend/newtype.py --- a/pypy/module/_ffi_backend/newtype.py +++ b/pypy/module/_ffi_backend/newtype.py @@ -31,7 +31,8 @@ eptype("unsigned int", rffi.INT, ctypeobj.W_CTypePrimitiveUnsigned) eptype("unsigned long", rffi.LONG, ctypeobj.W_CTypePrimitiveUnsigned) eptype("unsigned long long", rffi.LONGLONG, ctypeobj.W_CTypePrimitiveUnsigned) - +eptype("float", rffi.FLOAT, ctypeobj.W_CTypePrimitiveFloat) +eptype("double", rffi.DOUBLE, ctypeobj.W_CTypePrimitiveFloat) @unwrap_spec(name=str) def new_primitive_type(space, name): diff --git a/pypy/module/_ffi_backend/test/test_c.py b/pypy/module/_ffi_backend/test/test_c.py --- a/pypy/module/_ffi_backend/test/test_c.py +++ b/pypy/module/_ffi_backend/test/test_c.py @@ -92,10 +92,12 @@ assert long(cast(p, -1)) == max def test_no_float_on_int_types(self): - p = new_primitive_type('long') - py.test.raises(TypeError, float, cast(p, 42)) + p = self.b.new_primitive_type('long') + raises(TypeError, float, self.b.cast(p, 42)) def test_float_types(self): + new_primitive_type = self.b.new_primitive_type + cast = self.b.cast INF = 1E200 * 1E200 for name in ["float", "double"]: p = new_primitive_type(name) @@ -109,8 +111,8 @@ assert type(int(cast(p, 1E22))) is long assert type(long(cast(p, 61.91))) is long assert type(long(cast(p, 1E22))) is long - py.test.raises(OverflowError, int, cast(p, INF)) - py.test.raises(OverflowError, int, cast(p, -INF)) + raises(OverflowError, int, cast(p, INF)) + raises(OverflowError, int, cast(p, -INF)) assert float(cast(p, 1.25)) == 1.25 assert float(cast(p, INF)) == INF assert float(cast(p, -INF)) == -INF _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit