1# -*- coding: utf-8 -*-
2#
3# Copyright (C) 2008-2010 Edgewall Software
4# All rights reserved.
5#
6# This software is licensed as described in the file COPYING, which
7# you should have received as part of this distribution. The terms
8# are also available at http://genshi.edgewall.org/wiki/License.
9#
10# This software consists of voluntary contributions made by many
11# individuals. For the exact contribution history, see the revision
12# history and logs, available at http://genshi.edgewall.org/log/.
13
14"""Support classes for generating code from abstract syntax trees."""
15
16try:
17    import _ast
18except ImportError:
19    from genshi.template.ast24 import _ast, parse
20else:
21    def parse(source, mode):
22        return compile(source, '', mode, _ast.PyCF_ONLY_AST)
23
24from genshi.compat import IS_PYTHON2, isstring, _ast_Ellipsis
25
26__docformat__ = 'restructuredtext en'
27
28
29class ASTCodeGenerator(object):
30    """General purpose base class for AST transformations.
31
32    Every visitor method can be overridden to return an AST node that has been
33    altered or replaced in some way.
34    """
35    def __init__(self, tree):
36        self.lines_info = []
37        self.line_info = None
38        self.code = ''
39        self.line = None
40        self.last = None
41        self.indent = 0
42        self.blame_stack = []
43        self.visit(tree)
44        if self.line.strip():
45            self.code += self.line + '\n'
46            self.lines_info.append(self.line_info)
47        self.line = None
48        self.line_info = None
49
50    def _change_indent(self, delta):
51        self.indent += delta
52
53    def _new_line(self):
54        if self.line is not None:
55            self.code += self.line + '\n'
56            self.lines_info.append(self.line_info)
57        self.line = ' '*4*self.indent
58        if len(self.blame_stack) == 0:
59            self.line_info = []
60            self.last = None
61        else:
62            self.line_info = [(0, self.blame_stack[-1],)]
63            self.last = self.blame_stack[-1]
64
65    def _write(self, s):
66        if len(s) == 0:
67            return
68        if len(self.blame_stack) == 0:
69            if self.last is not None:
70                self.last = None
71                self.line_info.append((len(self.line), self.last))
72        else:
73            if self.last != self.blame_stack[-1]:
74                self.last = self.blame_stack[-1]
75                self.line_info.append((len(self.line), self.last))
76        self.line += s
77
78    def visit(self, node):
79        if node is None:
80            return None
81        if type(node) is tuple:
82            return tuple([self.visit(n) for n in node])
83        try:
84            self.blame_stack.append((node.lineno, node.col_offset,))
85            info = True
86        except AttributeError:
87            info = False
88        visitor = getattr(self, 'visit_%s' % node.__class__.__name__, None)
89        if visitor is None:
90            raise Exception('Unhandled node type %r' % type(node))
91        ret = visitor(node)
92        if info:
93            self.blame_stack.pop()
94        return ret
95
96    def visit_Module(self, node):
97        for n in node.body:
98            self.visit(n)
99    visit_Interactive = visit_Module
100    visit_Suite = visit_Module
101
102    def visit_Expression(self, node):
103        self._new_line()
104        return self.visit(node.body)
105
106    # Python < 3.4
107    # arguments = (expr* args, identifier? vararg,
108    #              identifier? kwarg, expr* defaults)
109    #
110    # Python >= 3.4
111    # arguments = (arg* args, arg? vararg, arg* kwonlyargs, expr* kw_defaults,
112    #              arg? kwarg, expr* defaults)
113    def visit_arguments(self, node):
114        def write_possible_comma():
115            if _first[0]:
116                _first[0] = False
117            else:
118                self._write(', ')
119        _first = [True]
120
121        def write_args(args, defaults):
122            no_default_count = len(args) - len(defaults)
123            for i, arg in enumerate(args):
124                write_possible_comma()
125                self.visit(arg)
126                default_idx = i - no_default_count
127                if default_idx >= 0 and defaults[default_idx] is not None:
128                    self._write('=')
129                    self.visit(defaults[i - no_default_count])
130
131        write_args(node.args, node.defaults)
132        if getattr(node, 'vararg', None):
133            write_possible_comma()
134            self._write('*')
135            if isstring(node.vararg):
136                self._write(node.vararg)
137            else:
138                self.visit(node.vararg)
139        if getattr(node, 'kwonlyargs', None):
140            write_args(node.kwonlyargs, node.kw_defaults)
141        if getattr(node, 'kwarg', None):
142            write_possible_comma()
143            self._write('**')
144            if isstring(node.kwarg):
145                self._write(node.kwarg)
146            else:
147                self.visit(node.kwarg)
148
149    if not IS_PYTHON2:
150        # In Python 3 arguments get a special node
151        def visit_arg(self, node):
152            self._write(node.arg)
153
154    def visit_Starred(self, node):
155        self._write('*')
156        self.visit(node.value)
157
158    # FunctionDef(identifier name, arguments args,
159    #                           stmt* body, expr* decorator_list)
160    def visit_FunctionDef(self, node):
161        decarators = ()
162        if hasattr(node, 'decorator_list'):
163            decorators = getattr(node, 'decorator_list')
164        else: # different name in earlier Python versions
165            decorators = getattr(node, 'decorators', ())
166        for decorator in decorators:
167            self._new_line()
168            self._write('@')
169            self.visit(decorator)
170        self._new_line()
171        self._write('def ' + node.name + '(')
172        self.visit(node.args)
173        self._write('):')
174        self._change_indent(1)
175        for statement in node.body:
176            self.visit(statement)
177        self._change_indent(-1)
178
179    # ClassDef(identifier name, expr* bases, stmt* body)
180    def visit_ClassDef(self, node):
181        self._new_line()
182        self._write('class ' + node.name)
183        if node.bases:
184            self._write('(')
185            self.visit(node.bases[0])
186            for base in node.bases[1:]:
187                self._write(', ')
188                self.visit(base)
189            self._write(')')
190        self._write(':')
191        self._change_indent(1)
192        for statement in node.body:
193            self.visit(statement)
194        self._change_indent(-1)
195
196    # Return(expr? value)
197    def visit_Return(self, node):
198        self._new_line()
199        self._write('return')
200        if getattr(node, 'value', None):
201            self._write(' ')
202            self.visit(node.value)
203
204    # Delete(expr* targets)
205    def visit_Delete(self, node):
206        self._new_line()
207        self._write('del ')
208        self.visit(node.targets[0])
209        for target in node.targets[1:]:
210            self._write(', ')
211            self.visit(target)
212
213    # Assign(expr* targets, expr value)
214    def visit_Assign(self, node):
215        self._new_line()
216        for target in node.targets:
217            self.visit(target)
218            self._write(' = ')
219        self.visit(node.value)
220
221    # AugAssign(expr target, operator op, expr value)
222    def visit_AugAssign(self, node):
223        self._new_line()
224        self.visit(node.target)
225        self._write(' ' + self.binary_operators[node.op.__class__] + '= ')
226        self.visit(node.value)
227
228    # Print(expr? dest, expr* values, bool nl)
229    def visit_Print(self, node):
230        self._new_line()
231        self._write('print')
232        if getattr(node, 'dest', None):
233            self._write(' >> ')
234            self.visit(node.dest)
235            if getattr(node, 'values', None):
236                self._write(', ')
237        else:
238            self._write(' ')
239        if getattr(node, 'values', None):
240            self.visit(node.values[0])
241            for value in node.values[1:]:
242                self._write(', ')
243                self.visit(value)
244        if not node.nl:
245            self._write(',')
246
247    # For(expr target, expr iter, stmt* body, stmt* orelse)
248    def visit_For(self, node):
249        self._new_line()
250        self._write('for ')
251        self.visit(node.target)
252        self._write(' in ')
253        self.visit(node.iter)
254        self._write(':')
255        self._change_indent(1)
256        for statement in node.body:
257            self.visit(statement)
258        self._change_indent(-1)
259        if getattr(node, 'orelse', None):
260            self._new_line()
261            self._write('else:')
262            self._change_indent(1)
263            for statement in node.orelse:
264                self.visit(statement)
265            self._change_indent(-1)
266
267    # While(expr test, stmt* body, stmt* orelse)
268    def visit_While(self, node):
269        self._new_line()
270        self._write('while ')
271        self.visit(node.test)
272        self._write(':')
273        self._change_indent(1)
274        for statement in node.body:
275            self.visit(statement)
276        self._change_indent(-1)
277        if getattr(node, 'orelse', None):
278            self._new_line()
279            self._write('else:')
280            self._change_indent(1)
281            for statement in node.orelse:
282                self.visit(statement)
283            self._change_indent(-1)
284
285    # If(expr test, stmt* body, stmt* orelse)
286    def visit_If(self, node):
287        self._new_line()
288        self._write('if ')
289        self.visit(node.test)
290        self._write(':')
291        self._change_indent(1)
292        for statement in node.body:
293            self.visit(statement)
294        self._change_indent(-1)
295        if getattr(node, 'orelse', None):
296            self._new_line()
297            self._write('else:')
298            self._change_indent(1)
299            for statement in node.orelse:
300                self.visit(statement)
301            self._change_indent(-1)
302
303    # With(expr context_expr, expr? optional_vars, stmt* body)
304    # With(withitem* items, stmt* body) in Python >= 3.3
305    def visit_With(self, node):
306        self._new_line()
307        self._write('with ')
308        items = getattr(node, 'items', None)
309        first = True
310        if items is None:
311            items = [node]
312        for item in items:
313            if not first:
314                self._write(', ')
315            first = False
316            self.visit(item.context_expr)
317            if getattr(item, 'optional_vars', None):
318                self._write(' as ')
319                self.visit(item.optional_vars)
320        self._write(':')
321        self._change_indent(1)
322        for statement in node.body:
323            self.visit(statement)
324        self._change_indent(-1)
325
326    if IS_PYTHON2:
327        # Raise(expr? type, expr? inst, expr? tback)
328        def visit_Raise(self, node):
329            self._new_line()
330            self._write('raise')
331            if not node.type:
332                return
333            self._write(' ')
334            self.visit(node.type)
335            if not node.inst:
336                return
337            self._write(', ')
338            self.visit(node.inst)
339            if not node.tback:
340                return
341            self._write(', ')
342            self.visit(node.tback)
343    else:
344        # Raise(expr? exc from expr? cause)
345        def visit_Raise(self, node):
346            self._new_line()
347            self._write('raise')
348            if not node.exc:
349                return
350            self._write(' ')
351            self.visit(node.exc)
352            if not node.cause:
353                return
354            self._write(' from ')
355            self.visit(node.cause)
356
357    # TryExcept(stmt* body, excepthandler* handlers, stmt* orelse)
358    def visit_TryExcept(self, node):
359        self._new_line()
360        self._write('try:')
361        self._change_indent(1)
362        for statement in node.body:
363            self.visit(statement)
364        self._change_indent(-1)
365        if getattr(node, 'handlers', None):
366            for handler in node.handlers:
367                self.visit(handler)
368        self._new_line()
369        if getattr(node, 'orelse', None):
370            self._write('else:')
371            self._change_indent(1)
372            for statement in node.orelse:
373                self.visit(statement)
374            self._change_indent(-1)
375
376    # excepthandler = (expr? type, expr? name, stmt* body)
377    def visit_ExceptHandler(self, node):
378        self._new_line()
379        self._write('except')
380        if getattr(node, 'type', None):
381            self._write(' ')
382            self.visit(node.type)
383        if getattr(node, 'name', None):
384            self._write(', ')
385            self.visit(node.name)
386        self._write(':')
387        self._change_indent(1)
388        for statement in node.body:
389            self.visit(statement)
390        self._change_indent(-1)
391    visit_excepthandler = visit_ExceptHandler
392
393    # TryFinally(stmt* body, stmt* finalbody)
394    def visit_TryFinally(self, node):
395        self._new_line()
396        self._write('try:')
397        self._change_indent(1)
398        for statement in node.body:
399            self.visit(statement)
400        self._change_indent(-1)
401
402        if getattr(node, 'finalbody', None):
403            self._new_line()
404            self._write('finally:')
405            self._change_indent(1)
406            for statement in node.finalbody:
407                self.visit(statement)
408            self._change_indent(-1)
409
410    # New in Py3.3
411    # Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
412    def visit_Try(self, node):
413        self._new_line()
414        self._write('try:')
415        self._change_indent(1)
416        for statement in node.body:
417            self.visit(statement)
418        self._change_indent(-1)
419        if getattr(node, 'handlers', None):
420            for handler in node.handlers:
421                self.visit(handler)
422        self._new_line()
423        if getattr(node, 'orelse', None):
424            self._write('else:')
425            self._change_indent(1)
426            for statement in node.orelse:
427                self.visit(statement)
428            self._change_indent(-1)
429        if getattr(node, 'finalbody', None):
430            self._new_line()
431            self._write('finally:')
432            self._change_indent(1)
433            for statement in node.finalbody:
434                self.visit(statement)
435            self._change_indent(-1)
436
437    # Assert(expr test, expr? msg)
438    def visit_Assert(self, node):
439        self._new_line()
440        self._write('assert ')
441        self.visit(node.test)
442        if getattr(node, 'msg', None):
443            self._write(', ')
444            self.visit(node.msg)
445
446    def visit_alias(self, node):
447        self._write(node.name)
448        if getattr(node, 'asname', None):
449            self._write(' as ')
450            self._write(node.asname)
451
452    # Import(alias* names)
453    def visit_Import(self, node):
454        self._new_line()
455        self._write('import ')
456        self.visit(node.names[0])
457        for name in node.names[1:]:
458            self._write(', ')
459            self.visit(name)
460
461    # ImportFrom(identifier module, alias* names, int? level)
462    def visit_ImportFrom(self, node):
463        self._new_line()
464        self._write('from ')
465        if node.level:
466            self._write('.' * node.level)
467        self._write(node.module)
468        self._write(' import ')
469        self.visit(node.names[0])
470        for name in node.names[1:]:
471            self._write(', ')
472            self.visit(name)
473
474    # Exec(expr body, expr? globals, expr? locals)
475    def visit_Exec(self, node):
476        self._new_line()
477        self._write('exec ')
478        self.visit(node.body)
479        if not node.globals:
480            return
481        self._write(', ')
482        self.visit(node.globals)
483        if not node.locals:
484            return
485        self._write(', ')
486        self.visit(node.locals)
487
488    # Global(identifier* names)
489    def visit_Global(self, node):
490        self._new_line()
491        self._write('global ')
492        self.visit(node.names[0])
493        for name in node.names[1:]:
494            self._write(', ')
495            self.visit(name)
496
497    # Expr(expr value)
498    def visit_Expr(self, node):
499        self._new_line()
500        self.visit(node.value)
501
502    # Pass
503    def visit_Pass(self, node):
504        self._new_line()
505        self._write('pass')
506
507    # Break
508    def visit_Break(self, node):
509        self._new_line()
510        self._write('break')
511
512    # Continue
513    def visit_Continue(self, node):
514        self._new_line()
515        self._write('continue')
516
517    ### EXPRESSIONS
518    def with_parens(f):
519        def _f(self, node):
520            self._write('(')
521            f(self, node)
522            self._write(')')
523        return _f
524
525    bool_operators = {_ast.And: 'and', _ast.Or: 'or'}
526
527    # BoolOp(boolop op, expr* values)
528    @with_parens
529    def visit_BoolOp(self, node):
530        joiner = ' ' + self.bool_operators[node.op.__class__] + ' '
531        self.visit(node.values[0])
532        for value in node.values[1:]:
533            self._write(joiner)
534            self.visit(value)
535
536    binary_operators = {
537        _ast.Add: '+',
538        _ast.Sub: '-',
539        _ast.Mult: '*',
540        _ast.Div: '/',
541        _ast.Mod: '%',
542        _ast.Pow: '**',
543        _ast.LShift: '<<',
544        _ast.RShift: '>>',
545        _ast.BitOr: '|',
546        _ast.BitXor: '^',
547        _ast.BitAnd: '&',
548        _ast.FloorDiv: '//'
549    }
550
551    # BinOp(expr left, operator op, expr right)
552    @with_parens
553    def visit_BinOp(self, node):
554        self.visit(node.left)
555        self._write(' ' + self.binary_operators[node.op.__class__] + ' ')
556        self.visit(node.right)
557
558    unary_operators = {
559        _ast.Invert: '~',
560        _ast.Not: 'not',
561        _ast.UAdd: '+',
562        _ast.USub: '-',
563    }
564
565    # UnaryOp(unaryop op, expr operand)
566    def visit_UnaryOp(self, node):
567        self._write(self.unary_operators[node.op.__class__] + ' ')
568        self.visit(node.operand)
569
570    # Lambda(arguments args, expr body)
571    @with_parens
572    def visit_Lambda(self, node):
573        self._write('lambda ')
574        self.visit(node.args)
575        self._write(': ')
576        self.visit(node.body)
577
578    # IfExp(expr test, expr body, expr orelse)
579    @with_parens
580    def visit_IfExp(self, node):
581        self.visit(node.body)
582        self._write(' if ')
583        self.visit(node.test)
584        self._write(' else ')
585        self.visit(node.orelse)
586
587    # Dict(expr* keys, expr* values)
588    def visit_Dict(self, node):
589        self._write('{')
590        for key, value in zip(node.keys, node.values):
591            self.visit(key)
592            self._write(': ')
593            self.visit(value)
594            self._write(', ')
595        self._write('}')
596
597    # ListComp(expr elt, comprehension* generators)
598    def visit_ListComp(self, node):
599        self._write('[')
600        self.visit(node.elt)
601        for generator in node.generators:
602            # comprehension = (expr target, expr iter, expr* ifs)
603            self._write(' for ')
604            self.visit(generator.target)
605            self._write(' in ')
606            self.visit(generator.iter)
607            for ifexpr in generator.ifs:
608                self._write(' if ')
609                self.visit(ifexpr)
610        self._write(']')
611
612    # GeneratorExp(expr elt, comprehension* generators)
613    def visit_GeneratorExp(self, node):
614        self._write('(')
615        self.visit(node.elt)
616        for generator in node.generators:
617            # comprehension = (expr target, expr iter, expr* ifs)
618            self._write(' for ')
619            self.visit(generator.target)
620            self._write(' in ')
621            self.visit(generator.iter)
622            for ifexpr in generator.ifs:
623                self._write(' if ')
624                self.visit(ifexpr)
625        self._write(')')
626
627    # Yield(expr? value)
628    def visit_Yield(self, node):
629        self._write('yield')
630        if getattr(node, 'value', None):
631            self._write(' ')
632            self.visit(node.value)
633
634    comparision_operators = {
635        _ast.Eq: '==',
636        _ast.NotEq: '!=',
637        _ast.Lt: '<',
638        _ast.LtE: '<=',
639        _ast.Gt: '>',
640        _ast.GtE: '>=',
641        _ast.Is: 'is',
642        _ast.IsNot: 'is not',
643        _ast.In: 'in',
644        _ast.NotIn: 'not in',
645    }
646
647    # Compare(expr left, cmpop* ops, expr* comparators)
648    @with_parens
649    def visit_Compare(self, node):
650        self.visit(node.left)
651        for op, comparator in zip(node.ops, node.comparators):
652            self._write(' ' + self.comparision_operators[op.__class__] + ' ')
653            self.visit(comparator)
654
655    # Call(expr func, expr* args, keyword* keywords,
656    #                         expr? starargs, expr? kwargs)
657    def visit_Call(self, node):
658        self.visit(node.func)
659        self._write('(')
660        first = True
661        for arg in node.args:
662            if not first:
663                self._write(', ')
664            first = False
665            self.visit(arg)
666
667        for keyword in node.keywords:
668            if not first:
669                self._write(', ')
670            first = False
671            if not keyword.arg:
672                # Python 3.5+ star-star args
673                self._write('**')
674            else:
675                # keyword = (identifier arg, expr value)
676                self._write(keyword.arg)
677                self._write('=')
678            self.visit(keyword.value)
679        if getattr(node, 'starargs', None):
680            if not first:
681                self._write(', ')
682            first = False
683            self._write('*')
684            self.visit(node.starargs)
685
686        if getattr(node, 'kwargs', None):
687            if not first:
688                self._write(', ')
689            first = False
690            self._write('**')
691            self.visit(node.kwargs)
692        self._write(')')
693
694    # Repr(expr value)
695    def visit_Repr(self, node):
696        self._write('`')
697        self.visit(node.value)
698        self._write('`')
699
700    # Num(object n)
701    def visit_Num(self, node):
702        self._write(repr(node.n))
703
704    # Str(string s)
705    def visit_Str(self, node):
706        self._write(repr(node.s))
707
708    # Constant(object value)
709    def visit_Constant(self, node):
710        self._write(repr(node.value))
711
712    if not IS_PYTHON2:
713        # Bytes(bytes s)
714        def visit_Bytes(self, node):
715            self._write(repr(node.s))
716
717    # Attribute(expr value, identifier attr, expr_context ctx)
718    def visit_Attribute(self, node):
719        self.visit(node.value)
720        self._write('.')
721        self._write(node.attr)
722
723    # Subscript(expr value, slice slice, expr_context ctx)
724    def visit_Subscript(self, node):
725        self.visit(node.value)
726        self._write('[')
727        def _process_slice(node):
728            if isinstance(node, _ast_Ellipsis):
729                self._write('...')
730            elif isinstance(node, _ast.Slice):
731                if getattr(node, 'lower', 'None'):
732                    self.visit(node.lower)
733                self._write(':')
734                if getattr(node, 'upper', None):
735                    self.visit(node.upper)
736                if getattr(node, 'step', None):
737                    self._write(':')
738                    self.visit(node.step)
739            elif isinstance(node, _ast.Index):
740                self.visit(node.value)
741            elif isinstance(node, _ast.ExtSlice):
742                self.visit(node.dims[0])
743                for dim in node.dims[1:]:
744                    self._write(', ')
745                    self.visit(dim)
746            else:
747                raise NotImplemented('Slice type not implemented')
748        _process_slice(node.slice)
749        self._write(']')
750
751    # Name(identifier id, expr_context ctx)
752    def visit_Name(self, node):
753        self._write(node.id)
754
755    # NameConstant(singleton value)
756    def visit_NameConstant(self, node):
757        if node.value is None:
758            self._write('None')
759        elif node.value is True:
760            self._write('True')
761        elif node.value is False:
762            self._write('False')
763        else:
764            raise Exception("Unknown NameConstant %r" % (node.value,))
765
766    # List(expr* elts, expr_context ctx)
767    def visit_List(self, node):
768        self._write('[')
769        for elt in node.elts:
770            self.visit(elt)
771            self._write(', ')
772        self._write(']')
773
774    # Tuple(expr *elts, expr_context ctx)
775    def visit_Tuple(self, node):
776        self._write('(')
777        for elt in node.elts:
778            self.visit(elt)
779            self._write(', ')
780        self._write(')')
781
782
783class ASTTransformer(object):
784    """General purpose base class for AST transformations.
785
786    Every visitor method can be overridden to return an AST node that has been
787    altered or replaced in some way.
788    """
789
790    def visit(self, node):
791        if node is None:
792            return None
793        if type(node) is tuple:
794            return tuple([self.visit(n) for n in node])
795        visitor = getattr(self, 'visit_%s' % node.__class__.__name__, None)
796        if visitor is None:
797            return node
798        return visitor(node)
799
800    def _clone(self, node):
801        clone = node.__class__()
802        for name in getattr(clone, '_attributes', ()):
803            try:
804                setattr(clone, name, getattr(node, name))
805            except AttributeError:
806                pass
807        for name in clone._fields:
808            try:
809                value = getattr(node, name)
810            except AttributeError:
811                pass
812            else:
813                if value is None:
814                    pass
815                elif isinstance(value, list):
816                    value = [self.visit(x) for x in value]
817                elif isinstance(value, tuple):
818                    value = tuple(self.visit(x) for x in value)
819                else:
820                    value = self.visit(value)
821                setattr(clone, name, value)
822        return clone
823
824    visit_Module = _clone
825    visit_Interactive = _clone
826    visit_Expression = _clone
827    visit_Suite = _clone
828
829    visit_FunctionDef = _clone
830    visit_ClassDef = _clone
831    visit_Return = _clone
832    visit_Delete = _clone
833    visit_Assign = _clone
834    visit_AugAssign = _clone
835    visit_Print = _clone
836    visit_For = _clone
837    visit_While = _clone
838    visit_If = _clone
839    visit_With = _clone
840    visit_Raise = _clone
841    visit_TryExcept = _clone
842    visit_TryFinally = _clone
843    visit_Try = _clone
844    visit_Assert = _clone
845    visit_ExceptHandler = _clone
846
847    visit_Import = _clone
848    visit_ImportFrom = _clone
849    visit_Exec = _clone
850    visit_Global = _clone
851    visit_Expr = _clone
852    # Pass, Break, Continue don't need to be copied
853
854    visit_BoolOp = _clone
855    visit_BinOp = _clone
856    visit_UnaryOp = _clone
857    visit_Lambda = _clone
858    visit_IfExp = _clone
859    visit_Dict = _clone
860    visit_ListComp = _clone
861    visit_GeneratorExp = _clone
862    visit_Yield = _clone
863    visit_Compare = _clone
864    visit_Call = _clone
865    visit_Repr = _clone
866    # Num, Str don't need to be copied
867
868    visit_Attribute = _clone
869    visit_Subscript = _clone
870    visit_Name = _clone
871    visit_NameConstant = _clone
872    visit_List = _clone
873    visit_Tuple = _clone
874
875    visit_comprehension = _clone
876    visit_excepthandler = _clone
877    visit_arguments = _clone
878    visit_keyword = _clone
879    visit_alias = _clone
880
881    visit_Slice = _clone
882    visit_ExtSlice = _clone
883    visit_Index = _clone
884
885    del _clone
886