[pypy-svn] r24971 - in pypy/dist/pypy: annotation interpreter interpreter/test

pedronis at codespeak.net pedronis at codespeak.net
Fri Mar 24 17:33:21 CET 2006


Author: pedronis
Date: Fri Mar 24 17:33:14 2006
New Revision: 24971

Added:
   pypy/dist/pypy/interpreter/test/test_argument.py   (contents, props changed)
Modified:
   pypy/dist/pypy/annotation/annrpython.py
   pypy/dist/pypy/annotation/bookkeeper.py
   pypy/dist/pypy/annotation/description.py
   pypy/dist/pypy/interpreter/argument.py
Log:
(arre, pedronis)

the logic in FunctionDesc.pycall may have discared changes to inputcells done by specialisation
when reparsing the args object. Reconstruct a new args object out of the possibly changed inputcells
instead. Introduced an unmatch_signature helper for this with some tests.



Modified: pypy/dist/pypy/annotation/annrpython.py
==============================================================================
--- pypy/dist/pypy/annotation/annrpython.py	(original)
+++ pypy/dist/pypy/annotation/annrpython.py	Fri Mar 24 17:33:14 2006
@@ -95,6 +95,7 @@
         return self.build_graph_types(flowgraph, inputcells)
 
     def annotate_helper(self, function, args_s, policy=None, complete_now=True):
+        args_s = args_s[:]
         saved = self.policy, self.added_blocks
         if policy is None:
             from pypy.annotation.policy import AnnotatorPolicy

Modified: pypy/dist/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/annotation/bookkeeper.py	(original)
+++ pypy/dist/pypy/annotation/bookkeeper.py	Fri Mar 24 17:33:14 2006
@@ -673,7 +673,10 @@
 
     def type(self, item):
         return type(item)
-    
+
+    def is_true(self, s_tup):
+        assert isinstance(s_tup, SomeTuple)
+        return bool(s_tup.items)
 
 class CallPatternTooComplex(Exception):
     pass

Modified: pypy/dist/pypy/annotation/description.py
==============================================================================
--- pypy/dist/pypy/annotation/description.py	(original)
+++ pypy/dist/pypy/annotation/description.py	Fri Mar 24 17:33:14 2006
@@ -222,8 +222,10 @@
         if isinstance(result, FunctionGraph):
             graph = result         # common case
             # if that graph has a different signature, we need to re-parse
-            # the arguments
-            inputcells = self.parse_arguments(args, graph)
+            # the arguments.
+            # recreate the args object because inputcells may have been changed
+            new_args = args.unmatch_signature(self.signature, inputcells)
+            inputcells = self.parse_arguments(new_args, graph)
             result = schedule(graph, inputcells)
         # Some specializations may break the invariant of returning
         # annotations that are always more general than the previous time.

Modified: pypy/dist/pypy/interpreter/argument.py
==============================================================================
--- pypy/dist/pypy/interpreter/argument.py	(original)
+++ pypy/dist/pypy/interpreter/argument.py	Fri Mar 24 17:33:14 2006
@@ -82,6 +82,49 @@
         self._match_signature(scope_w, argnames, has_vararg, has_kwarg, defaults_w, 0, None)
         return scope_w
 
+    def unmatch_signature(self, signature, data_w):
+        """kind of inverse of match_signature"""
+        args_w, kwds_w = self.unpack()
+        need_cnt = len(args_w)
+        need_kwds = kwds_w.keys()
+        space = self.space
+        argnames, varargname, kwargname = signature
+        cnt = len(argnames)
+        data_args_w = data_w[:cnt]
+        if varargname:
+            data_w_stararg = data_w[cnt]
+            cnt += 1
+        else:
+            data_w_stararg = space.newtuple([])
+
+        unfiltered_kwds_w = {}
+        if kwargname:
+            data_w_starargarg = data_w[cnt]
+            for w_key in space.unpackiterable(data_w_starargarg):
+                key = space.str_w(w_key)
+                w_value = space.getitem(data_w_starargarg, w_key)
+                unfiltered_kwds_w[key] = w_value            
+            cnt += 1
+        assert len(data_w) == cnt
+        
+        ndata_args_w = len(data_args_w)
+        if ndata_args_w >= need_cnt:
+            args_w = data_args_w[:need_cnt]
+            for argname, w_arg in zip(argnames[need_cnt:], data_args_w[need_cnt:]):
+                unfiltered_kwds_w[argname] = w_arg
+            assert not space.is_true(data_w_stararg)
+        else:
+            args_w = data_args_w[:]
+            for w_stararg in space.unpackiterable(data_w_stararg):
+                args_w.append(w_stararg)
+            assert len(args_w) == need_cnt
+            
+        kwds_w = {}
+        for key in need_kwds:
+            kwds_w[key] = unfiltered_kwds_w[key]
+                    
+        return Arguments(self.space, args_w, kwds_w)
+
     def normalize(self):
         """Return an instance of the Arguments class.  (Instances of other
         classes may not be suitable for long-term storage or multiple

Added: pypy/dist/pypy/interpreter/test/test_argument.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/interpreter/test/test_argument.py	Fri Mar 24 17:33:14 2006
@@ -0,0 +1,92 @@
+from pypy.interpreter.argument import Arguments
+
+
+class DummySpace(object):
+    def newtuple(self, items):
+        return tuple(items)
+
+    def is_true(self, obj):
+        return bool(obj)
+
+    def unpackiterable(self, it):
+        return list(it)
+
+    def newdict(self, items):
+        return dict(items)
+
+    def setitem(self, obj, key, value):
+        obj[key] = value
+
+    def getitem(self, obj, key):
+        return obj[key]
+
+    def wrap(self, obj):
+        return obj
+
+    def str_w(self, s):
+        return str(s)
+
+    def isinstance(self, obj, cls):
+        return isinstance(obj, cls)
+
+    w_dict = dict
+
+class TestArguments(object):
+
+
+    def test_unmatch_signature(self):
+        space = DummySpace()
+        args = Arguments(space, [1,2,3])
+        sig = (['a', 'b', 'c'], None, None)
+        data = args.match_signature(sig, [])
+        new_args = args.unmatch_signature(sig, data)
+        assert args.unpack() == new_args.unpack()
+
+        args = Arguments(space, [1])
+        sig = (['a', 'b', 'c'], None, None)
+        data = args.match_signature(sig, [2, 3])
+        new_args = args.unmatch_signature(sig, data)
+        assert args.unpack() == new_args.unpack()
+
+        args = Arguments(space, [1,2,3,4,5])
+        sig = (['a', 'b', 'c'], 'r', None)
+        data = args.match_signature(sig, [])
+        new_args = args.unmatch_signature(sig, data)
+        assert args.unpack() == new_args.unpack()
+
+        args = Arguments(space, [1], {'c': 3, 'b': 2})
+        sig = (['a', 'b', 'c'], None, None)
+        data = args.match_signature(sig, [])
+        new_args = args.unmatch_signature(sig, data)
+        assert args.unpack() == new_args.unpack()
+
+        args = Arguments(space, [1], {'c': 5})
+        sig = (['a', 'b', 'c'], None, None)
+        data = args.match_signature(sig, [2, 3])
+        new_args = args.unmatch_signature(sig, data)
+        assert args.unpack() == new_args.unpack()
+
+        args = Arguments(space, [1], {'c': 5, 'd': 7})
+        sig = (['a', 'b', 'c'], None, 'kw')
+        data = args.match_signature(sig, [2, 3])
+        new_args = args.unmatch_signature(sig, data)
+        assert args.unpack() == new_args.unpack()
+
+        args = Arguments(space, [1,2,3,4,5], {'e': 5, 'd': 7})
+        sig = (['a', 'b', 'c'], 'r', 'kw')
+        data = args.match_signature(sig, [2, 3])
+        new_args = args.unmatch_signature(sig, data)
+        assert args.unpack() == new_args.unpack()
+
+        args = Arguments(space, [], {}, w_stararg=[1], w_starstararg={'c': 5, 'd': 7})
+        sig = (['a', 'b', 'c'], None, 'kw')
+        data = args.match_signature(sig, [2, 3])
+        new_args = args.unmatch_signature(sig, data)
+        assert args.unpack() == new_args.unpack()
+
+        args = Arguments(space, [1,2], {'g': 9}, w_stararg=[3,4,5], w_starstararg={'e': 5, 'd': 7})
+        sig = (['a', 'b', 'c'], 'r', 'kw')
+        data = args.match_signature(sig, [2, 3])
+        new_args = args.unmatch_signature(sig, data)
+        assert args.unpack() == new_args.unpack()
+



More information about the Pypy-commit mailing list