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

arigo at codespeak.net arigo at codespeak.net
Wed Feb 13 17:05:32 CET 2008


Author: arigo
Date: Wed Feb 13 17:05:30 2008
New Revision: 51441

Modified:
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
Log:
It was possible already to take the fakeaddress just past the end
of an array of primitives; this allows the same for arrays of
structures.  Needed to llinterp the GCs handling dictionaries.


Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Wed Feb 13 17:05:30 2008
@@ -60,7 +60,18 @@
             if isinstance(index, str):
                 assert index.startswith('item')    # itemN => N
                 index = int(index[4:])
-            return parent.getitem(index + self.repeat)._as_ptr()
+            index += self.repeat
+            if index == parent.getlength():
+                # for references exactly to the end of the array
+                try:
+                    endmarker = _end_markers[parent]
+                except KeyError:
+                    endmarker = _endmarker_struct(A, parent=parent,
+                                                  parentindex=index)
+                    _end_markers[parent] = endmarker
+                return endmarker._as_ptr()
+            else:
+                return parent.getitem(index)._as_ptr()
         elif (isinstance(A, lltype.FixedSizeArray) and
               array_item_type_match(A.OF, self.TYPE)):
             # for array of primitives or pointers
@@ -99,6 +110,24 @@
             srcadr += ItemOffset(self.TYPE)
             dstadr += ItemOffset(self.TYPE)
 
+_end_markers = weakref.WeakKeyDictionary()  # <array of STRUCT> -> _endmarker
+class _endmarker_struct(lltype._struct):
+    __slots__ = ()
+    def __new__(self, *args, **kwds):
+        return object.__new__(self)
+    def __init__(self, *args, **kwds):
+        lltype._struct.__init__(self, *args, **kwds)
+        self._storage = False
+    def __getattr__(self, name):
+        raise AttributeError("cannot access fields in the endmarker "
+                             "structure at the end of the array")
+    def __setattr__(self, name, value):
+        if name.startswith('_'):
+            object.__setattr__(self, name, value)  # '_xxx' attributes
+        elif self._storage is False:
+            raise AttributeError("cannot access fields in the endmarker "
+                                 "structure at the end of the array")
+
 
 class FieldOffset(AddressOffset):
 

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	Wed Feb 13 17:05:30 2008
@@ -39,7 +39,35 @@
     assert b.signed[0] == 123
     b.signed[0] = 14
     assert x[3] == 14
-    
+
+def test_array_endaddress():
+    A = lltype.GcArray(lltype.Signed)
+    x = lltype.malloc(A, 5)
+    x[4] = 321
+    a = fakeaddress(x)
+    b = a + ArrayItemsOffset(A)
+    b += ItemOffset(lltype.Signed)*5
+    assert b == a + ArrayItemsOffset(A) + ItemOffset(lltype.Signed)*5
+    py.test.raises(IndexError, "b.signed[0]")
+    b -= ItemOffset(lltype.Signed)
+    assert b.signed[0] == 321
+
+def test_structarray_endaddress():
+    S = lltype.Struct('S', ('foo', lltype.Signed))
+    A = lltype.GcArray(S)
+    x = lltype.malloc(A, 5)
+    x[4].foo = 321
+    a = fakeaddress(x)
+    b = a + ArrayItemsOffset(A)
+    b += ItemOffset(S)*5
+    assert b == a + ArrayItemsOffset(A) + ItemOffset(S)*5
+    p = cast_adr_to_ptr(b, lltype.Ptr(S))
+    py.test.raises(AttributeError, "p.foo")
+    py.test.raises(AttributeError, "p.foo = 55")
+    b -= ItemOffset(S)
+    p = cast_adr_to_ptr(b, lltype.Ptr(S))
+    assert p.foo == 321
+
 def test_dont_mix_offsets_and_ints():
     o = AddressOffset()
     py.test.raises(TypeError, "1 + o")



More information about the Pypy-commit mailing list