xref: /OK3568_Linux_fs/yocto/poky/bitbake/lib/codegen.py (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun# -*- coding: utf-8 -*-
2*4882a593Smuzhiyun"""
3*4882a593Smuzhiyun    codegen
4*4882a593Smuzhiyun    ~~~~~~~
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun    Extension to ast that allow ast -> python code generation.
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun    :copyright: Copyright 2008 by Armin Ronacher.
9*4882a593Smuzhiyun    :license: BSD.
10*4882a593Smuzhiyun"""
11*4882a593Smuzhiyunfrom ast import *
12*4882a593Smuzhiyun
13*4882a593SmuzhiyunBOOLOP_SYMBOLS = {
14*4882a593Smuzhiyun    And:        'and',
15*4882a593Smuzhiyun    Or:         'or'
16*4882a593Smuzhiyun}
17*4882a593Smuzhiyun
18*4882a593SmuzhiyunBINOP_SYMBOLS = {
19*4882a593Smuzhiyun    Add:        '+',
20*4882a593Smuzhiyun    Sub:        '-',
21*4882a593Smuzhiyun    Mult:       '*',
22*4882a593Smuzhiyun    Div:        '/',
23*4882a593Smuzhiyun    FloorDiv:   '//',
24*4882a593Smuzhiyun    Mod:        '%',
25*4882a593Smuzhiyun    LShift:     '<<',
26*4882a593Smuzhiyun    RShift:     '>>',
27*4882a593Smuzhiyun    BitOr:      '|',
28*4882a593Smuzhiyun    BitAnd:     '&',
29*4882a593Smuzhiyun    BitXor:     '^'
30*4882a593Smuzhiyun}
31*4882a593Smuzhiyun
32*4882a593SmuzhiyunCMPOP_SYMBOLS = {
33*4882a593Smuzhiyun    Eq:         '==',
34*4882a593Smuzhiyun    Gt:         '>',
35*4882a593Smuzhiyun    GtE:        '>=',
36*4882a593Smuzhiyun    In:         'in',
37*4882a593Smuzhiyun    Is:         'is',
38*4882a593Smuzhiyun    IsNot:      'is not',
39*4882a593Smuzhiyun    Lt:         '<',
40*4882a593Smuzhiyun    LtE:        '<=',
41*4882a593Smuzhiyun    NotEq:      '!=',
42*4882a593Smuzhiyun    NotIn:      'not in'
43*4882a593Smuzhiyun}
44*4882a593Smuzhiyun
45*4882a593SmuzhiyunUNARYOP_SYMBOLS = {
46*4882a593Smuzhiyun    Invert:     '~',
47*4882a593Smuzhiyun    Not:        'not',
48*4882a593Smuzhiyun    UAdd:       '+',
49*4882a593Smuzhiyun    USub:       '-'
50*4882a593Smuzhiyun}
51*4882a593Smuzhiyun
52*4882a593SmuzhiyunALL_SYMBOLS = {}
53*4882a593SmuzhiyunALL_SYMBOLS.update(BOOLOP_SYMBOLS)
54*4882a593SmuzhiyunALL_SYMBOLS.update(BINOP_SYMBOLS)
55*4882a593SmuzhiyunALL_SYMBOLS.update(CMPOP_SYMBOLS)
56*4882a593SmuzhiyunALL_SYMBOLS.update(UNARYOP_SYMBOLS)
57*4882a593Smuzhiyun
58*4882a593Smuzhiyundef to_source(node, indent_with=' ' * 4, add_line_information=False):
59*4882a593Smuzhiyun    """This function can convert a node tree back into python sourcecode.
60*4882a593Smuzhiyun    This is useful for debugging purposes, especially if you're dealing with
61*4882a593Smuzhiyun    custom asts not generated by python itself.
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun    It could be that the sourcecode is evaluable when the AST itself is not
64*4882a593Smuzhiyun    compilable / evaluable.  The reason for this is that the AST contains some
65*4882a593Smuzhiyun    more data than regular sourcecode does, which is dropped during
66*4882a593Smuzhiyun    conversion.
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun    Each level of indentation is replaced with `indent_with`.  Per default this
69*4882a593Smuzhiyun    parameter is equal to four spaces as suggested by PEP 8, but it might be
70*4882a593Smuzhiyun    adjusted to match the application's styleguide.
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun    If `add_line_information` is set to `True` comments for the line numbers
73*4882a593Smuzhiyun    of the nodes are added to the output.  This can be used to spot wrong line
74*4882a593Smuzhiyun    number information of statement nodes.
75*4882a593Smuzhiyun    """
76*4882a593Smuzhiyun    generator = SourceGenerator(indent_with, add_line_information)
77*4882a593Smuzhiyun    generator.visit(node)
78*4882a593Smuzhiyun    return ''.join(generator.result)
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun
81*4882a593Smuzhiyunclass SourceGenerator(NodeVisitor):
82*4882a593Smuzhiyun    """This visitor is able to transform a well formed syntax tree into python
83*4882a593Smuzhiyun    sourcecode.  For more details have a look at the docstring of the
84*4882a593Smuzhiyun    `node_to_source` function.
85*4882a593Smuzhiyun    """
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun    def __init__(self, indent_with, add_line_information=False):
88*4882a593Smuzhiyun        self.result = []
89*4882a593Smuzhiyun        self.indent_with = indent_with
90*4882a593Smuzhiyun        self.add_line_information = add_line_information
91*4882a593Smuzhiyun        self.indentation = 0
92*4882a593Smuzhiyun        self.new_lines = 0
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun    def write(self, x):
95*4882a593Smuzhiyun        if self.new_lines:
96*4882a593Smuzhiyun            if self.result:
97*4882a593Smuzhiyun                self.result.append('\n' * self.new_lines)
98*4882a593Smuzhiyun            self.result.append(self.indent_with * self.indentation)
99*4882a593Smuzhiyun            self.new_lines = 0
100*4882a593Smuzhiyun        self.result.append(x)
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun    def newline(self, node=None, extra=0):
103*4882a593Smuzhiyun        self.new_lines = max(self.new_lines, 1 + extra)
104*4882a593Smuzhiyun        if node is not None and self.add_line_information:
105*4882a593Smuzhiyun            self.write('# line: %s' % node.lineno)
106*4882a593Smuzhiyun            self.new_lines = 1
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun    def body(self, statements):
109*4882a593Smuzhiyun        self.new_line = True
110*4882a593Smuzhiyun        self.indentation += 1
111*4882a593Smuzhiyun        for stmt in statements:
112*4882a593Smuzhiyun            self.visit(stmt)
113*4882a593Smuzhiyun        self.indentation -= 1
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun    def body_or_else(self, node):
116*4882a593Smuzhiyun        self.body(node.body)
117*4882a593Smuzhiyun        if node.orelse:
118*4882a593Smuzhiyun            self.newline()
119*4882a593Smuzhiyun            self.write('else:')
120*4882a593Smuzhiyun            self.body(node.orelse)
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun    def signature(self, node):
123*4882a593Smuzhiyun        want_comma = []
124*4882a593Smuzhiyun        def write_comma():
125*4882a593Smuzhiyun            if want_comma:
126*4882a593Smuzhiyun                self.write(', ')
127*4882a593Smuzhiyun            else:
128*4882a593Smuzhiyun                want_comma.append(True)
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun        padding = [None] * (len(node.args) - len(node.defaults))
131*4882a593Smuzhiyun        for arg, default in zip(node.args, padding + node.defaults):
132*4882a593Smuzhiyun            write_comma()
133*4882a593Smuzhiyun            self.visit(arg)
134*4882a593Smuzhiyun            if default is not None:
135*4882a593Smuzhiyun                self.write('=')
136*4882a593Smuzhiyun                self.visit(default)
137*4882a593Smuzhiyun        if node.vararg is not None:
138*4882a593Smuzhiyun            write_comma()
139*4882a593Smuzhiyun            self.write('*' + node.vararg)
140*4882a593Smuzhiyun        if node.kwarg is not None:
141*4882a593Smuzhiyun            write_comma()
142*4882a593Smuzhiyun            self.write('**' + node.kwarg)
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun    def decorators(self, node):
145*4882a593Smuzhiyun        for decorator in node.decorator_list:
146*4882a593Smuzhiyun            self.newline(decorator)
147*4882a593Smuzhiyun            self.write('@')
148*4882a593Smuzhiyun            self.visit(decorator)
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun    # Statements
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun    def visit_Assign(self, node):
153*4882a593Smuzhiyun        self.newline(node)
154*4882a593Smuzhiyun        for idx, target in enumerate(node.targets):
155*4882a593Smuzhiyun            if idx:
156*4882a593Smuzhiyun                self.write(', ')
157*4882a593Smuzhiyun            self.visit(target)
158*4882a593Smuzhiyun        self.write(' = ')
159*4882a593Smuzhiyun        self.visit(node.value)
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun    def visit_AugAssign(self, node):
162*4882a593Smuzhiyun        self.newline(node)
163*4882a593Smuzhiyun        self.visit(node.target)
164*4882a593Smuzhiyun        self.write(BINOP_SYMBOLS[type(node.op)] + '=')
165*4882a593Smuzhiyun        self.visit(node.value)
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun    def visit_ImportFrom(self, node):
168*4882a593Smuzhiyun        self.newline(node)
169*4882a593Smuzhiyun        self.write('from %s%s import ' % ('.' * node.level, node.module))
170*4882a593Smuzhiyun        for idx, item in enumerate(node.names):
171*4882a593Smuzhiyun            if idx:
172*4882a593Smuzhiyun                self.write(', ')
173*4882a593Smuzhiyun            self.write(item)
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun    def visit_Import(self, node):
176*4882a593Smuzhiyun        self.newline(node)
177*4882a593Smuzhiyun        for item in node.names:
178*4882a593Smuzhiyun            self.write('import ')
179*4882a593Smuzhiyun            self.visit(item)
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun    def visit_Expr(self, node):
182*4882a593Smuzhiyun        self.newline(node)
183*4882a593Smuzhiyun        self.generic_visit(node)
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun    def visit_FunctionDef(self, node):
186*4882a593Smuzhiyun        self.newline(extra=1)
187*4882a593Smuzhiyun        self.decorators(node)
188*4882a593Smuzhiyun        self.newline(node)
189*4882a593Smuzhiyun        self.write('def %s(' % node.name)
190*4882a593Smuzhiyun        self.signature(node.args)
191*4882a593Smuzhiyun        self.write('):')
192*4882a593Smuzhiyun        self.body(node.body)
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun    def visit_ClassDef(self, node):
195*4882a593Smuzhiyun        have_args = []
196*4882a593Smuzhiyun        def paren_or_comma():
197*4882a593Smuzhiyun            if have_args:
198*4882a593Smuzhiyun                self.write(', ')
199*4882a593Smuzhiyun            else:
200*4882a593Smuzhiyun                have_args.append(True)
201*4882a593Smuzhiyun                self.write('(')
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun        self.newline(extra=2)
204*4882a593Smuzhiyun        self.decorators(node)
205*4882a593Smuzhiyun        self.newline(node)
206*4882a593Smuzhiyun        self.write('class %s' % node.name)
207*4882a593Smuzhiyun        for base in node.bases:
208*4882a593Smuzhiyun            paren_or_comma()
209*4882a593Smuzhiyun            self.visit(base)
210*4882a593Smuzhiyun        # XXX: the if here is used to keep this module compatible
211*4882a593Smuzhiyun        #      with python 2.6.
212*4882a593Smuzhiyun        if hasattr(node, 'keywords'):
213*4882a593Smuzhiyun            for keyword in node.keywords:
214*4882a593Smuzhiyun                paren_or_comma()
215*4882a593Smuzhiyun                self.write(keyword.arg + '=')
216*4882a593Smuzhiyun                self.visit(keyword.value)
217*4882a593Smuzhiyun            if hasattr(node, 'starargs') and node.starargs is not None:
218*4882a593Smuzhiyun                paren_or_comma()
219*4882a593Smuzhiyun                self.write('*')
220*4882a593Smuzhiyun                self.visit(node.starargs)
221*4882a593Smuzhiyun            if hasattr(node, 'kwargs') and node.kwargs is not None:
222*4882a593Smuzhiyun                paren_or_comma()
223*4882a593Smuzhiyun                self.write('**')
224*4882a593Smuzhiyun                self.visit(node.kwargs)
225*4882a593Smuzhiyun        self.write(have_args and '):' or ':')
226*4882a593Smuzhiyun        self.body(node.body)
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun    def visit_If(self, node):
229*4882a593Smuzhiyun        self.newline(node)
230*4882a593Smuzhiyun        self.write('if ')
231*4882a593Smuzhiyun        self.visit(node.test)
232*4882a593Smuzhiyun        self.write(':')
233*4882a593Smuzhiyun        self.body(node.body)
234*4882a593Smuzhiyun        while True:
235*4882a593Smuzhiyun            else_ = node.orelse
236*4882a593Smuzhiyun            if len(else_) == 1 and isinstance(else_[0], If):
237*4882a593Smuzhiyun                node = else_[0]
238*4882a593Smuzhiyun                self.newline()
239*4882a593Smuzhiyun                self.write('elif ')
240*4882a593Smuzhiyun                self.visit(node.test)
241*4882a593Smuzhiyun                self.write(':')
242*4882a593Smuzhiyun                self.body(node.body)
243*4882a593Smuzhiyun            else:
244*4882a593Smuzhiyun                self.newline()
245*4882a593Smuzhiyun                self.write('else:')
246*4882a593Smuzhiyun                self.body(else_)
247*4882a593Smuzhiyun                break
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun    def visit_For(self, node):
250*4882a593Smuzhiyun        self.newline(node)
251*4882a593Smuzhiyun        self.write('for ')
252*4882a593Smuzhiyun        self.visit(node.target)
253*4882a593Smuzhiyun        self.write(' in ')
254*4882a593Smuzhiyun        self.visit(node.iter)
255*4882a593Smuzhiyun        self.write(':')
256*4882a593Smuzhiyun        self.body_or_else(node)
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun    def visit_While(self, node):
259*4882a593Smuzhiyun        self.newline(node)
260*4882a593Smuzhiyun        self.write('while ')
261*4882a593Smuzhiyun        self.visit(node.test)
262*4882a593Smuzhiyun        self.write(':')
263*4882a593Smuzhiyun        self.body_or_else(node)
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun    def visit_With(self, node):
266*4882a593Smuzhiyun        self.newline(node)
267*4882a593Smuzhiyun        self.write('with ')
268*4882a593Smuzhiyun        self.visit(node.context_expr)
269*4882a593Smuzhiyun        if node.optional_vars is not None:
270*4882a593Smuzhiyun            self.write(' as ')
271*4882a593Smuzhiyun            self.visit(node.optional_vars)
272*4882a593Smuzhiyun        self.write(':')
273*4882a593Smuzhiyun        self.body(node.body)
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun    def visit_Pass(self, node):
276*4882a593Smuzhiyun        self.newline(node)
277*4882a593Smuzhiyun        self.write('pass')
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun    def visit_Print(self, node):
280*4882a593Smuzhiyun        # XXX: python 2.6 only
281*4882a593Smuzhiyun        self.newline(node)
282*4882a593Smuzhiyun        self.write('print ')
283*4882a593Smuzhiyun        want_comma = False
284*4882a593Smuzhiyun        if node.dest is not None:
285*4882a593Smuzhiyun            self.write(' >> ')
286*4882a593Smuzhiyun            self.visit(node.dest)
287*4882a593Smuzhiyun            want_comma = True
288*4882a593Smuzhiyun        for value in node.values:
289*4882a593Smuzhiyun            if want_comma:
290*4882a593Smuzhiyun                self.write(', ')
291*4882a593Smuzhiyun            self.visit(value)
292*4882a593Smuzhiyun            want_comma = True
293*4882a593Smuzhiyun        if not node.nl:
294*4882a593Smuzhiyun            self.write(',')
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun    def visit_Delete(self, node):
297*4882a593Smuzhiyun        self.newline(node)
298*4882a593Smuzhiyun        self.write('del ')
299*4882a593Smuzhiyun        for idx, target in enumerate(node):
300*4882a593Smuzhiyun            if idx:
301*4882a593Smuzhiyun                self.write(', ')
302*4882a593Smuzhiyun            self.visit(target)
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun    def visit_TryExcept(self, node):
305*4882a593Smuzhiyun        self.newline(node)
306*4882a593Smuzhiyun        self.write('try:')
307*4882a593Smuzhiyun        self.body(node.body)
308*4882a593Smuzhiyun        for handler in node.handlers:
309*4882a593Smuzhiyun            self.visit(handler)
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun    def visit_TryFinally(self, node):
312*4882a593Smuzhiyun        self.newline(node)
313*4882a593Smuzhiyun        self.write('try:')
314*4882a593Smuzhiyun        self.body(node.body)
315*4882a593Smuzhiyun        self.newline(node)
316*4882a593Smuzhiyun        self.write('finally:')
317*4882a593Smuzhiyun        self.body(node.finalbody)
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun    def visit_Global(self, node):
320*4882a593Smuzhiyun        self.newline(node)
321*4882a593Smuzhiyun        self.write('global ' + ', '.join(node.names))
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun    def visit_Nonlocal(self, node):
324*4882a593Smuzhiyun        self.newline(node)
325*4882a593Smuzhiyun        self.write('nonlocal ' + ', '.join(node.names))
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun    def visit_Return(self, node):
328*4882a593Smuzhiyun        self.newline(node)
329*4882a593Smuzhiyun        self.write('return ')
330*4882a593Smuzhiyun        self.visit(node.value)
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun    def visit_Break(self, node):
333*4882a593Smuzhiyun        self.newline(node)
334*4882a593Smuzhiyun        self.write('break')
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun    def visit_Continue(self, node):
337*4882a593Smuzhiyun        self.newline(node)
338*4882a593Smuzhiyun        self.write('continue')
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun    def visit_Raise(self, node):
341*4882a593Smuzhiyun        # XXX: Python 2.6 / 3.0 compatibility
342*4882a593Smuzhiyun        self.newline(node)
343*4882a593Smuzhiyun        self.write('raise')
344*4882a593Smuzhiyun        if hasattr(node, 'exc') and node.exc is not None:
345*4882a593Smuzhiyun            self.write(' ')
346*4882a593Smuzhiyun            self.visit(node.exc)
347*4882a593Smuzhiyun            if node.cause is not None:
348*4882a593Smuzhiyun                self.write(' from ')
349*4882a593Smuzhiyun                self.visit(node.cause)
350*4882a593Smuzhiyun        elif hasattr(node, 'type') and node.type is not None:
351*4882a593Smuzhiyun            self.visit(node.type)
352*4882a593Smuzhiyun            if node.inst is not None:
353*4882a593Smuzhiyun                self.write(', ')
354*4882a593Smuzhiyun                self.visit(node.inst)
355*4882a593Smuzhiyun            if node.tback is not None:
356*4882a593Smuzhiyun                self.write(', ')
357*4882a593Smuzhiyun                self.visit(node.tback)
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun    # Expressions
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun    def visit_Attribute(self, node):
362*4882a593Smuzhiyun        self.visit(node.value)
363*4882a593Smuzhiyun        self.write('.' + node.attr)
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun    def visit_Call(self, node):
366*4882a593Smuzhiyun        want_comma = []
367*4882a593Smuzhiyun        def write_comma():
368*4882a593Smuzhiyun            if want_comma:
369*4882a593Smuzhiyun                self.write(', ')
370*4882a593Smuzhiyun            else:
371*4882a593Smuzhiyun                want_comma.append(True)
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun        self.visit(node.func)
374*4882a593Smuzhiyun        self.write('(')
375*4882a593Smuzhiyun        for arg in node.args:
376*4882a593Smuzhiyun            write_comma()
377*4882a593Smuzhiyun            self.visit(arg)
378*4882a593Smuzhiyun        for keyword in node.keywords:
379*4882a593Smuzhiyun            write_comma()
380*4882a593Smuzhiyun            self.write(keyword.arg + '=')
381*4882a593Smuzhiyun            self.visit(keyword.value)
382*4882a593Smuzhiyun        if hasattr(node, 'starargs') and node.starargs is not None:
383*4882a593Smuzhiyun            write_comma()
384*4882a593Smuzhiyun            self.write('*')
385*4882a593Smuzhiyun            self.visit(node.starargs)
386*4882a593Smuzhiyun        if hasattr(node, 'kwargs') and node.kwargs is not None:
387*4882a593Smuzhiyun            write_comma()
388*4882a593Smuzhiyun            self.write('**')
389*4882a593Smuzhiyun            self.visit(node.kwargs)
390*4882a593Smuzhiyun        self.write(')')
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun    def visit_Name(self, node):
393*4882a593Smuzhiyun        self.write(node.id)
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun    def visit_Str(self, node):
396*4882a593Smuzhiyun        self.write(repr(node.s))
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun    def visit_Bytes(self, node):
399*4882a593Smuzhiyun        self.write(repr(node.s))
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun    def visit_Num(self, node):
402*4882a593Smuzhiyun        self.write(repr(node.n))
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun    def visit_Constant(self, node):
405*4882a593Smuzhiyun        # Python 3.8 deprecated visit_Num(), visit_Str(), visit_Bytes(),
406*4882a593Smuzhiyun        # visit_NameConstant() and visit_Ellipsis(). They can be removed once we
407*4882a593Smuzhiyun        # require 3.8+.
408*4882a593Smuzhiyun        self.write(repr(node.value))
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun    def visit_Tuple(self, node):
411*4882a593Smuzhiyun        self.write('(')
412*4882a593Smuzhiyun        idx = -1
413*4882a593Smuzhiyun        for idx, item in enumerate(node.elts):
414*4882a593Smuzhiyun            if idx:
415*4882a593Smuzhiyun                self.write(', ')
416*4882a593Smuzhiyun            self.visit(item)
417*4882a593Smuzhiyun        self.write(idx and ')' or ',)')
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun    def sequence_visit(left, right):
420*4882a593Smuzhiyun        def visit(self, node):
421*4882a593Smuzhiyun            self.write(left)
422*4882a593Smuzhiyun            for idx, item in enumerate(node.elts):
423*4882a593Smuzhiyun                if idx:
424*4882a593Smuzhiyun                    self.write(', ')
425*4882a593Smuzhiyun                self.visit(item)
426*4882a593Smuzhiyun            self.write(right)
427*4882a593Smuzhiyun        return visit
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun    visit_List = sequence_visit('[', ']')
430*4882a593Smuzhiyun    visit_Set = sequence_visit('{', '}')
431*4882a593Smuzhiyun    del sequence_visit
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun    def visit_Dict(self, node):
434*4882a593Smuzhiyun        self.write('{')
435*4882a593Smuzhiyun        for idx, (key, value) in enumerate(zip(node.keys, node.values)):
436*4882a593Smuzhiyun            if idx:
437*4882a593Smuzhiyun                self.write(', ')
438*4882a593Smuzhiyun            self.visit(key)
439*4882a593Smuzhiyun            self.write(': ')
440*4882a593Smuzhiyun            self.visit(value)
441*4882a593Smuzhiyun        self.write('}')
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun    def visit_BinOp(self, node):
444*4882a593Smuzhiyun        self.visit(node.left)
445*4882a593Smuzhiyun        self.write(' %s ' % BINOP_SYMBOLS[type(node.op)])
446*4882a593Smuzhiyun        self.visit(node.right)
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun    def visit_BoolOp(self, node):
449*4882a593Smuzhiyun        self.write('(')
450*4882a593Smuzhiyun        for idx, value in enumerate(node.values):
451*4882a593Smuzhiyun            if idx:
452*4882a593Smuzhiyun                self.write(' %s ' % BOOLOP_SYMBOLS[type(node.op)])
453*4882a593Smuzhiyun            self.visit(value)
454*4882a593Smuzhiyun        self.write(')')
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun    def visit_Compare(self, node):
457*4882a593Smuzhiyun        self.write('(')
458*4882a593Smuzhiyun        self.write(node.left)
459*4882a593Smuzhiyun        for op, right in zip(node.ops, node.comparators):
460*4882a593Smuzhiyun            self.write(' %s %%' % CMPOP_SYMBOLS[type(op)])
461*4882a593Smuzhiyun            self.visit(right)
462*4882a593Smuzhiyun        self.write(')')
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun    def visit_UnaryOp(self, node):
465*4882a593Smuzhiyun        self.write('(')
466*4882a593Smuzhiyun        op = UNARYOP_SYMBOLS[type(node.op)]
467*4882a593Smuzhiyun        self.write(op)
468*4882a593Smuzhiyun        if op == 'not':
469*4882a593Smuzhiyun            self.write(' ')
470*4882a593Smuzhiyun        self.visit(node.operand)
471*4882a593Smuzhiyun        self.write(')')
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun    def visit_Subscript(self, node):
474*4882a593Smuzhiyun        self.visit(node.value)
475*4882a593Smuzhiyun        self.write('[')
476*4882a593Smuzhiyun        self.visit(node.slice)
477*4882a593Smuzhiyun        self.write(']')
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun    def visit_Slice(self, node):
480*4882a593Smuzhiyun        if node.lower is not None:
481*4882a593Smuzhiyun            self.visit(node.lower)
482*4882a593Smuzhiyun        self.write(':')
483*4882a593Smuzhiyun        if node.upper is not None:
484*4882a593Smuzhiyun            self.visit(node.upper)
485*4882a593Smuzhiyun        if node.step is not None:
486*4882a593Smuzhiyun            self.write(':')
487*4882a593Smuzhiyun            if not (isinstance(node.step, Name) and node.step.id == 'None'):
488*4882a593Smuzhiyun                self.visit(node.step)
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun    def visit_ExtSlice(self, node):
491*4882a593Smuzhiyun        for idx, item in node.dims:
492*4882a593Smuzhiyun            if idx:
493*4882a593Smuzhiyun                self.write(', ')
494*4882a593Smuzhiyun            self.visit(item)
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun    def visit_Yield(self, node):
497*4882a593Smuzhiyun        self.write('yield ')
498*4882a593Smuzhiyun        self.visit(node.value)
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun    def visit_Lambda(self, node):
501*4882a593Smuzhiyun        self.write('lambda ')
502*4882a593Smuzhiyun        self.signature(node.args)
503*4882a593Smuzhiyun        self.write(': ')
504*4882a593Smuzhiyun        self.visit(node.body)
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun    def visit_Ellipsis(self, node):
507*4882a593Smuzhiyun        self.write('Ellipsis')
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun    def generator_visit(left, right):
510*4882a593Smuzhiyun        def visit(self, node):
511*4882a593Smuzhiyun            self.write(left)
512*4882a593Smuzhiyun            self.visit(node.elt)
513*4882a593Smuzhiyun            for comprehension in node.generators:
514*4882a593Smuzhiyun                self.visit(comprehension)
515*4882a593Smuzhiyun            self.write(right)
516*4882a593Smuzhiyun        return visit
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun    visit_ListComp = generator_visit('[', ']')
519*4882a593Smuzhiyun    visit_GeneratorExp = generator_visit('(', ')')
520*4882a593Smuzhiyun    visit_SetComp = generator_visit('{', '}')
521*4882a593Smuzhiyun    del generator_visit
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun    def visit_DictComp(self, node):
524*4882a593Smuzhiyun        self.write('{')
525*4882a593Smuzhiyun        self.visit(node.key)
526*4882a593Smuzhiyun        self.write(': ')
527*4882a593Smuzhiyun        self.visit(node.value)
528*4882a593Smuzhiyun        for comprehension in node.generators:
529*4882a593Smuzhiyun            self.visit(comprehension)
530*4882a593Smuzhiyun        self.write('}')
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun    def visit_IfExp(self, node):
533*4882a593Smuzhiyun        self.visit(node.body)
534*4882a593Smuzhiyun        self.write(' if ')
535*4882a593Smuzhiyun        self.visit(node.test)
536*4882a593Smuzhiyun        self.write(' else ')
537*4882a593Smuzhiyun        self.visit(node.orelse)
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun    def visit_Starred(self, node):
540*4882a593Smuzhiyun        self.write('*')
541*4882a593Smuzhiyun        self.visit(node.value)
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun    def visit_Repr(self, node):
544*4882a593Smuzhiyun        # XXX: python 2.6 only
545*4882a593Smuzhiyun        self.write('`')
546*4882a593Smuzhiyun        self.visit(node.value)
547*4882a593Smuzhiyun        self.write('`')
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun    # Helper Nodes
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun    def visit_alias(self, node):
552*4882a593Smuzhiyun        self.write(node.name)
553*4882a593Smuzhiyun        if node.asname is not None:
554*4882a593Smuzhiyun            self.write(' as ' + node.asname)
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun    def visit_comprehension(self, node):
557*4882a593Smuzhiyun        self.write(' for ')
558*4882a593Smuzhiyun        self.visit(node.target)
559*4882a593Smuzhiyun        self.write(' in ')
560*4882a593Smuzhiyun        self.visit(node.iter)
561*4882a593Smuzhiyun        if node.ifs:
562*4882a593Smuzhiyun            for if_ in node.ifs:
563*4882a593Smuzhiyun                self.write(' if ')
564*4882a593Smuzhiyun                self.visit(if_)
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun    def visit_excepthandler(self, node):
567*4882a593Smuzhiyun        self.newline(node)
568*4882a593Smuzhiyun        self.write('except')
569*4882a593Smuzhiyun        if node.type is not None:
570*4882a593Smuzhiyun            self.write(' ')
571*4882a593Smuzhiyun            self.visit(node.type)
572*4882a593Smuzhiyun            if node.name is not None:
573*4882a593Smuzhiyun                self.write(' as ')
574*4882a593Smuzhiyun                self.visit(node.name)
575*4882a593Smuzhiyun        self.write(':')
576*4882a593Smuzhiyun        self.body(node.body)
577