parallel class structures for AST-based objects
Diez B. Roggisch
deets at nospam.web.de
Sun Nov 22 04:50:27 EST 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