Skip to content

Add a read-only visitor pattern. #96

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions fluent.syntax/fluent/syntax/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,36 @@
import json


class Visitor(object):
'''Read-only visitor pattern.

Subclass this to gather information from an AST.
To generally define which nodes not to descend in to, overload
`generic_visit`.
To handle specific node types, add methods like `visit_Pattern`.
The boolean value of the returned value determines if the visitor
descends into the children of the given AST node.
'''
def visit(self, value):
if isinstance(value, BaseNode):
self.visit_node(value)
if isinstance(value, list):
for node in value:
self.visit(node)

def visit_node(self, node):
nodename = type(node).__name__
visit = getattr(self, 'visit_{}'.format(nodename), self.generic_visit)
should_descend = visit(node)
if not should_descend:
return
for propname, propvalue in vars(node).items():
self.visit(propvalue)
Copy link
Contributor

@stasm stasm Feb 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to suggest a slightly more verbose way of writing this method. It's a nit, so feel free to ignore. As you know, I've been trying to promote the idea of self-documenting code in my reviews :) Here, the value I think this brings is that it gives an explicit meaning to the return value of the process_node method.

def visit_node(self, node):
    nodename = type(node).__name__
    process_node = getattr(self, 'visit_{}'.format(nodename), self.generic_visit)
    should_continue = process_node(node)
    if should_continue:
        for propname, propvalue in vars(node).items():
            self.visit(propvalue)


def generic_visit(self, node):
return True


def to_json(value, fn=None):
if isinstance(value, BaseNode):
return value.to_json(fn)
Expand Down
Loading