Author: Ronan Lamy <[email protected]>
Branch: refactor-pycall
Changeset: r76689:0e6061661c1e
Date: 2015-04-02 05:06 +0100
http://bitbucket.org/pypy/pypy/changeset/0e6061661c1e/
Log: Implement *-unpacking as an online transform
f(*(a, b, c)) should now be completely equivalent to f(a, b, c)
diff --git a/rpython/annotator/argument.py b/rpython/annotator/argument.py
--- a/rpython/annotator/argument.py
+++ b/rpython/annotator/argument.py
@@ -155,18 +155,6 @@
keywords_w = [_kwds_w[key] for key in self.keywords]
return ArgumentsForTranslation(args_w, dict(zip(self.keywords,
keywords_w)))
- @classmethod
- def fromshape(cls, (shape_cnt, shape_keys, shape_star), data_w):
- args_w = data_w[:shape_cnt]
- p = end_keys = shape_cnt + len(shape_keys)
- if shape_star:
- w_star = data_w[p]
- p += 1
- else:
- w_star = None
- return cls(args_w, dict(zip(shape_keys, data_w[shape_cnt:end_keys])),
- w_star)
-
def rawshape(args):
return args._rawshape()
diff --git a/rpython/annotator/test/test_annrpython.py
b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -354,6 +354,25 @@
assert isinstance(s, annmodel.SomeInteger)
assert s.const == 3
+ def test_star_unpack_list(self):
+ def g():
+ pass
+ def f(l):
+ return g(*l)
+ a = self.RPythonAnnotator()
+ with py.test.raises(annmodel.AnnotatorError):
+ a.build_types(f, [[int]])
+
+ def test_star_unpack_and_keywords(self):
+ def g(a, b, c=0, d=0):
+ return a + b + c + d
+
+ def f(a, b):
+ return g(a, *(b,), d=5)
+ a = self.RPythonAnnotator()
+ s_result = a.build_types(f, [int, int])
+ assert isinstance(s_result, annmodel.SomeInteger)
+
def test_pbc_attr_preserved_on_instance(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.preserve_pbc_attr_on_instance, [bool])
diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py
--- a/rpython/annotator/unaryop.py
+++ b/rpython/annotator/unaryop.py
@@ -6,6 +6,7 @@
from rpython.flowspace.operation import op
from rpython.flowspace.model import const, Constant
+from rpython.flowspace.argument import CallSpec
from rpython.annotator.model import (SomeObject, SomeInteger, SomeBool,
SomeString, SomeChar, SomeList, SomeDict, SomeTuple, SomeImpossibleValue,
SomeUnicodeCodePoint, SomeInstance, SomeBuiltin, SomeBuiltinMethod,
@@ -47,11 +48,35 @@
@op.simple_call.register(SomeObject)
def simple_call_SomeObject(annotator, func, *args):
- return
annotator.annotation(func).call(simple_args([annotator.annotation(arg) for arg
in args]))
+ return annotator.annotation(func).call(
+ simple_args([annotator.annotation(arg) for arg in args]))
+
[email protected]_args.register_transform(SomeObject)
+def transform_varargs(annotator, v_func, v_shape, *data_v):
+ callspec = CallSpec.fromshape(v_shape.value, list(data_v))
+ v_vararg = callspec.w_stararg
+ if callspec.w_stararg:
+ s_vararg = annotator.annotation(callspec.w_stararg)
+ if not isinstance(s_vararg, SomeTuple):
+ raise AnnotatorError(
+ "Calls like f(..., *arg) require 'arg' to be a tuple")
+ n_items = len(s_vararg.items)
+ ops = [op.getitem(v_vararg, const(i)) for i in range(n_items)]
+ new_args = callspec.arguments_w + [hlop.result for hlop in ops]
+ if callspec.keywords:
+ newspec = CallSpec(new_args, callspec.keywords)
+ shape, data_v = newspec.flatten()
+ call_op = op.call_args(v_func, const(shape), *data_v)
+ else:
+ call_op = op.simple_call(v_func, *new_args)
+ ops.append(call_op)
+ return ops
+
@op.call_args.register(SomeObject)
-def call_args(annotator, func, *args):
- return
annotator.annotation(func).call(complex_args([annotator.annotation(arg) for arg
in args]))
+def call_args(annotator, func, *args_v):
+ callspec = complex_args([annotator.annotation(v_arg) for v_arg in args_v])
+ return annotator.annotation(func).call(callspec)
class __extend__(SomeObject):
@@ -722,7 +747,7 @@
if attr not in dct:
continue
obj = dct[attr]
- if (not isinstance(obj, Constant) or
+ if (not isinstance(obj, Constant) or
not isinstance(obj.value, property)):
return
result.append(getattr(obj.value, meth))
diff --git a/rpython/flowspace/argument.py b/rpython/flowspace/argument.py
--- a/rpython/flowspace/argument.py
+++ b/rpython/flowspace/argument.py
@@ -111,3 +111,16 @@
return self.arguments_w
else:
return self.arguments_w + [const(x) for x in self.w_stararg.value]
+
+ @classmethod
+ def fromshape(cls, (shape_cnt, shape_keys, shape_star), data_w):
+ args_w = data_w[:shape_cnt]
+ p = end_keys = shape_cnt + len(shape_keys)
+ if shape_star:
+ w_star = data_w[p]
+ p += 1
+ else:
+ w_star = None
+ return cls(args_w, dict(zip(shape_keys, data_w[shape_cnt:end_keys])),
+ w_star)
+
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit