[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