[pypy-svn] r7796 - in pypy/trunk/src/pypy: annotation interpreter translator

arigo at codespeak.net arigo at codespeak.net
Thu Dec 9 22:40:56 CET 2004


Author: arigo
Date: Thu Dec  9 22:40:56 2004
New Revision: 7796

Modified:
   pypy/trunk/src/pypy/annotation/unaryop.py
   pypy/trunk/src/pypy/interpreter/argument.py
   pypy/trunk/src/pypy/translator/annrpython.py
Log:
In class Arguments, split method parse() in two: the outer parse() with the
same semantics now calls an inner match_signature() which makes little use of
self.space and raises ArgErr exceptions, which parse() turns into
OperationErrors with complete error messages.

Allows some clean-up of the RPythonCallsSpace hack and reintroduction of the
hack in annrpython which allows mismatching calls to be ignored (with a
warning message).



Modified: pypy/trunk/src/pypy/annotation/unaryop.py
==============================================================================
--- pypy/trunk/src/pypy/annotation/unaryop.py	(original)
+++ pypy/trunk/src/pypy/annotation/unaryop.py	Thu Dec  9 22:40:56 2004
@@ -65,11 +65,11 @@
         return obj   # default unbound __get__ implementation
 
     def simple_call(obj, *args_s):
-        space = RPythonCallsSpace(getbookkeeper())
+        space = RPythonCallsSpace()
         return obj.call(Arguments(space, args_s))
 
     def call_args(obj, s_shape, *args_s):
-        space = RPythonCallsSpace(getbookkeeper())
+        space = RPythonCallsSpace()
         return obj.call(Arguments.fromshape(space, s_shape.const, args_s))
 
     def call(obj, args):
@@ -240,14 +240,11 @@
     For the Arguments class: if it really needs other operations, it means
     that the call pattern is too complex for R-Python.
     """
-    def __init__(self, bookkeeper):
-        self.bookkeeper = bookkeeper
-
     def newtuple(self, items_s):
         return SomeTuple(items_s)
 
     def newdict(self, stuff):
-        raise Exception, "call pattern too complicated (** argument)"
+        raise CallPatternTooComplex, "'**' argument"
 
     def unpackiterable(self, s_obj, expected_length=None):
         if isinstance(s_obj, SomeTuple):
@@ -255,14 +252,7 @@
                 expected_length != len(s_obj.items)):
                 raise ValueError
             return s_obj.items
-        raise Exception, "RPythonCallsSpace.unpackiterable(): only for tuples"
+        raise CallPatternTooComplex, "'*' argument must be SomeTuple"
 
-    # XXX the following is only a hack to lead Arguments.parse() believe
-    # XXX that the *arg is always a tuple!
-    w_tuple = object()
-    def type(self, w_obj):
-        return self.w_tuple
-    def is_(self, w1, w2):
-        return w1 is w2
-    def is_true(self, x):
-        return bool(x)
+class CallPatternTooComplex(Exception):
+    pass

Modified: pypy/trunk/src/pypy/interpreter/argument.py
==============================================================================
--- pypy/trunk/src/pypy/interpreter/argument.py	(original)
+++ pypy/trunk/src/pypy/interpreter/argument.py	Thu Dec  9 22:40:56 2004
@@ -110,6 +110,23 @@
         according to the signature of code object.
         """
         space = self.space
+        # If w_stararg is not exactly a tuple, unpack it now:
+        # self.match_signature() assumes that it can use it directly for
+        # a matching *arg in the callee's signature.
+        if self.w_stararg is not None:
+            if not space.is_true(space.is_(space.type(self.w_stararg),
+                                           space.w_tuple)):
+                self.unpack()
+        try:
+            return self.match_signature(signature, defaults_w)
+        except ArgErr, e:
+            raise OperationError(space.w_TypeError,
+                                 space.wrap(e.getmsg(self, fnname)))
+
+    def match_signature(self, signature, defaults_w=[]):
+        """Parse args and kwargs according to the signature of a code object,
+        or raise ArgumentMatch in case of failure.
+        """
         argnames, varargname, kwargname = signature
         #
         #   args_w = list of the normal actual parameters, wrapped
@@ -117,16 +134,11 @@
         #   argnames = list of formal parameter names
         #   scope_w = resulting list of wrapped values
         #
-        # We try to give error messages following CPython's, which are
-        # very informative.
-        #
         co_argcount = len(argnames) # expected formal arguments, without */**
         if self.w_stararg is not None:
             # There is a case where we don't have to unpack() a w_stararg:
             # if it matches exactly a *arg in the signature.
-            if (len(self.arguments_w) == co_argcount and varargname is not None
-                and space.is_true(space.is_(space.type(self.w_stararg),
-                                            space.w_tuple))):
+            if len(self.arguments_w) == co_argcount and varargname is not None:
                 pass
             else:
                 self.unpack()   # sets self.w_stararg to None
@@ -144,7 +156,7 @@
         if kwds_w:
             for name in argnames[self.blind_arguments:input_argcount]:
                 if name in kwds_w:
-                    self.raise_argerr_multiple_values(fnname, name)
+                    raise ArgErrMultipleValues(name)
 
         remainingkwds_w = kwds_w.copy()
         if input_argcount < co_argcount:
@@ -158,31 +170,64 @@
                 elif i >= def_first:
                     scope_w.append(defaults_w[i-def_first])
                 else:
-                    self.raise_argerr(fnname, signature, defaults_w, False)
+                    raise ArgErrCount(signature, defaults_w, False)
                     
         # collect extra positional arguments into the *vararg
         if varargname is not None:
             if self.w_stararg is None:   # common case
-                scope_w.append(space.newtuple(args_w[co_argcount:]))
+                scope_w.append(self.space.newtuple(args_w[co_argcount:]))
             else:      # shortcut for the non-unpack() case above
                 scope_w.append(self.w_stararg)
         elif len(args_w) > co_argcount:
-            self.raise_argerr(fnname, signature, defaults_w, True)
+            raise ArgErrCount(signature, defaults_w, True)
 
         # collect extra keyword arguments into the **kwarg
         if kwargname is not None:
-            w_kwds = space.newdict([(space.wrap(key), w_value)
-                                    for key, w_value in remainingkwds_w.items()])
+            w_kwds = self.space.newdict([])
+            for key, w_value in remainingkwds_w.items():
+                self.space.setitem(w_kwds, self.space.wrap(key), w_value)
             scope_w.append(w_kwds)
         elif remainingkwds_w:
-            self.raise_argerr_unknown_kwds(fnname, remainingkwds_w)
+            raise ArgErrUnknownKwds(remainingkwds_w)
         return scope_w
 
-    # helper functions to build error message for the above
+    ### Argument <-> list of w_objects together with "shape" information
+
+    def flatten(self):
+        shape_cnt  = len(self.arguments_w)        # Number of positional args
+        shape_keys = self.kwds_w.keys()           # List of keywords (strings)
+        shape_star = self.w_stararg is not None   # Flag: presence of *arg
+        data_w = self.arguments_w + [self.kwds_w[key] for key in shape_keys]
+        if shape_star:
+            data_w.append(self.w_stararg)
+        return (shape_cnt, tuple(shape_keys), shape_star), data_w
+
+    def fromshape(space, (shape_cnt, shape_keys, shape_star), data_w):
+        args_w = data_w[:shape_cnt]
+        kwds_w = {}
+        for i in range(len(shape_keys)):
+            kwds_w[shape_keys[i]] = data_w[shape_cnt+i]
+        if shape_star:
+            w_star = data_w[-1]
+        else:
+            w_star = None
+        return Arguments(space, args_w, kwds_w, w_star)
+    fromshape = staticmethod(fromshape)
 
-    def raise_argerr(self, fnname, signature, defaults_w, too_many):
+
+#
+# ArgErr family of exceptions raised in case of argument mismatch.
+# We try to give error messages following CPython's, which are very informative.
+#
+
+class ArgErr(Exception):
+    pass
+
+class ArgErrCount(ArgErr):
+    def getmsg(self, args, fnname):
+        signature, defaults_w, too_many = self.args   # from self.__init__()
         argnames, varargname, kwargname = signature
-        args_w, kwds_w = self.unpack()
+        args_w, kwds_w = args.unpack()
         nargs = len(args_w)
         n = len(argnames)
         if n == 0:
@@ -219,15 +264,19 @@
                 msg2,
                 plural,
                 nargs)
-        raise OperationError(self.space.w_TypeError, self.space.wrap(msg))
+        return msg
 
-    def raise_argerr_multiple_values(self, fnname, argname):
+class ArgErrMultipleValues(ArgErr):
+    def getmsg(self, args, fnname):
+        argname, = self.args   # from self.__init__()
         msg = "%s() got multiple values for keyword argument '%s'" % (
             fnname,
             argname)
-        raise OperationError(self.space.w_TypeError, self.space.wrap(msg))
+        return msg
 
-    def raise_argerr_unknown_kwds(self, fnname, kwds_w):
+class ArgErrUnknownKwds(ArgErr):
+    def getmsg(self, args, fnname):
+        kwds_w, = self.args    # from self.__init__()
         if len(kwds_w) == 1:
             msg = "%s() got an unexpected keyword argument '%s'" % (
                 fnname,
@@ -236,27 +285,4 @@
             msg = "%s() got %d unexpected keyword arguments" % (
                 fnname,
                 len(kwds_w))
-        raise OperationError(self.space.w_TypeError, self.space.wrap(msg))
-
-    ### Argument <-> list of w_objects together with "shape" information
-
-    def flatten(self):
-        shape_cnt  = len(self.arguments_w)        # Number of positional args
-        shape_keys = self.kwds_w.keys()           # List of keywords (strings)
-        shape_star = self.w_stararg is not None   # Flag: presence of *arg
-        data_w = self.arguments_w + [self.kwds_w[key] for key in shape_keys]
-        if shape_star:
-            data_w.append(self.w_stararg)
-        return (shape_cnt, tuple(shape_keys), shape_star), data_w
-
-    def fromshape(space, (shape_cnt, shape_keys, shape_star), data_w):
-        args_w = data_w[:shape_cnt]
-        kwds_w = {}
-        for i in range(len(shape_keys)):
-            kwds_w[shape_keys[i]] = data_w[shape_cnt+i]
-        if shape_star:
-            w_star = data_w[-1]
-        else:
-            w_star = None
-        return Arguments(space, args_w, kwds_w, w_star)
-    fromshape = staticmethod(fromshape)
+        return msg

Modified: pypy/trunk/src/pypy/translator/annrpython.py
==============================================================================
--- pypy/trunk/src/pypy/translator/annrpython.py	(original)
+++ pypy/trunk/src/pypy/translator/annrpython.py	Thu Dec  9 22:40:56 2004
@@ -9,6 +9,7 @@
 from pypy.objspace.flow.model import SpaceOperation, FunctionGraph
 from pypy.objspace.flow.model import last_exception, last_exc_value
 from pypy.interpreter.pycode import cpython_code_signature
+from pypy.interpreter.argument import ArgErr
 
 
 class AnnotatorError(Exception):
@@ -187,13 +188,16 @@
         callpositions[position_key] = True
 
         # parse the arguments according to the function we are calling
+        signature = cpython_code_signature(func.func_code)
         defs_s = []
         if func.func_defaults:
             for x in func.func_defaults:
                 defs_s.append(self.bookkeeper.immutablevalue(x))
-        inputcells = args.parse(func.func_name,
-                                cpython_code_signature(func.func_code),
-                                defs_s)
+        try:
+            inputcells = args.match_signature(signature, defs_s)
+        except ArgErr, e:
+            print 'IGNORED', e     # hopefully temporary hack
+            return SomeImpossibleValue()
 
         # generalize the function's input arguments
         self.addpendingblock(func, graph.startblock, inputcells, position_key)



More information about the Pypy-commit mailing list