Author: Ronan Lamy <ronan.l...@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])) + +@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): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit