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

arigo at codespeak.net arigo at codespeak.net
Sun May 22 23:20:23 CEST 2005


Author: arigo
Date: Sun May 22 23:20:23 2005
New Revision: 12726

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:
Support for functions in c/database and c/node.
Missing: writing the body itself (duh).



Modified: pypy/dist/pypy/rpython/lltypes.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypes.py	(original)
+++ pypy/dist/pypy/rpython/lltypes.py	Sun May 22 23:20:23 2005
@@ -311,7 +311,7 @@
     return val
 
 def parentlink(container):
-    parent = container._check()
+    parent = container._parentstructure()
     if parent is not None:
         return parent, container._wrparent_index
 ##        if isinstance(parent, _struct):
@@ -455,18 +455,21 @@
             self._wrparent = weakref.ref(parent)
             self._wrparent_index = parentindex
 
-    def _check(self):
+    def _parentstructure(self):
         if self._wrparent is not None:
             parent = self._wrparent()
             if parent is None:
                 raise RuntimeError("accessing substructure %r,\n"
                                    "but already garbage collected parent %r"
                                    % (self, self._wrparent_type))
-            else:
-                parent._check()
-                return parent
+            return parent
         return None
 
+    def _check(self):
+        parent = self._parentstructure()
+        if parent is not None:
+            parent._check()
+
     def __repr__(self):
         return '<%s>' % (self,)
 
@@ -500,18 +503,21 @@
             self._wrparent = weakref.ref(parent)
             self._wrparent_index = parentindex
 
-    def _check(self):
+    def _parentstructure(self):
         if self._wrparent is not None:
             parent = self._wrparent()
             if parent is None:
                 raise RuntimeError("accessing subarray %r,\n"
                                    "but already garbage collected parent %r"
                                    % (self, self._wrparent_type))
-            else:
-                parent._check()
-                return parent
+            return parent
         return None
 
+    def _check(self):
+        parent = self._parentstructure()
+        if parent is not None:
+            parent._check()
+
     def __repr__(self):
         return '<%s>' % (self,)
 
@@ -526,6 +532,9 @@
         self._callable = None
         self.__dict__.update(attrs)
 
+    def _parentstructure(self):
+        return None
+
     def _check(self):
         if self._callable is None:
             raise RuntimeError,"calling undefined function"
@@ -545,3 +554,8 @@
         raise TypeError, "malloc for Structs and Arrays only"
     return _ptr(GcPtr(T), o)
 
+def function(TYPE, name, **attrs):
+    if not isinstance(TYPE, FuncType):
+        raise TypeError, "function() for FuncTypes only"
+    o = _func(TYPE, _name=name, **attrs)
+    return _ptr(NonGcPtr(TYPE), o)

Modified: pypy/dist/pypy/translator/c/database.py
==============================================================================
--- pypy/dist/pypy/translator/c/database.py	(original)
+++ pypy/dist/pypy/translator/c/database.py	Sun May 22 23:20:23 2005
@@ -1,12 +1,12 @@
 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 Struct, Array, FuncType, PyObject, Void
 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
 from pypy.translator.c.node import StructDefNode, ArrayDefNode
-from pypy.translator.c.node import ContainerNodeClass
+from pypy.translator.c.node import ContainerNodeClass, cdecl
 
 # ____________________________________________________________
 
@@ -51,7 +51,7 @@
             self.structdeflist.append(node)
         return node
 
-    def gettype(self, T, varlength=1, who_asks=None):
+    def gettype(self, T, varlength=1, who_asks=None, argnames=[]):
         if isinstance(T, Primitive):
             return PrimitiveType[T]
         elif isinstance(T, _PtrType):
@@ -62,16 +62,20 @@
             if who_asks is not None:
                 who_asks.dependencies[node] = True
             return 'struct %s @' % node.name
-        elif isinstance(T, PyObject):
+        elif T == PyObject:
             return 'PyObject'
         elif isinstance(T, FuncType):
             resulttype = self.gettype(T.RESULT)
-            argtypes = ', '.join([self.gettype(ARG) for ARG in T.ARGS
-                                                    if ARG != Void])
-            if argtypes:
-                argtypes = argtypes.replace('@', '')
-            else:
-                argtypes = 'void'
+            argtypes = []
+            for i in range(len(T.ARGS)):
+                if T.ARGS[i] != Void:
+                    argtype = self.gettype(T.ARGS[i])
+                    try:
+                        argname = argnames[i]
+                    except IndexError:
+                        argname = ''
+                    argtypes.append(cdecl(argtype, argname))
+            argtypes = ', '.join(argtypes) or 'void'
             return resulttype.replace('@', '(@)(%s)' % argtypes)
         else:
             raise Exception("don't know about type %r" % (T,))
@@ -92,8 +96,11 @@
         if isinstance(T, Primitive):
             return PrimitiveName[T](obj)
         elif isinstance(T, _PtrType):
-            node = self.getcontainernode(obj._obj)
-            return node.ptrname
+            if obj:   # test if the ptr is non-NULL
+                node = self.getcontainernode(obj._obj)
+                return node.ptrname
+            else:
+                return 'NULL'
         else:
             raise Exception("don't know about %r" % (obj,))
 
@@ -109,3 +116,25 @@
         for node in self.containerlist:
             if node.globalcontainer:
                 yield node
+
+    def write_all_declarations(self, f):
+        print >> f
+        print >> f, '/********************************************************/'
+        print >> f, '/***  Structures definition                           ***/'
+        print >> f
+        for node in self.structdeflist:
+            print >> f, '\n'.join(node.definition())
+        print >> f
+        print >> f, '/********************************************************/'
+        print >> f, '/***  Forward declarations                            ***/'
+        print >> f
+        for node in self.globalcontainers():
+            print >> f, '\n'.join(node.forward_declaration())
+
+    def write_all_implementations(self, f):
+        print >> f
+        print >> f, '/********************************************************/'
+        print >> f, '/***  Implementations                                 ***/'
+        print >> f
+        for node in self.globalcontainers():
+            print >> f, '\n'.join(node.implementation())

Modified: pypy/dist/pypy/translator/c/node.py
==============================================================================
--- pypy/dist/pypy/translator/c/node.py	(original)
+++ pypy/dist/pypy/translator/c/node.py	Sun May 22 23:20:23 2005
@@ -57,7 +57,7 @@
         if needs_refcount(self.STRUCT):
             yield '\tlong refcount;'
         for name, typename in self.fields:
-            yield '\t%s;' % typename.replace('@', name)
+            yield '\t%s;' % cdecl(typename, name)
         yield '};'
 
 
@@ -83,8 +83,7 @@
         if needs_refcount(self.ARRAY):
             yield '\tlong refcount;'
         yield '\tlong length;'
-        yield '\t%s;' % self.structname.replace('@', 'items[%d]' %
-                                                self.varlength)
+        yield '\t%s;' % cdecl(self.structname, 'items[%d]' % self.varlength)
         yield '};'
 
 
@@ -113,12 +112,12 @@
 
     def forward_declaration(self):
         yield '%s; /* forward */' % (
-            self.implementationtypename.replace('@', self.name))
+            cdecl(self.implementationtypename, self.name))
 
     def implementation(self):
         lines = list(self.initializationexpr())
         lines[0] = '%s = %s' % (
-            self.implementationtypename.replace('@', self.name),
+            cdecl(self.implementationtypename, self.name),
             lines[0])
         lines[-1] += ';'
         return lines
@@ -188,11 +187,56 @@
         yield '}'
 
 
+# XXX move FuncNode to funcdef.py
+from pypy.objspace.flow.model import *
+
 class FuncNode(ContainerNode):
+
+    def __init__(self, db, T, obj):
+        graph = obj.graph # only user-defined functions with graphs for now
+        argnames = [v.name for v in graph.getargs()]
+        self.db = db
+        self.T = T
+        self.obj = obj
+        #self.dependencies = {}
+        self.typename = db.gettype(T)  #, who_asks=self)
+        self.implementationtypename = db.gettype(T, argnames=argnames)
+        self.name = db.namespace.uniquename('g_' + self.basename())
+        self.globalcontainer = True
+        self.ptrname = self.name
+        # collect all variables and constants used in the body,
+        # and get their types now
+        result = []
+        def visit(block):
+            if isinstance(block, Block):
+                result.extend(block.inputargs)
+                for op in block.operations:
+                    result.extend(op.args)
+                for link in block.exits:
+                    result.extend(link.args)
+        traverse(visit, graph)
+        self.varmap = {}
+        for v in uniqueitems(result):
+            T = v.concretetype
+            self.varmap[v] = self.db.gettype(T)
+
     def basename(self):
         return self.obj._name
+
+    def allvariables(self):
+        return [v for v in self.varmap if isinstance(v, Variable)]
+
+    def allconstants(self):
+        return [v for v in self.varmap if isinstance(v, Constant)]
+
     def enum_dependencies(self):
-        Booom
+        return [c.value for c in self.allconstants()]
+
+    def implementation(self):
+        yield '%s {' % cdecl(self.implementationtypename, self.name)
+        yield '\tlots-of-strange-code'
+        yield '}'
+
 
 class PyObjectNode(ContainerNode):
     basename = 'BOOOM'
@@ -206,3 +250,16 @@
     FuncType: FuncNode,
     PyObject: PyObjectNode,
     }
+
+#
+# helper
+#
+def cdecl(ctype, cname):
+    """
+    Produce a C declaration from a 'type template' and an identifier.
+    The type template must contain a '@' sign at the place where the
+    name should be inserted, according to the strange C syntax rules.
+    """
+    # the (@) case is for functions, where if there is a plain (@) around
+    # the function name, we don't need the very confusing parenthesis
+    return ctype.replace('(@)', '@').replace('@', cname).strip()

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	Sun May 22 23:20:23 2005
@@ -1,7 +1,8 @@
-import autopath
+import autopath, sys
 from pypy.rpython.lltypes import *
 from pypy.translator.c.database import LowLevelDatabase
-from pypy.objspace.flow.model import Constant
+from pypy.objspace.flow.model import Constant, Variable, SpaceOperation
+from pypy.objspace.flow.model import Block, Link, FunctionGraph
 from pypy.rpython.lltypes import Struct, Array, malloc
 
 
@@ -60,12 +61,8 @@
     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())
+    db.write_all_declarations(sys.stdout)
+    db.write_all_implementations(sys.stdout)
 
 def test_codegen_2():
     db = LowLevelDatabase()
@@ -79,12 +76,8 @@
     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())
+    db.write_all_declarations(sys.stdout)
+    db.write_all_implementations(sys.stdout)
 
 def test_codegen_3():
     db = LowLevelDatabase()
@@ -103,9 +96,40 @@
     s.anarray = cast_flags(NonGcPtr(A.y), a.y)
     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())
+    db.write_all_declarations(sys.stdout)
+    db.write_all_implementations(sys.stdout)
+
+def test_func_simple():
+    # -------------------- flowgraph building --------------------
+    #     def f(x):
+    #         return x+1
+    x = Variable("x")
+    x.concretetype = Signed
+    result = Variable("result")
+    result.concretetype = Signed
+    one = Constant(1)
+    one.concretetype = Signed
+    op = SpaceOperation("int_add", [x, one], result)
+    block = Block([x])
+    graph = FunctionGraph("f", block)
+    block.operations.append(op)
+    block.closeblock(Link([result], graph.returnblock))
+    graph.getreturnvar().concretetype = Signed
+    # --------------------         end        --------------------
+    
+    F = FuncType([Signed], Signed)
+    f = function(F, "f", graph=graph)
+    db = LowLevelDatabase()
+    db.get(f)
+    db.complete()
+    db.write_all_declarations(sys.stdout)
+    db.write_all_implementations(sys.stdout)
+
+    S = GcStruct('testing', ('fptr', NonGcPtr(F)))
+    s = malloc(S)
+    s.fptr = f
+    db = LowLevelDatabase()
+    db.get(s)
+    db.complete()
+    db.write_all_declarations(sys.stdout)
+    db.write_all_implementations(sys.stdout)



More information about the Pypy-commit mailing list