summaryrefslogtreecommitdiff
path: root/external/construct/lib/expr.py
blob: 783c94789c411349687effc9f39ab0fea91bcba9 (plain) (blame)
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
156
157
158
159
160
161
162
163
164
165
166
import operator

if not hasattr(operator, "div"):
    operator.div = operator.truediv


opnames = {
    operator.add : "+",
    operator.sub : "-",
    operator.mul : "*",
    operator.div : "/",
    operator.floordiv : "//",
    operator.mod : "+",
    operator.pow : "**",
    operator.xor : "^",
    operator.lshift : "<<",
    operator.rshift : ">>",
    operator.and_ : "and",
    operator.or_ : "or",
    operator.not_ : "not",
    operator.neg : "-",
    operator.pos : "+",
    operator.contains : "in",
    operator.gt : ">",
    operator.ge : ">=",
    operator.lt : "<",
    operator.le : "<=",
    operator.eq : "==",
    operator.ne : "!=",
}


class ExprMixin(object):
    __slots__ = ()
    def __add__(self, other):
        return BinExpr(operator.add, self, other)
    def __sub__(self, other):
        return BinExpr(operator.sub, self, other)
    def __mul__(self, other):
        return BinExpr(operator.mul, self, other)
    def __floordiv__(self, other):
        return BinExpr(operator.floordiv, self, other)
    def __truediv__(self, other):
        return BinExpr(operator.div, self, other)
    __div__ = __floordiv__
    def __mod__(self, other):
        return BinExpr(operator.mod, self, other)
    def __pow__(self, other):
        return BinExpr(operator.pow, self, other)
    def __xor__(self, other):
        return BinExpr(operator.xor, self, other)
    def __rshift__(self, other):
        return BinExpr(operator.rshift, self, other)
    def __lshift__(self, other):
        return BinExpr(operator.rshift, self, other)
    def __and__(self, other):
        return BinExpr(operator.and_, self, other)
    def __or__(self, other):
        return BinExpr(operator.or_, self, other)
    
    def __radd__(self, other):
        return BinExpr(operator.add, other, self)
    def __rsub__(self, other):
        return BinExpr(operator.sub, other, self)
    def __rmul__(self, other):
        return BinExpr(operator.mul, other, self)
    def __rfloordiv__(self, other):
        return BinExpr(operator.floordiv, other, self)
    def __rtruediv__(self, other):
        return BinExpr(operator.div, other, self)
    __rdiv__ = __rfloordiv__
    def __rmod__(self, other):
        return BinExpr(operator.mod, other, self)
    def __rpow__(self, other):
        return BinExpr(operator.pow, other, self)
    def __rxor__(self, other):
        return BinExpr(operator.xor, other, self)
    def __rrshift__(self, other):
        return BinExpr(operator.rshift, other, self)
    def __rlshift__(self, other):
        return BinExpr(operator.rshift, other, self)
    def __rand__(self, other):
        return BinExpr(operator.and_, other, self)
    def __ror__(self, other):
        return BinExpr(operator.or_, other, self)

    def __neg__(self):
        return UniExpr(operator.neg, self)
    def __pos__(self):
        return UniExpr(operator.pos, self)
    def __invert__(self):
        return UniExpr(operator.not_, self)
    __inv__ = __invert__
    
    def __contains__(self, other):
        return BinExpr(operator.contains, self, other)
    def __gt__(self, other):
        return BinExpr(operator.gt, self, other)
    def __ge__(self, other):
        return BinExpr(operator.ge, self, other)
    def __lt__(self, other):
        return BinExpr(operator.lt, self, other)
    def __le__(self, other):
        return BinExpr(operator.le, self, other)
    def __eq__(self, other):
        return BinExpr(operator.eq, self, other)
    def __ne__(self, other):
        return BinExpr(operator.ne, self, other)


class UniExpr(ExprMixin):
    __slots__ = ["op", "operand"]
    def __init__(self, op, operand):
        self.op = op
        self.operand = operand
    def __repr__(self):
        return "%s %r" % (opnames[self.op], self.operand)
    def __call__(self, context):
        operand = self.operand(context) if callable(self.operand) else self.operand
        return self.op(operand)


class BinExpr(ExprMixin):
    __slots__ = ["op", "lhs", "rhs"]
    def __init__(self, op, lhs, rhs):
        self.op = op
        self.lhs = lhs
        self.rhs = rhs
    def __repr__(self):
        return "(%r %s %r)" % (self.lhs, opnames[self.op], self.rhs)
    def __call__(self, context):
        lhs = self.lhs(context) if callable(self.lhs) else self.lhs
        rhs = self.rhs(context) if callable(self.rhs) else self.rhs
        return self.op(lhs, rhs)


class Path(ExprMixin):
    __slots__ = ["__name", "__parent"]
    def __init__(self, name, parent = None):
        self.__name = name
        self.__parent = parent
    def __repr__(self):
        if self.__parent is None:
            return self.__name
        return "%r.%s" % (self.__parent, self.__name)
    def __call__(self, context):
        if self.__parent is None:
            return context
        context2 = self.__parent(context)
        return context2[self.__name]
    def __getattr__(self, name):
        return Path(name, self)


# let the magic begin!
this = Path("this")


if __name__ == "__main__":
    x = ~((this.foo * 2 + 3 << 2) % 11)
    print (x)
    print (x({"foo" : 7}))