[pypy-svn] r44978 - in pypy/dist/pypy/rpython/lltypesystem: . test
arigo at codespeak.net
arigo at codespeak.net
Thu Jul 12 17:34:44 CEST 2007
Author: arigo
Date: Thu Jul 12 17:34:42 2007
New Revision: 44978
Added:
pypy/dist/pypy/rpython/lltypesystem/compactlltype.py (contents, props changed)
pypy/dist/pypy/rpython/lltypesystem/test/test_compactlltype.py
- copied, changed from r44949, pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py
Log:
(lac, arigo)
Intermediate check-in: a very broken attempt. Will be removed anyway.
Added: pypy/dist/pypy/rpython/lltypesystem/compactlltype.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/lltypesystem/compactlltype.py Thu Jul 12 17:34:42 2007
@@ -0,0 +1,205 @@
+import ctypes, sys, weakref
+from pypy.rpython.lltypesystem.lltype import Signed, Struct, GcStruct, Ptr
+from pypy.rpython.lltypesystem.lltype import ContainerType, Array, GcArray
+from pypy.rpython.lltypesystem.lltype import typeOf, castable
+
+_Ctypes_PointerType = type(ctypes.POINTER(ctypes.c_int))
+
+
+def cast_pointer(PTRTYPE, ptr):
+ CURTYPE = typeOf(ptr)
+ if not isinstance(CURTYPE, Ptr) or not isinstance(PTRTYPE, Ptr):
+ raise TypeError, "can only cast pointers to other pointers"
+ return ptr._cast_to(PTRTYPE)
+
+
+class _parentable(ctypes.Structure): # won't work with Union
+ __slots__ = ()
+
+# ____________________________________________________________
+
+_ctypes_cache = {
+ Signed: ctypes.c_long,
+ }
+
+def _build_ctypes_struct(S, max_n=None):
+ fields = []
+ for fieldname in S._names:
+ FIELDTYPE = S._flds[fieldname]
+ if max_n is not None and fieldname == S._arrayfld:
+ cls = _build_ctypes_array(FIELDTYPE, max_n)
+ else:
+ cls = _get_ctypes_type(FIELDTYPE)
+ fields.append((fieldname, cls))
+
+ class CStruct(_parentable):
+ _fields_ = fields
+ _TYPE = S
+
+ def malloc(cls, n=None):
+ S = cls._TYPE
+ if S._arrayfld is None:
+ if n is not None:
+ raise TypeError("%r is not variable-sized" % (S,))
+ return ctypes.pointer(cls())
+ else:
+ if n is None:
+ raise TypeError("%r is variable-sized" % (S,))
+ smallercls = _build_ctypes_struct(S, n)
+ smallstruct = smallercls()
+ getattr(smallstruct, S._arrayfld).length = n
+ structptr = ctypes.cast(ctypes.pointer(smallstruct),
+ ctypes.POINTER(cls))
+ return structptr
+ malloc = classmethod(malloc)
+
+ CStruct.__name__ = 'ctypes_%s' % (S,)
+ return CStruct
+
+def _build_ctypes_array(A, max_n=None):
+ ITEM = A.OF
+ ctypes_item = _get_ctypes_type(ITEM)
+ if max_n is None:
+ max_n = sys.maxint // ctypes.sizeof(ctypes_item)
+ max_n //= 2 # XXX better safe than sorry about ctypes bugs
+
+ class CArray(_parentable):
+ _fields_ = [('length', ctypes.c_int),
+ ('items', max_n * ctypes_item)]
+ _TYPE = A
+
+ def malloc(cls, n=None):
+ if not isinstance(n, int):
+ raise TypeError, "array length must be an int"
+ smallercls = _build_ctypes_array(cls._TYPE, n)
+ smallarray = smallercls()
+ smallarray.length = n
+ arrayptr = ctypes.cast(ctypes.pointer(smallarray),
+ ctypes.POINTER(cls))
+ return arrayptr
+ malloc = classmethod(malloc)
+
+ CArray.__name__ = 'ctypes_%s' % (A,)
+ return CArray
+
+def _get_ctypes_type(T):
+ try:
+ return _ctypes_cache[T]
+ except KeyError:
+ if isinstance(T, Ptr):
+ cls = ctypes.POINTER(_get_ctypes_type(T.TO))
+ elif isinstance(T, Struct):
+ cls = _build_ctypes_struct(T)
+ elif isinstance(T, Array):
+ cls = _build_ctypes_array(T)
+ else:
+ raise NotImplementedError(T)
+ _ctypes_cache[T] = cls
+ return cls
+
+def _expose(val):
+ if isinstance(type(val), _Ctypes_PointerType):
+ val = val.contents
+ T = typeOf(val)
+ if isinstance(T, ContainerType):
+ val = _ptr(ctypes.pointer(val))
+ return val
+
+def _lltype2ctypes(val):
+ T = typeOf(val)
+ if isinstance(T, Ptr):
+ return val._storageptr
+ return val
+
+class _ptr(object):
+ __slots__ = ['_storageptr', '_TYPE']
+
+ def __init__(self, storageptr):
+ assert isinstance(type(storageptr), _Ctypes_PointerType)
+ _ptr._storageptr.__set__(self, storageptr)
+ _ptr._TYPE.__set__(self, Ptr(type(storageptr)._type_._TYPE))
+
+ def __getattr__(self, field_name):
+ if isinstance(self._TYPE.TO, Struct):
+ if field_name in self._TYPE.TO._flds:
+ return _expose(getattr(self._storageptr.contents, field_name))
+ raise AttributeError("%r instance has no field %r" % (self._TYPE.TO,
+ field_name))
+
+ def __setattr__(self, field_name, value):
+ if isinstance(self._TYPE.TO, Struct):
+ if field_name in self._TYPE.TO._flds:
+ setattr(self._storageptr.contents, field_name,
+ _lltype2ctypes(value))
+ return
+ raise AttributeError("%r instance has no field %r" % (self._TYPE.TO,
+ field_name))
+
+ def __nonzero__(self):
+ return bool(self._storageptr)
+
+ def __len__(self):
+ T = self._TYPE.TO
+ if isinstance(T, Array):# ,FixedSizeArray)):
+ #if self._T._hints.get('nolength', False):
+ # raise TypeError("%r instance has no length attribute" %
+ # (self._T,))
+ return self._storageptr.contents.length
+ raise TypeError("%r instance is not an array" % (T,))
+
+ def __getitem__(self, i):
+ T = self._TYPE.TO
+ if isinstance(T, Array):
+ start, stop = 0, self._storageptr.contents.length
+ if not (start <= i < stop):
+ if isinstance(i, slice):
+ raise TypeError("array slicing not supported")
+ raise IndexError("array index out of bounds")
+ return _expose(self._storageptr.contents.items[i])
+ raise TypeError("%r instance is not an array" % (T,))
+
+ def _cast_to(self, PTRTYPE):
+ CURTYPE = self._TYPE
+ down_or_up = castable(PTRTYPE, CURTYPE)
+ if down_or_up == 0:
+ return self
+ if not self: # null pointer cast
+ return PTRTYPE._defl()
+ WAAA
+ if isinstance(self._obj, int):
+ return _ptr(PTRTYPE, self._obj, solid=True)
+ if down_or_up > 0:
+ p = self
+ while down_or_up:
+ p = getattr(p, typeOf(p).TO._names[0])
+ down_or_up -= 1
+ return _ptr(PTRTYPE, p._obj, solid=self._solid)
+ u = -down_or_up
+ struc = self._obj
+ while u:
+ parent = struc._parentstructure()
+ if parent is None:
+ raise RuntimeError("widening to trash: %r" % self)
+ PARENTTYPE = struc._parent_type
+ if getattr(parent, PARENTTYPE._names[0]) is not struc:
+ raise InvalidCast(CURTYPE, PTRTYPE) # xxx different exception perhaps?
+ struc = parent
+ u -= 1
+ if PARENTTYPE != PTRTYPE.TO:
+ raise RuntimeError("widening %r inside %r instead of %r" % (CURTYPE, PARENTTYPE, PTRTYPE.TO))
+ return _ptr(PTRTYPE, struc, solid=self._solid)
+
+# ____________________________________________________________
+
+def malloc(T, n=None, immortal=False):
+ if T._gckind != 'gc' and not immortal:# and flavor.startswith('gc'):
+ raise TypeError, "gc flavor malloc of a non-GC non-immortal structure"
+ if isinstance(T, (Struct, Array)):
+ cls = _get_ctypes_type(T)
+ return _ptr(cls.malloc(n))
+ else:
+ raise TypeError, "malloc for Structs and Arrays only"
+
+def nullptr(T):
+ cls = _get_ctypes_type(T)
+ return _ptr(ctypes.POINTER(cls)())
More information about the Pypy-commit
mailing list