summaryrefslogtreecommitdiff
path: root/deferred_operand.py
blob: 4b12279b5726a2eb3a97eed1c20b1f708870143b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#!/usr/bin/env python3

from abc import ABC, abstractmethod
from typing import Any, Generic, TypeVar

# This module is commonly used by others in here and should avoid
# taking any unnecessary dependencies back on them.

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