[pypy-svn] r25613 - in pypy/dist/pypy/rpython/lltypesystem: . test

arigo at codespeak.net arigo at codespeak.net
Sun Apr 9 12:25:07 CEST 2006


Author: arigo
Date: Sun Apr  9 12:25:06 2006
New Revision: 25613

Modified:
   pypy/dist/pypy/rpython/lltypesystem/lltype.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py
Log:
(arre, arigo)

Conversion from Array to Array(nolength=True), as well as
from FixedSizeArray to Array(nolength=True).



Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py	Sun Apr  9 12:25:06 2006
@@ -612,6 +612,24 @@
         raise TypeError, "can only cast pointers to other pointers"
     return ptr._cast_to(PTRTYPE)
 
+def cast_array_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"
+    if (not isinstance(PTRTYPE.TO, Array) or
+        not PTRTYPE.TO._hints.get('nolength', False)):
+        raise TypeError, "can only convert to nolength Arrays"
+    if isinstance(CURTYPE.TO, Array):
+        if CURTYPE.TO._hints.get('nolength', False):
+            raise TypeError, "cannot convert from a nolength Array"
+    elif isinstance(CURTYPE.TO, FixedSizeArray):
+        pass
+    else:
+        raise TypeError, "can only convert from an array"
+    if CURTYPE.TO.OF != PTRTYPE.TO.OF:
+        raise TypeError, "pointers to arrays of different item types"
+    return ptr._cast_array_to(PTRTYPE)
+
 def _expose(val, solid=False):
     """XXX A nice docstring here"""
     T = typeOf(val)
@@ -692,7 +710,8 @@
     def _setobj(self, pointing_to, solid=False):        
         if pointing_to is None:
             obj0 = None
-        elif solid or isinstance(self._T, (GC_CONTAINER, FuncType)):
+        elif (solid or isinstance(self._T, (GC_CONTAINER, FuncType))
+                    or isinstance(pointing_to, _nolengtharray)):
             obj0 = pointing_to
         else:
             self._set_weak(True)
@@ -761,20 +780,15 @@
                                                               field_name))
 
     def __getitem__(self, i): # ! can only return basic or ptr !
-        if isinstance(self._T, Array):
-            if not (0 <= i < len(self._obj.items)):
+        if isinstance(self._T, (Array, FixedSizeArray)):
+            if not (0 <= i < self._obj.getlength()):
                 raise IndexError("array index out of bounds")
-            o = self._obj.items[i]
-            return _expose(o, self._solid)
-        if isinstance(self._T, FixedSizeArray):
-            if not (0 <= i < self._T.length):
-                raise IndexError("fixed-size array index out of bounds")
-            o = getattr(self._obj, 'item%d' % i)
+            o = self._obj.getitem(i)
             return _expose(o, self._solid)
         raise TypeError("%r instance is not an array" % (self._T,))
 
     def __setitem__(self, i, val):
-        if isinstance(self._T, Array):
+        if isinstance(self._T, (Array, FixedSizeArray)):
             T1 = self._T.OF
             if isinstance(T1, ContainerType):
                 raise TypeError("cannot directly assign to container array items")
@@ -783,34 +797,18 @@
                     raise TypeError("%r items:\n"
                                     "expect %r\n"
                                     "   got %r" % (self._T, T1, T2))                
-            if not (0 <= i < len(self._obj.items)):
+            if not (0 <= i < self._obj.getlength()):
                 raise IndexError("array index out of bounds")
-            self._obj.items[i] = val
-            return
-        if isinstance(self._T, FixedSizeArray):
-            T1 = self._T.OF
-            if isinstance(T1, ContainerType):
-                raise TypeError("cannot directly assign to container array items")
-            T2 = typeOf(val)
-            if T2 != T1:
-                    raise TypeError("%r items:\n"
-                                    "expect %r\n"
-                                    "   got %r" % (self._T, T1, T2))                
-            if not (0 <= i < self._T.length):
-                raise IndexError("fixed-size array index out of bounds")
-            setattr(self._obj, 'item%d' % i, val)
+            self._obj.setitem(i, val)
             return
         raise TypeError("%r instance is not an array" % (self._T,))
 
     def __len__(self):
-        if isinstance(self._T, Array):
+        if isinstance(self._T, (Array, FixedSizeArray)):
             if self._T._hints.get('nolength', False):
                 raise TypeError("%r instance has no length attribute" %
                                     (self._T,))
-
-            return len(self._obj.items)
-        if isinstance(self._T, FixedSizeArray):
-            return self._T.length
+            return self._obj.getlength()
         raise TypeError("%r instance is not an array" % (self._T,))
 
     def __repr__(self):
@@ -862,7 +860,10 @@
         if PARENTTYPE != PTRTYPE.TO:
             raise TypeError("widening %r inside %r instead of %r" % (CURTYPE, PARENTTYPE, PTRTYPE.TO))
         return _ptr(PTRTYPE, struc, solid=self._solid)
-        
+
+    def _cast_array_to(self, PTRTYPE):
+        return _ptr(PTRTYPE, _nolengtharray(PTRTYPE.TO, self._obj))
+
     def _cast_to_int(self):
         obj = self._obj
         while obj._parentstructure():
@@ -977,6 +978,18 @@
 
     __setstate__ = setstate_with_slots
 
+    def getlength(self):              # for FixedSizeArray kind of structs
+        assert isinstance(self._TYPE, FixedSizeArray)
+        return self._TYPE.length
+
+    def getitem(self, index):         # for FixedSizeArray kind of structs
+        assert isinstance(self._TYPE, FixedSizeArray)
+        return getattr(self, 'item%d' % index)
+
+    def setitem(self, index, value):  # for FixedSizeArray kind of structs
+        assert isinstance(self._TYPE, FixedSizeArray)
+        setattr(self, 'item%d' % index, value)
+
 class _array(_parentable):
     _kind = "array"
 
@@ -1010,6 +1023,41 @@
         return 'array [ %s ]' % (', '.join([self._str_item(item)
                                             for item in self.items]),)
 
+    def getlength(self):
+        return len(self.items)
+
+    def getitem(self, index):
+        return self.items[index]
+
+    def setitem(self, index, value):
+        self.items[index] = value
+
+class _nolengtharray(object):
+    _kind = "array"
+
+    __slots__ = ('_TYPE', 'wr_parentarray')
+
+    def __init__(self, TYPE, parentarray):
+        self._TYPE = TYPE
+        self.wr_parentarray = pickleable_weakref(parentarray)
+
+    def getparentarray(self):
+        parentarray = self.wr_parentarray()
+        if parentarray is None:
+            raise RuntimeError("accessing already garbage collected %r"
+                               % (self._T,))
+        return parentarray
+
+    def getlength(self):
+        # for debugging only
+        return self.getparentarray().getlength()
+
+    def getitem(self, index):
+        return self.getparentarray().getitem(index)
+
+    def setitem(self, index, value):
+        return self.getparentarray().setitem(index, value)
+
 assert not '__dict__' in dir(_array)
 assert not '__dict__' in dir(_struct)
 

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py	Sun Apr  9 12:25:06 2006
@@ -519,6 +519,50 @@
     a = malloc(A, 10)
     py.test.raises(TypeError, len, a)
 
+def test_cast_length_to_no_length():
+    A = Array(Char, hints={'nolength': True})
+    S = GcStruct("str", ("hash", Signed),
+                        ("chars", Array(Char)))
+    s = malloc(S, 5)
+    s.chars[0] = 'h'
+    s.chars[1] = 'e'
+    s.chars[2] = 'l'
+    s.chars[3] = 'l'
+    s.chars[4] = 'o'
+    a = cast_array_pointer(Ptr(A), s.chars)
+    assert a[0] == 'h'
+    assert a[1] == 'e'
+    assert a[2] == 'l'
+    assert a[3] == 'l'
+    assert a[4] == 'o'
+    py.test.raises(TypeError, len, a)
+    a[1] = 'E'
+    assert s.chars[1] == 'E'
+    s.chars[2] = 'L'
+    assert a[2] == 'L'
+
+def test_cast_fixed_to_no_length():
+    A = Array(Char, hints={'nolength': True})
+    S = GcStruct("str", ("hash", Signed),
+                        ("chars", FixedSizeArray(Char, 5)))
+    s = malloc(S)
+    s.chars[0] = 'h'
+    s.chars[1] = 'e'
+    s.chars[2] = 'l'
+    s.chars[3] = 'l'
+    s.chars[4] = 'o'
+    a = cast_array_pointer(Ptr(A), s.chars)
+    assert a[0] == 'h'
+    assert a[1] == 'e'
+    assert a[2] == 'l'
+    assert a[3] == 'l'
+    assert a[4] == 'o'
+    py.test.raises(TypeError, len, a)
+    a[1] = 'E'
+    assert s.chars[1] == 'E'
+    s.chars[2] = 'L'
+    assert a[2] == 'L'
+
 def test_dissect_ll_instance():
     assert list(dissect_ll_instance(1)) == [(Signed, 1)]
     GcS = GcStruct("S", ('x', Signed))



More information about the Pypy-commit mailing list