From 497fb9e21f45ec08e1486abaee6dfa7b20b8a691 Mon Sep 17 00:00:00 2001 From: Scott Gasch Date: Wed, 24 Mar 2021 18:08:54 -0700 Subject: Initial revision --- deferred_operand.py | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 deferred_operand.py (limited to 'deferred_operand.py') 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 -- cgit v1.3