Commits

Maciej Fijalkowski committed fa194dc

Remove an obscure feature that's more than a bit broken by design, the ability
to relax the check of signatures. Rationale is that if we have a non-standard
graph, we should really not be able to store it anywhere. Replace a bit of
unroll iterable magic with code concatanetion - ugly but works and it's
actually more understandable (IMO)

  • Participants
  • Parent commits bcf984f

Comments (0)

Files changed (5)

pypy/module/cpyext/api.py

 def make_wrapper(space, callable):
     "NOT_RPYTHON"
     names = callable.api_func.argnames
-    argtypes_enum_ui = unrolling_iterable(enumerate(zip(callable.api_func.argtypes,
-        [name.startswith("w_") for name in names])))
+    argtypes = callable.api_func.argtypes
+    is_wrapped_list = [name.startswith("w_") for name in names]
     fatal_value = callable.api_func.restype._defl()
 
-    def wrapper(*args):
+    lines = []
+    for i, (argtype, is_wrapped) in enumerate(zip(argtypes, is_wrapped_list)):
+        if is_PyObject(argtype) and is_wrapped:
+            new_lines = [
+                'if %(arg)s:',
+                '    %(arg)s = from_ref(space, rffi.cast(PyObject, %(arg)s))',
+                'else:',
+                '    %(arg)s = None',
+            ]
+            for j in range(len(new_lines)):
+                new_lines[j] = new_lines[j] % {'arg': 'arg%d' % i}
+            lines += new_lines
+    middle = '\n            '.join(lines)
+    arg_spec = ", ".join(["arg%d" % i for i in range(len(argtypes))])
+
+    source = py.code.Source("""
+    def wrapper(%(args)s):
         from pypy.module.cpyext.pyobject import make_ref, from_ref
         from pypy.module.cpyext.pyobject import Reference
         retval = fatal_value
         try:
             if not we_are_translated() and DEBUG_WRAPPER:
                 print >>sys.stderr, callable,
-            assert len(args) == len(callable.api_func.argtypes)
-            for i, (typ, is_wrapped) in argtypes_enum_ui:
-                arg = args[i]
-                if is_PyObject(typ) and is_wrapped:
-                    if arg:
-                        arg_conv = from_ref(space, rffi.cast(PyObject, arg))
-                    else:
-                        arg_conv = None
-                else:
-                    arg_conv = arg
-                boxed_args += (arg_conv, )
             state = space.fromcache(State)
+            %(middle)s
             try:
-                result = callable(space, *boxed_args)
+                result = callable(space, %(args)s)
                 if not we_are_translated() and DEBUG_WRAPPER:
                     print >>sys.stderr, " DONE"
             except OperationError, e:
             if failed:
                 error_value = callable.api_func.error_value
                 if error_value is CANNOT_FAIL:
-                    raise SystemError("The function '%s' was not supposed to fail"
-                                      % (callable.__name__,))
+                    raise SystemError("The function '%%s' was not supposed to fail"
+                                      %% (callable.__name__,))
                 retval = error_value
 
             elif is_PyObject(callable.api_func.restype):
                 print str(e)
                 pypy_debug_catch_fatal_exception()
         return retval
+    """ % {"middle": middle, "args": arg_spec})
+    d = {}
+    d.update(locals())
+    d.update(globals())
+    exec source.compile() in d
+    wrapper = d['wrapper']
     callable._always_inline_ = 'try'
     wrapper.__name__ = "wrapper for %r" % (callable, )
     return wrapper
         export_struct(name, struct)
 
     for name, func in FUNCTIONS.iteritems():
-        deco = entrypoint("cpyext", func.argtypes, name, relax=True)
+        deco = entrypoint("cpyext", func.argtypes, name)
         deco(func.get_wrapper(space))
 
     setup_init_functions(eci, translating=True)

rpython/annotator/description.py

         if len(self._cache) != 1:
             raise NoStandardGraph(self)
         [graph] = self._cache.values()
-        relax_sig_check = getattr(self.pyobj, "relax_sig_check", False)
         if (graph.signature != self.signature or
-            graph.defaults  != self.defaults) and not relax_sig_check:
+            graph.defaults  != self.defaults):
             raise NoStandardGraph(self)
         return graph
 

rpython/annotator/test/test_annrpython.py

         s = a.build_types(f, [int])
         assert s.knowntype is int
 
-    def test_relax(self):
-        def f(*args):
-            return args[0] + args[1]
-        f.relax_sig_check = True
-        def g(x):
-            return f(x, x - x)
-        a = self.RPythonAnnotator()
-        s = a.build_types(g, [int])
-        assert a.bookkeeper.getdesc(f).getuniquegraph()
-
     def test_cannot_raise_ll_exception(self):
         from rpython.rtyper.annlowlevel import cast_instance_to_base_ptr
         #

rpython/rlib/entrypoint.py

 
 pypy_debug_catch_fatal_exception = rffi.llexternal('pypy_debug_catch_fatal_exception', [], lltype.Void)
 
-def entrypoint(key, argtypes, c_name=None, relax=False):
+def entrypoint(key, argtypes, c_name=None):
     """ Note: entrypoint should call llop.gc_stack_bottom on it's own.
     That's necessary for making it work with asmgcc and hence JIT
 
         wrapper.func_name = func.func_name
         if c_name is not None:
             wrapper.c_name = c_name
-        if relax:
-            wrapper.relax_sig_check = True
         wrapper._compilation_info = ExternalCompilationInfo(
             export_symbols=[c_name or func.func_name])
         return wrapper

rpython/translator/c/test/test_genc.py

             f = getattr(self, "_f", None)
             if f is not None:
                 return f
-            f = lambda *args: self.func(*args)
+            f = lambda arg: self.func(arg)
             f.c_name = self.name
-            f.relax_sig_check = True
             f.__name__ = "WRAP%s" % (self.name, )
             self._f = f
             return f