python2.5-compiler-package

Changeset

4:5b1d239ec500
2012-05-17 Paul Boddie raw files shortlog changelog graph Changed the dispatch mechanism to use the visit methods provided by nodes. Removed obsolete classes and functions; tidied up the docstrings and comments.
compiler/visitor.py (file)
     1.1 --- a/compiler/visitor.py	Thu May 17 20:22:53 2012 +0200
     1.2 +++ b/compiler/visitor.py	Thu May 17 20:25:34 2012 +0200
     1.3 @@ -1,39 +1,24 @@
     1.4 -from compiler import ast
     1.5 +#!/usr/bin/env python
     1.6  
     1.7 -# XXX should probably rename ASTVisitor to ASTWalker
     1.8 -# XXX can it be made even more generic?
     1.9 +from compiler import ast
    1.10  
    1.11  class ASTVisitor:
    1.12 -    """Performs a depth-first walk of the AST
    1.13  
    1.14 -    The ASTVisitor will walk the AST, performing either a preorder or
    1.15 -    postorder traversal depending on which method is called.
    1.16 -
    1.17 -    methods:
    1.18 -    preorder(tree, visitor)
    1.19 -    postorder(tree, visitor)
    1.20 -        tree: an instance of ast.Node
    1.21 -        visitor: an instance with visitXXX methods
    1.22 +    """
    1.23 +    Performs a depth-first walk of the AST.
    1.24  
    1.25 -    The ASTVisitor is responsible for walking over the tree in the
    1.26 -    correct order.  For each node, it checks the visitor argument for
    1.27 -    a method named 'visitNodeType' where NodeType is the name of the
    1.28 -    node's class, e.g. Class.  If the method exists, it is called
    1.29 -    with the node as its sole argument.
    1.30 +    The ASTVisitor is responsible for walking over the tree in the correct
    1.31 +    order. For each node, it calls the 'visit' method on the node, and this
    1.32 +    method is then responsible to calling an appropriate method on the visitor.
    1.33  
    1.34 -    The visitor method for a particular node type can control how
    1.35 -    child nodes are visited during a preorder walk.  (It can't control
    1.36 -    the order during a postorder walk, because it is called _after_
    1.37 -    the walk has occurred.)  The ASTVisitor modifies the visitor
    1.38 -    argument by adding a visit method to the visitor; this method can
    1.39 -    be used to visit a child node of arbitrary type.
    1.40 +    For example, where 'Class' is the name of the node's class, the node's
    1.41 +    'visit' method might invoke a 'visitClass' method on the visitor, although
    1.42 +    it need not follow this particular naming convention.
    1.43      """
    1.44  
    1.45 -    VERBOSE = 0
    1.46 -
    1.47      def __init__(self):
    1.48          self.node = None
    1.49 -        self._cache = {}
    1.50 +        self.visitor = self
    1.51  
    1.52      def default(self, node, *args):
    1.53          for child in node.getChildNodes():
    1.54 @@ -41,73 +26,28 @@
    1.55  
    1.56      def dispatch(self, node, *args):
    1.57          self.node = node
    1.58 -        klass = node.__class__
    1.59 -        meth = self._cache.get(klass, None)
    1.60 -        if meth is None:
    1.61 -            className = klass.__name__
    1.62 -            meth = getattr(self.visitor, 'visit' + className, self.default)
    1.63 -            self._cache[klass] = meth
    1.64 -##        if self.VERBOSE > 0:
    1.65 -##            className = klass.__name__
    1.66 -##            if self.VERBOSE == 1:
    1.67 -##                if meth == 0:
    1.68 -##                    print "dispatch", className
    1.69 -##            else:
    1.70 -##                print "dispatch", className, (meth and meth.__name__ or '')
    1.71 -        return meth(node, *args)
    1.72 +        try:
    1.73 +            return node.visit(self.visitor, *args)
    1.74 +        except AttributeError:
    1.75 +            return self.visitor.default(node, *args)
    1.76  
    1.77      def preorder(self, tree, visitor, *args):
    1.78 -        """Do preorder walk of tree using visitor"""
    1.79 +
    1.80 +        "Do preorder walk of tree using visitor."
    1.81 +
    1.82          self.visitor = visitor
    1.83          visitor.visit = self.dispatch
    1.84 -        self.dispatch(tree, *args) # XXX *args make sense?
    1.85 -
    1.86 -class ExampleASTVisitor(ASTVisitor):
    1.87 -    """Prints examples of the nodes that aren't visited
    1.88 -
    1.89 -    This visitor-driver is only useful for development, when it's
    1.90 -    helpful to develop a visitor incrementally, and get feedback on what
    1.91 -    you still have to do.
    1.92 -    """
    1.93 -    examples = {}
    1.94  
    1.95 -    def dispatch(self, node, *args):
    1.96 -        self.node = node
    1.97 -        meth = self._cache.get(node.__class__, None)
    1.98 -        className = node.__class__.__name__
    1.99 -        if meth is None:
   1.100 -            meth = getattr(self.visitor, 'visit' + className, 0)
   1.101 -            self._cache[node.__class__] = meth
   1.102 -        if self.VERBOSE > 1:
   1.103 -            print "dispatch", className, (meth and meth.__name__ or '')
   1.104 -        if meth:
   1.105 -            meth(node, *args)
   1.106 -        elif self.VERBOSE > 0:
   1.107 -            klass = node.__class__
   1.108 -            if not self.examples.has_key(klass):
   1.109 -                self.examples[klass] = klass
   1.110 -                print
   1.111 -                print self.visitor
   1.112 -                print klass
   1.113 -                for attr in dir(node):
   1.114 -                    if attr[0] != '_':
   1.115 -                        print "\t", "%-12.12s" % attr, getattr(node, attr)
   1.116 -                print
   1.117 -            return self.default(node, *args)
   1.118 +        # NOTE: *args not exposed by the walk function.
   1.119  
   1.120 -# XXX this is an API change
   1.121 +        self.dispatch(tree, *args)
   1.122  
   1.123  _walker = ASTVisitor
   1.124 -def walk(tree, visitor, walker=None, verbose=None):
   1.125 +
   1.126 +def walk(tree, visitor, walker=None):
   1.127      if walker is None:
   1.128          walker = _walker()
   1.129 -    if verbose is not None:
   1.130 -        walker.VERBOSE = verbose
   1.131      walker.preorder(tree, visitor)
   1.132      return walker.visitor
   1.133  
   1.134 -def dumpNode(node):
   1.135 -    print node.__class__
   1.136 -    for attr in dir(node):
   1.137 -        if attr[0] != '_':
   1.138 -            print "\t", "%-10.10s" % attr, getattr(node, attr)
   1.139 +# vim: tabstop=4 expandtab shiftwidth=4