Source code for biogeme.expressions.visitor
"""Function to visit the tree of Expressions
Michel Bierlaire
15.04.2025 12:55
"""
from typing import Any
from .base_expressions import Expression
[docs]
class ExpressionVisitor:
"""Walks the tree and executes side-effect handlers with no return values."""
def __init__(self):
self._registry = {}
[docs]
def register(self, expr_type: type[Expression]):
"""
Register a handler function for a specific expression type. The handler must
return None and perform side effects only.
:param expr_type: the type of Expression for which the handler should be used
:return: decorator that registers the handler
"""
def decorator(func):
self._registry[expr_type] = func
return func
return decorator
[docs]
def visit(self, expr: Expression, context: Any = None) -> None:
"""
Traverse the expression tree and apply handlers for side effects.
:param expr: the root expression to visit
:param context: optional context object passed to handlers
"""
if context is None:
context = {}
if 'ancestors' not in context:
context['ancestors'] = []
context['ancestors'].append(expr)
handler = self._registry.get(type(expr))
if handler:
result = handler(expr, context)
if result is not None:
raise TypeError(
f"Handler for {type(expr).__name__} must return None, got {type(result).__name__}"
)
for child in expr.get_children():
self.visit(child, context)
context['ancestors'].pop()