Mercurial > p > roundup > code
diff roundup/mlink_expr.py @ 6401:8bc5faeb7677
Make rev multilink expressions work for anydbm
| author | Ralf Schlatterbeck <rsc@runtux.com> |
|---|---|
| date | Sat, 08 May 2021 12:52:35 +0200 |
| parents | |
| children | a0c0ee3ed8b1 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/roundup/mlink_expr.py Sat May 08 12:52:35 2021 +0200 @@ -0,0 +1,103 @@ +# +# Copyright: 2010 Intevation GmbH. +# 2021 Ralf Schlatterbeck, rsc@runtux.com. +# + +# This module is Free Software under the Roundup licensing, +# see the COPYING.txt file coming with Roundup. +# + +class Binary: + + def __init__(self, x, y): + self.x = x + self.y = y + + def visit(self, visitor): + self.x.visit(visitor) + self.y.visit(visitor) + +class Unary: + + def __init__(self, x): + self.x = x + + def generate(self, atom): + return atom(self) + + def visit(self, visitor): + self.x.visit(visitor) + +class Equals(Unary): + + def evaluate(self, v): + return self.x in v + + def visit(self, visitor): + visitor(self) + +class Empty(Unary): + + def evaluate(self, v): + return not v + + def visit(self, visitor): + visitor(self) + +class Not(Unary): + + def evaluate(self, v): + return not self.x.evaluate(v) + + def generate(self, atom): + return "NOT(%s)" % self.x.generate(atom) + +class Or(Binary): + + def evaluate(self, v): + return self.x.evaluate(v) or self.y.evaluate(v) + + def generate(self, atom): + return "(%s)OR(%s)" % ( + self.x.generate(atom), + self.y.generate(atom)) + +class And(Binary): + + def evaluate(self, v): + return self.x.evaluate(v) and self.y.evaluate(v) + + def generate(self, atom): + return "(%s)AND(%s)" % ( + self.x.generate(atom), + self.y.generate(atom)) + +def compile_expression(opcodes): + + stack = [] + push, pop = stack.append, stack.pop + for opcode in opcodes: + if opcode == -1: push(Empty(opcode)) + elif opcode == -2: push(Not(pop())) + elif opcode == -3: push(And(pop(), pop())) + elif opcode == -4: push(Or(pop(), pop())) + else: push(Equals(opcode)) + + return pop() + +class Expression: + + def __init__(self, v): + try: + opcodes = [int(x) for x in v] + if min(opcodes) >= -1: + raise ValueError() + + compiled = compile_expression(opcodes) + self.evaluate = lambda x: compiled.evaluate([int(y) for y in x]) + except: + if '-1' in v: + v = [x for x in v if int(x) > 0] + self.evaluate = lambda x: bool(set(x) & set(v)) or not x + else: + self.evaluate = lambda x: bool(set(x) & set(v))
