"""Function to visit the tree of ExpressionsMichel Bierlaire15.04.2025 12:55"""fromtypingimportAnyfrom.base_expressionsimportExpression
[docs]classExpressionVisitor:"""Walks the tree and executes side-effect handlers with no return values."""def__init__(self):self._registry={}
[docs]defregister(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 """defdecorator(func):self._registry[expr_type]=funcreturnfuncreturndecorator
[docs]defvisit(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 """ifcontextisNone:context={}if'ancestors'notincontext:context['ancestors']=[]context['ancestors'].append(expr)handler=self._registry.get(type(expr))ifhandler:result=handler(expr,context)ifresultisnotNone:raiseTypeError(f"Handler for {type(expr).__name__} must return None, got {type(result).__name__}")forchildinexpr.get_children():self.visit(child,context)context['ancestors'].pop()