[Zope-CVS] CVS: Packages/pypes/pypes - expression.py:1.12

Casey Duncan casey at zope.com
Wed Apr 21 01:26:23 EDT 2004


Update of /cvs-repository/Packages/pypes/pypes
In directory cvs.zope.org:/tmp/cvs-serv11141

Modified Files:
	expression.py 
Log Message:
Add __eq__, __and__ and __or__ support for comparing and combining expressions


=== Packages/pypes/pypes/expression.py 1.11 => 1.12 ===
--- Packages/pypes/pypes/expression.py:1.11	Tue Apr 13 00:21:31 2004
+++ Packages/pypes/pypes/expression.py	Wed Apr 21 01:25:52 2004
@@ -18,10 +18,12 @@
 import sys
 import __builtin__
 from sets import Set
+from copy import deepcopy
 from compiler import parse, ast
 from compiler.pycodegen import ExpressionCodeGenerator
 from zope.interface import implements
 from pypes.interfaces import IExpression
+from pypes.exceptions import PypesError
 
 class Expression(object):
     """Encapsulation of an expression and namespace for later evaluation"""
@@ -65,6 +67,10 @@
         tree.filename = '<pypes expression>' # ECG requires filename attr
         self._code = ExpressionCodeGenerator(tree).getCode()
         self._tree = tree
+        
+    def ast(self):
+        """Return the AST root node for the expression"""
+        return self._tree
     
     def names(self, _tree=None, _names=None):
         """Return a set of the names used in the expression"""
@@ -214,6 +220,41 @@
         the expression when constructed.
         """
         return eval(self._code, self._bindings, namespace)
+        
+    def __eq__(self, other):
+        return self is other or (nodesEqual(self._tree, other._tree)
+                                 and self._bindings == other._bindings)
+    
+    def _combineBindings(self, other):
+        """Combine the bindings between self and other. Bindings can only be 
+        combined if names common between them are assigned the same values
+        and unbound names in one are not bound by the other.
+        """
+        self_bound = Set(self._bindings)
+        other_bound = Set(other._bindings)
+        for name in other_bound & self_bound:
+            if self._bindings[name] != other._bindings[name]:
+                raise PypesError('cannot combine expressions, '
+                                 '%s is bound to different values')
+        if ((other_bound - self_bound) & self.names()
+            or (self_bound - other_bound) & other.names()):
+            raise PypesError('cannot combine expressions, '
+                             'unbound names in one are bound by the other')
+        bindings = self._bindings.copy()
+        bindings.update(other._bindings)
+        return bindings
+    
+    def __or__(self, other):
+        left = self.ast().getChildNodes()[0]
+        right = other.ast().getChildNodes()[0]
+        return self.fromAstNode(
+            ast.Or((left, right)), self._combineBindings(other))
+    
+    def __and__(self, other):
+        left = self.ast().getChildNodes()[0]
+        right = other.ast().getChildNodes()[0]
+        return self.fromAstNode(
+            ast.And((left, right)), self._combineBindings(other))
     
     def __str__(self):
         return "Expression('%s')" % self._expr




More information about the Zope-CVS mailing list