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:
tobymao 2026-03-21 23:36:50 -07:00
parent 4b6c3d6f4f
commit 5e110ec0d9
No known key found for this signature in database
GPG Key ID: 5B3B30F3BACB48DC
2 changed files with 5 additions and 2 deletions

View File

@ -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, ...]]

View File

@ -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."""