15e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis# Copyright 2006 Google, Inc. All Rights Reserved.
25e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis# Licensed to PSF under a Contributor Agreement.
35e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
45e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis"""Fixer for apply().
55e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
65e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. LöwisThis converts apply(func, v, k) into (func)(*v, **k)."""
75e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
85e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis# Local imports
95e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwisfrom .. import pytree
105e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwisfrom ..pgen2 import token
11e607823af57c176c3be23985f5bbf9260f6bd836Benjamin Petersonfrom .. import fixer_base
1243caaa09ea364aab6cbd7ede2aa9c3d004a129a5Benjamin Petersonfrom ..fixer_util import Call, Comma, parenthesize
135e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
14e607823af57c176c3be23985f5bbf9260f6bd836Benjamin Petersonclass FixApply(fixer_base.BaseFix):
15a81eae1fd71eed670d1c28bf940ea99b4bfa2335Benjamin Peterson    BM_compatible = True
165e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
175e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis    PATTERN = """
185e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis    power< 'apply'
195e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        trailer<
205e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            '('
215e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            arglist<
225e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis                (not argument<NAME '=' any>) func=any ','
235e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis                (not argument<NAME '=' any>) args=any [','
245e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis                (not argument<NAME '=' any>) kwds=any] [',']
255e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            >
265e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            ')'
275e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        >
285e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis    >
295e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis    """
305e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
315e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis    def transform(self, node, results):
325e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        syms = self.syms
335e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        assert results
345e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        func = results["func"]
355e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        args = results["args"]
365e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        kwds = results.get("kwds")
3788c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(%        # I feel like we should be able to express this logic in the
3888c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(%        # PATTERN above but I don't know how to do it so...
3988c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(%        if args:
4088c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(%            if args.type == self.syms.star_expr:
4188c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(%                return  # Make no change.
4288c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(%            if (args.type == self.syms.argument and
4388c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(%                args.children[0].value == '**'):
4488c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(%                return  # Make no change.
4588c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(%        if kwds and (kwds.type == self.syms.argument and
4688c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(%                     kwds.children[0].value == '**'):
4788c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(%            return  # Make no change.
486118040b7aee905bcddcb949c6815dc19ca23070Benjamin Peterson        prefix = node.prefix
495e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        func = func.clone()
505e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        if (func.type not in (token.NAME, syms.atom) and
515e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            (func.type != syms.power or
525e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis             func.children[-2].type == token.DOUBLESTAR)):
535e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            # Need to parenthesize
5443caaa09ea364aab6cbd7ede2aa9c3d004a129a5Benjamin Peterson            func = parenthesize(func)
556118040b7aee905bcddcb949c6815dc19ca23070Benjamin Peterson        func.prefix = ""
565e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        args = args.clone()
576118040b7aee905bcddcb949c6815dc19ca23070Benjamin Peterson        args.prefix = ""
585e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        if kwds is not None:
595e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            kwds = kwds.clone()
606118040b7aee905bcddcb949c6815dc19ca23070Benjamin Peterson            kwds.prefix = ""
6184ad84e0bb15e7c64109e88060afdcb60ae7b740Benjamin Peterson        l_newargs = [pytree.Leaf(token.STAR, u"*"), args]
625e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        if kwds is not None:
635e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            l_newargs.extend([Comma(),
6484ad84e0bb15e7c64109e88060afdcb60ae7b740Benjamin Peterson                              pytree.Leaf(token.DOUBLESTAR, u"**"),
655e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis                              kwds])
666118040b7aee905bcddcb949c6815dc19ca23070Benjamin Peterson            l_newargs[-2].prefix = u" " # that's the ** token
675e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        # XXX Sometimes we could be cleverer, e.g. apply(f, (x, y) + t)
685e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        # can be translated into f(x, y, *t) instead of f(*(x, y) + t)
695e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        #new = pytree.Node(syms.power, (func, ArgList(l_newargs)))
705e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        return Call(func, l_newargs, prefix=prefix)
71