ยปCore Development>Code coverage>Lib/compiler/visitor.py

Python code coverage for Lib/compiler/visitor.py

#countcontent
12from compiler import ast
2n/a
3n/a# XXX should probably rename ASTVisitor to ASTWalker
4n/a# XXX can it be made even more generic?
5n/a
64class ASTVisitor:
7n/a """Performs a depth-first walk of the AST
8n/a
9n/a The ASTVisitor will walk the AST, performing either a preorder or
10n/a postorder traversal depending on which method is called.
11n/a
12n/a methods:
13n/a preorder(tree, visitor)
14n/a postorder(tree, visitor)
15n/a tree: an instance of ast.Node
16n/a visitor: an instance with visitXXX methods
17n/a
18n/a The ASTVisitor is responsible for walking over the tree in the
19n/a correct order. For each node, it checks the visitor argument for
20n/a a method named 'visitNodeType' where NodeType is the name of the
21n/a node's class, e.g. Class. If the method exists, it is called
22n/a with the node as its sole argument.
23n/a
24n/a The visitor method for a particular node type can control how
25n/a child nodes are visited during a preorder walk. (It can't control
26n/a the order during a postorder walk, because it is called _after_
27n/a the walk has occurred.) The ASTVisitor modifies the visitor
28n/a argument by adding a visit method to the visitor; this method can
29n/a be used to visit a child node of arbitrary type.
302 """
31n/a
322 VERBOSE = 0
33n/a
342 def __init__(self):
352244 self.node = None
362244 self._cache = {}
37n/a
382 def default(self, node, *args):
39174388 for child in node.getChildNodes():
4092479 self.dispatch(child, *args)
41n/a
422 def dispatch(self, node, *args):
43118685 self.node = node
44118685 klass = node.__class__
45118685 meth = self._cache.get(klass, None)
46118685 if meth is None:
4713115 className = klass.__name__
4813115 meth = getattr(self.visitor, 'visit' + className, self.default)
4913115 self._cache[klass] = meth
50n/a## if self.VERBOSE > 0:
51n/a## className = klass.__name__
52n/a## if self.VERBOSE == 1:
53n/a## if meth == 0:
54n/a## print "dispatch", className
55n/a## else:
56n/a## print "dispatch", className, (meth and meth.__name__ or '')
57118685 return meth(node, *args)
58n/a
592 def preorder(self, tree, visitor, *args):
60n/a """Do preorder walk of tree using visitor"""
612244 self.visitor = visitor
622244 visitor.visit = self.dispatch
632244 self.dispatch(tree, *args) # XXX *args make sense?
64n/a
654class ExampleASTVisitor(ASTVisitor):
66n/a """Prints examples of the nodes that aren't visited
67n/a
68n/a This visitor-driver is only useful for development, when it's
69n/a helpful to develop a visitor incrementally, and get feedback on what
70n/a you still have to do.
712 """
722 examples = {}
73n/a
742 def dispatch(self, node, *args):
750 self.node = node
760 meth = self._cache.get(node.__class__, None)
770 className = node.__class__.__name__
780 if meth is None:
790 meth = getattr(self.visitor, 'visit' + className, 0)
800 self._cache[node.__class__] = meth
810 if self.VERBOSE > 1:
820 print "dispatch", className, (meth and meth.__name__ or '')
830 if meth:
840 meth(node, *args)
850 elif self.VERBOSE > 0:
860 klass = node.__class__
870 if klass not in self.examples:
880 self.examples[klass] = klass
890 print
900 print self.visitor
910 print klass
920 for attr in dir(node):
930 if attr[0] != '_':
940 print "\t", "%-12.12s" % attr, getattr(node, attr)
950 print
960 return self.default(node, *args)
97n/a
98n/a# XXX this is an API change
99n/a
1002_walker = ASTVisitor
1012def walk(tree, visitor, walker=None, verbose=None):
1022244 if walker is None:
1032244 walker = _walker()
1042244 if verbose is not None:
1051085 walker.VERBOSE = verbose
1062244 walker.preorder(tree, visitor)
1072244 return walker.visitor
108n/a
1092def dumpNode(node):
1100 print node.__class__
1110 for attr in dir(node):
1120 if attr[0] != '_':
1130 print "\t", "%-10.10s" % attr, getattr(node, attr)