diff --git a/src/spellbind/bool_values.py b/src/spellbind/bool_values.py index 90590c7..f21e79e 100644 --- a/src/spellbind/bool_values.py +++ b/src/spellbind/bool_values.py @@ -4,15 +4,35 @@ from abc import ABC from typing import TypeVar, Generic -from spellbind.values import Value, OneToOneValue, Constant, SimpleVariable +from spellbind.values import Value, OneToOneValue, Constant, SimpleVariable, TwoToOneValue _S = TypeVar('_S') +BoolLike = Value[bool] | bool + class BoolValue(Value[bool], ABC): def logical_not(self) -> BoolValue: return NotBoolValue(self) + def __and__(self, other: BoolLike) -> BoolValue: + return AndBoolValues(self, other) + + def __rand__(self, other: bool) -> BoolValue: + return AndBoolValues(other, self) + + def __or__(self, other: BoolLike) -> BoolValue: + return OrBoolValues(self, other) + + def __ror__(self, other: bool) -> BoolValue: + return OrBoolValues(other, self) + + def __xor__(self, other: BoolLike) -> BoolValue: + return XorBoolValues(self, other) + + def __rxor__(self, other: bool) -> BoolValue: + return XorBoolValues(other, self) + class OneToBoolValue(OneToOneValue[_S, bool], BoolValue, Generic[_S]): pass @@ -23,6 +43,21 @@ def __init__(self, value: Value[bool]): super().__init__(operator.not_, value) +class AndBoolValues(TwoToOneValue[bool, bool, bool], BoolValue): + def __init__(self, left: BoolLike, right: BoolLike): + super().__init__(operator.and_, left, right) + + +class OrBoolValues(TwoToOneValue[bool, bool, bool], BoolValue): + def __init__(self, left: BoolLike, right: BoolLike): + super().__init__(operator.or_, left, right) + + +class XorBoolValues(TwoToOneValue[bool, bool, bool], BoolValue): + def __init__(self, left: BoolLike, right: BoolLike): + super().__init__(operator.xor, left, right) + + class BoolConstant(BoolValue, Constant[bool]): pass diff --git a/tests/test_values/test_bool_values/test_logical_operators_bool_values.py b/tests/test_values/test_bool_values/test_logical_operators_bool_values.py new file mode 100644 index 0000000..45376a5 --- /dev/null +++ b/tests/test_values/test_bool_values/test_logical_operators_bool_values.py @@ -0,0 +1,145 @@ +from spellbind.bool_values import BoolVariable + + +def test_bool_variables_and_variable_true_variable_true(): + var1 = BoolVariable(True) + var2 = BoolVariable(True) + result = var1 & var2 + assert result.value + + var1.value = False + assert not result.value + + +def test_bool_variables_and_variable_true_variable_false(): + var1 = BoolVariable(True) + var2 = BoolVariable(False) + result = var1 & var2 + assert not result.value + + var2.value = True + assert result.value + + +def test_bool_variables_and_variable_false_variable_false(): + var1 = BoolVariable(False) + var2 = BoolVariable(False) + result = var1 & var2 + assert not result.value + + var1.value = True + assert not result.value + + +def test_bool_variable_and_variable_true_literal_false(): + var = BoolVariable(True) + result = var & False + assert not result.value + + var.value = False + assert not result.value + + +def test_bool_variable_and_literal_false_variable_true(): + var = BoolVariable(True) + result = False & var + assert not result.value + + var.value = False + assert not result.value + + +def test_bool_variables_or_variable_true_variable_true(): + var1 = BoolVariable(True) + var2 = BoolVariable(True) + result = var1 | var2 + assert result.value + + var1.value = False + assert result.value + + +def test_bool_variables_or_variable_true_variable_false(): + var1 = BoolVariable(True) + var2 = BoolVariable(False) + result = var1 | var2 + assert result.value + + var1.value = False + assert not result.value + + +def test_bool_variables_or_variable_false_variable_false(): + var1 = BoolVariable(False) + var2 = BoolVariable(False) + result = var1 | var2 + assert not result.value + + var2.value = True + assert result.value + + +def test_bool_variable_or_variable_false_literal_true(): + var = BoolVariable(False) + result = var | True + assert result.value + + var.value = True + assert result.value + + +def test_bool_variable_or_literal_true_variable_false(): + var = BoolVariable(False) + result = True | var + assert result.value + + var.value = True + assert result.value + + +def test_bool_variables_xor_variable_true_variable_true(): + var1 = BoolVariable(True) + var2 = BoolVariable(True) + result = var1 ^ var2 + assert not result.value + + var1.value = False + assert result.value + + +def test_bool_variables_xor_variable_true_variable_false(): + var1 = BoolVariable(True) + var2 = BoolVariable(False) + result = var1 ^ var2 + assert result.value + + var2.value = True + assert not result.value + + +def test_bool_variables_xor_variable_false_variable_false(): + var1 = BoolVariable(False) + var2 = BoolVariable(False) + result = var1 ^ var2 + assert not result.value + + var1.value = True + assert result.value + + +def test_bool_variable_xor_variable_true_literal_true(): + var = BoolVariable(True) + result = var ^ True + assert not result.value + + var.value = False + assert result.value + + +def test_bool_variable_xor_literal_true_variable_true(): + var = BoolVariable(True) + result = True ^ var + assert not result.value + + var.value = False + assert result.value