import abc from collections.abc import Callable, Mapping from .types import FunctionType, OperatorType, ValueType class Expression(abc.ABC): _evaluator: Callable[[Mapping[str, ValueType]], ValueType] def evaluate(self, variables: Mapping[str, ValueType]): return self._evaluator(variables) class ValueExpression(Expression): def __init__(self, a: str | ValueType): self.__debug_a = a if isinstance(a, str): self._evaluator = lambda vars: vars[a] else: self._evaluator = lambda _: a def __repr__(self): return f"<{self.__debug_a}>" class UnaryExpression(Expression): def __init__(self, function: FunctionType, a: Expression): self.__debug_f = function.__name__ self.__debug_a = repr(a) self._evaluator = lambda vars: function(a.evaluate(vars)) def __repr__(self): return f"<{self.__debug_f}({self.__debug_a})>" class BinaryExpression(Expression): def __init__( self, function: OperatorType, a: Expression, b: Expression, ): self.__debug_f = function.__name__ self.__debug_a = repr(a) self.__debug_b = repr(b) self._evaluator = lambda vars: function(a.evaluate(vars), b.evaluate(vars)) def __repr__(self): return f"<{self.__debug_a} {self.__debug_f} {self.__debug_b}>"