diff options
Diffstat (limited to 'external/construct/lib/expr.py')
-rw-r--r-- | external/construct/lib/expr.py | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/external/construct/lib/expr.py b/external/construct/lib/expr.py new file mode 100644 index 0000000..783c947 --- /dev/null +++ b/external/construct/lib/expr.py @@ -0,0 +1,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})) + + + + |