[pypy-svn] pypy default: Issue652 (kleptog) new lltype.Typedef, which allows to give different
amauryfa
commits-noreply at bitbucket.org
Fri Apr 15 00:36:37 CEST 2011
Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch:
Changeset: r43375:d381cb2c140b
Date: 2011-04-15 00:36 +0200
http://bitbucket.org/pypy/pypy/changeset/d381cb2c140b/
Log: Issue652 (kleptog) new lltype.Typedef, which allows to give
different names (in the C backend) to the same type.
Use it in cpyext to have "real" Py_ssize_t parameters
diff --git a/pypy/translator/c/test/test_database.py b/pypy/translator/c/test/test_database.py
--- a/pypy/translator/c/test/test_database.py
+++ b/pypy/translator/c/test/test_database.py
@@ -5,7 +5,7 @@
from pypy.objspace.flow.model import Constant, Variable, SpaceOperation
from pypy.objspace.flow.model import Block, Link, FunctionGraph
from pypy.rpython.typesystem import getfunctionptr
-from pypy.rpython.lltypesystem.rffi import VOIDP, INT_real, INT
+from pypy.rpython.lltypesystem.rffi import VOIDP, INT_real, INT, CArrayPtr
def dump_on_stdout(database):
@@ -244,3 +244,15 @@
db.get(p)
db.complete()
dump_on_stdout(db)
+
+def test_typedef():
+ A = Typedef(Signed, 'test4')
+ db = LowLevelDatabase()
+ assert db.gettype(A) == "test4 @"
+
+ PA = CArrayPtr(A)
+ assert db.gettype(PA) == "test4 *@"
+
+ F = FuncType((A,), A)
+ assert db.gettype(F) == "test4 (@)(test4)"
+
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -37,7 +37,7 @@
DEBUG_WRAPPER = True
# update these for other platforms
-Py_ssize_t = lltype.Signed
+Py_ssize_t = lltype.Typedef(rffi.SSIZE_T, 'Py_ssize_t')
Py_ssize_tP = rffi.CArrayPtr(Py_ssize_t)
size_t = rffi.ULONG
ADDR = lltype.Signed
@@ -192,14 +192,19 @@
- set `external` to False to get a C function pointer, but not exported by
the API headers.
"""
+ if isinstance(restype, lltype.Typedef):
+ real_restype = restype.OF
+ else:
+ real_restype = restype
+
if error is _NOT_SPECIFIED:
- if isinstance(restype, lltype.Ptr):
- error = lltype.nullptr(restype.TO)
- elif restype is lltype.Void:
+ if isinstance(real_restype, lltype.Ptr):
+ error = lltype.nullptr(real_restype.TO)
+ elif real_restype is lltype.Void:
error = CANNOT_FAIL
if type(error) is int:
- error = rffi.cast(restype, error)
- expect_integer = (isinstance(restype, lltype.Primitive) and
+ error = rffi.cast(real_restype, error)
+ expect_integer = (isinstance(real_restype, lltype.Primitive) and
rffi.cast(restype, 0) == 0)
def decorate(func):
diff --git a/pypy/rpython/lltypesystem/test/test_ll2ctypes.py b/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
--- a/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
@@ -1000,6 +1000,13 @@
p = ctypes2lltype(lltype.Ptr(NODE), ctypes.pointer(pc))
assert p.pong.ping == p
+ def test_typedef(self):
+ assert ctypes2lltype(lltype.Typedef(lltype.Signed, 'test'), 6) == 6
+ assert ctypes2lltype(lltype.Typedef(lltype.Float, 'test2'), 3.4) == 3.4
+
+ assert get_ctypes_type(lltype.Signed) == get_ctypes_type(
+ lltype.Typedef(lltype.Signed, 'test3'))
+
def test_cast_adr_to_int(self):
class someaddr(object):
def _cast_to_int(self):
diff --git a/pypy/rpython/lltypesystem/rffi.py b/pypy/rpython/lltypesystem/rffi.py
--- a/pypy/rpython/lltypesystem/rffi.py
+++ b/pypy/rpython/lltypesystem/rffi.py
@@ -818,6 +818,8 @@
"""Similar to llmemory.sizeof() but tries hard to return a integer
instead of a symbolic value.
"""
+ if isinstance(tp, lltype.Typedef):
+ tp = tp.OF
if isinstance(tp, lltype.FixedSizeArray):
return sizeof(tp.OF) * tp.length
if isinstance(tp, lltype.Struct):
diff --git a/pypy/module/cpyext/test/test_api.py b/pypy/module/cpyext/test/test_api.py
--- a/pypy/module/cpyext/test/test_api.py
+++ b/pypy/module/cpyext/test/test_api.py
@@ -70,11 +70,35 @@
if self.check_and_print_leaks():
assert False, "Test leaks or loses object(s)."
+ at api.cpython_api([api.Py_ssize_t], api.Py_ssize_t, error=-1)
+def PyPy_TypedefTest1(space, arg):
+ assert lltype.typeOf(arg) == api.Py_ssize_t
+ return 0
+
+ at api.cpython_api([api.Py_ssize_tP], api.Py_ssize_tP)
+def PyPy_TypedefTest2(space, arg):
+ assert lltype.typeOf(arg) == api.Py_ssize_tP
+ return None
+
class TestConversion(BaseApiTest):
def test_conversions(self, space, api):
api.PyPy_GetWrapped(space.w_None)
api.PyPy_GetReference(space.w_None)
+ def test_typedef(self, space):
+ from pypy.translator.c.database import LowLevelDatabase
+ db = LowLevelDatabase()
+ assert (api.c_function_signature(db, api.FUNCTIONS['PyPy_TypedefTest1'])
+ == ('Py_ssize_t', 'Py_ssize_t arg0'))
+ assert (api.c_function_signature(db, api.FUNCTIONS['PyPy_TypedefTest2'])
+ == ('Py_ssize_t *', 'Py_ssize_t *arg0'))
+
+ PyPy_TypedefTest1(space, 0)
+ ppos = lltype.malloc(api.Py_ssize_tP.TO, 1, flavor='raw')
+ ppos[0] = 0
+ PyPy_TypedefTest2(space, ppos)
+ lltype.free(ppos, flavor='raw')
+
def test_copy_header_files(tmpdir):
api.copy_header_files(tmpdir)
diff --git a/pypy/rpython/lltypesystem/ll2ctypes.py b/pypy/rpython/lltypesystem/ll2ctypes.py
--- a/pypy/rpython/lltypesystem/ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/ll2ctypes.py
@@ -255,6 +255,9 @@
return cls
def build_new_ctypes_type(T, delayed_builders):
+ if isinstance(T, lltype.Typedef):
+ T = T.OF
+
if isinstance(T, lltype.Ptr):
if isinstance(T.TO, lltype.FuncType):
argtypes = [get_ctypes_type(ARG) for ARG in T.TO.ARGS
@@ -758,6 +761,8 @@
"""
if T is lltype.Void:
return None
+ if isinstance(T, lltype.Typedef):
+ T = T.OF
if isinstance(T, lltype.Ptr):
if not cobj or not ctypes.cast(cobj, ctypes.c_void_p).value: # NULL pointer
# CFunctionType.__nonzero__ is broken before Python 2.6
diff --git a/pypy/rpython/lltypesystem/test/test_rffi.py b/pypy/rpython/lltypesystem/test/test_rffi.py
--- a/pypy/rpython/lltypesystem/test/test_rffi.py
+++ b/pypy/rpython/lltypesystem/test/test_rffi.py
@@ -728,6 +728,7 @@
for ll, ctp in cache.items():
assert sizeof(ll) == ctypes.sizeof(ctp)
+ assert sizeof(lltype.Typedef(ll, 'test')) == sizeof(ll)
assert not size_and_sign(lltype.Signed)[1]
assert not size_and_sign(lltype.Char)[1]
assert not size_and_sign(lltype.UniChar)[1]
diff --git a/pypy/annotation/model.py b/pypy/annotation/model.py
--- a/pypy/annotation/model.py
+++ b/pypy/annotation/model.py
@@ -641,6 +641,8 @@
except TypeError:
s = None # unhashable T, e.g. a Ptr(GcForwardReference())
if s is None:
+ if isinstance(T, lltype.Typedef):
+ return lltype_to_annotation(T.OF)
if isinstance(T, lltype.Number):
return SomeInteger(knowntype=T._type)
if isinstance(T, (ootype.Instance, ootype.BuiltinType)):
diff --git a/pypy/rpython/lltypesystem/lltype.py b/pypy/rpython/lltypesystem/lltype.py
--- a/pypy/rpython/lltypesystem/lltype.py
+++ b/pypy/rpython/lltypesystem/lltype.py
@@ -95,6 +95,8 @@
__slots__ = ['__dict__', '__cached_hash']
def __eq__(self, other):
+ if isinstance(other, Typedef):
+ return other.__eq__(self)
return self.__class__ is other.__class__ and (
self is other or safe_equal(self.__dict__, other.__dict__))
@@ -194,6 +196,36 @@
raise NotImplementedError
+class Typedef(LowLevelType):
+ """A typedef is just another name for an existing type"""
+ def __init__(self, OF, c_name):
+ """
+ @param OF: the equivalent rffi type
+ @param c_name: the name we want in C code
+ """
+ assert isinstance(OF, LowLevelType)
+ # Look through typedefs, so other places don't have to
+ if isinstance(OF, Typedef):
+ OF = OF.OF # haha
+ self.OF = OF
+ self.c_name = c_name
+
+ def __repr__(self):
+ return '<Typedef "%s" of %r>' % (self.c_name, self.OF)
+
+ def __eq__(self, other):
+ return other == self.OF
+
+ def __getattr__(self, name):
+ return self.OF.get(name)
+
+ def _defl(self, parent=None, parentindex=None):
+ return self.OF._defl()
+
+ def _allocate(self, initialization, parent=None, parentindex=None):
+ return self.OF._allocate(initialization, parent, parentindex)
+
+
class Struct(ContainerType):
_gckind = 'raw'
diff --git a/pypy/translator/c/database.py b/pypy/translator/c/database.py
--- a/pypy/translator/c/database.py
+++ b/pypy/translator/c/database.py
@@ -1,7 +1,7 @@
-from pypy.rpython.lltypesystem.lltype import \
- Primitive, Ptr, typeOf, RuntimeTypeInfo, \
- Struct, Array, FuncType, PyObject, Void, \
- ContainerType, OpaqueType, FixedSizeArray, _uninitialized
+
+from pypy.rpython.lltypesystem.lltype import (
+ Primitive, Ptr, typeOf, RuntimeTypeInfo, Struct, Array, FuncType, PyObject,
+ Void, ContainerType, OpaqueType, FixedSizeArray, _uninitialized, Typedef)
from pypy.rpython.lltypesystem import lltype, rffi
from pypy.rpython.lltypesystem.llmemory import WeakRef, _WeakRefType, GCREF
from pypy.rpython.lltypesystem.rffi import CConstant
@@ -100,6 +100,8 @@
def gettype(self, T, varlength=1, who_asks=None, argnames=[]):
if isinstance(T, Primitive) or T == GCREF:
return PrimitiveType[T]
+ elif isinstance(T, Typedef):
+ return '%s @' % T.c_name
elif isinstance(T, Ptr):
if (isinstance(T.TO, OpaqueType) and
T.TO.hints.get('c_pointer_typedef') is not None):
diff --git a/pypy/rpython/lltypesystem/test/test_lltype.py b/pypy/rpython/lltypesystem/test/test_lltype.py
--- a/pypy/rpython/lltypesystem/test/test_lltype.py
+++ b/pypy/rpython/lltypesystem/test/test_lltype.py
@@ -804,6 +804,21 @@
hints={'immutable_fields': FieldListAccessor({'x':'[*]'})})
assert S._immutable_field('x') == '[*]'
+def test_typedef():
+ T = Typedef(Signed, 'T')
+ assert T == Signed
+ assert Signed == T
+ T2 = Typedef(T, 'T2')
+ assert T2 == T
+ assert T2.OF is Signed
+ py.test.raises(TypeError, Ptr, T)
+ assert rffi.CArrayPtr(T) == rffi.CArrayPtr(Signed)
+ assert rffi.CArrayPtr(Signed) == rffi.CArrayPtr(T)
+
+ F = FuncType((T,), T)
+ assert F.RESULT == Signed
+ assert F.ARGS == (Signed,)
+
class TestTrackAllocation:
def test_automatic_tracking(self):
More information about the Pypy-commit
mailing list