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

arigo at codespeak.net arigo at codespeak.net
Sat May 21 23:21:55 CEST 2005


Author: arigo
Date: Sat May 21 23:21:55 2005
New Revision: 12719

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:
Very strange code, but does the job.
Generating variable-length, predefined global arrays in C is rather fun.



Modified: pypy/dist/pypy/rpython/lltypes.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypes.py	(original)
+++ pypy/dist/pypy/rpython/lltypes.py	Sat May 21 23:21:55 2005
@@ -27,7 +27,7 @@
     def __str__(self):
         return self.__class__.__name__
 
-    def _defl(self, parent=None):
+    def _defl(self, parent=None, parentindex=None):
         raise NotImplementedError
 
     def _freeze_(self):
@@ -95,8 +95,8 @@
         return "%s %s { %s }" % (self.__class__.__name__,
                                  self._name, self._str_fields())
 
-    def _defl(self, parent=None):
-        return _struct(self, parent=parent)
+    def _defl(self, parent=None, parentindex=None):
+        return _struct(self, parent=parent, parentindex=parentindex)
 
     def _container_example(self):
         if self._arrayfld is None:
@@ -173,7 +173,7 @@
     def __str__(self):
         return self._name
 
-    def _defl(self, parent=None):
+    def _defl(self, parent=None, parentindex=None):
         return self._default
     
     _example = _defl
@@ -211,7 +211,7 @@
     def __str__(self):
         return 'ptr(%s) to %s' % (self._str_flags(), self.TO)
 
-    def _defl(self, parent=None):
+    def _defl(self, parent=None, parentindex=None):
         return _ptr(self, None)
 
     def _example(self):
@@ -313,11 +313,16 @@
 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")
+        return parent, container._wrparent_index
+##        if isinstance(parent, _struct):
+##            for name in parent._TYPE._names:
+##                if getattr(parent, name) is container:
+##                    return parent, name
+##            raise RuntimeError("lost ourselves")
+##        if isinstance(parent, _array):
+##            raise TypeError("cannot fish a pointer to an array item or an "
+##                            "inlined substructure of it")
+##        raise AssertionError("don't know about %r" % (parent,))
     else:
         return None, None
 
@@ -431,7 +436,7 @@
 class _struct(object):
     _wrparent = None
 
-    def __init__(self, TYPE, n=None, parent=None):
+    def __init__(self, TYPE, n=None, parent=None, parentindex=None):
         self._TYPE = TYPE
         if n is not None and TYPE._arrayfld is None:
             raise TypeError("%r is not variable-sized" % (TYPE,))
@@ -439,15 +444,16 @@
             raise TypeError("%r is variable-sized" % (TYPE,))
         for fld, typ in TYPE._flds.items():
             if isinstance(typ, Struct):
-                value = _struct(typ, parent=self)
+                value = _struct(typ, parent=self, parentindex=fld)
             elif fld == TYPE._arrayfld:
-                value = _array(typ, n, parent=self)
+                value = _array(typ, n, parent=self, parentindex=fld)
             else:
                 value = typ._defl()
             setattr(self, fld, value)
         if parent is not None:
             self._wrparent_type = typeOf(parent)
             self._wrparent = weakref.ref(parent)
+            self._wrparent_index = parentindex
 
     def _check(self):
         if self._wrparent is not None:
@@ -481,16 +487,18 @@
 class _array(object):
     _wrparent = None
 
-    def __init__(self, TYPE, n, parent=None):
+    def __init__(self, TYPE, n, parent=None, parentindex=None):
         if not isinstance(n, int):
             raise TypeError, "array length must be an int"
         if n < 0:
             raise ValueError, "negative array length"
         self._TYPE = TYPE
-        self.items = [TYPE.OF._defl(parent=self) for j in range(n)]
+        self.items = [TYPE.OF._defl(parent=self, parentindex=j)
+                      for j in range(n)]
         if parent is not None:
             self._wrparent_type = typeOf(parent)
             self._wrparent = weakref.ref(parent)
+            self._wrparent_index = parentindex
 
     def _check(self):
         if self._wrparent is not None:

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 23:21:55 2005
@@ -32,28 +32,33 @@
            else      register  union
            ''')
 
-    def gettypedefnode(self, T):
+    def gettypedefnode(self, T, varlength=1):
+        if varlength <= 1:
+            varlength = 1   # it's C after all
+            key = T
+        else:
+            key = T, varlength
         try:
-            node = self.structdefnodes[T]
+            node = self.structdefnodes[key]
         except KeyError:
             if isinstance(T, Struct):
                 node = StructDefNode(self, T)
             elif isinstance(T, Array):
-                node = ArrayDefNode(self, T)
+                node = ArrayDefNode(self, T, varlength)
             else:
                 raise Exception("don't know about %r" % (T,))
-            self.structdefnodes[T] = node
+            self.structdefnodes[key] = node
             self.structdeflist.append(node)
         return node
 
-    def gettype(self, T, who_asks=None):
+    def gettype(self, T, varlength=1, who_asks=None):
         if isinstance(T, Primitive):
             return PrimitiveType[T]
         elif isinstance(T, _PtrType):
             typename = self.gettype(T.TO)   # who_asks not propagated
             return typename.replace('@', '*@')
         elif isinstance(T, (Struct, Array)):
-            node = self.gettypedefnode(T)
+            node = self.gettypedefnode(T, varlength=varlength)
             if who_asks is not None:
                 who_asks.dependencies[node] = True
             return 'struct %s @' % node.name

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 23:21:55 2005
@@ -40,6 +40,10 @@
     def c_struct_field_name(self, name):
         return self.prefix + name
 
+    def access_expr(self, baseexpr, fldname):
+        fldname = self.c_struct_field_name(fldname)
+        return '%s.%s' % (baseexpr, fldname)
+
     def definition(self):
         yield 'struct %s {' % self.name
         if needs_refcount(self.STRUCT):
@@ -51,18 +55,28 @@
 
 class ArrayDefNode:
 
-    def __init__(self, db, ARRAY):
+    def __init__(self, db, ARRAY, varlength):
         self.ARRAY = ARRAY
-        self.name = db.namespace.uniquename('array')
+        if varlength == 1:
+            basename = 'array'
+        else:
+            basename = db.gettypedefnode(ARRAY).name
+            basename = '%s_len%d' % (basename, varlength)
+        self.name = db.namespace.uniquename(basename)
         self.dependencies = {}
         self.structname = db.gettype(ARRAY.OF, who_asks=self)
+        self.varlength = varlength
+
+    def access_expr(self, baseexpr, index):
+        return '%s.items[%d]' % (baseexpr, index)
 
     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 '\t%s;' % self.structname.replace('@', 'items[%d]' %
+                                                self.varlength)
         yield '};'
 
 
@@ -74,27 +88,36 @@
         self.obj = obj
         #self.dependencies = {}
         self.typename = db.gettype(T)  #, who_asks=self)
-        parent, fldname = parentlink(obj)
+        self.implementationtypename = db.gettype(T, varlength=self.getlength())
+        parent, parentindex = parentlink(obj)
         if parent is None:
             self.name = db.namespace.uniquename('g_' + self.basename())
             self.globalcontainer = True
         else:
+            self.globalcontainer = False
             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.name = defnode.access_expr(parentnode.name, parentindex)
         self.ptrname = '&%s' % self.name
+        if self.typename != self.implementationtypename:
+            self.ptrname = '((%s)(void*)%s)' % (self.typename.replace('@', '*'),
+                                                self.ptrname)
 
     def forward_declaration(self):
-        yield '%s; /* forward */' % self.typename.replace('@', self.name)
+        yield '%s; /* forward */' % (
+            self.implementationtypename.replace('@', self.name))
 
     def implementation(self):
         lines = list(self.initializationexpr())
-        lines[0] = '%s = %s' % (self.typename.replace('@', self.name), lines[0])
+        lines[0] = '%s = %s' % (
+            self.implementationtypename.replace('@', self.name),
+            lines[0])
         lines[-1] += ';'
         return lines
 
+    def getlength(self):
+        return 1
+
 
 class StructNode(ContainerNode):
 
@@ -126,11 +149,28 @@
 
 
 class ArrayNode(ContainerNode):
+
     def basename(self):
         return 'array'
+
     def enum_dependencies(self):
-        for i in range(len(self.obj)):
-            yield self.obj[i]
+        return self.obj.items
+
+    def getlength(self):
+        return len(self.obj.items)
+
+    def initializationexpr(self, prefix=''):
+        yield '{'
+        if needs_refcount(self.T):
+            yield '\t1,'
+        yield '\t%d,' % len(self.obj.items)
+        for j in range(len(self.obj.items)):
+            node = self.db.getcontainernode(self.obj.items[j])
+            expr = '\n'.join(node.initializationexpr('%s%d.' % (prefix, j)))
+            expr += ','
+            expr = expr.replace('\n', '\n\t')      # indentation
+            yield '\t%s' % expr
+        yield '}'
 
 class FuncNode(ContainerNode):
     def basename(self):

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 23:21:55 2005
@@ -66,3 +66,22 @@
         print '\n'.join(node.forward_declaration())
     for node in db.globalcontainers():
         print '\n'.join(node.implementation())
+
+def test_codegen_2():
+    db = LowLevelDatabase()
+    A = GcArray(('x', Signed))
+    S = GcStruct('test', ('aptr', GcPtr(A)))
+    a = malloc(A, 3)
+    a[0].x = 100
+    a[1].x = 101
+    a[2].x = 102
+    s = malloc(S)
+    s.aptr = a
+    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