]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.2/Lib/lib2to3/fixes/fix_tuple_params.py
EmbeddedPkg: Extend NvVarStoreFormattedLib LIBRARY_CLASS
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Lib / lib2to3 / fixes / fix_tuple_params.py
CommitLineData
4710c53d 1"""Fixer for function definitions with tuple parameters.\r
2\r
3def func(((a, b), c), d):\r
4 ...\r
5\r
6 ->\r
7\r
8def func(x, d):\r
9 ((a, b), c) = x\r
10 ...\r
11\r
12It will also support lambdas:\r
13\r
14 lambda (x, y): x + y -> lambda t: t[0] + t[1]\r
15\r
16 # The parens are a syntax error in Python 3\r
17 lambda (x): x + y -> lambda x: x + y\r
18"""\r
19# Author: Collin Winter\r
20\r
21# Local imports\r
22from .. import pytree\r
23from ..pgen2 import token\r
24from .. import fixer_base\r
25from ..fixer_util import Assign, Name, Newline, Number, Subscript, syms\r
26\r
27def is_docstring(stmt):\r
28 return isinstance(stmt, pytree.Node) and \\r
29 stmt.children[0].type == token.STRING\r
30\r
31class FixTupleParams(fixer_base.BaseFix):\r
32 run_order = 4 #use a lower order since lambda is part of other\r
33 #patterns\r
34 BM_compatible = True\r
35\r
36 PATTERN = """\r
37 funcdef< 'def' any parameters< '(' args=any ')' >\r
38 ['->' any] ':' suite=any+ >\r
39 |\r
40 lambda=\r
41 lambdef< 'lambda' args=vfpdef< '(' inner=any ')' >\r
42 ':' body=any\r
43 >\r
44 """\r
45\r
46 def transform(self, node, results):\r
47 if "lambda" in results:\r
48 return self.transform_lambda(node, results)\r
49\r
50 new_lines = []\r
51 suite = results["suite"]\r
52 args = results["args"]\r
53 # This crap is so "def foo(...): x = 5; y = 7" is handled correctly.\r
54 # TODO(cwinter): suite-cleanup\r
55 if suite[0].children[1].type == token.INDENT:\r
56 start = 2\r
57 indent = suite[0].children[1].value\r
58 end = Newline()\r
59 else:\r
60 start = 0\r
61 indent = u"; "\r
62 end = pytree.Leaf(token.INDENT, u"")\r
63\r
64 # We need access to self for new_name(), and making this a method\r
65 # doesn't feel right. Closing over self and new_lines makes the\r
66 # code below cleaner.\r
67 def handle_tuple(tuple_arg, add_prefix=False):\r
68 n = Name(self.new_name())\r
69 arg = tuple_arg.clone()\r
70 arg.prefix = u""\r
71 stmt = Assign(arg, n.clone())\r
72 if add_prefix:\r
73 n.prefix = u" "\r
74 tuple_arg.replace(n)\r
75 new_lines.append(pytree.Node(syms.simple_stmt,\r
76 [stmt, end.clone()]))\r
77\r
78 if args.type == syms.tfpdef:\r
79 handle_tuple(args)\r
80 elif args.type == syms.typedargslist:\r
81 for i, arg in enumerate(args.children):\r
82 if arg.type == syms.tfpdef:\r
83 # Without add_prefix, the emitted code is correct,\r
84 # just ugly.\r
85 handle_tuple(arg, add_prefix=(i > 0))\r
86\r
87 if not new_lines:\r
88 return\r
89\r
90 # This isn't strictly necessary, but it plays nicely with other fixers.\r
91 # TODO(cwinter) get rid of this when children becomes a smart list\r
92 for line in new_lines:\r
93 line.parent = suite[0]\r
94\r
95 # TODO(cwinter) suite-cleanup\r
96 after = start\r
97 if start == 0:\r
98 new_lines[0].prefix = u" "\r
99 elif is_docstring(suite[0].children[start]):\r
100 new_lines[0].prefix = indent\r
101 after = start + 1\r
102\r
103 for line in new_lines:\r
104 line.parent = suite[0]\r
105 suite[0].children[after:after] = new_lines\r
106 for i in range(after+1, after+len(new_lines)+1):\r
107 suite[0].children[i].prefix = indent\r
108 suite[0].changed()\r
109\r
110 def transform_lambda(self, node, results):\r
111 args = results["args"]\r
112 body = results["body"]\r
113 inner = simplify_args(results["inner"])\r
114\r
115 # Replace lambda ((((x)))): x with lambda x: x\r
116 if inner.type == token.NAME:\r
117 inner = inner.clone()\r
118 inner.prefix = u" "\r
119 args.replace(inner)\r
120 return\r
121\r
122 params = find_params(args)\r
123 to_index = map_to_index(params)\r
124 tup_name = self.new_name(tuple_name(params))\r
125\r
126 new_param = Name(tup_name, prefix=u" ")\r
127 args.replace(new_param.clone())\r
128 for n in body.post_order():\r
129 if n.type == token.NAME and n.value in to_index:\r
130 subscripts = [c.clone() for c in to_index[n.value]]\r
131 new = pytree.Node(syms.power,\r
132 [new_param.clone()] + subscripts)\r
133 new.prefix = n.prefix\r
134 n.replace(new)\r
135\r
136\r
137### Helper functions for transform_lambda()\r
138\r
139def simplify_args(node):\r
140 if node.type in (syms.vfplist, token.NAME):\r
141 return node\r
142 elif node.type == syms.vfpdef:\r
143 # These look like vfpdef< '(' x ')' > where x is NAME\r
144 # or another vfpdef instance (leading to recursion).\r
145 while node.type == syms.vfpdef:\r
146 node = node.children[1]\r
147 return node\r
148 raise RuntimeError("Received unexpected node %s" % node)\r
149\r
150def find_params(node):\r
151 if node.type == syms.vfpdef:\r
152 return find_params(node.children[1])\r
153 elif node.type == token.NAME:\r
154 return node.value\r
155 return [find_params(c) for c in node.children if c.type != token.COMMA]\r
156\r
157def map_to_index(param_list, prefix=[], d=None):\r
158 if d is None:\r
159 d = {}\r
160 for i, obj in enumerate(param_list):\r
161 trailer = [Subscript(Number(unicode(i)))]\r
162 if isinstance(obj, list):\r
163 map_to_index(obj, trailer, d=d)\r
164 else:\r
165 d[obj] = prefix + trailer\r
166 return d\r
167\r
168def tuple_name(param_list):\r
169 l = []\r
170 for obj in param_list:\r
171 if isinstance(obj, list):\r
172 l.append(tuple_name(obj))\r
173 else:\r
174 l.append(obj)\r
175 return u"_".join(l)\r