import operator
import typing as t

from construct.core import *

UniOperator = t.Callable[[t.Any], t.Any]
BinOperator = t.Callable[[t.Any, t.Any], t.Any]

ReturnType = t.TypeVar("ReturnType")
LhsReturnType = t.TypeVar("LhsReturnType")
RhsReturnType = t.TypeVar("RhsReturnType")

ConstOrCallable = t.Union[ReturnType, t.Callable[[ReturnType], ReturnType]]


class ExprMixin(t.Generic[ReturnType], object):
    # __add__ ##########################################################################################################
    @t.overload
    def __add__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __add__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __add__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __add__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __add__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[float]: ...
    @t.overload
    def __add__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[float]: ...
    @t.overload
    def __add__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[float]: ...
    @t.overload

    # __sub__ ##########################################################################################################
    @t.overload
    def __sub__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __sub__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __sub__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __sub__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __sub__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[float]: ...
    @t.overload
    def __sub__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[float]: ...
    @t.overload
    def __sub__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[float]: ...
    @t.overload
    def __sub__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __mul__ ##########################################################################################################
    @t.overload
    def __mul__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __mul__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __mul__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __mul__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __mul__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[float]: ...
    @t.overload
    def __mul__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[float]: ...
    @t.overload
    def __mul__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[float]: ...
    @t.overload
    def __mul__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __floordiv__ #####################################################################################################
    @t.overload
    def __floordiv__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __floordiv__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __floordiv__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __floordiv__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __floordiv__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[float]: ...
    @t.overload
    def __floordiv__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[float]: ...
    @t.overload
    def __floordiv__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[float]: ...
    @t.overload
    def __floordiv__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __truediv__ ######################################################################################################
    @t.overload
    def __truediv__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[float]: ...
    @t.overload
    def __truediv__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[float]: ...
    @t.overload
    def __truediv__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[float]: ...
    @t.overload
    def __truediv__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[float]: ...
    @t.overload
    def __truediv__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[float]: ...
    @t.overload
    def __truediv__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[float]: ...
    @t.overload
    def __truediv__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[float]: ...
    @t.overload
    def __truediv__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __div__ ##########################################################################################################
    def __div__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __mod__ ##########################################################################################################
    @t.overload
    def __mod__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __mod__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __mod__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __mod__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __mod__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[float]: ...
    @t.overload
    def __mod__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[float]: ...
    @t.overload
    def __mod__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[float]: ...
    @t.overload
    def __mod__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __pow__ ##########################################################################################################
    @t.overload
    def __pow__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __pow__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __pow__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __pow__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __pow__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[float]: ...
    @t.overload
    def __pow__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[float]: ...
    @t.overload
    def __pow__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[float]: ...
    @t.overload
    def __pow__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __xor__ ##########################################################################################################
    @t.overload
    def __xor__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __xor__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __xor__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __xor__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __rshift__ #######################################################################################################
    @t.overload
    def __rshift__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rshift__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __rshift__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rshift__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __rshift__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __lshift__ #######################################################################################################
    @t.overload
    def __lshift__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __lshift__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __lshift__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __lshift__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __lshift__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __and__ ##########################################################################################################
    @t.overload
    def __and__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __and__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __and__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __and__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __or__ ###########################################################################################################
    @t.overload
    def __or__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __or__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __or__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __or__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __radd__ #########################################################################################################
    @t.overload
    def __radd__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __radd__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __radd__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __radd__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __radd__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[float]: ...
    @t.overload
    def __radd__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[float]: ...
    @t.overload
    def __radd__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[float]: ...
    @t.overload
    def __radd__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __rsub__ #########################################################################################################
    @t.overload
    def __rsub__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rsub__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __rsub__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rsub__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __rsub__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[float]: ...
    @t.overload
    def __rsub__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[float]: ...
    @t.overload
    def __rsub__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[float]: ...
    @t.overload
    def __rsub__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __rmul__ #########################################################################################################
    @t.overload
    def __rmul__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rmul__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __rmul__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rmul__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __rmul__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[float]: ...
    @t.overload
    def __rmul__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[float]: ...
    @t.overload
    def __rmul__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[float]: ...
    @t.overload
    def __rmul__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __rfloordiv__ ####################################################################################################
    @t.overload
    def __rfloordiv__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rfloordiv__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __rfloordiv__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rfloordiv__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __rfloordiv__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[float]: ...
    @t.overload
    def __rfloordiv__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[float]: ...
    @t.overload
    def __rfloordiv__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[float]: ...
    @t.overload
    def __rfloordiv__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __rtruediv__ #####################################################################################################
    @t.overload
    def __rtruediv__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[float]: ...
    @t.overload
    def __rtruediv__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[float]: ...
    @t.overload
    def __rtruediv__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[float]: ...
    @t.overload
    def __rtruediv__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[float]: ...
    @t.overload
    def __rtruediv__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[float]: ...
    @t.overload
    def __rtruediv__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[float]: ...
    @t.overload
    def __rtruediv__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[float]: ...
    @t.overload
    def __rtruediv__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __rdiv__ #########################################################################################################
    def __rdiv__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __rmod__ #########################################################################################################
    @t.overload
    def __rmod__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rmod__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __rmod__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rmod__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __rmod__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[float]: ...
    @t.overload
    def __rmod__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[float]: ...
    @t.overload
    def __rmod__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[float]: ...
    @t.overload
    def __rmod__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __rpow__ #########################################################################################################
    @t.overload
    def __rpow__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rpow__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __rpow__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rpow__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __rpow__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[float]: ...
    @t.overload
    def __rpow__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[float]: ...
    @t.overload
    def __rpow__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[float]: ...
    @t.overload
    def __rpow__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __rxor__ #########################################################################################################
    @t.overload
    def __rxor__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rxor__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __rxor__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rxor__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __rrshift__ ######################################################################################################
    @t.overload
    def __rrshift__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rrshift__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __rrshift__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rrshift__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __rrshift__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __rlshift__ ######################################################################################################
    @t.overload
    def __rlshift__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rlshift__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __rlshift__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rlshift__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __rlshift__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __rand__ #########################################################################################################
    @t.overload
    def __rand__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rand__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __rand__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __rand__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __ror__ ##########################################################################################################
    @t.overload
    def __ror__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __ror__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[int]: ...
    @t.overload
    def __ror__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[int]: ...
    @t.overload
    def __ror__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __contains__ #####################################################################################################
    def __contains__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __gt__ ###########################################################################################################
    @t.overload
    def __gt__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[bool]: ...
    @t.overload
    def __gt__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[bool]: ...
    @t.overload
    def __gt__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[bool]: ...
    @t.overload
    def __gt__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[bool]: ...
    @t.overload
    def __gt__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[bool]: ...
    @t.overload
    def __gt__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[bool]: ...
    @t.overload
    def __gt__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[bool]: ...
    @t.overload
    def __gt__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __ge__ ###########################################################################################################
    @t.overload
    def __ge__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[bool]: ...
    @t.overload
    def __ge__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[bool]: ...
    @t.overload
    def __ge__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[bool]: ...
    @t.overload
    def __ge__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[bool]: ...
    @t.overload
    def __ge__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[bool]: ...
    @t.overload
    def __ge__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[bool]: ...
    @t.overload
    def __ge__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[bool]: ...
    @t.overload
    def __ge__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __lt__ ###########################################################################################################
    @t.overload
    def __lt__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[bool]: ...
    @t.overload
    def __lt__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[bool]: ...
    @t.overload
    def __lt__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[bool]: ...
    @t.overload
    def __lt__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[bool]: ...
    @t.overload
    def __lt__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[bool]: ...
    @t.overload
    def __lt__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[bool]: ...
    @t.overload
    def __lt__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[bool]: ...
    @t.overload
    def __lt__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __le__ ###########################################################################################################
    @t.overload
    def __le__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[bool]: ...
    @t.overload
    def __le__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[bool]: ...
    @t.overload
    def __le__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[bool]: ...
    @t.overload
    def __le__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[bool]: ...
    @t.overload
    def __le__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[bool]: ...
    @t.overload
    def __le__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[bool]: ...
    @t.overload
    def __le__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[bool]: ...
    @t.overload
    def __le__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __eq__ ###########################################################################################################
    @t.overload
    def __eq__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[bool]: ...
    @t.overload
    def __eq__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[bool]: ...
    @t.overload
    def __eq__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[bool]: ...
    @t.overload
    def __eq__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[bool]: ...
    @t.overload
    def __eq__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[bool]: ...
    @t.overload
    def __eq__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[bool]: ...
    @t.overload
    def __eq__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[bool]: ...
    @t.overload
    def __eq__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __ne__ ###########################################################################################################
    @t.overload
    def __ne__(self: ExprMixin[int], other: ConstOrCallable[int]) -> BinExpr[bool]: ...
    @t.overload
    def __ne__(self: ExprMixin[int], other: ConstOrCallable[bool]) -> BinExpr[bool]: ...
    @t.overload
    def __ne__(self: ExprMixin[bool], other: ConstOrCallable[int]) -> BinExpr[bool]: ...
    @t.overload
    def __ne__(self: ExprMixin[bool], other: ConstOrCallable[bool]) -> BinExpr[bool]: ...
    @t.overload
    def __ne__(self: ExprMixin[float], other: ConstOrCallable[int]) -> BinExpr[bool]: ...
    @t.overload
    def __ne__(self: ExprMixin[float], other: ConstOrCallable[bool]) -> BinExpr[bool]: ...
    @t.overload
    def __ne__(self: ExprMixin[float], other: ConstOrCallable[float]) -> BinExpr[bool]: ...
    @t.overload
    def __ne__(self, other: t.Any) -> BinExpr[t.Any]: ...

    # __neg__ ##########################################################################################################
    @t.overload
    def __neg__(self: ExprMixin[int]) -> BinExpr[int]: ...
    @t.overload
    def __neg__(self: ExprMixin[bool]) -> BinExpr[int]: ...
    @t.overload
    def __neg__(self: ExprMixin[float]) -> BinExpr[float]: ...
    @t.overload
    def __neg__(self) -> UniExpr[t.Any]: ...

    # __pos__ ##########################################################################################################
    @t.overload
    def __pos__(self: ExprMixin[int]) -> BinExpr[int]: ...
    @t.overload
    def __pos__(self: ExprMixin[bool]) -> BinExpr[int]: ...
    @t.overload
    def __pos__(self: ExprMixin[float]) -> BinExpr[float]: ...
    @t.overload
    def __pos__(self) -> UniExpr[t.Any]: ...

    # __invert__ #######################################################################################################
    @t.overload
    def __invert__(self: ExprMixin[int]) -> BinExpr[int]: ...
    @t.overload
    def __invert__(self: ExprMixin[bool]) -> BinExpr[int]: ...
    @t.overload
    def __invert__(self) -> UniExpr[t.Any]: ...

    # __inv__ ##########################################################################################################
    def __inv__(self) -> UniExpr[t.Any]: ...

class UniExpr(ExprMixin[ReturnType]):
    def __init__(self, op: UniOperator, operand: t.Any) -> None: ...
    def __call__(self, obj: t.Union[Context, dict[str, t.Any], t.Any], *args: t.Any) -> ReturnType: ...

class BinExpr(ExprMixin[ReturnType]):
    def __init__(self, op: BinOperator, lhs: t.Any, rhs: t.Any) -> None: ...
    def __call__(self, obj: t.Union[Context, dict[str, t.Any], t.Any], *args: t.Any) -> ReturnType: ...

class Path(ExprMixin[ReturnType]):
    def __init__(self, name: str, field: t.Optional[str] = ..., parent: t.Optional[Path[t.Any]] = ...) -> None: ...
    def __call__(self, obj: t.Union[Context, dict[str, t.Any], t.Any], *args: t.Any) -> ReturnType: ...
    def __getattr__(self, name: str) -> Path[t.Any]: ...
    def __getitem__(self, name: str) -> Path[t.Any]: ...


class Path2(ExprMixin[ReturnType]):
    def __init__(self, name: str, index: t.Optional[int] = ..., parent: t.Optional[Path2[t.Any]] = ...) -> None: ...
    def __call__(self, *args: t.Any) -> ReturnType: ...
    def __getitem__(self, index: int) -> Path2[t.Any]: ...


class FuncPath(ExprMixin[ReturnType]):
    def __init__(self, func: t.Callable[[t.Any], ReturnType], operand: t.Optional[t.Any] = ...) -> None: ...
    def __call__(self, operand: t.Any, *args: t.Any) -> ReturnType: ...


this: Path[t.Any]
obj_: Path[t.Any]
list_: Path2[t.Any]

len_: FuncPath[int]
sum_: FuncPath[int]
min_: FuncPath[int]
max_: FuncPath[int]
abs_: FuncPath[int]
