Amaury Forgeot d'Arc avatar Amaury Forgeot d'Arc committed 26f5a87

Refactor a bit

Comments (0)

Files changed (3)

pypy/translator/c/genc.py

         return None
 
     def getexportsymbols(self):
-        self.export_node_names = dict(
-            (funcname, self.db.get(funcptr))
-            for funcname, funcptr in self.entrypoint.items())
         return self.export_node_names.values() + ['RPython_StartupCode']
 
     def compile(self):

pypy/translator/c/separate.py

 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rpython.extregistry import ExtRegistryEntry
 import py
-import types
 
-def make_wrapper_for_constructor(cls, name):
-    nbargs = len(cls.__init__.argtypes)
-    args = ', '.join(['arg%d' % d for d in range(nbargs)])
+class ExportTable(object):
+    """A table with information about the exported symbols of a module
+    compiled by pypy."""
 
-    source = py.code.Source(r"""
-        def wrapper(%s):
-            obj = instantiate(cls)
-            obj.__init__(%s)
-            return obj
-        """ % (args, args))
-    miniglobals = {'cls': cls, 'instantiate': instantiate}
-    exec source.compile() in miniglobals
-    wrapper = miniglobals['wrapper']
-    wrapper._annspecialcase_ = 'specialize:ll'
-    wrapper._always_inline_ = True
-    return func_with_new_name(wrapper, name)
+    def __init__(self):
+        self.exported_function = {}
+        self.exported_class = {}
 
-def annotate_exported_functions(annotator, exports):
-    bk = annotator.bookkeeper
+    def make_wrapper_for_constructor(self, cls, name):
+        nbargs = len(cls.__init__.argtypes)
+        args = ', '.join(['arg%d' % d for d in range(nbargs)])
 
-    # annotate classes
-    for clsname, cls in exports.items():
-        if not isinstance(cls, (type, types.ClassType)):
-            continue
-        desc = bk.getdesc(cls)
-        classdef = desc.getuniqueclassdef()
-        s_init = desc.s_read_attribute('__init__')
-        if isinstance(s_init, model.SomeImpossibleValue):
-            continue
+        source = py.code.Source(r"""
+            def wrapper(%s):
+                obj = instantiate(cls)
+                obj.__init__(%s)
+                return obj
+            """ % (args, args))
+        miniglobals = {'cls': cls, 'instantiate': instantiate}
+        exec source.compile() in miniglobals
+        wrapper = miniglobals['wrapper']
+        wrapper._annspecialcase_ = 'specialize:ll'
+        wrapper._always_inline_ = True
+        return func_with_new_name(wrapper, name)
 
-        wrapper = make_wrapper_for_constructor(cls, clsname)
-        exports[clsname] = wrapper
+    def annotate_exported_functions(self, annotator):
+        bk = annotator.bookkeeper
 
-        annotator.build_types(wrapper, cls.__init__.argtypes,
-                              complete_now=False)
+        # annotate classes
+        for clsname, cls in self.exported_class.items():
+            desc = bk.getdesc(cls)
+            classdef = desc.getuniqueclassdef()
+            s_init = desc.s_read_attribute('__init__')
+            if isinstance(s_init, model.SomeImpossibleValue):
+                continue
 
-    # annotate functions with signatures
-    for funcname, func in exports.items():
-        if hasattr(func, 'argtypes'):
-            annotator.build_types(func, func.argtypes,
+            # Replace class with its constructor
+            wrapper = self.make_wrapper_for_constructor(cls, clsname)
+            self.exported_function[clsname] = wrapper
+
+            annotator.build_types(wrapper, cls.__init__.argtypes,
                                   complete_now=False)
-    annotator.complete()
 
-    # ensure that functions without signature are not constant-folded
-    for funcname, func in exports.items():
-        if not hasattr(func, 'argtypes'):
-            # build a list of arguments where constants are erased
-            newargs = []
-            desc = bk.getdesc(func)
+        # annotate functions with signatures
+        for funcname, func in self.exported_function.items():
+            if hasattr(func, 'argtypes'):
+                annotator.build_types(func, func.argtypes,
+                                      complete_now=False)
+        annotator.complete()
+
+        # ensure that functions without signature are not constant-folded
+        for funcname, func in self.exported_function.items():
+            if not hasattr(func, 'argtypes'):
+                # build a list of arguments where constants are erased
+                newargs = []
+                desc = bk.getdesc(func)
+                if isinstance(desc, description.FunctionDesc):
+                    graph = desc.getuniquegraph()
+                    for arg in graph.startblock.inputargs:
+                        newarg = model.not_const(annotator.binding(arg))
+                        newargs.append(newarg)
+                    # and reflow
+                    annotator.build_types(func, newargs)
+
+    def get_exported_functions(self, annotator):
+        bk = annotator.bookkeeper
+
+        exported_funcptr = {}
+        for itemname, item in self.exported_function.items():
+            desc = bk.getdesc(item)
             if isinstance(desc, description.FunctionDesc):
                 graph = desc.getuniquegraph()
-                for arg in graph.startblock.inputargs:
-                    newarg = model.not_const(annotator.binding(arg))
-                    newargs.append(newarg)
-                # and reflow
-                annotator.build_types(func, newargs)
+                funcptr = getfunctionptr(graph)
+            elif isinstance(desc, description.ClassDesc):
+                continue
 
-def get_exported_functions(annotator, exports):
-    bk = annotator.bookkeeper
+            exported_funcptr[itemname] = funcptr
+        return exported_funcptr
 
-    exported_funcptr = {}
-    for itemname, item in exports.items():
-        desc = bk.getdesc(item)
-        if isinstance(desc, description.FunctionDesc):
-            graph = desc.getuniquegraph()
-            funcptr = getfunctionptr(graph)
-        elif isinstance(desc, description.ClassDesc):
-            continue
+    def make_import_module(self, builder, node_names):
+        class Module:
+            pass
+        mod = Module()
+        mod.__file__ = builder.so_name
 
-        exported_funcptr[itemname] = funcptr
-    return exported_funcptr
+        forwards = []
+        for node in builder.db.globalcontainers():
+            if node.nodekind == 'func' and node.name in node_names.values():
+                forwards.append('\n'.join(node.forward_declaration()))
 
-def make_import_module(builder):
-    class Module:
-        pass
-    mod = Module()
-    mod.__file__ = builder.so_name
+        import_eci = ExternalCompilationInfo(
+            libraries = [builder.so_name],
+            post_include_bits = forwards
+            )
 
-    forwards = []
-    node_names = builder.export_node_names.values()
-    for node in builder.db.globalcontainers():
-        if node.nodekind == 'func' and node.name in node_names:
-            forwards.append('\n'.join(node.forward_declaration()))
-
-    import_eci = ExternalCompilationInfo(
-        libraries = [builder.so_name],
-        post_include_bits = forwards
-        )
-
-    for funcname, import_name in builder.export_node_names.items():
-        functype = lltype.typeOf(builder.entrypoint[funcname])
-        func = make_ll_import_function(import_name, functype, import_eci)
-        setattr(mod, funcname, func)
-    return mod
+        for funcname, import_name in builder.export_node_names.items():
+            functype = lltype.typeOf(builder.entrypoint[funcname])
+            func = make_ll_import_function(import_name, functype, import_eci)
+            setattr(mod, funcname, func)
+        return mod
 
 def make_ll_import_arg_converter(TARGET):
     from pypy.annotation import model

pypy/translator/c/test/test_separate.py

 from pypy.translator.c import separate
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 import py
-import sys, os
+import sys, os, types
 
 class TestSeparation:
     def setup_method(self, method):
         t = TranslationContext()
         t.buildannotator()
 
-        separate.annotate_exported_functions(t.annotator, exports)
+        table = separate.ExportTable()
+        for name, obj in exports.items():
+            if isinstance(obj, (type, types.ClassType)):
+                table.exported_class[name] = obj
+            else:
+                table.exported_function[name] = obj
+        table.annotate_exported_functions(t.annotator)
 
         t.buildrtyper().specialize()
 
-        exported_funcptr = separate.get_exported_functions(t.annotator, exports)
+        exported_funcptr = table.get_exported_functions(t.annotator)
 
         builder = CLibraryBuilder(t, exported_funcptr, config=t.config)
         builder.generate_source()
+        node_names = dict(
+            (funcname, builder.db.get(funcptr))
+            for funcname, funcptr in builder.entrypoint.items())
         builder.compile()
 
-        mod = separate.make_import_module(builder)
+        mod = table.make_import_module(builder, node_names)
 
         if sys.platform == 'win32':
             filepath = os.path.dirname(builder.so_name)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.