Initial revision
[python_utils.git] / deferred_operand.py
1 #!/usr/bin/env python3
2
3 from abc import ABC, abstractmethod
4 from typing import Any, Generic, TypeVar
5
6 T = TypeVar('T')
7
8
9 class DeferredOperand(ABC, Generic[T]):
10     """A wrapper around an operand whose value is deferred until it is
11     needed.  See subclass SmartFuture for an example usage.
12     """
13
14     @abstractmethod
15     def _resolve(self) -> T:
16         pass
17
18     @staticmethod
19     def resolve(x: Any) -> Any:
20         while isinstance(x, DeferredOperand):
21             x = x._resolve()
22         return x
23
24     def __lt__(self, other: Any) -> bool:
25         return DeferredOperand.resolve(self) < DeferredOperand.resolve(other)
26
27     def __le__(self, other: Any) -> bool:
28         return DeferredOperand.resolve(self) <= DeferredOperand.resolve(other)
29
30     def __eq__(self, other: Any) -> bool:
31         return DeferredOperand.resolve(self) == DeferredOperand.resolve(other)
32
33     def __ne__(self, other: Any) -> bool:
34         return DeferredOperand.resolve(self) != DeferredOperand.resolve(other)
35
36     def __gt__(self, other: Any) -> bool:
37         return DeferredOperand.resolve(self) > DeferredOperand.resolve(other)
38
39     def __ge__(self, other: Any) -> bool:
40         return DeferredOperand.resolve(self) >= DeferredOperand.resolve(other)
41
42     def __not__(self) -> bool:
43         return not DeferredOperand.resolve(self)
44
45     def bool(self) -> bool:
46         return DeferredOperand.resolve(self)
47
48     def __add__(self, other: Any) -> T:
49         return DeferredOperand.resolve(self) + DeferredOperand.resolve(other)
50
51     def __iadd__(self, other: Any) -> T:
52         return DeferredOperand.resolve(self) + DeferredOperand.resolve(other)
53
54     def __radd__(self, other: Any) -> T:
55         return DeferredOperand.resolve(self) + DeferredOperand.resolve(other)
56
57     def __sub__(self, other: Any) -> T:
58         return DeferredOperand.resolve(self) - DeferredOperand.resolve(other)
59
60     def __mul__(self, other: Any) -> T:
61         return DeferredOperand.resolve(self) * DeferredOperand.resolve(other)
62
63     def __pow__(self, other: Any) -> T:
64         return DeferredOperand.resolve(self) ** DeferredOperand.resolve(other)
65
66     def __truediv__(self, other: Any) -> Any:
67         return DeferredOperand.resolve(self) / DeferredOperand.resolve(other)
68
69     def __floordiv__(self, other: Any) -> T:
70         return DeferredOperand.resolve(self) // DeferredOperand.resolve(other)
71
72     def __contains__(self, other):
73         return DeferredOperand.resolve(other) in DeferredOperand.resolve(self)
74
75     def and_(self, other):
76         return DeferredOperand.resolve(self) & DeferredOperand.resolve(other)
77
78     def or_(self, other):
79         return DeferredOperand.resolve(self) & DeferredOperand.resolve(other)
80
81     def xor(self, other):
82         return DeferredOperand.resolve(self) & DeferredOperand.resolve(other)
83
84     def invert(self):
85         return ~(DeferredOperand.resolve(self))
86
87     def is_(self, other):
88         return DeferredOperand.resolve(self) is DeferredOperand.resolve(other)
89
90     def is_not(self, other):
91         return DeferredOperand.resolve(self) is not DeferredOperand.resolve(other)
92
93     def __abs__(self):
94         return abs(DeferredOperand.resolve(self))
95
96     def setitem(self, k, v):
97         DeferredOperand.resolve(self)[DeferredOperand.resolve(k)] = v
98
99     def delitem(self, k):
100         del DeferredOperand.resolve(self)[DeferredOperand.resolve(k)]
101
102     def getitem(self, k):
103         return DeferredOperand.resolve(self)[DeferredOperand.resolve(k)]
104
105     def lshift(self, other):
106         return DeferredOperand.resolve(self) << DeferredOperand.resolve(other)
107
108     def rshift(self, other):
109         return DeferredOperand.resolve(self) >> DeferredOperand.resolve(other)
110
111     def mod(self, other):
112         return DeferredOperand.resolve(self) % DeferredOperand.resolve(other)
113
114     def matmul(self, other):
115         return DeferredOperand.resolve(self) @ DeferredOperand.resolve(other)
116
117     def neg(self):
118         return -(DeferredOperand.resolve(self))
119
120     def pos(self):
121         return +(DeferredOperand.resolve(self))
122
123     def truth(self):
124         return DeferredOperand.resolve(self)
125
126     def __hash__(self):
127         return DeferredOperand.resolve(self).__hash__()
128
129     def __call__(self):
130         return DeferredOperand.resolve(self)()
131
132     def __iter__(self):
133         return DeferredOperand.resolve(self).__iter__()
134
135     def __repr__(self) -> str:
136         return DeferredOperand.resolve(self).__repr__()
137
138     def __bytes__(self) -> bytes:
139         return DeferredOperand.resolve(self).__bytes__()
140
141     def __int__(self) -> int:
142         return int(DeferredOperand.resolve(self))
143
144     def __float__(self) -> float:
145         return float(DeferredOperand.resolve(self))
146
147     def __getattr__(self, method_name):
148         def method(*args, **kwargs):
149             return getattr(DeferredOperand.resolve(self), method_name)(
150                 *args, **kwargs
151             )
152         return method