[pypy-commit] pypy default: Import and pass the test about _Bool.
arigo
noreply at buildbot.pypy.org
Thu Sep 13 18:40:47 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r57324:c5f0e18c0b8c
Date: 2012-09-13 18:40 +0200
http://bitbucket.org/pypy/pypy/changeset/c5f0e18c0b8c/
Log: Import and pass the test about _Bool.
diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py
--- a/pypy/module/_cffi_backend/ctypeprim.py
+++ b/pypy/module/_cffi_backend/ctypeprim.py
@@ -52,19 +52,25 @@
if (isinstance(ob, cdataobj.W_CData) and
isinstance(ob.ctype, ctypeptr.W_CTypePtrOrArray)):
value = rffi.cast(lltype.Signed, ob._cdata)
- value = r_ulonglong(value)
+ value = self._cast_result(value)
elif space.isinstance_w(w_ob, space.w_str):
value = self.cast_str(w_ob)
- value = r_ulonglong(value)
+ value = self._cast_result(value)
elif space.isinstance_w(w_ob, space.w_unicode):
value = self.cast_unicode(w_ob)
- value = r_ulonglong(value)
+ value = self._cast_result(value)
else:
- value = misc.as_unsigned_long_long(space, w_ob, strict=False)
+ value = self._cast_generic(w_ob)
w_cdata = cdataobj.W_CDataMem(space, self.size, self)
w_cdata.write_raw_integer_data(value)
return w_cdata
+ def _cast_result(self, intvalue):
+ return r_ulonglong(intvalue)
+
+ def _cast_generic(self, w_ob):
+ return misc.as_unsigned_long_long(self.space, w_ob, strict=False)
+
def _overflow(self, w_ob):
space = self.space
s = space.str_w(space.str(w_ob))
@@ -203,8 +209,11 @@
W_CTypePrimitive.__init__(self, *args)
self.value_fits_long = self.size < rffi.sizeof(lltype.Signed)
if self.size < rffi.sizeof(lltype.SignedLongLong):
- sh = self.size * 8
- self.vrangemax = (r_ulonglong(1) << sh) - 1
+ self.vrangemax = self._compute_vrange_max()
+
+ def _compute_vrange_max(self):
+ sh = self.size * 8
+ return (r_ulonglong(1) << sh) - 1
def int(self, cdata):
return self.convert_to_object(cdata)
@@ -231,6 +240,23 @@
return self
+class W_CTypePrimitiveBool(W_CTypePrimitiveUnsigned):
+ _attrs_ = []
+
+ def _compute_vrange_max(self):
+ return r_ulonglong(1)
+
+ def _cast_result(self, intvalue):
+ return r_ulonglong(intvalue != 0)
+
+ def _cast_generic(self, w_ob):
+ return misc.object_as_bool(self.space, w_ob)
+
+ def string(self, cdataobj, maxlen):
+ # bypass the method 'string' implemented in W_CTypePrimitive
+ return W_CType.string(self, cdataobj, maxlen)
+
+
class W_CTypePrimitiveFloat(W_CTypePrimitive):
_attrs_ = []
diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py
--- a/pypy/module/_cffi_backend/misc.py
+++ b/pypy/module/_cffi_backend/misc.py
@@ -3,7 +3,9 @@
from pypy.rpython.lltypesystem import lltype, llmemory, rffi
from pypy.rlib.rarithmetic import r_ulonglong
from pypy.rlib.unroll import unrolling_iterable
+from pypy.rlib.objectmodel import keepalive_until_here
from pypy.rlib import jit
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
# ____________________________________________________________
@@ -181,6 +183,63 @@
# ____________________________________________________________
+class _NotStandardObject(Exception):
+ pass
+
+def _standard_object_as_bool(space, w_ob):
+ if space.isinstance_w(w_ob, space.w_int):
+ return space.int_w(w_ob) != 0
+ if space.isinstance_w(w_ob, space.w_long):
+ return space.bigint_w(w_ob).tobool()
+ if space.isinstance_w(w_ob, space.w_float):
+ return space.float_w(w_ob) != 0.0
+ raise _NotStandardObject
+
+# hackish, but the most straightforward way to know if a LONGDOUBLE object
+# contains the value 0 or not.
+eci = ExternalCompilationInfo(post_include_bits=["""
+static bool_t pypy__is_nonnull_longdouble(long double x) {
+ return x != 0.0;
+}
+"""])
+is_nonnull_longdouble = rffi.llexternal(
+ "pypy__is_nonnull_longdouble", [rffi.LONGDOUBLE], lltype.Bool,
+ compilation_info=eci, _nowrapper=True, elidable_function=True,
+ sandboxsafe=True)
+
+def object_as_bool(space, w_ob):
+ # convert and cast a Python object to a boolean. Accept an integer
+ # or a float object, up to a CData 'long double'.
+ try:
+ return _standard_object_as_bool(space, w_ob)
+ except _NotStandardObject:
+ pass
+ #
+ from pypy.module._cffi_backend.cdataobj import W_CData
+ from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveFloat
+ from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveLongDouble
+ ob = space.interpclass_w(w_ob)
+ is_cdata = isinstance(ob, W_CData)
+ if is_cdata and isinstance(ob.ctype, W_CTypePrimitiveFloat):
+ if isinstance(ob.ctype, W_CTypePrimitiveLongDouble):
+ result = is_nonnull_longdouble(read_raw_longdouble_data(ob._cdata))
+ else:
+ result = read_raw_float_data(ob._cdata, ob.ctype.size) != 0.0
+ keepalive_until_here(ob)
+ return result
+ #
+ if not is_cdata and space.lookup(w_ob, '__float__') is not None:
+ w_io = space.float(w_ob)
+ else:
+ w_io = space.int(w_ob)
+ try:
+ return _standard_object_as_bool(space, w_io)
+ except _NotStandardObject:
+ raise OperationError(space.w_TypeError,
+ space.wrap("integer/float expected"))
+
+# ____________________________________________________________
+
def _raw_memcopy(source, dest, size):
if jit.isconstant(size):
# for the JIT: first handle the case where 'size' is known to be
diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py
--- a/pypy/module/_cffi_backend/newtype.py
+++ b/pypy/module/_cffi_backend/newtype.py
@@ -38,6 +38,7 @@
eptype("float", rffi.FLOAT, ctypeprim.W_CTypePrimitiveFloat)
eptype("double", rffi.DOUBLE, ctypeprim.W_CTypePrimitiveFloat)
eptype("long double", rffi.LONGDOUBLE, ctypeprim.W_CTypePrimitiveLongDouble)
+eptype("_Bool", lltype.Bool, ctypeprim.W_CTypePrimitiveBool)
@unwrap_spec(name=str)
def new_primitive_type(space, name):
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -2085,3 +2085,33 @@
BFloat = new_primitive_type("float")
py.test.raises(TypeError, newp, BIntP, cast(BFloat, 0.0))
py.test.raises(TypeError, newp, BUIntP, cast(BFloat, 0.0))
+
+def test_bool():
+ BBool = new_primitive_type("_Bool")
+ BBoolP = new_pointer_type(BBool)
+ assert int(cast(BBool, False)) == 0
+ assert int(cast(BBool, True)) == 1
+ assert bool(cast(BBool, False)) is True # warning!
+ assert int(cast(BBool, 3)) == 1
+ assert int(cast(BBool, long(3))) == 1
+ assert int(cast(BBool, long(10)**4000)) == 1
+ assert int(cast(BBool, -0.1)) == 1
+ assert int(cast(BBool, -0.0)) == 0
+ assert int(cast(BBool, '\x00')) == 0
+ assert int(cast(BBool, '\xff')) == 1
+ assert newp(BBoolP, False)[0] == 0
+ assert newp(BBoolP, True)[0] == 1
+ assert newp(BBoolP, 0)[0] == 0
+ assert newp(BBoolP, 1)[0] == 1
+ py.test.raises(TypeError, newp, BBoolP, 1.0)
+ py.test.raises(TypeError, newp, BBoolP, '\x00')
+ py.test.raises(OverflowError, newp, BBoolP, 2)
+ py.test.raises(OverflowError, newp, BBoolP, -1)
+ BCharP = new_pointer_type(new_primitive_type("char"))
+ p = newp(BCharP, 'X')
+ q = cast(BBoolP, p)
+ assert q[0] == ord('X')
+ py.test.raises(TypeError, string, cast(BBool, False))
+ BDouble = new_primitive_type("double")
+ assert int(cast(BBool, cast(BDouble, 0.1))) == 1
+ assert int(cast(BBool, cast(BDouble, 0.0))) == 0
More information about the pypy-commit
mailing list