Commits

Amaury Forgeot d'Arc committed 0389993

Expose the constructor directly.
Next step: access to struct members

Comments (0)

Files changed (2)

pypy/translator/c/separate.py

 from pypy.annotation import model, description
 from pypy.tool.sourcetools import func_with_new_name
 from pypy.rlib.unroll import unrolling_iterable
+from pypy.rlib.objectmodel import instantiate
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rpython.typesystem import getfunctionptr
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rpython.extregistry import ExtRegistryEntry
+import py
+import types
 
-import types
+def make_wrapper_for_constructor(cls, name):
+    nbargs = len(cls.__init__.argtypes)
+    args = ', '.join(['arg%d' % d for d in range(nbargs)])
+
+    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 annotate_exported_functions(annotator, exports):
     bk = annotator.bookkeeper
 
-    # annotate functions with signatures
-    for funcname, func in exports.items():
-        if hasattr(func, 'argtypes'):
-            annotator.build_types(func, func.argtypes,
-                                  complete_now=False)
     # annotate classes
-    for funcname, cls in exports.items():
+    for clsname, cls in exports.items():
         if not isinstance(cls, (type, types.ClassType)):
             continue
         desc = bk.getdesc(cls)
         if isinstance(s_init, model.SomeImpossibleValue):
             continue
 
-        argtypes = (model.SomeInstance(classdef),)
-        argtypes += tuple(cls.__init__.argtypes)
-        annotator.build_types(cls.__init__.im_func, argtypes,
+        wrapper = make_wrapper_for_constructor(cls, clsname)
+        exports[clsname] = wrapper
+
+        annotator.build_types(wrapper, cls.__init__.argtypes,
                               complete_now=False)
 
+    # annotate functions with signatures
+    for funcname, func in exports.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
     bk = annotator.bookkeeper
 
     exported_funcptr = {}
-    for funcname, func in exports.items():
-        desc = bk.getdesc(func)
-        if not isinstance(desc, description.FunctionDesc):
+    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
-        graph = desc.getuniquegraph()
-        funcptr = getfunctionptr(graph)
 
-        exported_funcptr[funcname] = funcptr
+        exported_funcptr[itemname] = funcptr
     return exported_funcptr
 
 def make_import_module(builder):

pypy/translator/c/test/test_separate.py

 import sys, os
 
 class TestSeparation:
+    def setup_method(self, method):
+        class S:
+            @export(float)
+            def __init__(self, x):
+                self.x = x
+
+        # functions exported from the 'first' module
+        @export(float)
+        def newS(x):
+            return S(x)
+
+        @export(S, S, int)
+        def f2S(s, t, v):
+            return s.x + t.x + v
+
+        self.S = S
+        self.newS = newS
+        self.f2S = f2S
+
     def compile_function(self, func, argtypes):
         t = TranslationContext()
         t.buildannotator().build_types(func, argtypes)
         assert c_fn() == 42.5
 
     def test_pass_structure(self):
-        class S:
-            @export(float)
-            def __init__(self, x):
-                self.x = x
-
-        # function exported from the 'first' module
-        @export(S, S, int)
-        def f(s, t, v):
-            return s.x + t.x + v
-        firstmodule = self.compile_separated("first", f=f, S=S)
+        firstmodule = self.compile_separated("first", f=self.f2S, S=self.S)
+        S = self.S
 
         # call it from a function compiled in another module
         @export()
         assert c_fn() == 73.5
 
     def test_create_structure(self):
-        class S:
-            @export(float)
-            def __init__(self, x):
-                self.x = x
-
-        # functions exported from the 'first' module
-        @export(float)
-        def newS(x):
-            return S(x)
-
-        @export(S)
-        def f(s):
-            return s.x + 1.5
-        firstmodule = self.compile_separated("first", newS=newS, f=f)
+        firstmodule = self.compile_separated(
+            "first", newS=self.newS, S=self.S, f=self.f2S)
 
         # call them from a function compiled in another module
         @export()
         def g():
             s = firstmodule.newS(41.0)
-            return firstmodule.f(s)
+            t = firstmodule.S(25.5)
+            return firstmodule.f(s, t, 7)
         secondmodule = self.compile_separated("second", g=g)
 
         def fn():
             filepath = os.path.dirname(firstmodule.__file__)
             os.environ['PATH'] = "%s;%s" % (filepath, os.environ['PATH'])
 
-        assert fn() == 42.5
+        assert fn() == 73.5
         c_fn = self.compile_function(fn, [])
-        assert c_fn() == 42.5
+        assert c_fn() == 73.5
 
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.