[pypy-commit] pypy default: merge branch refactor-pycall
rlamy
noreply at buildbot.pypy.org
Tue Apr 7 19:51:36 CEST 2015
Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch:
Changeset: r76737:cacbf7ed6310
Date: 2015-04-07 18:38 +0100
http://bitbucket.org/pypy/pypy/changeset/cacbf7ed6310/
Log: merge branch refactor-pycall
diff --git a/rpython/annotator/annrpython.py b/rpython/annotator/annrpython.py
--- a/rpython/annotator/annrpython.py
+++ b/rpython/annotator/annrpython.py
@@ -10,7 +10,6 @@
Variable, Constant, FunctionGraph, checkgraph)
from rpython.translator import simplify, transform
from rpython.annotator import model as annmodel, signature
-from rpython.annotator.argument import simple_args
from rpython.annotator.bookkeeper import Bookkeeper
from rpython.rtyper.normalizecalls import perform_normalizations
@@ -91,22 +90,14 @@
def get_call_parameters(self, function, args_s, policy):
desc = self.bookkeeper.getdesc(function)
- args = simple_args(args_s)
- result = []
- def schedule(graph, inputcells):
- result.append((graph, inputcells))
- return annmodel.s_ImpossibleValue
-
prevpolicy = self.policy
self.policy = policy
self.bookkeeper.enter(None)
try:
- desc.pycall(schedule, args, annmodel.s_ImpossibleValue)
+ return desc.get_call_parameters(args_s)
finally:
self.bookkeeper.leave()
self.policy = prevpolicy
- [(graph, inputcells)] = result
- return graph, inputcells
def annotate_helper(self, function, args_s, policy=None):
if policy is None:
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/description.py b/rpython/annotator/description.py
--- a/rpython/annotator/description.py
+++ b/rpython/annotator/description.py
@@ -1,13 +1,14 @@
from __future__ import absolute_import
import types
from rpython.annotator.signature import (
- enforce_signature_args, enforce_signature_return)
+ enforce_signature_args, enforce_signature_return, finish_type)
from rpython.flowspace.model import Constant, FunctionGraph
from rpython.flowspace.bytecode import cpython_code_signature
-from rpython.annotator.argument import rawshape, ArgErr
+from rpython.annotator.argument import rawshape, ArgErr, simple_args
from rpython.tool.sourcetools import valid_identifier, func_with_new_name
from rpython.tool.pairtype import extendabletype
-from rpython.annotator.model import AnnotatorError, SomeInteger, SomeString
+from rpython.annotator.model import (
+ AnnotatorError, SomeInteger, SomeString, s_ImpossibleValue)
class CallFamily(object):
"""A family of Desc objects that could be called from common call sites.
@@ -75,7 +76,6 @@
try:
return self.attrs[attrname]
except KeyError:
- from rpython.annotator.model import s_ImpossibleValue
return s_ImpossibleValue
def set_s_value(self, attrname, s_value):
@@ -97,7 +97,6 @@
# ClassAttrFamily is more precise: it is only about one attribut name.
def __init__(self, desc):
- from rpython.annotator.model import s_ImpossibleValue
self.descs = {desc: True}
self.read_locations = {} # set of position_keys
self.s_value = s_ImpossibleValue # union of possible values
@@ -321,6 +320,24 @@
result = unionof(result, s_previous_result)
return result
+ def get_call_parameters(self, args_s):
+ args = simple_args(args_s)
+ inputcells = self.parse_arguments(args)
+ graph = self.specialize(inputcells)
+ assert isinstance(graph, FunctionGraph)
+ # if that graph has a different signature, we need to re-parse
+ # 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)
+ signature = getattr(self.pyobj, '_signature_', None)
+ if signature:
+ s_result = finish_type(signature[1], self.bookkeeper, self.pyobj)
+ if s_result is not None:
+ self.bookkeeper.annotator.addpendingblock(
+ graph, graph.returnblock, [s_result])
+ return graph, inputcells
+
def bind_under(self, classdef, name):
# XXX static methods
return self.bookkeeper.getmethoddesc(self,
@@ -352,7 +369,6 @@
@staticmethod
def row_to_consider(descs, args, op):
# see comments in CallFamily
- from rpython.annotator.model import s_ImpossibleValue
row = {}
for desc in descs:
def enlist(graph, ignore):
@@ -685,7 +701,6 @@
# look up an attribute in the class
cdesc = self.lookup(name)
if cdesc is None:
- from rpython.annotator.model import s_ImpossibleValue
return s_ImpossibleValue
else:
# delegate to s_get_value to turn it into an annotation
@@ -999,7 +1014,6 @@
try:
value = self.read_attribute(attr)
except AttributeError:
- from rpython.annotator.model import s_ImpossibleValue
return s_ImpossibleValue
else:
return self.bookkeeper.immutablevalue(value)
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]))
+
+ at op.call_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)
+
diff --git a/rpython/rtyper/normalizecalls.py b/rpython/rtyper/normalizecalls.py
--- a/rpython/rtyper/normalizecalls.py
+++ b/rpython/rtyper/normalizecalls.py
@@ -86,12 +86,7 @@
return False # nothing to do, all signatures already match
shape_cnt, shape_keys, shape_star = shape
- if shape_star:
- raise TyperError(
- "not implemented: a call is done with a '*' argument, and the"
- " multiple functions or methods that it can go to don't have"
- " all the same signature (different argument names or defaults)."
- " The call can go to:\n%s" % '\n'.join(map(repr, graphs)))
+ assert not shape_star, "should have been removed at this stage"
# for the first 'shape_cnt' arguments we need to generalize to
# a common type
diff --git a/rpython/rtyper/rbuiltin.py b/rpython/rtyper/rbuiltin.py
--- a/rpython/rtyper/rbuiltin.py
+++ b/rpython/rtyper/rbuiltin.py
@@ -47,31 +47,14 @@
# to it.
return (self.__class__, self.methodname, id(self.s_self))
-def call_args_expand(hop, takes_kwds = True):
+def call_args_expand(hop):
hop = hop.copy()
from rpython.annotator.argument import ArgumentsForTranslation
arguments = ArgumentsForTranslation.fromshape(
hop.args_s[1].const, # shape
range(hop.nb_args-2))
- if arguments.w_stararg is not None:
- # expand the *arg in-place -- it must be a tuple
- from rpython.rtyper.rtuple import TupleRepr
- if arguments.w_stararg != hop.nb_args - 3:
- raise TyperError("call pattern too complex")
- v_tuple = hop.args_v.pop()
- s_tuple = hop.args_s.pop()
- r_tuple = hop.args_r.pop()
- if not isinstance(r_tuple, TupleRepr):
- raise TyperError("*arg must be a tuple")
- for i in range(len(r_tuple.items_r)):
- v_item = r_tuple.getitem_internal(hop.llops, v_tuple, i)
- hop.args_v.append(v_item)
- hop.args_s.append(s_tuple.items[i])
- hop.args_r.append(r_tuple.items_r[i])
-
+ assert arguments.w_stararg is None
keywords = arguments.keywords
- if not takes_kwds and keywords:
- raise TyperError("kwds args not supported")
# prefix keyword arguments with 'i_'
kwds_i = {}
for key in keywords:
diff --git a/rpython/rtyper/rptr.py b/rpython/rtyper/rptr.py
--- a/rpython/rtyper/rptr.py
+++ b/rpython/rtyper/rptr.py
@@ -1,4 +1,3 @@
-from rpython.annotator import model as annmodel
from rpython.rtyper.llannotation import (
SomePtr, SomeInteriorPtr, SomeLLADTMeth, lltype_to_annotation)
from rpython.flowspace import model as flowmodel
@@ -107,11 +106,7 @@
resulttype = self.lowleveltype.TO.RESULT)
def rtype_call_args(self, hop):
- from rpython.rtyper.rbuiltin import call_args_expand
- hop, _ = call_args_expand(hop, takes_kwds=False)
- hop.swap_fst_snd_args()
- hop.r_s_popfirstarg()
- return self.rtype_simple_call(hop)
+ raise TyperError("kwds args not supported")
class __extend__(pairtype(PtrRepr, PtrRepr)):
def convert_from_to((r_ptr1, r_ptr2), v, llop):
diff --git a/rpython/rtyper/test/test_normalizecalls.py b/rpython/rtyper/test/test_normalizecalls.py
--- a/rpython/rtyper/test/test_normalizecalls.py
+++ b/rpython/rtyper/test/test_normalizecalls.py
@@ -237,25 +237,6 @@
import re
assert re.match(msg, excinfo.value.args[0])
- def test_methods_with_named_arg_call(self):
- class Base:
- def fn(self, y):
- raise NotImplementedError
- class Sub1(Base):
- def fn(self, y):
- return 1 + y
- class Sub2(Base):
- def fn(self, x): # different name!
- return x - 2
- def dummyfn(n):
- if n == 1:
- s = Sub1()
- else:
- s = Sub2()
- return s.fn(*(n,))
-
- py.test.raises(TyperError, self.rtype, dummyfn, [int], int)
-
class PBase:
def fn(self):
More information about the pypy-commit
mailing list