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

arigo at codespeak.net arigo at codespeak.net
Thu Apr 13 16:22:08 CEST 2006


Author: arigo
Date: Thu Apr 13 16:22:05 2006
New Revision: 25795

Modified:
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/lltypesystem/lltype.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py
Log:
Yet another strange lltype operation: cast_structfield_pointer().
It allows a pointer to a structure field to be taken.  This
pointer gets a type of Ptr(FixedSizeArray(FIELD_TYPE, 1)).
As with cast_subarray_pointer(), the actual implementation will
use address manipulations.


Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Thu Apr 13 16:22:05 2006
@@ -129,7 +129,7 @@
     def set(self, value):
         setattr(self.struct, self.fieldname, value)
     def type(self):
-        return getattr(lltype.typeOf(self.struct), self.fieldname)
+        return getattr(lltype.typeOf(self.struct).TO, self.fieldname)
 
 class _obref(object):
     def __init__(self, ob):
@@ -218,12 +218,18 @@
         ref = self.ref()
         if (isinstance(ref, _arrayitemref) and
             isinstance(EXPECTED_TYPE.TO, lltype.FixedSizeArray) and
-            isinstance(lltype.typeOf(ref.array).TO, (lltype.FixedSizeArray,
-                                                     lltype.Array))):
+            ref.type() == EXPECTED_TYPE.TO.OF):
             # special case that requires cast_subarray_pointer
             return lltype.cast_subarray_pointer(EXPECTED_TYPE,
                                                 ref.array,
                                                 ref.index)
+        elif (isinstance(ref, _structfieldref) and
+              isinstance(EXPECTED_TYPE.TO, lltype.FixedSizeArray) and
+              ref.type() == EXPECTED_TYPE.TO.OF):
+            # special case that requires cast_structfield_pointer
+            return lltype.cast_structfield_pointer(EXPECTED_TYPE,
+                                                   ref.struct,
+                                                   ref.fieldname)
         else:
             # regular case
             assert isinstance(ref.type(), lltype.ContainerType)

Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py	Thu Apr 13 16:22:05 2006
@@ -636,6 +636,31 @@
         subarray = cache[key] = _subarray(ARRAYTYPE, arrayptr._obj, baseoffset)
     return _ptr(ARRAYPTRTYPE, subarray)
 
+def cast_structfield_pointer(ARRAYPTRTYPE, structptr, fieldname):
+    CURPTRTYPE = typeOf(structptr)
+    if not isinstance(CURPTRTYPE, Ptr) or not isinstance(ARRAYPTRTYPE, Ptr):
+        raise TypeError, "can only cast pointers to other pointers"
+    ARRAYTYPE = ARRAYPTRTYPE.TO
+    if (not isinstance(CURPTRTYPE.TO, Struct) or
+        not isinstance(ARRAYTYPE, FixedSizeArray)):
+        raise TypeError, "can only cast from (Gc)Struct to FixedSizeArray"
+    if ARRAYTYPE.length != 1:
+        raise TypeError, "can only cast to FixedSizeArray of length 1"
+    if getattr(CURPTRTYPE.TO, fieldname) != ARRAYTYPE.OF:
+        raise TypeError, "mismatching array item type"
+    if not structptr:
+        raise RuntimeError("cast_structfield_pointer: NULL argument")
+    try:
+        cache = _subarray._cache[structptr._obj]
+    except KeyError:
+        cache = _subarray._cache[structptr._obj] = {}
+    try:
+        subarray = cache[fieldname]
+    except KeyError:
+        subarray = cache[fieldname] = _subarray(ARRAYTYPE, structptr._obj,
+                                                fieldname)
+    return _ptr(ARRAYPTRTYPE, subarray)
+
 def _expose(val, solid=False):
     """XXX A nice docstring here"""
     T = typeOf(val)
@@ -1066,12 +1091,13 @@
 
 
 class _subarray(_parentable):     # only for cast_subarray_pointer()
+                                  # and cast_structfield_pointer()
     _kind = "subarray"
     _cache = weakref.WeakKeyDictionary()  # parentarray -> {subarrays}
 
-    def __init__(self, TYPE, arrayobj, baseoffset):
+    def __init__(self, TYPE, parent, baseoffset_or_fieldname):
         _parentable.__init__(self, TYPE)
-        self._setparentstructure(arrayobj, baseoffset)
+        self._setparentstructure(parent, baseoffset_or_fieldname)
 
     def getlength(self):
         assert isinstance(self._TYPE, FixedSizeArray)
@@ -1079,16 +1105,28 @@
 
     def getbounds(self):
         baseoffset = self._parent_index
+        if isinstance(baseoffset, str):
+            return 0, 1     # structfield case
         start, stop = self._parentstructure().getbounds()
         return start - baseoffset, stop - baseoffset
 
     def getitem(self, index):
         baseoffset = self._parent_index
-        return self._parentstructure().getitem(baseoffset + index)
+        if isinstance(baseoffset, str):
+            assert index == 0
+            fieldname = baseoffset    # structfield case
+            return getattr(self._parentstructure(), fieldname)
+        else:
+            return self._parentstructure().getitem(baseoffset + index)
 
     def setitem(self, index, value):
         baseoffset = self._parent_index
-        self._parentstructure().setitem(baseoffset + index, value)
+        if isinstance(baseoffset, str):
+            assert index == 0
+            fieldname = baseoffset    # structfield case
+            setattr(self._parentstructure(), fieldname, value)
+        else:
+            self._parentstructure().setitem(baseoffset + index, value)
 
 
 class _func(object):

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	Thu Apr 13 16:22:05 2006
@@ -173,3 +173,12 @@
         assert subarray[0] == 132
         subarray[0] += 2
         assert a[3] == 134
+
+def test_cast_structfield_pointer():
+    S = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed))
+    s = lltype.malloc(S)
+    SUBARRAY = lltype.FixedSizeArray(lltype.Signed, 1)
+    adr = cast_ptr_to_adr(s) + offsetof(S, 'y')
+    subarray = cast_adr_to_ptr(adr, lltype.Ptr(SUBARRAY))
+    subarray[0] = 121
+    assert s.y == 121

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	Thu Apr 13 16:22:05 2006
@@ -610,3 +610,12 @@
         py.test.raises(IndexError, "b01[-1]")
         py.test.raises(IndexError, "b34[2]")
         py.test.raises(IndexError, "b12[4]")
+
+def test_cast_structfield_pointer():
+    S = GcStruct('S', ('x', Signed), ('y', Signed))
+    A = FixedSizeArray(Signed, 1)
+    s = malloc(S)
+    a = cast_structfield_pointer(Ptr(A), s, 'y')
+    a[0] = 34
+    assert s.y == 34
+    py.test.raises(IndexError, "a[1]")



More information about the Pypy-commit mailing list