[pypy-svn] r12715 - in pypy/dist/pypy: annotation annotation/test rpython rpython/test translator/genc translator/genc/test

arigo at codespeak.net arigo at codespeak.net
Sat May 21 19:06:16 CEST 2005


Author: arigo
Date: Sat May 21 19:06:16 2005
New Revision: 12715

Modified:
   pypy/dist/pypy/annotation/builtin.py
   pypy/dist/pypy/annotation/test/test_model.py
   pypy/dist/pypy/rpython/lltypes.py
   pypy/dist/pypy/rpython/rlist.py
   pypy/dist/pypy/rpython/test/test_llann.py
   pypy/dist/pypy/rpython/test/test_lltypes.py
   pypy/dist/pypy/translator/genc/lltype.py
   pypy/dist/pypy/translator/genc/test/test_lltyped.py
Log:
Added a distinction between Struct and GcStruct, as well as Array and GcArray.
The Gc version are the ones that come with a reference counter (or other GC
supporting memory), and can be malloc'ed.  The non-Gc versions are the ones 
that can be inlined inside other structures.

Lots of other small changes triggered by this...



Modified: pypy/dist/pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py	(original)
+++ pypy/dist/pypy/annotation/builtin.py	Sat May 21 19:06:16 2005
@@ -265,12 +265,9 @@
     assert isinstance(s_p, SomePtr), "casting of non-pointer: %r" % s_p
     assert PtrT.is_constant()
     PtrT = PtrT.const
-    parent_example_p = PtrT._example()
-    first_p = parent_example_p._first()
-    if s_p.ll_ptrtype == lltypes.typeOf(first_p):
-        candidate_p = first_p
-    else:
-        candidate_p = s_p.ll_ptrtype._example()
+    parent_p = PtrT._example()
+    candidate_p = s_p.ll_ptrtype._example()
+    parent_p._setfirst(candidate_p)
     return SomePtr(ll_ptrtype=lltypes.typeOf(lltypes.cast_parent(PtrT, candidate_p)))
 
 BUILTIN_ANALYZERS[lltypes.malloc] = malloc

Modified: pypy/dist/pypy/annotation/test/test_model.py
==============================================================================
--- pypy/dist/pypy/annotation/test/test_model.py	(original)
+++ pypy/dist/pypy/annotation/test/test_model.py	Sat May 21 19:06:16 2005
@@ -112,8 +112,8 @@
     assert s_uz.contains(s_u)
     assert ll_to_annotation(lltypes.Bool._defl()).contains(SomeBool())
     assert ll_to_annotation(lltypes.Char._defl()).contains(SomeChar())
-    S = lltypes.Struct('s')
-    A = lltypes.Array()
+    S = lltypes.GcStruct('s')
+    A = lltypes.GcArray()
     s_p = ll_to_annotation(lltypes.malloc(S))
     assert isinstance(s_p, SomePtr) and s_p.ll_ptrtype == lltypes.GcPtr(S)
     s_p = ll_to_annotation(lltypes.malloc(A, 0))
@@ -136,17 +136,17 @@
     assert annotation_to_lltype(s_u1) == lltypes.Unsigned
     assert annotation_to_lltype(SomeBool()) == lltypes.Bool
     assert annotation_to_lltype(SomeChar()) == lltypes.Char
-    PS = lltypes.GcPtr(lltypes.Struct('s'))
+    PS = lltypes.GcPtr(lltypes.GcStruct('s'))
     s_p = SomePtr(ll_ptrtype=PS)
     assert annotation_to_lltype(s_p) == PS
     py.test.raises(ValueError, "annotation_to_lltype(si0)")
     
 def test_ll_union():
-    PS1 = lltypes.GcPtr(lltypes.Struct('s'))
-    PS2 = lltypes.GcPtr(lltypes.Struct('s'))
-    PS3 = lltypes.GcPtr(lltypes.Struct('s3'))
-    PA1 = lltypes.GcPtr(lltypes.Array())
-    PA2 = lltypes.GcPtr(lltypes.Array())
+    PS1 = lltypes.GcPtr(lltypes.GcStruct('s'))
+    PS2 = lltypes.GcPtr(lltypes.GcStruct('s'))
+    PS3 = lltypes.GcPtr(lltypes.GcStruct('s3'))
+    PA1 = lltypes.GcPtr(lltypes.GcArray())
+    PA2 = lltypes.GcPtr(lltypes.GcArray())
 
     assert unionof(SomePtr(PS1),SomePtr(PS1)) == SomePtr(PS1)
     assert unionof(SomePtr(PS1),SomePtr(PS2)) == SomePtr(PS2)

Modified: pypy/dist/pypy/rpython/lltypes.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypes.py	(original)
+++ pypy/dist/pypy/rpython/lltypes.py	Sat May 21 19:06:16 2005
@@ -56,11 +56,18 @@
             if name in flds:
                 raise TypeError("%s: repeated field name" % self._name)
             flds[name] = typ
- 
+            if isinstance(typ, GC_CONTAINER):
+                if name == fields[0][0] and isinstance(self, GC_CONTAINER):
+                    pass  # can inline a GC_CONTAINER as 1st field of GcStruct
+                else:
+                    raise TypeError("%s: cannot inline GC container %r" % (
+                        self._name, typ))
+
         # look if we have an inlined variable-sized array as the last field
         if fields:
             for name, typ in fields[:-1]:
                 typ._inline_is_varsize(False)
+                first = False
             name, typ = fields[-1]
             if typ._inline_is_varsize(True):
                 self._arrayfld = name
@@ -85,7 +92,8 @@
                           for name in self._names])
 
     def __str__(self):
-        return "Struct %s { %s }" % (self._name, self._str_fields())
+        return "%s %s { %s }" % (self.__class__.__name__,
+                                 self._name, self._str_fields())
 
     def _defl(self, parent=None):
         return _struct(self, parent=parent)
@@ -97,6 +105,9 @@
             n = 1
         return _struct(self, n)
 
+class GcStruct(Struct):
+    pass
+
 class Array(ContainerType):
     def __init__(self, *fields):
         self.OF = Struct("<arrayitem>", *fields)
@@ -109,11 +120,16 @@
         return True
 
     def __str__(self):
-        return "Array of { %s }" % (self.OF._str_fields(),)
+        return "%s of { %s }" % (self.__class__.__name__,
+                                 self.OF._str_fields(),)
 
     def _container_example(self):
         return _array(self, 1)
 
+class GcArray(Array):
+    def _inline_is_varsize(self, last):
+        raise TypeError("cannot inline a GC array inside a structure")
+
 class FuncType(ContainerType):
     def __init__(self, args, result):
         for arg in args:
@@ -140,9 +156,14 @@
 
 class ForwardReference(ContainerType):
     def become(self, realcontainertype):
+        if not isinstance(realcontainertype, GC_CONTAINER):
+            raise TypeError("ForwardReference can only be to GcStruct or "
+                            "GcArray, not %r" % (realcontainertype,))
         self.__class__ = realcontainertype.__class__
         self.__dict__ = realcontainertype.__dict__
 
+GC_CONTAINER = (GcStruct, GcArray, PyObjectType, ForwardReference)
+
 
 class Primitive(LowLevelType):
     def __init__(self, name, default):
@@ -170,10 +191,12 @@
         if not isinstance(TO, ContainerType):
             raise TypeError, ("can only point to a Struct or an Array or a FuncType, "
                               "not to %s" % (TO,))
+        if 'gc' in flags:
+            if not isinstance(TO, GC_CONTAINER):
+                raise TypeError, ("GcPtr can only point to GcStruct, GcArray or"
+                                  " PyObject, not to %s" % (TO,))
         self.TO = TO
         self.flags = frozendict(flags)
-        if isinstance(TO, FuncType) and 'gc' in self.flags:
-            raise TypeError, "function pointers are not gc-able"
 
     def _str_flags(self):
         flags = self.flags.keys()
@@ -261,7 +284,9 @@
     # * converting from TO-structure to a parent TO-structure whose first
     #     field is the original structure
     if (not isinstance(CURTYPE.TO, Struct) or
-        not isinstance(PTRTYPE.TO, Struct)):
+        not isinstance(PTRTYPE.TO, Struct) or
+        len(PTRTYPE.TO._names) == 0 or
+        PTRTYPE.TO._flds[PTRTYPE.TO._names[0]] != CURTYPE.TO):
         raise InvalidCast(CURTYPE, PTRTYPE)
     ptr._check()
     parent = ptr._obj._wrparent()
@@ -279,7 +304,7 @@
     T = typeOf(val)
     if isinstance(T, ContainerType):
         assert not isinstance(T, FuncType), "functions cannot be substructures"
-        if can_have_gc and isinstance(T, Struct):
+        if can_have_gc and isinstance(T, GcStruct):
             val = _ptr(GcPtr(T), val)
         else:
             val = _ptr(_TmpPtr(T), val)
@@ -323,10 +348,21 @@
         raise AttributeError("%r instance has no field %r" % (self._T,
                                                               field_name))
 
-    def _first(self):
+    def _setfirst(self, p):
         if isinstance(self._T, Struct) and self._T._names:
-            return self.__getattr__(self._T._names[0])
-        raise AttributeError("%r instance has no first field" % (self._T,))
+            if not isinstance(p, _ptr) or not isinstance(p._obj, _struct):
+                raise InvalidCast(typeOf(p), typeOf(self))
+            field_name = self._T._names[0]
+            T1 = self._T._flds[field_name]
+            T2 = typeOf(p._obj)
+            if T1 != T2:
+                raise InvalidCast(typeOf(p), typeOf(self))
+            self._check()
+            setattr(self._obj, field_name, p._obj)
+            p._obj._wrparent = weakref.ref(self._obj)
+            p._obj._wrparent_type = typeOf(self._obj)
+            return
+        raise TypeError("%r instance has no first field" % (self._T,))
 
     def __setattr__(self, field_name, val):
         if isinstance(self._T, Struct):

Modified: pypy/dist/pypy/rpython/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/rlist.py	(original)
+++ pypy/dist/pypy/rpython/rlist.py	Sat May 21 19:06:16 2005
@@ -19,8 +19,8 @@
         LISTPTR = self.LISTPTR
         LIST    = self.LIST
         ITEM    = self.ITEM
-        LIST.become(Struct("list",
-                           ("items", GcPtr(Array(('item', ITEM))))))
+        LIST.become(GcStruct("list",
+                             ("items", GcPtr(GcArray(('item', ITEM))))))
 
         def getitem(l, i):
             return l.items[i].item

Modified: pypy/dist/pypy/rpython/test/test_llann.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_llann.py	(original)
+++ pypy/dist/pypy/rpython/test/test_llann.py	Sat May 21 19:06:16 2005
@@ -8,7 +8,7 @@
     from pypy.translator.annrpython import RPythonAnnotator
 
     def test_simple(self):
-        S = Struct("s", ('v', Signed))
+        S = GcStruct("s", ('v', Signed))
         def llf():
             s = malloc(S)
             return s.v
@@ -18,7 +18,7 @@
 
     def test_simple2(self):
         S = Struct("s", ('v', Signed))
-        S2 = Struct("s2", ('a',S), ('b',S))
+        S2 = GcStruct("s2", ('a',S), ('b',S))
         def llf():
             s = malloc(S2)
             return s.a.v+s.b.v
@@ -27,7 +27,7 @@
         assert s.knowntype == int
 
     def test_array(self):
-        A = Array(('v', Signed))
+        A = GcArray(('v', Signed))
         def llf():
             a = malloc(A, 1)
             return a[0].v
@@ -36,7 +36,7 @@
         assert s.knowntype == int
 
     def test_cast_flags(self):
-        S1 = Struct("s1", ('a', Signed), ('b', Unsigned))
+        S1 = GcStruct("s1", ('a', Signed), ('b', Unsigned))
         NGCPS1 = NonGcPtr(S1)
         def llf():
             p1 = malloc(S1)
@@ -49,7 +49,25 @@
         
     def test_cast_parent(self):
         S2 = Struct("s2", ('a', Signed))
-        S1 = Struct("s1", ('sub1', S2), ('sub2', S2))
+        S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2))
+        GCPS1 = GcPtr(S1)
+        NGCPS1 = NonGcPtr(S1)
+        NGCPS2 = NonGcPtr(S2)
+        def llf():
+            p1 = malloc(S1)
+            p2 = p1.sub1
+            p3 = cast_flags(NGCPS2, p2)
+            p4 = cast_parent(NGCPS1, p3)
+            p5 = cast_flags(GCPS1, p4)
+            return p5
+        a = self.RPythonAnnotator()
+        s = a.build_types(llf, [])
+        assert isinstance(s, annmodel.SomePtr)
+        assert s.ll_ptrtype == GCPS1
+
+    def test_cast_parent_from_gc(self):
+        S2 = GcStruct("s2", ('a', Signed))
+        S1 = GcStruct("s1", ('sub1', S2), ('x', Signed))
         GCPS1 = GcPtr(S1)
         def llf():
             p1 = malloc(S1)
@@ -62,7 +80,7 @@
         assert s.ll_ptrtype == GCPS1
 
     def test_array_length(self):
-        A = Array(('v', Signed))
+        A = GcArray(('v', Signed))
         def llf():
             a = malloc(A, 1)
             return len(a)

Modified: pypy/dist/pypy/rpython/test/test_lltypes.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_lltypes.py	(original)
+++ pypy/dist/pypy/rpython/test/test_lltypes.py	Sat May 21 19:06:16 2005
@@ -2,7 +2,7 @@
 from pypy.rpython.lltypes import _TmpPtr
 
 def test_basics():
-    S0 = Struct("s0", ('a', Signed), ('b', Signed))
+    S0 = GcStruct("s0", ('a', Signed), ('b', Signed))
     assert S0.a == Signed
     assert S0.b == Signed
     s0 = malloc(S0)
@@ -16,7 +16,7 @@
     assert s0.a == 1
     assert s0.b == 1
     # simple array
-    Ar = Array(('v', Signed))
+    Ar = GcArray(('v', Signed))
     x = malloc(Ar,0)
     print x
     assert len(x) == 0
@@ -32,8 +32,8 @@
     assert [x[z].v for z in range(3)] == [1, 2, 3]
     #
     def define_list(T):
-        List_typ = Struct("list",
-                ("items", GcPtr(Array(('item',T)))))
+        List_typ = GcStruct("list",
+                ("items", GcPtr(GcArray(('item',T)))))
         def newlist():
             l = malloc(List_typ)
             items = malloc(List_typ.items.TO, 0)
@@ -65,7 +65,7 @@
     assert iitem(l, 0) == 2
     assert iitem(l, 1) == 3
 
-    IWrap = Struct("iwrap", ('v', Signed))
+    IWrap = GcStruct("iwrap", ('v', Signed))
     List_typ, iwnewlist, iwappend, iwitem = define_list(GcPtr(IWrap))
 
     l = iwnewlist()
@@ -82,12 +82,14 @@
     assert iwitem(l, 1).v == 3
 
     # not allowed
-    List_typ, iwnewlistzzz, iwappendzzz, iwitemzzz = define_list(IWrap) # works but
+    S = Struct("s", ('v', Signed))
+    List_typ, iwnewlistzzz, iwappendzzz, iwitemzzz = define_list(S) # works but
     l = iwnewlistzzz()
-    py.test.raises(TypeError, "iwappendzzz(l, malloc(IWrap))")
+    S1 = GcStruct("strange", ('s', S))
+    py.test.raises(TypeError, "iwappendzzz(l, malloc(S1).s)")
 
 def test_varsizestruct():
-    S1 = Struct("s1", ('a', Signed), ('rest', Array(('v', Signed))))
+    S1 = GcStruct("s1", ('a', Signed), ('rest', Array(('v', Signed))))
     py.test.raises(TypeError, "malloc(S1)")
     s1 = malloc(S1, 4)
     assert s1.a == 0
@@ -105,17 +107,27 @@
     assert s1.rest[3].v == 5
 
     py.test.raises(TypeError, "Struct('invalid', ('rest', Array(('v', Signed))), ('a', Signed))")
+    py.test.raises(TypeError, "Struct('invalid', ('rest', GcArray(('v', Signed))), ('a', Signed))")
+    py.test.raises(TypeError, "Struct('invalid', ('x', Struct('s1', ('a', Signed), ('rest', Array(('v', Signed))))))")
     py.test.raises(TypeError, "Struct('invalid', ('x', S1))")
 
 def test_substructure_ptr():
     S2 = Struct("s2", ('a', Signed))
-    S1 = Struct("s1", ('sub1', S2), ('sub2', S2))
+    S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2))
     p1 = malloc(S1)
-    assert typeOf(p1.sub1) == GcPtr(S2)
+    assert typeOf(p1.sub1) == _TmpPtr(S2)
+    assert typeOf(p1.sub2) == _TmpPtr(S2)
+
+def test_gc_substructure_ptr():
+    S1 = GcStruct("s2", ('a', Signed))
+    S2 = Struct("s3", ('a', Signed))
+    S0 = GcStruct("s1", ('sub1', S1), ('sub2', S2))
+    p1 = malloc(S0)
+    assert typeOf(p1.sub1) == GcPtr(S1)
     assert typeOf(p1.sub2) == _TmpPtr(S2)
 
 def test_tagged_pointer():
-    S1 = Struct("s1", ('a', Signed), ('b', Unsigned))
+    S1 = GcStruct("s1", ('a', Signed), ('b', Unsigned))
     PList = [
         GcPtr(S1),
         NonGcPtr(S1),
@@ -129,7 +141,7 @@
     assert PList[2] == GcPtr(S1, mytag=True)
 
 def test_cast_flags():
-    S1 = Struct("s1", ('a', Signed), ('b', Unsigned))
+    S1 = GcStruct("s1", ('a', Signed), ('b', Unsigned))
     p1 = malloc(S1)
     p2 = cast_flags(NonGcPtr(S1), p1)
     assert typeOf(p2) == NonGcPtr(S1)
@@ -150,19 +162,27 @@
 
 def test_cast_parent():
     S2 = Struct("s2", ('a', Signed))
-    S1 = Struct("s1", ('sub1', S2), ('sub2', S2))
+    S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2))
     p1 = malloc(S1)
     p2 = p1.sub1
-    assert typeOf(p2) == GcPtr(S2)
-    p3 = cast_parent(GcPtr(S1), p2)
-    assert typeOf(p3) == GcPtr(S1)
-    assert p3 == p1
+    assert typeOf(p2) == _TmpPtr(S2)
+    p3 = cast_flags(NonGcPtr(S2), p2)
+    assert typeOf(p3) == NonGcPtr(S2)
+    p4 = cast_parent(NonGcPtr(S1), p3)
+    assert typeOf(p4) == NonGcPtr(S1)
+    p5 = cast_flags(GcPtr(S1), p4)
+    assert typeOf(p5) == GcPtr(S1)
+    assert p5 == p1
+    py.test.raises(TypeError, "cast_parent(GcPtr(S1), p1.sub1)")
     py.test.raises(TypeError, "cast_parent(GcPtr(S1), p1.sub2)")
     py.test.raises(TypeError, "cast_parent(_TmpPtr(S1), p1.sub2)")
+    py.test.raises(TypeError, "cast_parent(NonGcPtr(S2), p3)")
+    SUnrelated = Struct("unrelated")
+    py.test.raises(TypeError, "cast_parent(NonGcPtr(SUnrelated), p3)")
 
 def test_best_effort_gced_parent_detection():
     S2 = Struct("s2", ('a', Signed))
-    S1 = Struct("s1", ('sub1', S2), ('sub2', S2), ('tail', Array(('e', Signed))))
+    S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2), ('tail', Array(('e', Signed))))
     p1 = malloc(S1, 1)
     p2 = p1.sub2
     assert p2.a == 0
@@ -176,7 +196,7 @@
     py.test.raises(RuntimeError, "p3[0]")
 
 def test_best_effort_gced_parent_for_arrays():
-    A1 = Array(('v', Signed))
+    A1 = GcArray(('v', Signed))
     p1 = malloc(A1, 10)
     p1[5].v=3
     assert p1[0].v == 0
@@ -189,9 +209,9 @@
     py.test.raises(RuntimeError, "p1_5.v")        
 
 def test_examples():
-    A1 = Array(('v', Signed))
-    S = Struct("s", ('v', Signed))
-    St = Struct("st", ('v', Signed),('trail', A1))
+    A1 = GcArray(('v', Signed))
+    S = GcStruct("s", ('v', Signed))
+    St = GcStruct("st", ('v', Signed),('trail', Array(('v', Signed))))
 
     PA1 = GcPtr(A1)
     PS = GcPtr(S)
@@ -220,3 +240,20 @@
     py.test.raises(TypeError, pf, 0, 0)
     py.test.raises(TypeError, pf, 'a')
 
+def test_inconsistent_gc_containers():
+    A = GcArray(('y', Signed))
+    S = GcStruct('b', ('y', Signed))
+    py.test.raises(TypeError, "GcPtr(Struct('a', ('x', Signed)))")
+    py.test.raises(TypeError, "Struct('a', ('x', S))")
+    py.test.raises(TypeError, "GcStruct('a', ('x', Signed), ('y', S))")
+    py.test.raises(TypeError, "Array(('x', S))")
+    py.test.raises(TypeError, "GcArray(('x', S))")
+    py.test.raises(TypeError, "Struct('a', ('x', A))")
+    py.test.raises(TypeError, "GcStruct('a', ('x', A))")
+
+def test_forward_reference():
+    F = ForwardReference()
+    S = GcStruct('abc', ('x', GcPtr(F)))
+    F.become(S)
+    assert S.x == GcPtr(S)
+    py.test.raises(TypeError, "ForwardReference().become(Struct('abc'))")

Modified: pypy/dist/pypy/translator/genc/lltype.py
==============================================================================
--- pypy/dist/pypy/translator/genc/lltype.py	(original)
+++ pypy/dist/pypy/translator/genc/lltype.py	Sat May 21 19:06:16 2005
@@ -203,7 +203,9 @@
 
 ll2concretetypemap = {
     lltypes.Struct: CStructType,
+    lltypes.GcStruct: CStructType,
     lltypes.Array: CArrayType,
+    lltypes.GcArray: CArrayType,
     lltypes._PtrType: CPtrType,
     lltypes.Primitive: get_primitive_type,
     }

Modified: pypy/dist/pypy/translator/genc/test/test_lltyped.py
==============================================================================
--- pypy/dist/pypy/translator/genc/test/test_lltyped.py	(original)
+++ pypy/dist/pypy/translator/genc/test/test_lltyped.py	Sat May 21 19:06:16 2005
@@ -18,7 +18,7 @@
         return skip_missing_compiler(t.ccompile)
 
     def test_simple(self):
-        S = Struct("s", ('v', Signed))
+        S = GcStruct("s", ('v', Signed))
         def llf():
             s = malloc(S)
             return s.v
@@ -27,7 +27,7 @@
 
     def test_simple2(self):
         S = Struct("s", ('v', Signed))
-        S2 = Struct("s2", ('a',S), ('b',S))
+        S2 = GcStruct("s2", ('a',S), ('b',S))
         def llf():
             s = malloc(S2)
             s.a.v = 6



More information about the Pypy-commit mailing list