Exemplo n.º 1
0
    def test_unmatch_signature(self):
        args = MockArgs([1, 2, 3])
        sig = Signature(['a', 'b', 'c'], None, None)
        data = args.match_signature(sig, [])
        new_args = args.unmatch_signature(sig, data)
        assert args.unpack() == new_args.unpack()

        args = MockArgs([1])
        sig = Signature(['a', 'b', 'c'], None, None)
        data = args.match_signature(sig, [2, 3])
        new_args = args.unmatch_signature(sig, data)
        assert args.unpack() == new_args.unpack()

        args = MockArgs([1, 2, 3, 4, 5])
        sig = Signature(['a', 'b', 'c'], 'r', None)
        data = args.match_signature(sig, [])
        new_args = args.unmatch_signature(sig, data)
        assert args.unpack() == new_args.unpack()

        args = MockArgs([1], {'c': 3, 'b': 2})
        sig = Signature(['a', 'b', 'c'], None, None)
        data = args.match_signature(sig, [])
        new_args = args.unmatch_signature(sig, data)
        assert args.unpack() == new_args.unpack()

        args = MockArgs([1], {'c': 5})
        sig = Signature(['a', 'b', 'c'], None, None)
        data = args.match_signature(sig, [2, 3])
        new_args = args.unmatch_signature(sig, data)
        assert args.unpack() == new_args.unpack()
Exemplo n.º 2
0
 def builder(translator, func):
     # build a hacked graph that doesn't take a *arg any more, but
     # individual extra arguments
     graph = translator.buildflowgraph(func)
     argnames, vararg, kwarg = graph.signature
     assert vararg, "graph should have a *arg at this point"
     assert not kwarg, "where does this **arg come from??"
     argscopy = [Variable(v) for v in graph.getargs()]
     starargs = [
         Variable('stararg%d' % i) for i in range(nb_extra_args)
     ]
     newstartblock = Block(argscopy[:-1] + starargs)
     newtup = op.newtuple(*starargs)
     newtup.result = argscopy[-1]
     newstartblock.operations.append(newtup)
     newstartblock.closeblock(Link(argscopy, graph.startblock))
     graph.startblock = newstartblock
     argnames = argnames + ['.star%d' % i for i in range(nb_extra_args)]
     graph.signature = Signature(argnames)
     # note that we can mostly ignore defaults: if nb_extra_args > 0,
     # then defaults aren't applied.  if nb_extra_args == 0, then this
     # just removes the *arg and the defaults keep their meaning.
     if nb_extra_args > 0:
         graph.defaults = None  # shouldn't be used in this case
     checkgraph(graph)
     return graph
Exemplo n.º 3
0
 def __init__(self,
              bookkeeper,
              pyobj=None,
              name=None,
              signature=None,
              defaults=None,
              specializer=None):
     super(FunctionDesc, self).__init__(bookkeeper, pyobj)
     if name is None:
         name = pyobj.func_name
     if signature is None:
         if hasattr(pyobj, '_generator_next_method_of_'):
             from rpython.flowspace.argument import Signature
             signature = Signature(['entry'])  # haaaaaack
             defaults = ()
         else:
             signature = cpython_code_signature(pyobj.func_code)
     if defaults is None:
         defaults = pyobj.func_defaults
     self.name = name
     self.signature = signature
     self.defaults = defaults or ()
     # 'specializer' is a function with the following signature:
     #      specializer(funcdesc, args_s) => graph
     #                                 or => s_result (overridden/memo cases)
     self.specializer = specializer
     self._cache = {}  # convenience for the specializer
Exemplo n.º 4
0
def cpython_code_signature(code):
    "([list-of-arg-names], vararg-name-or-None, kwarg-name-or-None)."
    argcount = code.co_argcount
    argnames = list(code.co_varnames[:argcount])
    if code.co_flags & CO_VARARGS:
        varargname = code.co_varnames[argcount]
        argcount += 1
    else:
        varargname = None
    if code.co_flags & CO_VARKEYWORDS:
        kwargname = code.co_varnames[argcount]
        argcount += 1
    else:
        kwargname = None
    return Signature(argnames, varargname, kwargname)
Exemplo n.º 5
0
 def newfuncdesc(self, pyfunc):
     name = pyfunc.__name__
     if hasattr(pyfunc, '_generator_next_method_of_'):
         from rpython.flowspace.argument import Signature
         signature = Signature(['entry'])  # haaaaaack
         defaults = ()
     else:
         signature = cpython_code_signature(pyfunc.__code__)
         defaults = pyfunc.__defaults__
     # get the specializer based on the tag of the 'pyobj'
     # (if any), according to the current policy
     tag = getattr(pyfunc, '_annspecialcase_', None)
     specializer = self.annotator.policy.get_specializer(tag)
     if specializer is memo:
         return description.MemoDesc(self, pyfunc, name, signature,
                                     defaults, specializer)
     return description.FunctionDesc(self, pyfunc, name, signature,
                                     defaults, specializer)
Exemplo n.º 6
0
def tweak_generator_body_graph(Entry, graph):
    # First, always run simplify_graph in order to reduce the number of
    # variables passed around
    simplify_graph(graph)
    insert_empty_startblock(graph)
    _insert_reads(graph.startblock, Entry.varnames)
    Entry.block = graph.startblock
    #
    mappings = [Entry]
    #
    stopblock = Block([])
    op0 = op.simple_call(const(StopIteration))
    op1 = op.type(op0.result)
    stopblock.operations = [op0, op1]
    stopblock.closeblock(Link([op1.result, op0.result], graph.exceptblock))
    #
    for block in list(graph.iterblocks()):
        for exit in block.exits:
            if exit.target is graph.returnblock:
                exit.args = []
                exit.target = stopblock
        assert block is not stopblock
        for index in range(len(block.operations) - 1, -1, -1):
            hlop = block.operations[index]
            if hlop.opname == 'yield_':
                [v_yielded_value] = hlop.args
                del block.operations[index]
                newlink = split_block(block, index)
                newblock = newlink.target

                #
                class Resume(AbstractPosition):
                    _immutable_ = True
                    block = newblock

                Resume.__name__ = 'Resume%d' % len(mappings)
                mappings.append(Resume)
                varnames = get_variable_names(newlink.args)
                #
                _insert_reads(newblock, varnames)
                #
                op_resume = op.simple_call(const(Resume))
                block.operations.append(op_resume)
                v_resume = op_resume.result
                for i, name in enumerate(varnames):
                    block.operations.append(
                        op.setattr(v_resume, const(name), newlink.args[i]))
                op_pair = op.newtuple(v_resume, v_yielded_value)
                block.operations.append(op_pair)
                newlink.args = [op_pair.result]
                newlink.target = graph.returnblock
    #
    regular_entry_block = Block([Variable('entry')])
    block = regular_entry_block
    for Resume in mappings:
        op_check = op.isinstance(block.inputargs[0], const(Resume))
        block.operations.append(op_check)
        block.exitswitch = op_check.result
        link1 = Link([block.inputargs[0]], Resume.block)
        link1.exitcase = True
        nextblock = Block([Variable('entry')])
        link2 = Link([block.inputargs[0]], nextblock)
        link2.exitcase = False
        block.closeblock(link1, link2)
        block = nextblock
    block.closeblock(
        Link([
            Constant(AssertionError),
            Constant(AssertionError("bad generator class"))
        ], graph.exceptblock))
    graph.startblock = regular_entry_block
    graph.signature = Signature(['entry'])
    graph.defaults = ()
    checkgraph(graph)
    eliminate_empty_blocks(graph)
Exemplo n.º 7
0
def normalize_calltable_row_signature(annotator, shape, row):
    graphs = row.values()
    assert graphs, "no graph??"
    sig0 = graphs[0].signature
    defaults0 = graphs[0].defaults
    for graph in graphs[1:]:
        if graph.signature != sig0:
            break
        if graph.defaults != defaults0:
            break
    else:
        return False  # nothing to do, all signatures already match

    shape_cnt, shape_keys, shape_star = shape
    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
    call_nbargs = shape_cnt + len(shape_keys)

    did_something = False

    for graph in graphs:
        argnames, varargname, kwargname = graph.signature
        assert not varargname, "XXX not implemented"
        assert not kwargname, "XXX not implemented"  # ?
        inputargs_s = [annotator.binding(v) for v in graph.getargs()]
        argorder = range(shape_cnt)
        for key in shape_keys:
            i = list(argnames).index(key)
            assert i not in argorder
            argorder.append(i)
        need_reordering = (argorder != range(call_nbargs))
        if need_reordering or len(graph.getargs()) != call_nbargs:
            oldblock = graph.startblock
            inlist = []
            defaults = graph.defaults or ()
            num_nondefaults = len(inputargs_s) - len(defaults)
            defaults = [description.NODEFAULT
                        ] * num_nondefaults + list(defaults)
            newdefaults = []
            for j in argorder:
                v = Variable(graph.getargs()[j])
                annotator.setbinding(v, inputargs_s[j])
                inlist.append(v)
                newdefaults.append(defaults[j])
            newblock = Block(inlist)
            # prepare the output args of newblock:
            # 1. collect the positional arguments
            outlist = inlist[:shape_cnt]
            # 2. add defaults and keywords
            for j in range(shape_cnt, len(inputargs_s)):
                try:
                    i = argorder.index(j)
                    v = inlist[i]
                except ValueError:
                    default = defaults[j]
                    if default is description.NODEFAULT:
                        raise TyperError(
                            "call pattern has %d positional arguments, "
                            "but %r takes at least %d arguments" %
                            (shape_cnt, graph.name, num_nondefaults))
                    v = Constant(default)
                outlist.append(v)
            newblock.closeblock(Link(outlist, oldblock))
            graph.startblock = newblock
            for i in range(len(newdefaults) - 1, -1, -1):
                if newdefaults[i] is description.NODEFAULT:
                    newdefaults = newdefaults[i:]
                    break
            graph.defaults = tuple(newdefaults)
            graph.signature = Signature([argnames[j] for j in argorder], None,
                                        None)
            # finished
            checkgraph(graph)
            annotator.annotated[newblock] = annotator.annotated[oldblock]
            did_something = True
    return did_something
Exemplo n.º 8
0
 def test_helpers(self):
     sig = Signature(["a", "b", "c"], None, None)
     assert sig.num_argnames() == 3
     assert not sig.has_vararg()
     assert not sig.has_kwarg()
     assert sig.scope_length() == 3
     assert sig.getallvarnames() == ["a", "b", "c"]
     sig = Signature(["a", "b", "c"], "c", None)
     assert sig.num_argnames() == 3
     assert sig.has_vararg()
     assert not sig.has_kwarg()
     assert sig.scope_length() == 4
     assert sig.getallvarnames() == ["a", "b", "c", "c"]
     sig = Signature(["a", "b", "c"], None, "c")
     assert sig.num_argnames() == 3
     assert not sig.has_vararg()
     assert sig.has_kwarg()
     assert sig.scope_length() == 4
     assert sig.getallvarnames() == ["a", "b", "c", "c"]
     sig = Signature(["a", "b", "c"], "d", "c")
     assert sig.num_argnames() == 3
     assert sig.has_vararg()
     assert sig.has_kwarg()
     assert sig.scope_length() == 5
     assert sig.getallvarnames() == ["a", "b", "c", "d", "c"]
Exemplo n.º 9
0
 def test_find_argname(self):
     sig = Signature(["a", "b", "c"], None, None)
     assert sig.find_argname("a") == 0
     assert sig.find_argname("b") == 1
     assert sig.find_argname("c") == 2
     assert sig.find_argname("d") == -1
Exemplo n.º 10
0
 def test_tuply(self):
     sig = Signature(["a", "b", "c"], "d", "e")
     x, y, z = sig
     assert x == ["a", "b", "c"]
     assert y == "d"
     assert z == "e"
Exemplo n.º 11
0
 def test_helpers(self):
     sig = Signature(["a", "b", "c"], None, None)
     assert sig.num_argnames() == 3
     assert not sig.has_vararg()
     assert not sig.has_kwarg()
     assert sig.scope_length() == 3
     assert sig.getallvarnames() == ["a", "b", "c"]
     sig = Signature(["a", "b", "c"], "c", None)
     assert sig.num_argnames() == 3
     assert sig.has_vararg()
     assert not sig.has_kwarg()
     assert sig.scope_length() == 4
     assert sig.getallvarnames() == ["a", "b", "c", "c"]
     sig = Signature(["a", "b", "c"], None, "c")
     assert sig.num_argnames() == 3
     assert not sig.has_vararg()
     assert sig.has_kwarg()
     assert sig.scope_length() == 4
     assert sig.getallvarnames() == ["a", "b", "c", "c"]
     sig = Signature(["a", "b", "c"], "d", "c")
     assert sig.num_argnames() == 3
     assert sig.has_vararg()
     assert sig.has_kwarg()
     assert sig.scope_length() == 5
     assert sig.getallvarnames() == ["a", "b", "c", "d", "c"]
Exemplo n.º 12
0
 def test_find_argname(self):
     sig = Signature(["a", "b", "c"], None, None)
     assert sig.find_argname("a") == 0
     assert sig.find_argname("b") == 1
     assert sig.find_argname("c") == 2
     assert sig.find_argname("d") == -1
Exemplo n.º 13
0
 def test_eq(self):
     sig1 = Signature(["a", "b", "c"], "d", "c")
     sig2 = Signature(["a", "b", "c"], "d", "c")
     assert sig1 == sig2