from ailment.expression import Convert, BinaryOp, Const, UnaryOp

from .base import PeepholeOptimizationExprBase


class OneSubBool(PeepholeOptimizationExprBase):
    __slots__ = ()

    NAME = "1 - bool_expr => !bool_expr"
    expr_classes = (BinaryOp,)  # all expressions are allowed

    def optimize(self, expr: BinaryOp, **kwargs):
        # Sub(1, Conv(1->N, some bool expression)) ==> Conv(1->N, Not(some bool expression))
        if (
            expr.op == "Sub"
            and isinstance(expr.operands[0], Const)
            and expr.operands[0].value == 1
            and isinstance(expr.operands[1], Convert)
            and expr.operands[1].from_bits == 1
        ):
            conv_expr = expr.operands[1]
            if self.is_bool_expr(conv_expr.operand):
                new_expr = Convert(
                    None,
                    1,
                    conv_expr.to_bits,
                    conv_expr.is_signed,
                    UnaryOp(None, "Not", conv_expr.operand, **conv_expr.operand.tags),
                    **conv_expr.tags,
                )
                return new_expr

        return None
