[pypy-svn] r12745 - pypy/dist/pypy/translator/c

arigo at codespeak.net arigo at codespeak.net
Mon May 23 17:46:30 CEST 2005


Author: arigo
Date: Mon May 23 17:46:29 2005
New Revision: 12745

Added:
   pypy/dist/pypy/translator/c/funcgen.py
      - copied, changed from r12743, pypy/dist/pypy/translator/c/funcdef.py
   pypy/dist/pypy/translator/c/support.py   (contents, props changed)
Removed:
   pypy/dist/pypy/translator/c/funcdef.py
Modified:
   pypy/dist/pypy/translator/c/database.py
   pypy/dist/pypy/translator/c/node.py
   pypy/dist/pypy/translator/c/primitive.py
Log:
In the process of integrating node.py and funcgen.py (formerly funcdef.py).


Modified: pypy/dist/pypy/translator/c/database.py
==============================================================================
--- pypy/dist/pypy/translator/c/database.py	(original)
+++ pypy/dist/pypy/translator/c/database.py	Mon May 23 17:46:29 2005
@@ -1,12 +1,13 @@
-from pypy.translator.gensupp import NameManager
 from pypy.rpython.lltypes import Primitive, _PtrType, typeOf
 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.primitive import PrimitiveErrorValue
 from pypy.translator.c.node import StructDefNode, ArrayDefNode
-from pypy.translator.c.node import ContainerNodeClass, cdecl
+from pypy.translator.c.node import ContainerNodeClass
+from pypy.translator.c.support import cdecl, CNameManager, ErrorValue
 
 # ____________________________________________________________
 
@@ -17,20 +18,7 @@
         self.structdeflist = []
         self.containernodes = {}
         self.containerlist = []
-        self.namespace = NameManager()
-        # keywords cannot be reused.  This is the C99 draft's list.
-        self.namespace.make_reserved_names('''
-           auto      enum      restrict  unsigned
-           break     extern    return    void
-           case      float     short     volatile
-           char      for       signed    while
-           const     goto      sizeof    _Bool
-           continue  if        static    _Complex
-           default   inline    struct    _Imaginary
-           do        int       switch
-           double    long      typedef
-           else      register  union
-           ''')
+        self.namespace = CNameManager()
 
     def gettypedefnode(self, T, varlength=1):
         if varlength <= 1:
@@ -92,17 +80,24 @@
         return node
 
     def get(self, obj):
-        T = typeOf(obj)
-        if isinstance(T, Primitive):
-            return PrimitiveName[T](obj)
-        elif isinstance(T, _PtrType):
-            if obj:   # test if the ptr is non-NULL
-                node = self.getcontainernode(obj._obj)
-                return node.ptrname
+        if isinstance(obj, ErrorValue):
+            T = obj.TYPE
+            if isinstance(T, Primitive):
+                return PrimitiveErrorValue[T]
             else:
                 return 'NULL'
         else:
-            raise Exception("don't know about %r" % (obj,))
+            T = typeOf(obj)
+            if isinstance(T, Primitive):
+                return PrimitiveName[T](obj)
+            elif isinstance(T, _PtrType):
+                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,))
 
     def complete(self):
         for node in self.containerlist:
@@ -120,21 +115,24 @@
     def write_all_declarations(self, f):
         print >> f
         print >> f, '/********************************************************/'
-        print >> f, '/***  Structures definition                           ***/'
+        print >> f, '/***  Structure definitions                           ***/'
         print >> f
         for node in self.structdeflist:
-            print >> f, '\n'.join(node.definition())
+            for line in node.definition():
+                print >> f, line
         print >> f
         print >> f, '/********************************************************/'
         print >> f, '/***  Forward declarations                            ***/'
         print >> f
         for node in self.globalcontainers():
-            print >> f, '\n'.join(node.forward_declaration())
+            for line in node.forward_declaration():
+                print >> f, line
 
     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())
+            print >> f
+            for line in node.implementation():
+                print >> f, line

Deleted: /pypy/dist/pypy/translator/c/funcdef.py
==============================================================================
--- /pypy/dist/pypy/translator/c/funcdef.py	Mon May 23 17:46:29 2005
+++ (empty file)
@@ -1,607 +0,0 @@
-from __future__ import generators
-from pypy.objspace.flow import FlowObjSpace
-from pypy.objspace.flow.model import Variable, Constant, SpaceOperation
-from pypy.objspace.flow.model import traverse, uniqueitems, checkgraph
-from pypy.objspace.flow.model import Block, Link, FunctionGraph
-from pypy.objspace.flow.model import last_exception
-from pypy.translator.simplify import simplify_graph
-from pypy.translator.unsimplify import remove_direct_loops
-from pypy.rpython.typer import PyObjPtr
-from pypy.interpreter.pycode import CO_VARARGS
-from pypy.tool.compile import compile2
-from types import FunctionType
-
-from pypy.translator.gensupp import c_string
-
-# Set this if you want call trace frames to be built
-USE_CALL_TRACE = False
-# XXX doesn't work any more because of the way gen_wrapper() works, sorry
-
-
-class FunctionDef:
-    """
-    Collects information about a function which we have to generate.
-    The operations of each function are collected in a C function
-    with signature:
-
-        static T fn_xxx(T1 arg1, T2 arg2, etc);
-
-    where the T, T1, T2.. are C types like 'int' or 'PyObject *'.
-
-    If needed, another wrapper function is created with a signature
-    suitable for the built-in function type of CPython:
-
-        static PyObject *pyfn_xxx(PyObject *self, PyObject *args, PyObject* kw);
-
-    The built-in function object, if needed, is put in the global
-    variable named gfn_xxx.
-    """
-
-    def __init__(self, func, genc, graph=None, fast_name=None):
-        self.func = func
-        self.genc = genc
-
-        # get the function name
-        namespace = genc.namespace
-        if fast_name is None:
-            fast_name  = namespace.uniquename('fn_' + func.__name__) # fn_xxx
-        self.fast_name = fast_name
-        self.base_name = fast_name[3:]                               # xxx
-        self.wrapper_name = None                                     # pyfn_xxx
-        self.globalobject_name = None                                # gfunc_xxx
-        self.localscope = namespace.localScope()
-
-        # get the flow graph, and ensure that there is no direct loop in it
-        # as we cannot generate valid code for this case.
-        if graph is None:
-            graph = genc.translator.getflowgraph(func)
-        self.graph = graph
-        remove_direct_loops(genc.translator, graph)
-        checkgraph(graph)
-        graph_args = graph.getargs()
-
-        # collect all the local variables
-        localslst = []
-        def visit(node):
-            if isinstance(node, Block):
-                localslst.extend(node.getvariables())
-        traverse(visit, graph)
-        fast_set = dict(zip(graph_args, graph_args))
-        self.localnames = [self.decl(a) for a in localslst if a not in fast_set]
-
-        # collect all the arguments
-        fast_args         = [self.expr(a) for a in graph_args]
-        declare_fast_args = [self.decl(a) for a in graph_args]
-        if USE_CALL_TRACE:
-            declare_fast_args.insert(0, 'TRACE_ARGS')
-        declare_fast_args = ', '.join(declare_fast_args) or 'void'
-        ctret = self.ctypeof(graph.getreturnvar())
-        fast_function_header = 'static %s %s(%s)' % (
-            ctret.typename, self.fast_name, declare_fast_args)
-
-        # store misc. information
-        self.fast_function_header = fast_function_header
-        self.graphargs = graph_args
-        self.ctret = ctret
-        self.vararg = bool(func.func_code.co_flags & CO_VARARGS)
-        self.fast_args = fast_args
-        self.func_defaults = func.func_defaults or ()
-        
-        error_return = getattr(ctret, 'error_return', 'NULL')
-        self.return_error = 'FUNCTION_RETURN(%s)' % error_return
-
-        # generate the forward header
-        self.genc.globaldecl.append(fast_function_header + ';  /* forward */')
-
-
-    def ctypeof(self, var_or_const):
-        return getattr(var_or_const, 'concretetype', PyObjPtr)
-
-    def get_globalobject(self):
-        if self.globalobject_name is None:
-            self.wrapper_name = 'py' + self.fast_name
-            self.globalobject_name = self.genc.pyobj.uniquename('gfunc_' +
-                                                          self.base_name)
-        return self.globalobject_name
-
-    def clear(self):
-        del self.localscope
-        del self.localnames
-        del self.graph
-
-    def decl(self, v):
-        assert isinstance(v, Variable)
-        ct = self.ctypeof(v)
-        return '%s %s' % (ct.typename, self.localscope.localname(v.name))
-
-    def expr(self, v):
-        if isinstance(v, Variable):
-            return self.localscope.localname(v.name)
-        elif isinstance(v, Constant):
-            return self.genc.nameofconst(v,
-                               debug=('Constant in the graph of', self.func))
-        else:
-            raise TypeError, "expr(%r)" % (v,)
-
-    # ____________________________________________________________
-
-    def gen_wrapper(self):
-        # the wrapper is the function that takes the CPython signature
-        #
-        #    PyObject *fn(PyObject *self, PyObject *args, PyObject *kwds)
-        #
-        # and decodes the arguments and calls the "real" C function.
-        # We generate the wrapper itself as a Python function which is
-        # turned into C.  This makes gen_wrapper() more or less clean.
-        #
-
-        TPyObject = self.genc.pyobjtype
-        TInt      = self.genc.translator.getconcretetype(CIntType)
-        TNone     = self.genc.translator.getconcretetype(CNoneType)
-        TBorrowed = self.genc.translator.getconcretetype(CBorrowedPyObjectType)
-        args_ct   = [self.ctypeof(a) for a in self.graphargs]
-        res_ct    = self.ctret
-        nb_positional_args = len(self.graphargs) - self.vararg
-
-        # "def wrapper(self, args, kwds)"
-        vself = Variable('self')
-        vargs = Variable('args')
-        vkwds = Variable('kwds')
-        block = Block([vself, vargs, vkwds])
-        vfname = Constant(self.base_name)
-
-        # avoid incref/decref on the arguments: 'self' and 'kwds' can be NULL
-        vself.concretetype = TBorrowed
-        vargs.concretetype = TBorrowed
-        vkwds.concretetype = TBorrowed
-
-        # "argument_i = decode_arg(fname, pos, name, vargs, vkwds)"  or
-        # "argument_i = decode_arg_def(fname, pos, name, vargs, vkwds, default)"
-        varguments = []
-        varnames = self.func.func_code.co_varnames
-        for i in range(nb_positional_args):
-            opargs = [vfname, Constant(i),
-                      Constant(varnames[i]), vargs, vkwds]
-            opargs[1].concretetype = TInt
-            try:
-                default_value = self.func_defaults[i - nb_positional_args]
-            except IndexError:
-                opname = 'decode_arg'
-            else:
-                opname = 'decode_arg_def'
-                opargs.append(Constant(default_value))
-            v = Variable('a%d' % i)
-            block.operations.append(SpaceOperation(opname, opargs, v))
-            varguments.append(v)
-
-        if self.vararg:
-            # "vararg = vargs[n:]"
-            vararg = Variable('vararg')
-            opargs = [vargs, Constant(nb_positional_args), Constant(None)]
-            block.operations.append(SpaceOperation('getslice', opargs, vararg))
-            varguments.append(vararg)
-        else:
-            # "check_no_more_arg(fname, n, vargs)"
-            vnone = Variable()
-            vnone.concretetype = TNone
-            opargs = [vfname, Constant(nb_positional_args), vargs]
-            opargs[1].concretetype = TInt
-            block.operations.append(SpaceOperation('check_no_more_arg',
-                                                   opargs, vnone))
-
-        if self.genc.translator.annotator is not None:
-            # "argument_i = type_conversion_operations(argument_i)"
-            from pypy.translator.genc.ctyper import GenCSpecializer
-            from pypy.translator.typer import flatten_ops
-            typer = GenCSpecializer(self.genc.translator.annotator)
-
-            assert len(varguments) == len(self.graphargs)
-            for i in range(len(varguments)):
-                varguments[i].concretetype = TPyObject
-                varguments[i], convops = typer.convertvar(varguments[i],
-                                                          args_ct[i])
-                flatten_ops(convops, block.operations)
-        else:
-            typer = None
-
-        # "result = direct_call(func, argument_0, argument_1, ..)"
-        opargs = [Constant(self.func)] + varguments
-        opargs[0].concretetype = self.genc.translator.getconcretetype(
-            CFuncPtrType, tuple(args_ct), res_ct)
-        vresult = Variable('result')
-        block.operations.append(SpaceOperation('direct_call', opargs, vresult))
-
-        if typer is not None:
-            # "result2 = type_conversion_operations(result)"
-            vresult.concretetype = res_ct
-            vresult, convops = typer.convertvar(vresult, TPyObject)
-            flatten_ops(convops, block.operations)
-
-        # "return result"
-        wgraph = FunctionGraph(self.wrapper_name, block)
-        block.closeblock(Link([vresult], wgraph.returnblock))
-        checkgraph(wgraph)
-
-        # generate the C source of this wrapper function
-        wfuncdef = FunctionDef(dummy_wrapper, self.genc,
-                               wgraph, self.wrapper_name)
-        self.genc.gen_cfunction(wfuncdef)
-
-
-    def DISABLED_OLD_gen_wrapper(self, f):
-        # XXX this is a huge mess.  Think about producing the wrapper by
-        #     generating its content as a flow graph...
-        func             = self.func
-        f_name           = self.wrapper_name
-        name_of_defaults = self.name_of_defaults
-        graphargs        = self.graphargs
-        vararg           = self.vararg
-        nb_positional_args = len(graphargs) - vararg
-
-        min_number_of_args = nb_positional_args - len(name_of_defaults)
-        print >> f, 'static PyObject *'
-        print >> f, '%s(PyObject* self, PyObject* args, PyObject* kwds)' % (
-            f_name,)
-        print >> f, '{'
-        if USE_CALL_TRACE:
-            print >> f, '\tFUNCTION_HEAD(%s, %s, args, %s, __FILE__, __LINE__ - 2)' % (
-                c_string('%s(%s)' % (self.base_name, ', '.join(name_of_defaults))),
-                self.globalobject_name,
-                '(%s)' % (', '.join(map(c_string, name_of_defaults) + ['NULL']),),
-            )
-
-        kwlist = ['"%s"' % name for name in
-                      func.func_code.co_varnames[:func.func_code.co_argcount]]
-        kwlist.append('0')
-        print >> f, '\tstatic char* kwlist[] = {%s};' % (', '.join(kwlist),)
-
-        numberednames = ['o%d' % (i+1) for i in range(len(graphargs))]
-        if vararg:
-            numberednames[-1] = 'ovararg'
-        numberednames.append('oret')
-        print >> f, '\tPyObject *%s;' % (', *'.join(numberednames))
-        conversions = []
-        call_fast_args = []
-        for a, numberedname in zip(graphargs, numberednames):
-            ct = self.ctypeof(a)
-            if ct == self.genc.pyobjtype:
-                call_fast_args.append(numberedname)
-            else:
-                convert_from_obj = ct.opname_conv_from_obj  # simple conv only!
-                convertedname = numberedname.replace('o', 'a')
-                print >> f, '\t%s %s;' % (ct.typename, convertedname)
-                conversions.append('\tOP_%s(%s, %s, type_error)' % (
-                    convert_from_obj.upper(), numberedname, convertedname))
-                # XXX successfully converted objects may need to be decrefed
-                # XXX even though they are not PyObjects
-                call_fast_args.append(convertedname)
-        # return value conversion
-        ct = self.ctret
-        if ct == self.genc.pyobjtype:
-            putresultin = 'oret'
-            footer = None
-        else:
-            convert_to_obj = ct.opname_conv_to_obj  # simple conv only for now!
-            print >> f, '\t%s aret;' % (ct.typename,)
-            putresultin = 'aret'
-            footer = 'OP_%s(aret, oret, type_error)' % convert_to_obj.upper()
-        print >> f
-
-        if USE_CALL_TRACE:
-            print >> f, '\tFUNCTION_CHECK()'
-
-        # argument unpacking
-        if vararg:
-            print >> f, '\tovararg = PyTuple_GetSlice(args, %d, INT_MAX);' % (
-                nb_positional_args,)
-            print >> f, '\tif (ovararg == NULL)'
-            print >> f, '\t\tFUNCTION_RETURN(NULL)'
-            print >> f, '\targs = PyTuple_GetSlice(args, 0, %d);' % (
-                nb_positional_args,)
-            print >> f, '\tif (args == NULL) {'
-            print >> f, '\t\tERR_DECREF(ovararg)'
-            print >> f, '\t\tFUNCTION_RETURN(NULL)'
-            print >> f, '\t}'
-            tail = """{
-\t\tERR_DECREF(args)
-\t\tERR_DECREF(ovararg)
-\t\tFUNCTION_RETURN(NULL);
-\t}
-\tPy_DECREF(args);"""
-        else:
-            tail = '\n\t\tFUNCTION_RETURN(NULL)'
-        for i in range(len(name_of_defaults)):
-            print >> f, '\t%s = %s;' % (
-                numberednames[min_number_of_args+i],
-                name_of_defaults[i])
-        fmt = 'O'*min_number_of_args
-        if min_number_of_args < nb_positional_args:
-            fmt += '|' + 'O'*(nb_positional_args-min_number_of_args)
-        lst = ['args', 'kwds',
-               '"%s:%s"' % (fmt, func.__name__),
-               'kwlist',
-               ]
-        lst += ['&' + a for a in numberednames]
-        print >> f, '\tif (!PyArg_ParseTupleAndKeywords(%s))' % ', '.join(lst),
-        print >> f, tail
-
-        for line in conversions:
-            print >> f, line
-
-        if USE_CALL_TRACE:
-            call_fast_args.insert(0, 'TRACE_CALL')
-        call_fast_args = ', '.join(call_fast_args)
-        print >> f, '\t%s = %s(%s);' % (putresultin, self.fast_name,
-                                        call_fast_args)
-        if footer:
-            print >> f, '\t' + footer
-        print >> f, '\treturn oret;'
-
-        if conversions or footer:
-            print >> f, '    type_error:'
-            print >> f, '        return NULL;'
-        
-        print >> f, '}'
-        print >> f
-
-    # ____________________________________________________________
-
-    def gen_cfunction(self, f, body):
-        print >> f, self.fast_function_header
-        print >> f, '{'
-
-        localnames = self.localnames
-        lengths = [len(a) for a in localnames]
-        lengths.append(9999)
-        start = 0
-        while start < len(localnames):
-            total = lengths[start] + 9
-            end = start+1
-            while total + lengths[end] < 76:
-                total += lengths[end] + 2
-                end += 1
-            print >> f, '\t' + '; '.join(localnames[start:end]) + ';'
-            start = end
-        
-        # generate an incref for each input argument
-        for a in self.graphargs:
-            print >> f, '\t' + self.cincref(a)
-
-        # print the body
-        for line in body:
-            if line.endswith(':'):
-                if line.startswith('err'):
-                    fmt = '\t%s'
-                else:
-                    fmt = '    %s\n'
-            elif line:
-                fmt = '\t%s\n'
-            else:
-                fmt = '%s\n'
-            f.write(fmt % line)
-        print >> f, '}'
-        print >> f
-
-    # ____________________________________________________________
-
-    def cfunction_body(self):
-        graph = self.graph
-
-        blocknum = {}
-        allblocks = []
-
-        def gen_link(link, linklocalvars=None):
-            "Generate the code to jump across the given Link."
-            has_ref = {}
-            linklocalvars = linklocalvars or {}
-            for v in to_release:
-                linklocalvars[v] = self.expr(v)
-            has_ref = linklocalvars.copy()
-            for a1, a2 in zip(link.args, link.target.inputargs):
-                if a1 in linklocalvars:
-                    src = linklocalvars[a1]
-                else:
-                    src = self.expr(a1)
-                line = 'MOVE(%s, %s)' % (src, self.expr(a2))
-                if a1 in has_ref:
-                    del has_ref[a1]
-                else:
-                    ct1 = self.ctypeof(a1)
-                    ct2 = self.ctypeof(a2)
-                    assert ct1 == ct2
-                    line += '\t' + self.cincref(a2)
-                yield line
-            for v in has_ref:
-                yield self.cdecref(v, linklocalvars[v])
-            yield 'goto block%d;' % blocknum[link.target]
-
-        # collect all blocks
-        def visit(block):
-            if isinstance(block, Block):
-                allblocks.append(block)
-                blocknum[block] = len(blocknum)
-        traverse(visit, graph)
-
-        # generate the body of each block
-        for block in allblocks:
-            yield ''
-            yield 'block%d:' % blocknum[block]
-            to_release = list(block.inputargs)
-            for op in block.operations:
-                err   = 'err%d_%d' % (blocknum[block], len(to_release))
-                macro = 'OP_%s' % op.opname.upper()
-                meth  = getattr(self, macro, None)
-                if meth:
-                    yield meth(op, err)
-                else:
-                    lst = [self.expr(v) for v in op.args]
-                    lst.append(self.expr(op.result))
-                    lst.append(err)
-                    yield '%s(%s)' % (macro, ', '.join(lst))
-                to_release.append(op.result)
-
-            err_reachable = False
-            if len(block.exits) == 0:
-                if len(block.inputargs) == 2:   # exc_cls, exc_value
-                    # exceptional return block
-                    exc_cls   = self.expr(block.inputargs[0])
-                    exc_value = self.expr(block.inputargs[1])
-                    yield 'PyErr_Restore(%s, %s, NULL);' % (exc_cls, exc_value)
-                    yield self.return_error
-                else:
-                    # regular return block
-                    retval = self.expr(block.inputargs[0])
-                    yield 'FUNCTION_RETURN(%s)' % retval
-                continue
-            elif block.exitswitch is None:
-                # single-exit block
-                assert len(block.exits) == 1
-                for op in gen_link(block.exits[0]):
-                    yield op
-                yield ''
-            elif block.exitswitch == Constant(last_exception):
-                # block catching the exceptions raised by its last operation
-                # we handle the non-exceptional case first
-                link = block.exits[0]
-                assert link.exitcase is None
-                for op in gen_link(link):
-                    yield op
-                # we must catch the exception raised by the last operation,
-                # which goes to the last err%d_%d label written above.
-                yield ''
-                to_release.pop()  # skip default error handling for this label
-                yield 'err%d_%d:' % (blocknum[block], len(to_release))
-                yield ''
-                for link in block.exits[1:]:
-                    assert issubclass(link.exitcase, Exception)
-                    yield 'if (PyErr_ExceptionMatches(%s)) {' % (
-                        self.genc.nameofvalue(link.exitcase),)
-                    yield '\tPyObject *exc_cls, *exc_value, *exc_tb;'
-                    yield '\tPyErr_Fetch(&exc_cls, &exc_value, &exc_tb);'
-                    yield '\tif (exc_value == NULL) {'
-                    yield '\t\texc_value = Py_None;'
-                    yield '\t\tPy_INCREF(Py_None);'
-                    yield '\t}'
-                    yield '\tPy_XDECREF(exc_tb);'
-                    for op in gen_link(link, {
-                                link.last_exception: 'exc_cls',
-                                link.last_exc_value: 'exc_value'}):
-                        yield '\t' + op
-                    yield '}'
-                err_reachable = True
-            else:
-                # block ending in a switch on a value
-                ct = self.ctypeof(block.exitswitch)
-                for link in block.exits[:-1]:
-                    assert link.exitcase in (False, True)
-                    yield 'if (%s == %s) {' % (self.expr(block.exitswitch),
-                                       self.genc.nameofvalue(link.exitcase, ct))
-                    for op in gen_link(link):
-                        yield '\t' + op
-                    yield '}'
-                link = block.exits[-1]
-                assert link.exitcase in (False, True)
-                yield 'assert(%s == %s);' % (self.expr(block.exitswitch),
-                                       self.genc.nameofvalue(link.exitcase, ct))
-                for op in gen_link(block.exits[-1]):
-                    yield op
-                yield ''
-
-            while to_release:
-                v = to_release.pop()
-                if err_reachable:
-                    yield self.cdecref(v)
-                yield 'err%d_%d:' % (blocknum[block], len(to_release))
-                err_reachable = True
-            if err_reachable:
-                yield self.return_error
-
-    # ____________________________________________________________
-
-    # the C preprocessor cannot handle operations taking a variable number
-    # of arguments, so here are Python methods that do it
-    
-    def OP_NEWLIST(self, op, err):
-        args = [self.expr(v) for v in op.args]
-        r = self.expr(op.result)
-        if len(args) == 0:
-            return 'OP_NEWLIST0(%s, %s)' % (r, err)
-        else:
-            args.insert(0, '%d' % len(args))
-            return 'OP_NEWLIST((%s), %s, %s)' % (', '.join(args), r, err)
-
-    def OP_NEWDICT(self, op, err):
-        args = [self.expr(v) for v in op.args]
-        r = self.expr(op.result)
-        if len(args) == 0:
-            return 'OP_NEWDICT0(%s, %s)' % (r, err)
-        else:
-            assert len(args) % 2 == 0
-            args.insert(0, '%d' % (len(args)//2))
-            return 'OP_NEWDICT((%s), %s, %s)' % (', '.join(args), r, err)
-
-    def OP_NEWTUPLE(self, op, err):
-        args = [self.expr(v) for v in op.args]
-        r = self.expr(op.result)
-        args.insert(0, '%d' % len(args))
-        return 'OP_NEWTUPLE((%s), %s, %s)' % (', '.join(args), r, err)
-
-    def OP_SIMPLE_CALL(self, op, err):
-        args = [self.expr(v) for v in op.args]
-        r = self.expr(op.result)
-        args.append('NULL')
-        return 'OP_SIMPLE_CALL((%s), %s, %s)' % (', '.join(args), r, err)
-
-    def OP_CALL_ARGS(self, op, err):
-        args = [self.expr(v) for v in op.args]
-        r = self.expr(op.result)
-        return 'OP_CALL_ARGS((%s), %s, %s)' % (', '.join(args), r, err)
-
-    def OP_DIRECT_CALL(self, op, err):
-        args = [self.expr(v) for v in op.args]
-        r = self.expr(op.result)
-        return '%s = %s(%s); if (PyErr_Occurred()) FAIL(%s)' % (
-            r, args[0], ', '.join(args[1:]), err)
-
-    def OP_INST_GETATTR(self, op, err):
-        return '%s = INST_ATTR_%s__%s(%s);' % (
-            self.expr(op.result),
-            op.args[0].concretetype.typename,
-            op.args[1].value,
-            self.expr(op.args[0]))
-
-    def OP_INST_SETATTR(self, op, err):
-        return 'INST_ATTR_%s__%s(%s) = %s;' % (
-            op.args[0].concretetype.typename,
-            op.args[1].value,
-            self.expr(op.args[0]),
-            self.expr(op.args[2]))
-
-    def OP_CONV_TO_OBJ(self, op, err):
-        v = op.args[0]
-        return '%s = CONV_TO_OBJ_%s(%s); if (PyErr_Occurred()) FAIL(%s)' % (
-            self.expr(op.result), self.ctypeof(v).typename, self.expr(v), err)
-
-    def OP_CONV_FROM_OBJ(self, op, err):
-        v = op.args[0]
-        return '%s = CONV_FROM_OBJ_%s(%s); if (PyErr_Occurred()) FAIL(%s)' %(
-            self.expr(op.result), self.ctypeof(op.result).typename,
-            self.expr(v), err)
-
-    def OP_INCREF(self, op, err):
-        return self.cincref(op.args[0])
-
-    def OP_DECREF(self, op, err):
-        return self.cdecref(op.args[0])
-
-    def cincref(self, v):
-        return 'OP_INCREF_%s(%s)' % (self.ctypeof(v).typename, self.expr(v))
-
-    def cdecref(self, v, expr=None):
-        return 'OP_DECREF_%s(%s)' % (self.ctypeof(v).typename,
-                                     expr or self.expr(v))
-
-# ____________________________________________________________
-
-def dummy_wrapper(self, args, kwds):
-    pass

Copied: pypy/dist/pypy/translator/c/funcgen.py (from r12743, pypy/dist/pypy/translator/c/funcdef.py)
==============================================================================
--- pypy/dist/pypy/translator/c/funcdef.py	(original)
+++ pypy/dist/pypy/translator/c/funcgen.py	Mon May 23 17:46:29 2005
@@ -1,394 +1,93 @@
 from __future__ import generators
-from pypy.objspace.flow import FlowObjSpace
-from pypy.objspace.flow.model import Variable, Constant, SpaceOperation
-from pypy.objspace.flow.model import traverse, uniqueitems, checkgraph
-from pypy.objspace.flow.model import Block, Link, FunctionGraph
-from pypy.objspace.flow.model import last_exception
-from pypy.translator.simplify import simplify_graph
-from pypy.translator.unsimplify import remove_direct_loops
-from pypy.rpython.typer import PyObjPtr
-from pypy.interpreter.pycode import CO_VARARGS
-from pypy.tool.compile import compile2
-from types import FunctionType
-
-from pypy.translator.gensupp import c_string
-
-# Set this if you want call trace frames to be built
-USE_CALL_TRACE = False
-# XXX doesn't work any more because of the way gen_wrapper() works, sorry
+from pypy.rpython.lltypes import PyObject, GcPtr
+from pypy.translator.gensupp import ordered_blocks
+from pypy.translator.c.support import cdecl, ErrorValue
+from pypy.objspace.flow.model import Variable, Constant, Block
+from pypy.objspace.flow.model import traverse, uniqueitems
 
 
-class FunctionDef:
-    """
-    Collects information about a function which we have to generate.
-    The operations of each function are collected in a C function
-    with signature:
-
-        static T fn_xxx(T1 arg1, T2 arg2, etc);
-
-    where the T, T1, T2.. are C types like 'int' or 'PyObject *'.
-
-    If needed, another wrapper function is created with a signature
-    suitable for the built-in function type of CPython:
+PyObjPtr = GcPtr(PyObject)   # default type for untyped Vars and Consts
 
-        static PyObject *pyfn_xxx(PyObject *self, PyObject *args, PyObject* kw);
 
-    The built-in function object, if needed, is put in the global
-    variable named gfn_xxx.
+class FunctionCodeGenerator:
+    """
+    Collects information about a function which we have to generate
+    from a flow graph.
     """
 
-    def __init__(self, func, genc, graph=None, fast_name=None):
-        self.func = func
-        self.genc = genc
-
-        # get the function name
-        namespace = genc.namespace
-        if fast_name is None:
-            fast_name  = namespace.uniquename('fn_' + func.__name__) # fn_xxx
-        self.fast_name = fast_name
-        self.base_name = fast_name[3:]                               # xxx
-        self.wrapper_name = None                                     # pyfn_xxx
-        self.globalobject_name = None                                # gfunc_xxx
-        self.localscope = namespace.localScope()
-
-        # get the flow graph, and ensure that there is no direct loop in it
-        # as we cannot generate valid code for this case.
-        if graph is None:
-            graph = genc.translator.getflowgraph(func)
+    def __init__(self, graph, gettype, getvalue):
         self.graph = graph
-        remove_direct_loops(genc.translator, graph)
-        checkgraph(graph)
-        graph_args = graph.getargs()
-
-        # collect all the local variables
-        localslst = []
-        def visit(node):
-            if isinstance(node, Block):
-                localslst.extend(node.getvariables())
-        traverse(visit, graph)
-        fast_set = dict(zip(graph_args, graph_args))
-        self.localnames = [self.decl(a) for a in localslst if a not in fast_set]
-
-        # collect all the arguments
-        fast_args         = [self.expr(a) for a in graph_args]
-        declare_fast_args = [self.decl(a) for a in graph_args]
-        if USE_CALL_TRACE:
-            declare_fast_args.insert(0, 'TRACE_ARGS')
-        declare_fast_args = ', '.join(declare_fast_args) or 'void'
-        ctret = self.ctypeof(graph.getreturnvar())
-        fast_function_header = 'static %s %s(%s)' % (
-            ctret.typename, self.fast_name, declare_fast_args)
-
-        # store misc. information
-        self.fast_function_header = fast_function_header
-        self.graphargs = graph_args
-        self.ctret = ctret
-        self.vararg = bool(func.func_code.co_flags & CO_VARARGS)
-        self.fast_args = fast_args
-        self.func_defaults = func.func_defaults or ()
-        
-        error_return = getattr(ctret, 'error_return', 'NULL')
-        self.return_error = 'FUNCTION_RETURN(%s)' % error_return
-
-        # generate the forward header
-        self.genc.globaldecl.append(fast_function_header + ';  /* forward */')
-
-
-    def ctypeof(self, var_or_const):
-        return getattr(var_or_const, 'concretetype', PyObjPtr)
-
-    def get_globalobject(self):
-        if self.globalobject_name is None:
-            self.wrapper_name = 'py' + self.fast_name
-            self.globalobject_name = self.genc.pyobj.uniquename('gfunc_' +
-                                                          self.base_name)
-        return self.globalobject_name
-
-    def clear(self):
-        del self.localscope
-        del self.localnames
-        del self.graph
+        self.getvalue = getvalue
+        self.typemap = self.collecttypes(gettype)
+
+    def collecttypes(self, gettype):
+        # 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, self.graph)
+        typemap = {}
+        for v in uniqueitems(result):
+            T = getattr(v, 'concretetype', PyObjPtr)
+            typemap[v] = gettype(T)
+        return typemap
+
+    def argnames(self):
+        return [v.name for v in self.graph.getargs()]
+
+    def allvariables(self):
+        return [v for v in self.typemap if isinstance(v, Variable)]
+
+    def allconstants(self):
+        return [v for v in self.typemap if isinstance(v, Constant)]
+
+    def allconstantvalues(self):
+        for v, T in self.typemap.iteritems():
+            if isinstance(v, Constant):
+                yield v.value
 
     def decl(self, v):
-        assert isinstance(v, Variable)
-        ct = self.ctypeof(v)
-        return '%s %s' % (ct.typename, self.localscope.localname(v.name))
+        assert isinstance(v, Variable), repr(v)
+        return cdecl(self.typemap[v], v.name)
 
     def expr(self, v):
         if isinstance(v, Variable):
-            return self.localscope.localname(v.name)
+            return v.name
         elif isinstance(v, Constant):
-            return self.genc.nameofconst(v,
-                               debug=('Constant in the graph of', self.func))
+            return self.getvalue(v.value)
         else:
             raise TypeError, "expr(%r)" % (v,)
 
-    # ____________________________________________________________
-
-    def gen_wrapper(self):
-        # the wrapper is the function that takes the CPython signature
-        #
-        #    PyObject *fn(PyObject *self, PyObject *args, PyObject *kwds)
-        #
-        # and decodes the arguments and calls the "real" C function.
-        # We generate the wrapper itself as a Python function which is
-        # turned into C.  This makes gen_wrapper() more or less clean.
-        #
-
-        TPyObject = self.genc.pyobjtype
-        TInt      = self.genc.translator.getconcretetype(CIntType)
-        TNone     = self.genc.translator.getconcretetype(CNoneType)
-        TBorrowed = self.genc.translator.getconcretetype(CBorrowedPyObjectType)
-        args_ct   = [self.ctypeof(a) for a in self.graphargs]
-        res_ct    = self.ctret
-        nb_positional_args = len(self.graphargs) - self.vararg
-
-        # "def wrapper(self, args, kwds)"
-        vself = Variable('self')
-        vargs = Variable('args')
-        vkwds = Variable('kwds')
-        block = Block([vself, vargs, vkwds])
-        vfname = Constant(self.base_name)
-
-        # avoid incref/decref on the arguments: 'self' and 'kwds' can be NULL
-        vself.concretetype = TBorrowed
-        vargs.concretetype = TBorrowed
-        vkwds.concretetype = TBorrowed
-
-        # "argument_i = decode_arg(fname, pos, name, vargs, vkwds)"  or
-        # "argument_i = decode_arg_def(fname, pos, name, vargs, vkwds, default)"
-        varguments = []
-        varnames = self.func.func_code.co_varnames
-        for i in range(nb_positional_args):
-            opargs = [vfname, Constant(i),
-                      Constant(varnames[i]), vargs, vkwds]
-            opargs[1].concretetype = TInt
-            try:
-                default_value = self.func_defaults[i - nb_positional_args]
-            except IndexError:
-                opname = 'decode_arg'
-            else:
-                opname = 'decode_arg_def'
-                opargs.append(Constant(default_value))
-            v = Variable('a%d' % i)
-            block.operations.append(SpaceOperation(opname, opargs, v))
-            varguments.append(v)
-
-        if self.vararg:
-            # "vararg = vargs[n:]"
-            vararg = Variable('vararg')
-            opargs = [vargs, Constant(nb_positional_args), Constant(None)]
-            block.operations.append(SpaceOperation('getslice', opargs, vararg))
-            varguments.append(vararg)
-        else:
-            # "check_no_more_arg(fname, n, vargs)"
-            vnone = Variable()
-            vnone.concretetype = TNone
-            opargs = [vfname, Constant(nb_positional_args), vargs]
-            opargs[1].concretetype = TInt
-            block.operations.append(SpaceOperation('check_no_more_arg',
-                                                   opargs, vnone))
-
-        if self.genc.translator.annotator is not None:
-            # "argument_i = type_conversion_operations(argument_i)"
-            from pypy.translator.genc.ctyper import GenCSpecializer
-            from pypy.translator.typer import flatten_ops
-            typer = GenCSpecializer(self.genc.translator.annotator)
-
-            assert len(varguments) == len(self.graphargs)
-            for i in range(len(varguments)):
-                varguments[i].concretetype = TPyObject
-                varguments[i], convops = typer.convertvar(varguments[i],
-                                                          args_ct[i])
-                flatten_ops(convops, block.operations)
-        else:
-            typer = None
-
-        # "result = direct_call(func, argument_0, argument_1, ..)"
-        opargs = [Constant(self.func)] + varguments
-        opargs[0].concretetype = self.genc.translator.getconcretetype(
-            CFuncPtrType, tuple(args_ct), res_ct)
-        vresult = Variable('result')
-        block.operations.append(SpaceOperation('direct_call', opargs, vresult))
-
-        if typer is not None:
-            # "result2 = type_conversion_operations(result)"
-            vresult.concretetype = res_ct
-            vresult, convops = typer.convertvar(vresult, TPyObject)
-            flatten_ops(convops, block.operations)
-
-        # "return result"
-        wgraph = FunctionGraph(self.wrapper_name, block)
-        block.closeblock(Link([vresult], wgraph.returnblock))
-        checkgraph(wgraph)
-
-        # generate the C source of this wrapper function
-        wfuncdef = FunctionDef(dummy_wrapper, self.genc,
-                               wgraph, self.wrapper_name)
-        self.genc.gen_cfunction(wfuncdef)
-
-
-    def DISABLED_OLD_gen_wrapper(self, f):
-        # XXX this is a huge mess.  Think about producing the wrapper by
-        #     generating its content as a flow graph...
-        func             = self.func
-        f_name           = self.wrapper_name
-        name_of_defaults = self.name_of_defaults
-        graphargs        = self.graphargs
-        vararg           = self.vararg
-        nb_positional_args = len(graphargs) - vararg
-
-        min_number_of_args = nb_positional_args - len(name_of_defaults)
-        print >> f, 'static PyObject *'
-        print >> f, '%s(PyObject* self, PyObject* args, PyObject* kwds)' % (
-            f_name,)
-        print >> f, '{'
-        if USE_CALL_TRACE:
-            print >> f, '\tFUNCTION_HEAD(%s, %s, args, %s, __FILE__, __LINE__ - 2)' % (
-                c_string('%s(%s)' % (self.base_name, ', '.join(name_of_defaults))),
-                self.globalobject_name,
-                '(%s)' % (', '.join(map(c_string, name_of_defaults) + ['NULL']),),
-            )
-
-        kwlist = ['"%s"' % name for name in
-                      func.func_code.co_varnames[:func.func_code.co_argcount]]
-        kwlist.append('0')
-        print >> f, '\tstatic char* kwlist[] = {%s};' % (', '.join(kwlist),)
-
-        numberednames = ['o%d' % (i+1) for i in range(len(graphargs))]
-        if vararg:
-            numberednames[-1] = 'ovararg'
-        numberednames.append('oret')
-        print >> f, '\tPyObject *%s;' % (', *'.join(numberednames))
-        conversions = []
-        call_fast_args = []
-        for a, numberedname in zip(graphargs, numberednames):
-            ct = self.ctypeof(a)
-            if ct == self.genc.pyobjtype:
-                call_fast_args.append(numberedname)
-            else:
-                convert_from_obj = ct.opname_conv_from_obj  # simple conv only!
-                convertedname = numberedname.replace('o', 'a')
-                print >> f, '\t%s %s;' % (ct.typename, convertedname)
-                conversions.append('\tOP_%s(%s, %s, type_error)' % (
-                    convert_from_obj.upper(), numberedname, convertedname))
-                # XXX successfully converted objects may need to be decrefed
-                # XXX even though they are not PyObjects
-                call_fast_args.append(convertedname)
-        # return value conversion
-        ct = self.ctret
-        if ct == self.genc.pyobjtype:
-            putresultin = 'oret'
-            footer = None
-        else:
-            convert_to_obj = ct.opname_conv_to_obj  # simple conv only for now!
-            print >> f, '\t%s aret;' % (ct.typename,)
-            putresultin = 'aret'
-            footer = 'OP_%s(aret, oret, type_error)' % convert_to_obj.upper()
-        print >> f
-
-        if USE_CALL_TRACE:
-            print >> f, '\tFUNCTION_CHECK()'
-
-        # argument unpacking
-        if vararg:
-            print >> f, '\tovararg = PyTuple_GetSlice(args, %d, INT_MAX);' % (
-                nb_positional_args,)
-            print >> f, '\tif (ovararg == NULL)'
-            print >> f, '\t\tFUNCTION_RETURN(NULL)'
-            print >> f, '\targs = PyTuple_GetSlice(args, 0, %d);' % (
-                nb_positional_args,)
-            print >> f, '\tif (args == NULL) {'
-            print >> f, '\t\tERR_DECREF(ovararg)'
-            print >> f, '\t\tFUNCTION_RETURN(NULL)'
-            print >> f, '\t}'
-            tail = """{
-\t\tERR_DECREF(args)
-\t\tERR_DECREF(ovararg)
-\t\tFUNCTION_RETURN(NULL);
-\t}
-\tPy_DECREF(args);"""
-        else:
-            tail = '\n\t\tFUNCTION_RETURN(NULL)'
-        for i in range(len(name_of_defaults)):
-            print >> f, '\t%s = %s;' % (
-                numberednames[min_number_of_args+i],
-                name_of_defaults[i])
-        fmt = 'O'*min_number_of_args
-        if min_number_of_args < nb_positional_args:
-            fmt += '|' + 'O'*(nb_positional_args-min_number_of_args)
-        lst = ['args', 'kwds',
-               '"%s:%s"' % (fmt, func.__name__),
-               'kwlist',
-               ]
-        lst += ['&' + a for a in numberednames]
-        print >> f, '\tif (!PyArg_ParseTupleAndKeywords(%s))' % ', '.join(lst),
-        print >> f, tail
-
-        for line in conversions:
-            print >> f, line
-
-        if USE_CALL_TRACE:
-            call_fast_args.insert(0, 'TRACE_CALL')
-        call_fast_args = ', '.join(call_fast_args)
-        print >> f, '\t%s = %s(%s);' % (putresultin, self.fast_name,
-                                        call_fast_args)
-        if footer:
-            print >> f, '\t' + footer
-        print >> f, '\treturn oret;'
-
-        if conversions or footer:
-            print >> f, '    type_error:'
-            print >> f, '        return NULL;'
-        
-        print >> f, '}'
-        print >> f
+    def error_return_value(self):
+        T = self.typemap[self.graph.getreturnvar()]
+        return self.getvalue(ErrorValue(T))
 
     # ____________________________________________________________
 
-    def gen_cfunction(self, f, body):
-        print >> f, self.fast_function_header
-        print >> f, '{'
-
-        localnames = self.localnames
-        lengths = [len(a) for a in localnames]
-        lengths.append(9999)
-        start = 0
-        while start < len(localnames):
-            total = lengths[start] + 9
-            end = start+1
-            while total + lengths[end] < 76:
-                total += lengths[end] + 2
-                end += 1
-            print >> f, '\t' + '; '.join(localnames[start:end]) + ';'
-            start = end
-        
-        # generate an incref for each input argument
-        for a in self.graphargs:
-            print >> f, '\t' + self.cincref(a)
-
-        # print the body
-        for line in body:
-            if line.endswith(':'):
-                if line.startswith('err'):
-                    fmt = '\t%s'
-                else:
-                    fmt = '    %s\n'
-            elif line:
-                fmt = '\t%s\n'
-            else:
-                fmt = '%s\n'
-            f.write(fmt % line)
-        print >> f, '}'
-        print >> f
+    def cfunction_declarations(self):
+        # declare the local variables, excluding the function arguments
+        inputargset = {}
+        for a in self.graph.getargs():
+            inputargset[a] = True
+
+        for v in self.allvariables():
+            if v not in inputargset:
+                yield '%s;' % self.decl(v)
 
     # ____________________________________________________________
 
     def cfunction_body(self):
         graph = self.graph
 
-        blocknum = {}
-        allblocks = []
+        # generate an incref for each input argument
+        for a in self.graph.getargs():
+            yield self.cincref(a)
 
         def gen_link(link, linklocalvars=None):
             "Generate the code to jump across the given Link."
@@ -402,7 +101,7 @@
                     src = linklocalvars[a1]
                 else:
                     src = self.expr(a1)
-                line = 'MOVE(%s, %s)' % (src, self.expr(a2))
+                line = '%s = %s;' % (self.expr(a2), src)
                 if a1 in has_ref:
                     del has_ref[a1]
                 else:
@@ -416,11 +115,10 @@
             yield 'goto block%d;' % blocknum[link.target]
 
         # collect all blocks
-        def visit(block):
-            if isinstance(block, Block):
-                allblocks.append(block)
-                blocknum[block] = len(blocknum)
-        traverse(visit, graph)
+        allblocks = ordered_blocks(graph)
+        blocknum = {}
+        for block in allblocks:
+            blocknum[block] = len(blocknum)
 
         # generate the body of each block
         for block in allblocks:
@@ -437,7 +135,7 @@
                     lst = [self.expr(v) for v in op.args]
                     lst.append(self.expr(op.result))
                     lst.append(err)
-                    yield '%s(%s)' % (macro, ', '.join(lst))
+                    yield '%s(%s);' % (macro, ', '.join(lst))
                 to_release.append(op.result)
 
             err_reachable = False
@@ -447,11 +145,11 @@
                     exc_cls   = self.expr(block.inputargs[0])
                     exc_value = self.expr(block.inputargs[1])
                     yield 'PyErr_Restore(%s, %s, NULL);' % (exc_cls, exc_value)
-                    yield self.return_error
+                    yield 'return %s;' % self.error_return_value()
                 else:
                     # regular return block
                     retval = self.expr(block.inputargs[0])
-                    yield 'FUNCTION_RETURN(%s)' % retval
+                    yield 'return %s;' % retval
                 continue
             elif block.exitswitch is None:
                 # single-exit block
@@ -514,7 +212,7 @@
                 yield 'err%d_%d:' % (blocknum[block], len(to_release))
                 err_reachable = True
             if err_reachable:
-                yield self.return_error
+                yield 'return %s;' % self.error_return_value()
 
     # ____________________________________________________________
 
@@ -595,13 +293,7 @@
         return self.cdecref(op.args[0])
 
     def cincref(self, v):
-        return 'OP_INCREF_%s(%s)' % (self.ctypeof(v).typename, self.expr(v))
+        return '/*XXX INCREF*/'
 
     def cdecref(self, v, expr=None):
-        return 'OP_DECREF_%s(%s)' % (self.ctypeof(v).typename,
-                                     expr or self.expr(v))
-
-# ____________________________________________________________
-
-def dummy_wrapper(self, args, kwds):
-    pass
+        return '/*XXX DECREF*/'

Modified: pypy/dist/pypy/translator/c/node.py
==============================================================================
--- pypy/dist/pypy/translator/c/node.py	(original)
+++ pypy/dist/pypy/translator/c/node.py	Mon May 23 17:46:29 2005
@@ -1,8 +1,9 @@
 from __future__ import generators
-from pypy.translator.gensupp import C_IDENTIFIER
 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
+from pypy.translator.c.funcgen import FunctionCodeGenerator
+from pypy.translator.c.support import cdecl, somelettersfrom
 
 
 def needs_refcount(T):
@@ -13,16 +14,6 @@
             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:
 
@@ -86,6 +77,8 @@
         yield '\t%s;' % cdecl(self.structname, 'items[%d]' % self.varlength)
         yield '};'
 
+# ____________________________________________________________
+
 
 class ContainerNode:
 
@@ -111,7 +104,7 @@
                                                 self.ptrname)
 
     def forward_declaration(self):
-        yield '%s; /* forward */' % (
+        yield '%s;' % (
             cdecl(self.implementationtypename, self.name))
 
     def implementation(self):
@@ -187,54 +180,69 @@
         yield '}'
 
 
-# XXX move FuncNode to funcdef.py
-from pypy.objspace.flow.model import *
-
 class FuncNode(ContainerNode):
+    globalcontainer = True
 
     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.funcgen = FunctionCodeGenerator(graph, db.gettype, db.get)
         self.db = db
         self.T = T
         self.obj = obj
         #self.dependencies = {}
         self.typename = db.gettype(T)  #, who_asks=self)
+        argnames = self.funcgen.argnames()
         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):
-        return [c.value for c in self.allconstants()]
+        return self.funcgen.allconstantvalues()
 
     def implementation(self):
+        funcgen = self.funcgen
         yield '%s {' % cdecl(self.implementationtypename, self.name)
-        yield '\tlots-of-strange-code'
+        #
+        # declare the local variables
+        #
+        localnames = list(funcgen.cfunction_declarations())
+        lengths = [len(a) for a in localnames]
+        lengths.append(9999)
+        start = 0
+        while start < len(localnames):
+            # pack the local declarations over a few lines as possible
+            total = lengths[start] + 8
+            end = start+1
+            while total + lengths[end] < 77:
+                total += lengths[end] + 1
+                end += 1
+            yield '\t' + ' '.join(localnames[start:end])
+            start = end
+        #
+        # generate the body itself
+        #
+        lineprefix = ''
+        for line in funcgen.cfunction_body():
+            # performs some formatting on the generated body:
+            # indent normal lines with tabs; indent labels less than the rest
+            if line.endswith(':'):
+                if line.startswith('err'):
+                    lineprefix += '\t' + line
+                    continue  # merge this 'err:' label with the following line
+                else:
+                    fmt = '%s    %s'
+            elif line:
+                fmt = '%s\t%s'
+            else:
+                fmt = '%s%s'
+            yield fmt % (lineprefix, line)
+            lineprefix = ''
+
+        if lineprefix:         # unlikely
+            yield lineprefix
         yield '}'
 
 
@@ -250,16 +258,3 @@
     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/primitive.py
==============================================================================
--- pypy/dist/pypy/translator/c/primitive.py	(original)
+++ pypy/dist/pypy/translator/c/primitive.py	Mon May 23 17:46:29 2005
@@ -40,3 +40,11 @@
     Bool:     'char @',
     Void:     'void @',
     }
+
+PrimitiveErrorValue = {
+    Signed:   '-1',
+    Unsigned: '((unsigned) -1)',
+    Char:     '((char) -1)',
+    Bool:     '((char) -1)',
+    Void:     '/* error */',
+    }

Added: pypy/dist/pypy/translator/c/support.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/c/support.py	Mon May 23 17:46:29 2005
@@ -0,0 +1,47 @@
+from pypy.translator.gensupp import NameManager
+
+class ErrorValue:
+    def __init__(self, TYPE):
+        self.TYPE = TYPE
+
+
+#
+# helpers
+#
+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()
+
+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 CNameManager(NameManager):
+    def __init__(self):
+        NameManager.__init__(self)
+        # keywords cannot be reused.  This is the C99 draft's list.
+        self.make_reserved_names('''
+           auto      enum      restrict  unsigned
+           break     extern    return    void
+           case      float     short     volatile
+           char      for       signed    while
+           const     goto      sizeof    _Bool
+           continue  if        static    _Complex
+           default   inline    struct    _Imaginary
+           do        int       switch
+           double    long      typedef
+           else      register  union
+           ''')



More information about the Pypy-commit mailing list