pre-compute visitor method names on node classes
Store the visitor method name (e.g. "visit_If") as _visit_name on each node class at definition time. This avoids an f-string format on every one of the ~500K visitor dispatch calls per compile.
This commit is contained in:
parent
4b6c3d6f4f
commit
5e110ec0d9
@ -65,6 +65,7 @@ class NodeType(type):
|
||||
assert len(storage) == len(set(storage)), "layout conflict"
|
||||
d[attr] = tuple(storage)
|
||||
d.setdefault("abstract", False)
|
||||
d["_visit_name"] = f"visit_{name}"
|
||||
return type.__new__(mcs, name, bases, d)
|
||||
|
||||
def _classify_fields(cls, ns: dict[str, t.Any]) -> None:
|
||||
@ -191,7 +192,9 @@ class Node(metaclass=NodeType):
|
||||
attributes: tuple[str, ...] = ("lineno", "environment")
|
||||
abstract = True
|
||||
|
||||
#: Pre-classified field tuples, set by _init_field_classifications().
|
||||
#: Pre-computed visitor method name and field tuples, set at class
|
||||
#: definition time by the metaclass and _init_field_classifications().
|
||||
_visit_name: t.ClassVar[str]
|
||||
_node_fields: t.ClassVar[tuple[str, ...]]
|
||||
_node_list_fields: t.ClassVar[tuple[str, ...]]
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@ class NodeVisitor:
|
||||
exists for this node. In that case the generic visit function is
|
||||
used instead.
|
||||
"""
|
||||
return getattr(self, f"visit_{type(node).__name__}", None)
|
||||
return getattr(self, type(node)._visit_name, None)
|
||||
|
||||
def visit(self, node: Node, *args: t.Any, **kwargs: t.Any) -> t.Any:
|
||||
"""Visit a node."""
|
||||
|
||||
Loading…
Reference in New Issue
Block a user