[pypy-svn] r76408 - in pypy/branch/call-method-kwarg/pypy: interpreter/astcompiler interpreter/test objspace/std objspace/std/test
agaynor at codespeak.net
agaynor at codespeak.net
Fri Jul 30 20:17:58 CEST 2010
Author: agaynor
Date: Fri Jul 30 20:17:55 2010
New Revision: 76408
Modified:
pypy/branch/call-method-kwarg/pypy/interpreter/astcompiler/codegen.py
pypy/branch/call-method-kwarg/pypy/interpreter/test/test_compiler.py
pypy/branch/call-method-kwarg/pypy/objspace/std/callmethod.py
pypy/branch/call-method-kwarg/pypy/objspace/std/test/test_callmethod.py
Log:
Started implementing kwarg support for CALL_METHOD, the compiler test needs work.
Modified: pypy/branch/call-method-kwarg/pypy/interpreter/astcompiler/codegen.py
==============================================================================
--- pypy/branch/call-method-kwarg/pypy/interpreter/astcompiler/codegen.py (original)
+++ pypy/branch/call-method-kwarg/pypy/interpreter/astcompiler/codegen.py Fri Jul 30 20:17:55 2010
@@ -960,9 +960,12 @@
elif call_type == 3:
op = ops.CALL_FUNCTION_VAR_KW
self.emit_op_arg(op, arg)
+
+ def _call_has_no_star_args(self, call):
+ return not call.starargs and not call.kwargs
def _call_has_simple_args(self, call):
- return not call.starargs and not call.kwargs and not call.keywords
+ return self._call_has_no_star_args(call) and not call.keywords
def _optimize_builtin_call(self, call):
if not self.space.config.objspace.opcodes.CALL_LIKELY_BUILTIN or \
@@ -988,7 +991,7 @@
def _optimize_method_call(self, call):
if not self.space.config.objspace.opcodes.CALL_METHOD or \
- not self._call_has_simple_args(call) or \
+ not self._call_has_no_star_args(call) or \
not isinstance(call.func, ast.Attribute):
return False
attr_lookup = call.func
@@ -1000,7 +1003,12 @@
arg_count = len(call.args)
else:
arg_count = 0
- self.emit_op_arg(ops.CALL_METHOD, arg_count)
+ if call.kwargs:
+ call.kwargs.walkabout(self)
+ kwarg_count = len(call.kwargs)
+ else:
+ kwarg_count = 0
+ self.emit_op_arg(ops.CALL_METHOD, (kwarg_count << 8) + arg_count)
return True
def _listcomp_generator(self, list_name, gens, gen_index, elt):
Modified: pypy/branch/call-method-kwarg/pypy/interpreter/test/test_compiler.py
==============================================================================
--- pypy/branch/call-method-kwarg/pypy/interpreter/test/test_compiler.py (original)
+++ pypy/branch/call-method-kwarg/pypy/interpreter/test/test_compiler.py Fri Jul 30 20:17:55 2010
@@ -848,13 +848,38 @@
import StringIO, sys, dis
s = StringIO.StringIO()
+ out = sys.stdout
sys.stdout = s
try:
dis.dis(code)
finally:
- sys.stdout = sys.__stdout__
+ sys.stdout = out
output = s.getvalue()
assert "LOAD_GLOBAL" not in output
+
+ def test_call_method_kwargs(self):
+ source = """def _f(a):
+ return a.f(a=a)
+ """
+ CALL_METHOD = self.space.config.objspace.opcodes.CALL_METHOD
+ self.space.config.objspace.opcodes.CALL_METHOD = True
+ try:
+ exec source
+ finally:
+ self.space.config.objspace.opcodes.CALL_METHOD = CALL_METHOD
+ code = _f.func_code
+
+ import StringIO, sys, dis
+ s = StringIO.StringIO()
+ out = sys.stdout
+ sys.stdout = s
+ try:
+ dis.dis(code)
+ finally:
+ sys.stdout = out
+ output = s.getvalue()
+ assert "CALL_METHOD" in output
+
class AppTestExceptions:
def test_indentation_error(self):
Modified: pypy/branch/call-method-kwarg/pypy/objspace/std/callmethod.py
==============================================================================
--- pypy/branch/call-method-kwarg/pypy/objspace/std/callmethod.py (original)
+++ pypy/branch/call-method-kwarg/pypy/objspace/std/callmethod.py Fri Jul 30 20:17:55 2010
@@ -56,16 +56,37 @@
f.pushvalue(w_value)
f.pushvalue(None)
-def CALL_METHOD(f, nargs, *ignored):
- # 'nargs' is the argument count excluding the implicit 'self'
- w_self = f.peekvalue(nargs)
- w_callable = f.peekvalue(nargs + 1)
- n = nargs + (w_self is not None)
+def CALL_METHOD(f, oparg, *ignored):
+ # opargs contains the arg, and kwarg count, excluding the implicit 'self'
+ n_args = oparg & 0xff
+ n_kwargs = (oparg >> 8) & 0xff
+ w_self = f.peekvalue(n_args + (2 * n_kwargs))
+ w_callable = f.peekvalue(n_args + (2 * n_kwargs) + 1)
+
+ if n_kwargs:
+ keywords = [None] * n_kwargs
+ keywords_w = [None] * n_kwargs
+ while True:
+ n_kwargs -= 1
+ if n_kwargs < 0:
+ break
+ w_value = f.popvalue()
+ w_key = f.popvalue()
+ key = f.space.str_w(w_key)
+ keywords[n_keywords] = key
+ keywords_w[n_keywords] = w_value
+ else:
+ keywords = None
+ keywords_w = None
+
+ arguments = f.popvalues(n_args + (w_self is not None))
+ args = f.argument_factory(arguments, keywords, keywords_w, None, None)
+
try:
- w_result = f.space.call_valuestack(w_callable, n, f)
- rstack.resume_point("CALL_METHOD", f, nargs, returns=w_result)
+ w_result = f.space.call_args(w_callable, args)
+ rstack.resume_point("CALL_METHOD", f, returns=w_result)
finally:
- f.dropvalues(nargs + 2)
+ f.dropvalues(1 + (w_self is None))
f.pushvalue(w_result)
Modified: pypy/branch/call-method-kwarg/pypy/objspace/std/test/test_callmethod.py
==============================================================================
--- pypy/branch/call-method-kwarg/pypy/objspace/std/test/test_callmethod.py (original)
+++ pypy/branch/call-method-kwarg/pypy/objspace/std/test/test_callmethod.py Fri Jul 30 20:17:55 2010
@@ -106,6 +106,15 @@
else:
raise Exception("did not raise?")
"""
+
+ def test_kwargs(self):
+ exec """if 1:
+ class C(object):
+ def f(self, a):
+ return a + 2
+
+ assert C().f(a=3) == 5
+ """
class AppTestCallMethodWithGetattributeShortcut(AppTestCallMethod):
More information about the Pypy-commit
mailing list