Skip to content

Commit 6d6a682

Browse files
committed
Implement BoolValue.select
1 parent 9208971 commit 6d6a682

File tree

6 files changed

+444
-9
lines changed

6 files changed

+444
-9
lines changed

src/spellbind/bool_values.py

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,25 @@
22

33
import operator
44
from abc import ABC
5-
from typing import TypeVar, Generic
5+
from typing import TypeVar, Generic, overload, TYPE_CHECKING, TypeAlias
6+
from spellbind.values import Value, OneToOneValue, Constant, SimpleVariable, TwoToOneValue, SelectValue
67

7-
from spellbind.values import Value, OneToOneValue, Constant, SimpleVariable, TwoToOneValue
8+
if TYPE_CHECKING:
9+
from spellbind.float_values import FloatValue # pragma: no cover
10+
from spellbind.int_values import IntValue # pragma: no cover
11+
from spellbind.str_values import StrValue # pragma: no cover
12+
13+
IntValueLike: TypeAlias = 'IntValue | int'
14+
FloatValueLike: TypeAlias = 'FloatValue | float'
15+
StrValueLike: TypeAlias = 'StrValue | str'
16+
BoolValueLike: TypeAlias = 'BoolValue | bool'
817

918
_S = TypeVar('_S')
1019

11-
BoolLike = Value[bool] | bool
20+
BoolLike = bool | Value[bool]
21+
IntLike = int | Value[int]
22+
FloatLike = float | Value[float]
23+
StrLike = str | Value[str]
1224

1325

1426
class BoolValue(Value[bool], ABC):
@@ -33,6 +45,37 @@ def __xor__(self, other: BoolLike) -> BoolValue:
3345
def __rxor__(self, other: bool) -> BoolValue:
3446
return XorBoolValues(other, self)
3547

48+
@overload
49+
def select(self, if_true: IntValueLike, if_false: IntValueLike) -> IntValue: ...
50+
51+
@overload
52+
def select(self, if_true: FloatValueLike, if_false: FloatValueLike) -> FloatValue: ...
53+
54+
@overload
55+
def select(self, if_true: StrValueLike, if_false: StrValueLike) -> StrValue: ...
56+
57+
@overload
58+
def select(self, if_true: BoolValue, if_false: BoolValue) -> BoolValue: ...
59+
60+
@overload
61+
def select(self, if_true: Value[_S] | _S, if_false: Value[_S] | _S) -> Value[_S]: ...
62+
63+
def select(self, if_true, if_false):
64+
from spellbind.float_values import FloatValue, SelectFloatValue
65+
from spellbind.int_values import IntValue, SelectIntValue
66+
from spellbind.str_values import StrValue, SelectStrValue
67+
68+
if isinstance(if_true, (FloatValue, float)) and isinstance(if_false, (FloatValue, float)):
69+
return SelectFloatValue(self, if_true, if_false)
70+
elif isinstance(if_true, (StrValue, str)) and isinstance(if_false, (StrValue, str)):
71+
return SelectStrValue(self, if_true, if_false)
72+
elif isinstance(if_true, (BoolValue, bool)) and isinstance(if_false, (BoolValue, bool)):
73+
return SelectBoolValue(self, if_true, if_false)
74+
elif isinstance(if_true, (IntValue, int)) and isinstance(if_false, (IntValue, int)):
75+
return SelectIntValue(self, if_true, if_false)
76+
else:
77+
return SelectValue(self, if_true, if_false)
78+
3679

3780
class OneToBoolValue(OneToOneValue[_S, bool], BoolValue, Generic[_S]):
3881
pass
@@ -66,5 +109,10 @@ class BoolVariable(SimpleVariable[bool], BoolValue):
66109
pass
67110

68111

112+
class SelectBoolValue(SelectValue[bool], BoolValue):
113+
def __init__(self, condition: BoolLike, if_true: BoolLike, if_false: BoolLike):
114+
super().__init__(condition, if_true, if_false)
115+
116+
69117
TRUE = BoolConstant(True)
70118
FALSE = BoolConstant(False)

src/spellbind/float_values.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
from typing_extensions import Self
88
from typing_extensions import TYPE_CHECKING
99

10-
from spellbind.bool_values import BoolValue
10+
from spellbind.bool_values import BoolValue, BoolLike
1111
from spellbind.functions import clamp_float, multiply_all_floats
12-
from spellbind.values import Value, SimpleVariable, OneToOneValue, DerivedValueBase, Constant, TwoToOneValue
12+
from spellbind.values import Value, SimpleVariable, OneToOneValue, DerivedValueBase, Constant, TwoToOneValue, \
13+
SelectValue
1314

1415
if TYPE_CHECKING:
1516
from spellbind.int_values import IntValue, IntLike # pragma: no cover
@@ -235,3 +236,8 @@ def __init__(self, left: FloatLike, right: FloatLike, op: Callable[[float, float
235236
class ClampFloatValue(ThreeFloatToOneValue[float], FloatValue):
236237
def __init__(self, value: FloatLike, min_value: FloatLike, max_value: FloatLike):
237238
super().__init__(clamp_float, value, min_value, max_value)
239+
240+
241+
class SelectFloatValue(SelectValue[float], FloatValue):
242+
def __init__(self, condition: BoolLike, if_true: float | Value[float], if_false: float | Value[float]):
243+
super().__init__(condition, if_true, if_false)

src/spellbind/int_values.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77

88
from typing_extensions import Self, TypeVar
99

10-
from spellbind.bool_values import BoolValue
10+
from spellbind.bool_values import BoolValue, BoolLike
1111
from spellbind.float_values import FloatValue, MultiplyFloatValues, DivideValues, SubtractFloatValues, \
1212
AddFloatValues, CompareNumbersValues
1313
from spellbind.functions import clamp_int, multiply_all_ints
1414
from spellbind.values import Value, ManyToOneValue, SimpleVariable, TwoToOneValue, OneToOneValue, Constant, \
15-
ThreeToOneValue
15+
ThreeToOneValue, SelectValue
1616

1717
IntLike = int | Value[int]
1818
FloatLike = IntLike | float | FloatValue
@@ -217,3 +217,8 @@ def __init__(self, value: Value[float]):
217217
class ClampIntValue(ThreeToOneValue[int, int, int, int], IntValue):
218218
def __init__(self, value: IntLike, min_value: IntLike, max_value: IntLike) -> None:
219219
super().__init__(clamp_int, value, min_value, max_value)
220+
221+
222+
class SelectIntValue(SelectValue[int], IntValue):
223+
def __init__(self, condition: BoolLike, if_true: IntLike, if_false: IntLike):
224+
super().__init__(condition, if_true, if_false)

src/spellbind/str_values.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
from abc import ABC
44
from typing import Any, Generic, TypeVar
55

6-
from spellbind.values import Value, OneToOneValue, ManyToOneValue, SimpleVariable, Constant
6+
from spellbind.bool_values import BoolLike, StrLike
7+
from spellbind.values import Value, OneToOneValue, ManyToOneValue, SimpleVariable, Constant, SelectValue
78

89
StringLike = str | Value[str]
910

@@ -41,3 +42,8 @@ def __init__(self, value: Value[Any]):
4142
class ConcatenateStrValues(ManyToOneValue[str, str], StrValue):
4243
def __init__(self, *values: StringLike):
4344
super().__init__(''.join, *values)
45+
46+
47+
class SelectStrValue(SelectValue[str], StrValue):
48+
def __init__(self, condition: BoolLike, if_true: StrLike, if_false: StrLike):
49+
super().__init__(condition, if_true, if_false)

src/spellbind/values.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
if TYPE_CHECKING:
1010
from spellbind.str_values import StrValue # pragma: no cover
1111
from spellbind.int_values import IntValue # pragma: no cover
12-
from spellbind.bool_values import BoolValue # pragma: no cover
12+
from spellbind.bool_values import BoolValue, BoolLike # pragma: no cover
1313

1414

1515
EMPTY_FROZEN_SET: frozenset = frozenset()
@@ -275,3 +275,8 @@ def __init__(self, transformer: Callable[[_S, _T, _U], _V],
275275

276276
def _calculate_value(self) -> _V:
277277
return self._transformer(self._first_getter(), self._second_getter(), self._third_getter())
278+
279+
280+
class SelectValue(ThreeToOneValue[bool, _S, _S, _S], Generic[_S]):
281+
def __init__(self, condition: BoolLike, if_true: Value[_S] | _S, if_false: Value[_S] | _S):
282+
super().__init__(lambda b, t, f: t if b else f, condition, if_true, if_false)

0 commit comments

Comments
 (0)