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))

Roundup Issue Tracker: http://roundup-tracker.org/