From 9e0b68ed0779025166c83a196c184dea71802d46 Mon Sep 17 00:00:00 2001
From: Andreas Kloeckner <inform@tiker.net>
Date: Mon, 13 Nov 2006 18:39:12 -0500
Subject: [PATCH] [pymbolic @ inform@tiker.net-20061113233912-fc703fc42ec0a232]
 Rewrote mappers to new recursion scheme.

---
 src/mapper/__init__.py       | 74 +++++++++++++++++++-----------------
 src/mapper/dependency.py     |  5 +--
 src/mapper/differentiator.py | 38 +++++++-----------
 src/mapper/evaluator.py      | 34 +++++++++--------
 src/mapper/stringifier.py    | 35 +++++++++--------
 src/mapper/substitutor.py    |  2 +-
 src/polynomial.py            |  3 --
 src/rational.py              | 10 -----
 8 files changed, 93 insertions(+), 108 deletions(-)

diff --git a/src/mapper/__init__.py b/src/mapper/__init__.py
index be8e3c3..2f71ad6 100644
--- a/src/mapper/__init__.py
+++ b/src/mapper/__init__.py
@@ -1,48 +1,53 @@
-class Mapper:
-    def __call__(self, *args, **kwargs):
-class CombineMapper:
+class Mapper(object):
+    def __call__(self, victim, *args, **kwargs):
+        try:
+            victim.invoke_mapper(self, *args, **kwargs)
+        except AttributeError:
+            self.map_constant(victim)
+
+    def map_rational(self, expr):
+        return self.map_quotient(self, expr)
+
+
+
+
+
+class CombineMapper(Mapper):
     def combine(self, values):
         raise NotImplementedError
 
     def map_call(self, expr):
-        return self.combine([expr.function.invoke_mapper(self)] + 
-                            [child.invoke_mapper(self)
-                             for child in expr.parameters])
+        return self.combine([self(expr.function)] + 
+                            [self(child) for child in expr.parameters])
 
     def map_subscript(self, expr):
-        return self.combine([expr.aggregate.invoke_mapper(self),
-                             expr.index.invoke_mapper(self)])
+        return self.combine(
+                [self(expr.aggregate), self(expr.index)])
 
     def map_lookup(self, expr):
-        return expr.aggregate.invoke_mapper(self)
+        return self(expr.aggregate)
 
     def map_negation(self, expr):
-        return expr.child.invoke_mapper(self)
+        return self(expr.child)
 
     def map_sum(self, expr):
-        return self.combine(child.invoke_mapper(self)
-                            for child in expr.children)
+        return self.combine(self(child) for child in expr.children)
 
     map_product = map_sum
 
-    def map_rational(self, expr):
-        return self.combine((expr.numerator.invoke_mapper(self),
-                             expr.denominator.invoke_mapper(self)))
+    def map_quotient(self, expr):
+        return self.combine((self(expr.numerator), self(expr.denominator)))
 
     def map_power(self, expr):
-        return self.combine((expr.base.invoke_mapper(self),
-                             expr.exponent.invoke_mapper(self)))
+        return self.combine(self(expr.base), self(expr.exponent))
 
-    def map_polynomial(self, expr):
-        raise NotImplementedError
-    
     map_list = map_sum
 
 
 
 
 
-class IdentityMapper:
+class IdentityMapper(Mapper):
     def map_constant(self, expr):
         return expr
 
@@ -50,34 +55,33 @@ class IdentityMapper:
         return expr
 
     def map_call(self, expr):
-        return expr.__class__(expr.function.invoke_mapper(self),
-                              tuple(child.invoke_mapper(self)
-                                    for child in expr.parameters))
+        return expr.__class__(
+                self(expr.function),
+                tuple(self(child)
+                    for child in expr.parameters))
 
     def map_subscript(self, expr):
-        return expr.__class__(expr.aggregate.invoke_mapper(self),
-                              expr.index.invoke_mapper(self))
+        return expr.__class__(self(expr.aggregate), self(expr.index))
 
     def map_lookup(self, expr):
-        return expr.__class__(expr.aggregate.invoke_mapper(self),
-                              expr.name)
+        return expr.__class__(self(expr.aggregate), expr.name)
 
     def map_negation(self, expr):
-        return expr.__class__(expr.child.invoke_mapper(self))
+        return expr.__class__(self(expr.child))
 
     def map_sum(self, expr):
-        return expr.__class__(*[child.invoke_mapper(self)
-                                for child in expr.children])
+        return expr.__class__(
+                *[self(child) for child in expr.children])
     
     map_product = map_sum
     
     def map_rational(self, expr):
-        return expr.__class__(expr.numerator.invoke_mapper(self),
-                              expr.denominator.invoke_mapper(self))
+        return expr.__class__(self(expr.numerator),
+                              self(expr.denominator))
 
     def map_power(self, expr):
-        return expr.__class__(expr.base.invoke_mapper(self),
-                              expr.exponent.invoke_mapper(self))
+        return expr.__class__(self(expr.base),
+                              self(expr.exponent))
 
     def map_polynomial(self, expr):
         raise NotImplementedError
diff --git a/src/mapper/dependency.py b/src/mapper/dependency.py
index 524c8c8..cb84a71 100644
--- a/src/mapper/dependency.py
+++ b/src/mapper/dependency.py
@@ -1,6 +1,4 @@
 import sets
-import operator
-
 import pymbolic.mapper
 
 
@@ -8,6 +6,7 @@ import pymbolic.mapper
 
 class DependencyMapper(pymbolic.mapper.CombineMapper):
     def combine(self, values):
+        import operator
         return reduce(operator.or_, values)
 
     def map_constant(self, expr):
@@ -20,7 +19,7 @@ class DependencyMapper(pymbolic.mapper.CombineMapper):
 
 
 def get_dependencies(expr):
-    return expr.invoke_mapper(DependencyMapper())
+    return DependencyMapper()(expr)
 
 
 
diff --git a/src/mapper/differentiator.py b/src/mapper/differentiator.py
index 50f3d7e..855cf26 100644
--- a/src/mapper/differentiator.py
+++ b/src/mapper/differentiator.py
@@ -3,6 +3,7 @@ import cmath
 
 import pymbolic
 import pymbolic.primitives as primitives
+import pymbolic.mapper
 import pymbolic.mapper.evaluator
 
 
@@ -32,7 +33,7 @@ def map_math_functions_by_name(i, func, pars):
 
 
 
-class DifferentiationMapper:
+class DifferentiationMapper(pymbolic.mapper.Mapper):
     def __init__(self, variable, func_map):
         self.Variable = variable
         self.FunctionMap = func_map
@@ -49,24 +50,24 @@ class DifferentiationMapper:
     def map_call(self, expr):
         return pymbolic.sum(*(
             self.FunctionMap(i, expr.function, expr.parameters)
-            * par.invoke_mapper(self)
+            * self(par)
             for i, par in enumerate(expr.parameters)
             if not self._isc(par)))
 
     map_subscript = map_variable
 
     def map_negation(self, expr):
-        return -expr.child.invoke_mapper(self)
+        return -self(expr.child)
 
     def map_sum(self, expr):
-        return pymbolic.sum(*(child.invoke_mapper(self)
+        return pymbolic.sum(*(self(child)
                               for child in expr.children
                               if not self._isc(child)))
 
     def map_product(self, expr):
         return pymbolic.sum(*(
             pymbolic.product(*(expr.children[0:i] + 
-                             (child.invoke_mapper(self),) +
+                             (self(child),) +
                              expr.children[i+1:]))
             for i, child in enumerate(expr.children)
             if not self._isc(child)))
@@ -80,13 +81,11 @@ class DifferentiationMapper:
         if f_const and g_const:
             return primitives.Constant(0)
         elif f_const:
-            f = self._eval(f)
-            return -f*g.invoke_mapper(self)/g**2
+            return -f*self(g)/g**2
         elif g_const:
-            g = self._eval(g)
-            return f.invoke_mapper(self)/g
+            return self(f)/g
         else:
-            return (f.invoke_mapper(self)*g-g.invoke_mapper(self)*f)/g**2
+            return (self(f)*g-self(g)*f)/g**2
 
     def map_power(self, expr):
         f = expr.base
@@ -99,26 +98,18 @@ class DifferentiationMapper:
         if f_const and g_const:
             return primitives.Constant(0)
         elif f_const:
-            f = self._eval(f)
-            return log(f) * f**g * g.invoke_mapper(self)
+            return log(f) * f**g * self(g)
         elif g_const:
-            g = self._eval(g)
-            return g * f**(g-1) * f.invoke_mapper(self)
+            return g * f**(g-1) * self(f)
         else:
-            return log(f) * f**g * g.invoke_mapper(self) + \
-                   g * f**(g-1) * f.invoke_mapper(self)
+            return log(f) * f**g * self(g) + \
+                   g * f**(g-1) * self(f)
 
     def map_polynomial(self, expr):
         raise NotImplementedError
     
     def _isc(self,subexp):
         return pymbolic.is_constant(subexp, [self.Variable])
-
-    def _eval(self,subexp):
-        try:
-            return primitives.Constant(pymbolic.evaluate(subexp))
-        except KeyError:
-            return subexp
   
 
 
@@ -128,5 +119,4 @@ def differentiate(expression,
                   func_mapper=map_math_functions_by_name):
     if not isinstance(variable, (primitives.Variable, primitives.Subscript)):
         variable = primitives.make_variable(variable)
-    return expression.invoke_mapper(DifferentiationMapper(variable,
-                                                          func_mapper))
+    return DifferentiationMapper(variable, func_mapper)(expression)
diff --git a/src/mapper/evaluator.py b/src/mapper/evaluator.py
index 19604f8..70c60dd 100644
--- a/src/mapper/evaluator.py
+++ b/src/mapper/evaluator.py
@@ -1,10 +1,15 @@
+import pymbolic.mapper
+
+
+
+
 class UnknownVariableError(Exception):
     pass
 
 
 
 
-class EvaluationMapper:
+class EvaluationMapper(pymbolic.mapper.Mapper):
     def __init__(self, context={}):
         self.Context = context
 
@@ -18,46 +23,43 @@ class EvaluationMapper:
             raise UnknownVariableError, expr.name
 
     def map_call(self, expr):
-        return expr.function.invoke_mapper(self)(
-            *[par.invoke_mapper(self)
-              for par in expr.parameters])
+        return self(expr.function)(*[self(par) for par in expr.parameters])
 
     def map_subscript(self, expr):
-        return expr.aggregate.invoke_mapper(self)[expr.index.invoke_mapper(self)]
+        return self(expr.aggregate)[self(expr.index)]
 
     def map_lookup(self, expr):
-        return getattr(expr.aggregate.invoke_mapper(self), expr.name)
+        return getattr(self(expr.aggregate), expr.name)
 
     def map_negation(self, expr):
-        return -expr.child.invoke_mapper(self)
+        return -self(expr.child)
 
     def map_sum(self, expr):
-        return sum(child.invoke_mapper(self)
-                   for child in expr.children)
+        return sum(self(child) for child in expr.children)
 
     def map_product(self, expr):
         if len(expr.children) == 0:
-            return 1
-        result = expr.children[0].invoke_mapper(self)
+            return 1 # FIXME?
+        result = self(expr.children[0])
         for child in expr.children[1:]:
-            result *= child.invoke_mapper(self)
+            result *= self(child)
         return result
 
     def map_rational(self, expr):
-        return expr.numerator.invoke_mapper(self) / expr.denominator.invoke_mapper(self)
+        return self(expr.numerator) / self(expr.denominator)
 
     def map_power(self, expr):
-        return expr.base.invoke_mapper(self) ** expr.exponent.invoke_mapper(self)
+        return self(expr.base) ** self(expr.exponent)
 
     def map_polynomial(self, expr):
         raise NotImplementedError
 
     def map_list(self, expr):
-        return [child.invoke_mapper(self) for child in expr.Children]
+        return [self(child) for child in expr.Children]
 
 
 
 
 def evaluate(expression, context={}):
-    return expression.invoke_mapper(EvaluationMapper(context))
+    return EvaluationMapper(context)(expression)
     
diff --git a/src/mapper/stringifier.py b/src/mapper/stringifier.py
index 586a6e4..80e5051 100644
--- a/src/mapper/stringifier.py
+++ b/src/mapper/stringifier.py
@@ -1,3 +1,8 @@
+import pymbolic.mapper
+
+
+
+
 PREC_CALL = 5
 PREC_POWER = 4
 PREC_UNARY = 3
@@ -7,7 +12,7 @@ PREC_NONE = 0
 
 
 
-class StringifyMapper:
+class StringifyMapper(pymbolic.mapper.Mapper):
     def map_constant(self, expr, enclosing_prec):
         return str(expr.value)
 
@@ -16,8 +21,8 @@ class StringifyMapper:
 
     def map_call(self, expr, enclosing_prec):
         result = "%s(%s)" % \
-                (expr.function.invoke_mapper(self, PREC_CALL),
-                        ", ".join(i.invoke_mapper(self, PREC_NONE) 
+                (self(expr.function, PREC_CALL),
+                        ", ".join(self(i, PREC_NONE) 
                             for i in expr.parameters))
         if enclosing_prec > PREC_CALL:
             return "(%s)" % result
@@ -26,38 +31,35 @@ class StringifyMapper:
 
     def map_subscript(self, expr, enclosing_prec):
         result = "%s[%s]" % \
-                (expr.aggregate.invoke_mapper(self, PREC_CALL),
-                        expr.index.invoke_mapper(self, PREC_CALL))
+                (self(expr.aggregate, PREC_CALL), self(expr.index, PREC_CALL))
         if enclosing_prec > PREC_CALL:
             return "(%s)" % result
         else:
             return result
 
     def map_lookup(self, expr, enclosing_prec):
-        result = "%s.%s" % \
-               (expr.aggregate.invoke_mapper(self, PREC_CALL), 
-                       expr.name)
+        result = "%s.%s" % (self(expr.aggregate, PREC_CALL), expr.name)
         if enclosing_prec > PREC_CALL:
             return "(%s)" % result
         else:
             return result
 
     def map_negation(self, expr, enclosing_prec):
-        result = "-%s" % expr.child.invoke_mapper(self, PREC_UNARY)
+        result = "-%s" % self(expr.child, PREC_UNARY)
         if enclosing_prec > PREC_UNARY:
             return "(%s)" % result
         else:
             return result
 
     def map_sum(self, expr, enclosing_prec):
-        result = "+".join(i.invoke_mapper(self, PREC_SUM) for i in expr.children)
+        result = "+".join(self(i, PREC_SUM) for i in expr.children)
         if enclosing_prec > PREC_SUM:
             return "(%s)" % result
         else:
             return result
 
     def map_product(self, expr, enclosing_prec):
-        result = "*".join(i.invoke_mapper(self, PREC_PRODUCT) 
+        result = "*".join(self(i, PREC_PRODUCT) 
                 for i in expr.children)
         if enclosing_prec > PREC_PRODUCT:
             return "(%s)" % result
@@ -66,8 +68,8 @@ class StringifyMapper:
 
     def map_quotient(self, expr, enclosing_prec):
         result = "%s/%s" % (
-                expr.numerator.invoke_mapper(self, PREC_PRODUCT), 
-                expr.denominator.invoke_mapper(self, PREC_PRODUCT)
+                self(expr.numerator, PREC_PRODUCT), 
+                self(expr.denominator, PREC_PRODUCT)
                 )
         if enclosing_prec > PREC_PRODUCT:
             return "(%s)" % result
@@ -77,8 +79,8 @@ class StringifyMapper:
 
     def map_power(self, expr, enclosing_prec):
         result = "%s**%s" % (
-                expr.base.invoke_mapper(self, PREC_POWER), 
-                expr.exponent.invoke_mapper(self, PREC_POWER)
+                self(expr.base, PREC_POWER), 
+                self(expr.exponent, PREC_POWER)
                 )
         if enclosing_prec > PREC_POWER:
             return "(%s)" % result
@@ -89,4 +91,5 @@ class StringifyMapper:
         raise NotImplementedError
 
     def map_list(self, expr, enclosing_prec):
-        return "[%s]" % ", ".join([i.invoke_mapper(self) for i in expr.children])
+        return "[%s]" % ", ".join([self(i, PREC_NONE) for i in expr.children])
+
diff --git a/src/mapper/substitutor.py b/src/mapper/substitutor.py
index 9284c79..3329da3 100644
--- a/src/mapper/substitutor.py
+++ b/src/mapper/substitutor.py
@@ -35,4 +35,4 @@ def substitute(expression, variable_assignments = {}):
     for k, v in variable_assignments.iteritems():
         new_var_ass[primitives.make_variable(k)] = v
 
-    return expression.invoke_mapper(SubstitutionMapper(new_var_ass))
+    return SubstitutionMapper(new_var_ass)(expression)
diff --git a/src/polynomial.py b/src/polynomial.py
index e9e9d8a..53495c1 100644
--- a/src/polynomial.py
+++ b/src/polynomial.py
@@ -211,9 +211,6 @@ class Polynomial(primitives.Expression):
                                repr(self.Base), 
                                repr(self.Data))
         
-    def __hash__(self):
-        return hash(self.Base) ^ hash(self.Children)
-
     def invoke_mapper(self, mapper, *args, **kwargs):
         return mapper.map_polynomial(self, *args, **kwargs)
 
diff --git a/src/rational.py b/src/rational.py
index 6b304bb..8c42a90 100644
--- a/src/rational.py
+++ b/src/rational.py
@@ -90,19 +90,9 @@ class Rational(prm.Expression):
     def __float__(self):
         return float(self.Numerator) / flaot(self.Denominator)
 
-    def __hash__(self):
-        return 0xcafe ^ hash(self.Numerator) ^ hash(self.Denominator)
-
     def invoke_mapper(self, mapper, *args, **kwargs):
         return mapper.map_rational(self, *args, **kwargs)
 
-    def __str__(self):
-        if isinstance(self.Numerator, primitives.Expression):
-            return primitives.Expression.__str__(self)
-        else:
-            return "%s/%s" % (str(self.Numerator), str(self.Denominator))
-
-
 
 
 
-- 
GitLab