[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