# Path: krakatau-lib/src/main/resources/Lib/Krakatau/ssa/mixin.py
# class ValueType(object):
#     '''Define _key() and inherit from this class to implement comparison and hashing'''
#     # def __init__(self, *args, **kwargs): super(ValueType, self).__init__(*args, **kwargs)
#     def __eq__(self, other): return type(self) == type(other) and self._key() == other._key()
#     def __ne__(self, other): return type(self) != type(other) or self._key() != other._key()
#     def __hash__(self): return hash(self._key())   


from ..mixin import ValueType

class IntConstraint(ValueType):
    __slots__ = "width min max".split()

    def __init__(self, width, min_, max_):
        self.width = width
        self.min = min_
        self.max = max_
        # self.isBot = (-min_ == max_+1 == (1<<width)//2)

    @staticmethod
    def range(width, min_, max_):
        if min_ > max_:
            return None
        return IntConstraint(width, min_, max_)

    @staticmethod
    def const(width, val):
        return IntConstraint(width, val, val)

    @staticmethod
    def bot(width):
        return IntConstraint(width, -1<<(width-1), (1<<(width-1))-1)

    def _key(self): return self.min, self.max

    def join(*cons):
        xmin = max(c.min for c in cons)
        xmax = min(c.max for c in cons)
        if xmin > xmax:

# Path: krakatau-lib/src/main/resources/Lib/Krakatau/ssa/mixin.py
# class ValueType(object):
#     '''Define _key() and inherit from this class to implement comparison and hashing'''
#     # def __init__(self, *args, **kwargs): super(ValueType, self).__init__(*args, **kwargs)
#     def __eq__(self, other): return type(self) == type(other) and self._key() == other._key()
#     def __ne__(self, other): return type(self) != type(other) or self._key() != other._key()
#     def __hash__(self): return hash(self._key())   


# Path: krakatau-lib/src/main/resources/Lib/Krakatau/ssa/constraints/int_c.py
from ..mixin import ValueType


class IntConstraint(ValueType):
    __slots__ = "width min max".split()

    def __init__(self, width, min_, max_):
        self.width = width
        self.min = min_
        self.max = max_
        # self.isBot = (-min_ == max_+1 == (1<<width)//2)

    @staticmethod
    def range(width, min_, max_):
        if min_ > max_:
            return None
        return IntConstraint(width, min_, max_)

    @staticmethod
    def const(width, val):
        return IntConstraint(width, val, val)

    @staticmethod
    def bot(width):
        return IntConstraint(width, -1<<(width-1), (1<<(width-1))-1)

    def _key(self): return self.min, self.max

    def join(*cons):
        xmin = max(c.min for c in cons)
        xmax = min(c.max for c in cons)
        if xmin > xmax:

            return None