[pypy-svn] r12717 - in pypy/dist/pypy: rpython translator/c translator/c/test

arigo at codespeak.net arigo at codespeak.net
Sat May 21 22:14:43 CEST 2005


Author: arigo
Date: Sat May 21 22:14:42 2005
New Revision: 12717

Modified:
   pypy/dist/pypy/rpython/lltypes.py
   pypy/dist/pypy/translator/c/database.py
   pypy/dist/pypy/translator/c/node.py
   pypy/dist/pypy/translator/c/test/test_database.py
Log:
Generating now static structure definitions, possibly nested ones.


Modified: pypy/dist/pypy/rpython/lltypes.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypes.py	(original)
+++ pypy/dist/pypy/rpython/lltypes.py	Sat May 21 22:14:42 2005
@@ -310,6 +310,17 @@
             val = _ptr(_TmpPtr(T), val)
     return val
 
+def parentlink(container):
+    parent = container._check()
+    if parent is not None:
+        assert isinstance(parent, _struct)
+        for name in parent._TYPE._names:
+            if getattr(parent, name) is container:
+                return parent, name
+        raise RuntimeError("lost ourselves")
+    else:
+        return None, None
+
 
 class _ptr(object):
 
@@ -447,6 +458,8 @@
                                    % (self, self._wrparent_type))
             else:
                 parent._check()
+                return parent
+        return None
 
     def __repr__(self):
         return '<%s>' % (self,)
@@ -465,7 +478,6 @@
     def __str__(self):
         return 'struct %s { %s }' % (self._TYPE._name, self._str_fields())
 
-
 class _array(object):
     _wrparent = None
 
@@ -489,6 +501,8 @@
                                    % (self, self._wrparent_type))
             else:
                 parent._check()
+                return parent
+        return None
 
     def __repr__(self):
         return '<%s>' % (self,)

Modified: pypy/dist/pypy/translator/c/database.py
==============================================================================
--- pypy/dist/pypy/translator/c/database.py	(original)
+++ pypy/dist/pypy/translator/c/database.py	Sat May 21 22:14:42 2005
@@ -1,6 +1,7 @@
 from pypy.translator.gensupp import NameManager
 from pypy.rpython.lltypes import Primitive, _PtrType, typeOf
 from pypy.rpython.lltypes import Struct, Array, FuncType, PyObject
+from pypy.rpython.lltypes import ContainerType
 from pypy.rpython.typer import PyObjPtr
 from pypy.objspace.flow.model import Constant
 from pypy.translator.c.primitive import PrimitiveName, PrimitiveType
@@ -31,6 +32,20 @@
            else      register  union
            ''')
 
+    def gettypedefnode(self, T):
+        try:
+            node = self.structdefnodes[T]
+        except KeyError:
+            if isinstance(T, Struct):
+                node = StructDefNode(self, T)
+            elif isinstance(T, Array):
+                node = ArrayDefNode(self, T)
+            else:
+                raise Exception("don't know about %r" % (T,))
+            self.structdefnodes[T] = node
+            self.structdeflist.append(node)
+        return node
+
     def gettype(self, T, who_asks=None):
         if isinstance(T, Primitive):
             return PrimitiveType[T]
@@ -38,15 +53,7 @@
             typename = self.gettype(T.TO)   # who_asks not propagated
             return typename.replace('@', '*@')
         elif isinstance(T, (Struct, Array)):
-            try:
-                node = self.structdefnodes[T]
-            except KeyError:
-                if isinstance(T, Struct):
-                    node = StructDefNode(self, T)
-                else:
-                    node = ArrayDefNode(self, T)
-                self.structdefnodes[T] = node
-                self.structdeflist.append(node)
+            node = self.gettypedefnode(T)
             if who_asks is not None:
                 who_asks.dependencies[node] = True
             return 'struct %s @' % node.name
@@ -64,23 +71,36 @@
         else:
             raise Exception("don't know about type %r" % (T,))
 
+    def getcontainernode(self, container):
+        try:
+            node = self.containernodes[container]
+        except KeyError:
+            T = typeOf(container)
+            nodecls = ContainerNodeClass[T.__class__]
+            node = nodecls(self, T, container)
+            self.containernodes[container] = node
+            self.containerlist.append(node)
+        return node
+
     def get(self, obj):
         T = typeOf(obj)
         if isinstance(T, Primitive):
             return PrimitiveName[T](obj)
         elif isinstance(T, _PtrType):
-            try:
-                node = self.containernodes[obj]
-            except KeyError:
-                nodecls = ContainerNodeClass[T.TO.__class__]
-                node = nodecls(self, T.TO, obj)
-                self.containernodes[obj] = node
-                self.containerlist.append(node)
+            node = self.getcontainernode(obj._obj)
             return node.ptrname
         else:
             raise Exception("don't know about %r" % (obj,))
 
     def complete(self):
         for node in self.containerlist:
-            for value in node.enum_dependencies(self):
-                self.get(value)
+            for value in node.enum_dependencies():
+                if isinstance(typeOf(value), ContainerType):
+                    self.getcontainernode(value)
+                else:
+                    self.get(value)
+
+    def globalcontainers(self):
+        for node in self.containerlist:
+            if node.globalcontainer:
+                yield node

Modified: pypy/dist/pypy/translator/c/node.py
==============================================================================
--- pypy/dist/pypy/translator/c/node.py	(original)
+++ pypy/dist/pypy/translator/c/node.py	Sat May 21 22:14:42 2005
@@ -1,7 +1,27 @@
 from __future__ import generators
 from pypy.translator.gensupp import C_IDENTIFIER
-from pypy.rpython.lltypes import Struct, Array, FuncType, PyObject
-from pypy.rpython.lltypes import GcStruct, GcArray
+from pypy.rpython.lltypes import Struct, Array, FuncType, PyObject, typeOf
+from pypy.rpython.lltypes import GcStruct, GcArray, GC_CONTAINER, ContainerType
+from pypy.rpython.lltypes import parentlink
+
+
+def needs_refcount(T):
+    if not isinstance(T, GC_CONTAINER):
+        return False
+    if isinstance(T, GcStruct):
+        if T._names and isinstance(T._flds[T._names[0]], GC_CONTAINER):
+            return False   # refcount already in the first first
+    return True
+
+def somelettersfrom(s):
+    upcase = [c for c in s if c.isupper()]
+    if not upcase:
+        upcase = [c for c in s.title() if c.isupper()]
+    locase = [c for c in s if c.islower()]
+    if locase and upcase:
+        return ''.join(upcase).lower()
+    else:
+        return s[:2].lower()
 
 
 class StructDefNode:
@@ -10,10 +30,23 @@
         self.STRUCT = STRUCT
         self.name = db.namespace.uniquename(STRUCT._name)
         self.dependencies = {}
-        self.typenames = []
+        self.fields = []
+        self.prefix = somelettersfrom(STRUCT._name) + '_'
         for name in STRUCT._names:
             T = STRUCT._flds[name]
-            self.typenames.append(db.gettype(T, who_asks=self))
+            typename = db.gettype(T, who_asks=self)
+            self.fields.append((self.c_struct_field_name(name), typename))
+
+    def c_struct_field_name(self, name):
+        return self.prefix + name
+
+    def definition(self):
+        yield 'struct %s {' % self.name
+        if needs_refcount(self.STRUCT):
+            yield '\tlong refcount;'
+        for name, typename in self.fields:
+            yield '\t%s;' % typename.replace('@', name)
+        yield '};'
 
 
 class ArrayDefNode:
@@ -24,36 +57,85 @@
         self.dependencies = {}
         self.structname = db.gettype(ARRAY.OF, who_asks=self)
 
+    def definition(self):
+        yield 'struct %s {' % self.name
+        if needs_refcount(self.ARRAY):
+            yield '\tlong refcount;'
+        yield '\tlong length;'
+        yield '\t%s;' % self.structname.replace('@', 'items[1]')
+        yield '};'
+
 
 class ContainerNode:
 
     def __init__(self, db, T, obj):
+        self.db = db
         self.T = T
         self.obj = obj
-        self.name = db.namespace.uniquename('g_' + self.basename())
-        self.ptrname = '&' + self.name
-        self.dependencies = {}
-        self.typename = db.gettype(T, who_asks=self)
+        #self.dependencies = {}
+        self.typename = db.gettype(T)  #, who_asks=self)
+        parent, fldname = parentlink(obj)
+        if parent is None:
+            self.name = db.namespace.uniquename('g_' + self.basename())
+            self.globalcontainer = True
+        else:
+            parentnode = db.getcontainernode(parent)
+            defnode = db.gettypedefnode(parentnode.T)
+            fldname = defnode.c_struct_field_name(fldname)
+            self.name = parentnode.name + '.' + fldname
+            self.globalcontainer = False
+        self.ptrname = '&%s' % self.name
+
+    def forward_declaration(self):
+        yield '%s; /* forward */' % self.typename.replace('@', self.name)
+
+    def implementation(self):
+        lines = list(self.initializationexpr())
+        lines[0] = '%s = %s' % (self.typename.replace('@', self.name), lines[0])
+        lines[-1] += ';'
+        return lines
 
 
 class StructNode(ContainerNode):
+
     def basename(self):
         return self.T._name
-    def enum_dependencies(self, db):
+
+    def enum_dependencies(self):
         for name in self.T._names:
             yield getattr(self.obj, name)
 
+    def initializationexpr(self, prefix=''):
+        yield '{'
+        if needs_refcount(self.T):
+            yield '\t1,'
+        for name in self.T._names:
+            value = getattr(self.obj, name)
+            if isinstance(typeOf(value), ContainerType):
+                node = self.db.getcontainernode(value)
+                expr = '\n'.join(node.initializationexpr(prefix+name+'.'))
+                expr += ','
+            else:
+                expr = self.db.get(value)
+                i = expr.find('\n')
+                if i<0: i = len(expr)
+                expr = '%s,\t/* %s%s */%s' % (expr[:i], prefix, name, expr[i:])
+            expr = expr.replace('\n', '\n\t')      # indentation
+            yield '\t%s' % expr
+        yield '}'
+
+
 class ArrayNode(ContainerNode):
     def basename(self):
         return 'array'
-    def enum_dependencies(self, db):
+    def enum_dependencies(self):
         for i in range(len(self.obj)):
             yield self.obj[i]
 
 class FuncNode(ContainerNode):
     def basename(self):
         return self.obj._name
-    def enum_dependencies(self, db):
+    def enum_dependencies(self):
         Booom
 
 class PyObjectNode(ContainerNode):

Modified: pypy/dist/pypy/translator/c/test/test_database.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_database.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_database.py	Sat May 21 22:14:42 2005
@@ -17,7 +17,7 @@
     s = malloc(S)
     s.x = 42
     assert db.get(s).startswith('&g_')
-    assert db.containernodes.keys() == [s]
+    assert db.containernodes.keys() == [s._obj]
     assert db.structdefnodes.keys() == [S]
 
 def test_inlined_struct():
@@ -26,7 +26,7 @@
     s = malloc(S)
     s.x.y = 42
     assert db.get(s).startswith('&g_')
-    assert db.containernodes.keys() == [s]
+    assert db.containernodes.keys() == [s._obj]
     assert len(db.structdefnodes) == 2
     assert S in db.structdefnodes
     assert S.x in db.structdefnodes
@@ -39,11 +39,30 @@
     s.x = malloc(T)
     s.x.y = 42
     assert db.get(s).startswith('&g_')
-    assert db.containernodes.keys() == [s]
+    assert db.containernodes.keys() == [s._obj]
     db.complete()
     assert len(db.containernodes) == 2
-    assert s in db.containernodes
-    assert s.x in db.containernodes
+    assert s._obj in db.containernodes
+    assert s.x._obj in db.containernodes
     assert len(db.structdefnodes) == 2
     assert S in db.structdefnodes
     assert S.x.TO in db.structdefnodes
+
+def test_codegen():
+    db = LowLevelDatabase()
+    U = Struct('inlined', ('z', Signed))
+    T = GcStruct('subtest', ('y', Signed))
+    S = GcStruct('test', ('x', GcPtr(T)), ('u', U), ('p', NonGcPtr(U)))
+    s = malloc(S)
+    s.x = malloc(T)
+    s.x.y = 42
+    s.u.z = -100
+    s.p = cast_flags(NonGcPtr(U), s.u)
+    db.get(s)
+    db.complete()
+    for node in db.structdeflist:
+        print '\n'.join(node.definition())
+    for node in db.globalcontainers():
+        print '\n'.join(node.forward_declaration())
+    for node in db.globalcontainers():
+        print '\n'.join(node.implementation())



More information about the Pypy-commit mailing list