[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