parallel class structures for AST-based objects

Diez B. Roggisch deets at nospam.web.de
Sun Nov 22 10:50:27 CET 2009


Steve Howell schrieb:
> On Nov 21, 4:07 pm, MRAB <pyt... at mrabarnett.plus.com> wrote:
>> I don't see the point of EvalNode and PrettyPrintNode. Why don't you
>> just give Integer, Sum and Product 'eval' and 'pprint' methods?
> 
> That's a good question, and it's the crux of my design dilemma.  If
> ALL I ever wanted to to with Integer/Sum/Product was to eval() and
> pprint(), then I would just add those methods to Integer, Sum, and
> Product, and be done with it, as you suggest.  But what happens when
> somebody wants to extend capability?  Should every future software
> developer that wants to use Integer/Sum/Product extend those classes
> to get work done?  What if they want to store additional state for
> nodes?
> 

What's usually done is to create visitors/matchers. Those traverse the 
AST, and either only visit, or return transformed versions of it (think 
e.g. algebraic optimization)

A visitor will roughly look like this:


class ASTVisitor(object):



    def visit(self, node):
        name = node.__class__.__name__.lower()
        if hasattr(self, "visit_%s" % name):
            getattr(self, "visit_%s" % name)(node)
        for child in node:
            self.visit(child)



You can of course chose another type of dispatch, using e.g. a generic 
method.

Then you create Visitors for specific tasks - pretty-printing, 
evaluation, rewriting. Those don't have the overhead of your current 
design with all those factory-mapping stuff, and yet you aren't forced 
to put logic into AST you don't want there.


Diez




More information about the Python-list mailing list