[pypy-svn] r15524 - in pypy/dist/pypy/rpython/memory: . test
cfbolz at codespeak.net
cfbolz at codespeak.net
Tue Aug 2 22:27:52 CEST 2005
Author: cfbolz
Date: Tue Aug 2 22:27:47 2005
New Revision: 15524
Modified:
pypy/dist/pypy/rpython/memory/lltypesimulation.py
pypy/dist/pypy/rpython/memory/test/test_lltypesimulation.py
Log:
enhanced the lltypesimulation in the following ways:
- added array support
- added support for structs with inlined arrays
- added cast_pointer
- tests for the above
Modified: pypy/dist/pypy/rpython/memory/lltypesimulation.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/lltypesimulation.py (original)
+++ pypy/dist/pypy/rpython/memory/lltypesimulation.py Tue Aug 2 22:27:47 2005
@@ -1,39 +1,70 @@
+import py
+
from pypy.rpython.memory import lladdress
from pypy.rpython import lltype
import struct
+log = py.log.Producer("lltypesim")
+
primitive_to_fmt = {lltype.Signed: "i",
lltype.Unsigned: "I",
lltype.Char: "c",
}
+#returns some sort of layout information that is useful for the simulatorptr
def get_layout(TYPE):
layout = {}
if isinstance(TYPE, lltype.Primitive):
return primitive_to_fmt[TYPE]
- if isinstance(TYPE, lltype.Ptr):
+ elif isinstance(TYPE, lltype.Ptr):
return "P"
- if isinstance(TYPE, lltype.Struct):
+ elif isinstance(TYPE, lltype.Struct):
curr = 0
for name in TYPE._names:
layout[name] = curr
- curr += get_size(TYPE._flds[name])
+ curr += get_fixed_size(TYPE._flds[name])
layout["_size"] = curr
return layout
+ elif isinstance(TYPE, lltype.Array):
+ return (get_fixed_size(lltype.Signed), get_fixed_size(TYPE.OF))
else:
assert 0, "not yet implemented"
-def get_size(TYPE):
+def get_fixed_size(TYPE):
if isinstance(TYPE, lltype.Primitive):
return struct.calcsize(primitive_to_fmt[TYPE])
elif isinstance(TYPE, lltype.Ptr):
return struct.calcsize("P")
elif isinstance(TYPE, lltype.Struct):
return get_layout(TYPE)["_size"]
+ elif isinstance(TYPE, lltype.Array):
+ return get_fixed_size(lltype.Unsigned)
+ assert 0, "not yet implemented"
+
+def get_variable_size(TYPE):
+ if isinstance(TYPE, lltype.Array):
+ return get_fixed_size(TYPE.OF)
+ elif isinstance(TYPE, lltype.Primitive):
+ return 0
+ elif isinstance(TYPE, lltype.Struct):
+ if isinstance(TYPE._flds[TYPE._names[-1]], lltype.Array):
+ return get_variable_size(TYPE._flds[TYPE._arrayfld])
+ else:
+ return 0
else:
assert 0, "not yet implemented"
-
+
+def _expose(T, address):
+ """XXX A nice docstring here"""
+ if isinstance(T, (lltype.Struct, lltype.Array)):
+ return simulatorptr(lltype.Ptr(T), address)
+ elif isinstance(T, lltype.Primitive):
+ return address._load(primitive_to_fmt[T])
+ else:
+ assert 0, "not implemented yet"
+
+
# this class is intended to replace the _ptr class in lltype
# using the memory simulator
class simulatorptr(object):
@@ -42,12 +73,27 @@
self.__dict__['_T'] = TYPE.TO
self.__dict__['_address'] = address
self.__dict__['_layout'] = get_layout(TYPE.TO)
- self._zero_initialize()
- def _zero_initialize(self):
- size = get_size(self._T)
+ def _zero_initialize(self, i=None):
+ fixedsize = get_fixed_size(self._T)
+ varsize = get_variable_size(self._T)
+ if i is None:
+ assert varsize == 0
+ size = fixedsize
+ else:
+ size = fixedsize + i * varsize
self._address._store("c" * size, *(["\x00"] * size))
+ def _init_size(self, size):
+ if isinstance(self._T, lltype.Array):
+ self._address.signed[0] = size
+ elif isinstance(self._T, lltype.Struct):
+ if isinstance(self._T._flds[self._T._names[-1]], lltype.Array):
+ addr = self._address + self._layout[self._T._arrayfld]
+ addr.signed[0] = size
+ else:
+ assert size is None, "setting not implemented"
+
def __getattr__(self, field_name):
if isinstance(self._T, lltype.Struct):
offset = self._layout[field_name]
@@ -55,7 +101,14 @@
T = self._T._flds[field_name]
base = self._layout[field_name]
if isinstance(T, lltype.Primitive):
- return (self._address + offset)._load(primitive_to_fmt[T])[0]
+ res = (self._address + offset)._load(primitive_to_fmt[T])[0]
+ return res
+ elif isinstance(T, lltype.Ptr):
+ res = _expose(T.TO, (self._address + offset).address[0])
+ return res
+ elif isinstance(T, lltype.ContainerType):
+ res = _expose(T, (self._address + offset))
+ return res
else:
assert 0, "not implemented"
raise AttributeError, ("%r instance has no field %r" % (self._T,
@@ -65,18 +118,93 @@
if isinstance(self._T, lltype.Struct):
if field_name in self._T._flds:
T = self._T._flds[field_name]
- base = self._layout[field_name]
+ offset = self._layout[field_name]
if isinstance(T, lltype.Primitive):
- (self._address + base)._store(primitive_to_fmt[T], value)
+ (self._address + offset)._store(primitive_to_fmt[T], value)
+ return
+ elif isinstance(T, lltype.Ptr):
+ assert value._TYPE == T
+ (self._address + offset).address[0] = value._address
return
else:
assert 0, "not implemented"
raise AttributeError, ("%r instance has no field %r" % (self._T,
field_name))
+ def __getitem__(self, i):
+ if isinstance(self._T, lltype.Array):
+ if not (0 <= i < self._address.signed[0]):
+ raise IndexError, "array index out of bounds"
+ addr = self._address + self._layout[0] + i * self._layout[1]
+ return _expose(self._T.OF, addr)
+ raise TypeError("%r instance is not an array" % (self._T,))
+
+ def __setitem__(self, i, value):
+ if isinstance(self._T, lltype.Array):
+ T1 = self._T.OF
+ if isinstance(T1, lltype.ContainerType):
+ s = "cannot directly assign to container array items"
+ raise TypeError, s
+ 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._address.signed[0]):
+ raise IndexError, "array index out of bounds"
+ self._address._store(get_layout(self._T.OF), value)
+ return
+ raise TypeError("%r instance is not an array" % (self._T,))
+
+ def __len__(self):
+ if isinstance(self._T, lltype.Array):
+ return self._address.signed[0]
+ raise TypeError("%r instance is not an array" % (self._T,))
+
+ def __nonzero__(self):
+ return self._address != lladdres.NULL
+
+ def __eq__(self, other):
+ if not isinstance(other, simulatorptr):
+ raise TypeError("comparing pointer with %r object" % (
+ type(other).__name__,))
+ if self._TYPE != other._TYPE:
+ raise TypeError("comparing %r and %r" % (self._TYPE, other._TYPE))
+ return self._address == other._address
+
+ def __repr__(self):
+ addr = self._address.intaddress
+ if addr < 0:
+ addr += 256 ** struct.calcsize("P")
+ return '<simulatorptr %s to 0x%x>' % (self._TYPE.TO, addr)
+
+
+def cast_pointer(PTRTYPE, ptr):
+ if not isinstance(ptr, simulatorptr) or not isinstance(PTRTYPE, lltype.Ptr):
+ raise TypeError, "can only cast pointers to other pointers"
+ CURTYPE = ptr._TYPE
+ down_or_up = lltype.castable(PTRTYPE, CURTYPE)
+ if down_or_up == 0:
+ return ptr
+ # XXX the lltype.cast_pointer does a lot of checks here:
+ # I can't think of a way to do that with simulatorptr.
+ # I'm not sure whether this is the right way to go...
+ return simulatorptr(PTRTYPE, ptr._address)
+
+
# for now use the simulators raw_malloc
def malloc(T, n=None, immortal=False):
- size = get_size(T)
+ fixedsize = get_fixed_size(T)
+ varsize = get_variable_size(T)
+ if n is None:
+ if varsize:
+ raise TypeError, "%r is variable-sized" % (T,)
+ size = fixedsize
+ else:
+ size = fixedsize + n * varsize
address = lladdress.raw_malloc(size)
- return simulatorptr(lltype.Ptr(T), address)
+ result = simulatorptr(lltype.Ptr(T), address)
+ result._zero_initialize(n)
+ result._init_size(n)
+ return result
Modified: pypy/dist/pypy/rpython/memory/test/test_lltypesimulation.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_lltypesimulation.py (original)
+++ pypy/dist/pypy/rpython/memory/test/test_lltypesimulation.py Tue Aug 2 22:27:47 2005
@@ -1,10 +1,11 @@
from pypy.rpython.memory.lltypesimulation import *
-from pypy.rpython.lltype import GcStruct, Ptr, Signed, Char
+
+py.log.setconsumer("lltypesim", None)
def test_struct():
- S0 = GcStruct("s0", ('a', Signed), ('b', Signed), ('c', Char))
+ S0 = lltype.GcStruct("s0", ('a', lltype.Signed),
+ ('b', lltype.Signed), ('c', lltype.Char))
s0 = malloc(S0)
- print s0
assert s0.a == 0
assert s0.b == 0
assert s0.c == '\x00'
@@ -19,17 +20,114 @@
assert s0.a == 1
assert s0.b == 1
-def DONOTtest_array():
- Ar = lltype.GcArray(('v', Signed))
- x = malloc(Ar,0)
- print x
+def test_array():
+ Ar = lltype.GcArray(('v', lltype.Signed))
+ x = malloc(Ar, 0)
assert len(x) == 0
- x = malloc(Ar,3)
- print x
- assert typeOf(x) == Ptr(Ar)
- assert typeOf(x[0].v) == Signed
+ x = malloc(Ar, 3)
+ assert lltype.typeOf(x) == lltype.Ptr(Ar)
+ assert lltype.typeOf(x[0].v) == lltype.Signed
assert x[0].v == 0
x[0].v = 1
x[1].v = 2
x[2].v = 3
assert [x[z].v for z in range(3)] == [1, 2, 3]
+
+
+
+def define_list(T):
+ List_typ = lltype.GcStruct(
+ "list", ("items", lltype.Ptr(lltype.GcArray(('item',T)))))
+ def newlist():
+ l = malloc(List_typ)
+ items = malloc(List_typ.items.TO, 0)
+ l.items = items
+ return l
+
+ def append(l, newitem):
+ length = len(l.items)
+ newitems = malloc(List_typ.items.TO, length+1)
+ i = 0
+ while i<length:
+ newitems[i].item = l.items[i].item
+ i += 1
+ newitems[length].item = newitem
+ l.items = newitems
+
+ def item(l, i):
+ return l.items[i].item
+
+ return List_typ, newlist, append, item
+
+
+def test_simple_list():
+ List_typ, inewlist, iappend, iitem = define_list(lltype.Signed)
+ l = inewlist()
+ assert lltype.typeOf(l) == lltype.Ptr(List_typ)
+ iappend(l, 2)
+ assert len(l.items) == 1
+ assert iitem(l, 0) == 2
+ iappend(l, 3)
+ assert len(l.items) == 2
+ assert iitem(l, 1) == 3
+
+def test_list_of_struct():
+ IWrap = lltype.GcStruct("iwrap", ('v', lltype.Signed))
+ List_typ, iwnewlist, iwappend, iwitem = define_list(lltype.Ptr(IWrap))
+ l = iwnewlist()
+ assert lltype.typeOf(l) == lltype.Ptr(List_typ)
+ iw2 = malloc(IWrap)
+ iw3 = malloc(IWrap)
+ iw2.v = 2
+ iw3.v = 3
+ assert iw3.v == 3
+ iwappend(l, iw2)
+ iwappend(l, iw3)
+ assert len(l.items) == 2
+ assert iwitem(l, 0).v == 2
+ assert iwitem(l, 1).v == 3
+
+def test_varsizestruct():
+ S1 = lltype.GcStruct("s1", ('a', lltype.Signed),
+ ('rest', lltype.Array(('v', lltype.Signed))))
+ py.test.raises(TypeError, "malloc(S1)")
+ s1 = malloc(S1, 4)
+ assert s1.a == 0
+ s1.rest[1].v = 211
+ s1.a = 42
+ assert len(s1.rest) == 4
+ assert lltype.typeOf(s1.rest[0].v) == lltype.Signed
+ assert s1.rest[0].v == 0
+ assert s1.rest[1].v == 211
+ assert s1.a == 42
+ py.test.raises(IndexError, "s1.rest[4]")
+ py.test.raises(IndexError, "s1.rest[-1]")
+ s1.a = 17
+ s1.rest[3].v = 5
+ assert s1.a == 17
+ assert s1.rest[3].v == 5
+
+def test_substructure_ptr():
+ S3 = lltype.Struct("s3", ('a', lltype.Signed))
+ S2 = lltype.Struct("s2", ('s3', S3), ('char', lltype.Char))
+ S1 = lltype.GcStruct("s1", ('sub1', S2), ('sub2', S2))
+ p1 = malloc(S1)
+ p1.sub1.char = "a"
+ p1.sub2.char = "b"
+ p1.sub1.s3.a = 12
+ p1.sub2.s3.a = 14
+ assert p1.sub1.char == "a"
+ assert p1.sub2.char == "b"
+ assert p1.sub1.s3.a == 12
+ assert p1.sub2.s3.a == 14
+
+def test_cast_simple_widening():
+ S2 = lltype.Struct("s2", ('a', lltype.Signed))
+ S1 = lltype.Struct("s1", ('sub1', S2), ('sub2', S2))
+ p1 = malloc(S1, immortal=True)
+ p2 = p1.sub1
+ p3 = p2
+ p4 = cast_pointer(lltype.Ptr(S1), p3)
+ assert p4 == p1
+ SUnrelated = lltype.Struct("unrelated")
+ py.test.raises(TypeError, "cast_pointer(lltype.Ptr(SUnrelated), p3)")
More information about the Pypy-commit
mailing list