summaryrefslogtreecommitdiff
path: root/deferred_operand.py
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2021-03-24 18:08:54 -0700
committerScott Gasch <[email protected]>2021-03-24 18:08:54 -0700
commit497fb9e21f45ec08e1486abaee6dfa7b20b8a691 (patch)
tree47aa97a0fca36c4e7025cee5ad4e9ec6db49b881 /deferred_operand.py
Initial revision
Diffstat (limited to 'deferred_operand.py')
-rw-r--r--deferred_operand.py152
1 files changed, 152 insertions, 0 deletions
diff --git a/deferred_operand.py b/deferred_operand.py
new file mode 100644
index 0000000..f2af66c
--- /dev/null
+++ b/deferred_operand.py
@@ -0,0 +1,152 @@
+#!/usr/bin/env python3
+
+from abc import ABC, abstractmethod
+from typing import Any, Generic, TypeVar
+
+T = TypeVar('T')
+
+
+class DeferredOperand(ABC, Generic[T]):
+ """A wrapper around an operand whose value is deferred until it is
+ needed. See subclass SmartFuture for an example usage.
+ """
+
+ @abstractmethod
+ def _resolve(self) -> T:
+ pass
+
+ @staticmethod
+ def resolve(x: Any) -> Any:
+ while isinstance(x, DeferredOperand):
+ x = x._resolve()
+ return x
+
+ def __lt__(self, other: Any) -> bool:
+ return DeferredOperand.resolve(self) < DeferredOperand.resolve(other)
+
+ def __le__(self, other: Any) -> bool:
+ return DeferredOperand.resolve(self) <= DeferredOperand.resolve(other)
+
+ def __eq__(self, other: Any) -> bool:
+ return DeferredOperand.resolve(self) == DeferredOperand.resolve(other)
+
+ def __ne__(self, other: Any) -> bool:
+ return DeferredOperand.resolve(self) != DeferredOperand.resolve(other)
+
+ def __gt__(self, other: Any) -> bool:
+ return DeferredOperand.resolve(self) > DeferredOperand.resolve(other)
+
+ def __ge__(self, other: Any) -> bool:
+ return DeferredOperand.resolve(self) >= DeferredOperand.resolve(other)
+
+ def __not__(self) -> bool:
+ return not DeferredOperand.resolve(self)
+
+ def bool(self) -> bool:
+ return DeferredOperand.resolve(self)
+
+ def __add__(self, other: Any) -> T:
+ return DeferredOperand.resolve(self) + DeferredOperand.resolve(other)
+
+ def __iadd__(self, other: Any) -> T:
+ return DeferredOperand.resolve(self) + DeferredOperand.resolve(other)
+
+ def __radd__(self, other: Any) -> T:
+ return DeferredOperand.resolve(self) + DeferredOperand.resolve(other)
+
+ def __sub__(self, other: Any) -> T:
+ return DeferredOperand.resolve(self) - DeferredOperand.resolve(other)
+
+ def __mul__(self, other: Any) -> T:
+ return DeferredOperand.resolve(self) * DeferredOperand.resolve(other)
+
+ def __pow__(self, other: Any) -> T:
+ return DeferredOperand.resolve(self) ** DeferredOperand.resolve(other)
+
+ def __truediv__(self, other: Any) -> Any:
+ return DeferredOperand.resolve(self) / DeferredOperand.resolve(other)
+
+ def __floordiv__(self, other: Any) -> T:
+ return DeferredOperand.resolve(self) // DeferredOperand.resolve(other)
+
+ def __contains__(self, other):
+ return DeferredOperand.resolve(other) in DeferredOperand.resolve(self)
+
+ def and_(self, other):
+ return DeferredOperand.resolve(self) & DeferredOperand.resolve(other)
+
+ def or_(self, other):
+ return DeferredOperand.resolve(self) & DeferredOperand.resolve(other)
+
+ def xor(self, other):
+ return DeferredOperand.resolve(self) & DeferredOperand.resolve(other)
+
+ def invert(self):
+ return ~(DeferredOperand.resolve(self))
+
+ def is_(self, other):
+ return DeferredOperand.resolve(self) is DeferredOperand.resolve(other)
+
+ def is_not(self, other):
+ return DeferredOperand.resolve(self) is not DeferredOperand.resolve(other)
+
+ def __abs__(self):
+ return abs(DeferredOperand.resolve(self))
+
+ def setitem(self, k, v):
+ DeferredOperand.resolve(self)[DeferredOperand.resolve(k)] = v
+
+ def delitem(self, k):
+ del DeferredOperand.resolve(self)[DeferredOperand.resolve(k)]
+
+ def getitem(self, k):
+ return DeferredOperand.resolve(self)[DeferredOperand.resolve(k)]
+
+ def lshift(self, other):
+ return DeferredOperand.resolve(self) << DeferredOperand.resolve(other)
+
+ def rshift(self, other):
+ return DeferredOperand.resolve(self) >> DeferredOperand.resolve(other)
+
+ def mod(self, other):
+ return DeferredOperand.resolve(self) % DeferredOperand.resolve(other)
+
+ def matmul(self, other):
+ return DeferredOperand.resolve(self) @ DeferredOperand.resolve(other)
+
+ def neg(self):
+ return -(DeferredOperand.resolve(self))
+
+ def pos(self):
+ return +(DeferredOperand.resolve(self))
+
+ def truth(self):
+ return DeferredOperand.resolve(self)
+
+ def __hash__(self):
+ return DeferredOperand.resolve(self).__hash__()
+
+ def __call__(self):
+ return DeferredOperand.resolve(self)()
+
+ def __iter__(self):
+ return DeferredOperand.resolve(self).__iter__()
+
+ def __repr__(self) -> str:
+ return DeferredOperand.resolve(self).__repr__()
+
+ def __bytes__(self) -> bytes:
+ return DeferredOperand.resolve(self).__bytes__()
+
+ def __int__(self) -> int:
+ return int(DeferredOperand.resolve(self))
+
+ def __float__(self) -> float:
+ return float(DeferredOperand.resolve(self))
+
+ def __getattr__(self, method_name):
+ def method(*args, **kwargs):
+ return getattr(DeferredOperand.resolve(self), method_name)(
+ *args, **kwargs
+ )
+ return method