removed unused level of indirection from tree visitors to save some processing cycles
authorStefan Behnel <scoder@users.berlios.de>
Mon, 15 Nov 2010 21:54:59 +0000 (22:54 +0100)
committerStefan Behnel <scoder@users.berlios.de>
Mon, 15 Nov 2010 21:54:59 +0000 (22:54 +0100)
Cython/Compiler/Visitor.pxd
Cython/Compiler/Visitor.py

index 8c88a3dc9c71fa627e84e7111e7d943d731ba655..81a1bbd2895dce1afbbe542ec68018680ff9e526 100644 (file)
@@ -1,13 +1,12 @@
 cimport cython
 
-cdef class BasicVisitor:
+cdef class TreeVisitor:
+    cdef public list access_path
     cdef dict dispatch_table
+
     cpdef visit(self, obj)
     cdef _visit(self, obj)
     cdef find_handler(self, obj)
-
-cdef class TreeVisitor(BasicVisitor):
-    cdef public list access_path
     cdef _visitchild(self, child, parent, attrname, idx)
     @cython.locals(idx=int)
     cdef dict _visitchildren(self, parent, attrs)
index a9cd264c9df814270d0711b67aa976fc57a3237a..283b09eb3fcdcbaea8d77485af54044bb548f0f8 100644 (file)
@@ -11,49 +11,7 @@ import Naming
 import Errors
 import DebugFlags
 
-class BasicVisitor(object):
-    """A generic visitor base class which can be used for visiting any kind of object."""
-    # Note: If needed, this can be replaced with a more efficient metaclass
-    # approach, resolving the jump table at module load time rather than per visitor
-    # instance.
-    def __init__(self):
-        self.dispatch_table = {}
-
-    def visit(self, obj):
-        return self._visit(obj)
-
-    def _visit(self, obj):
-        try:
-            handler_method = self.dispatch_table[type(obj)]
-        except KeyError:
-            handler_method = self.find_handler(obj)
-            self.dispatch_table[type(obj)] = handler_method
-        return handler_method(obj)
-
-    def find_handler(self, obj):
-        cls = type(obj)
-        #print "Cache miss for class %s in visitor %s" % (
-        #    cls.__name__, type(self).__name__)
-        # Must resolve, try entire hierarchy
-        pattern = "visit_%s"
-        mro = inspect.getmro(cls)
-        handler_method = None
-        for mro_cls in mro:
-            if hasattr(self, pattern % mro_cls.__name__):
-                handler_method = getattr(self, pattern % mro_cls.__name__)
-                break
-        if handler_method is None:
-            print type(self), cls
-            if hasattr(self, 'access_path') and self.access_path:
-                print self.access_path
-                if self.access_path:
-                    print self.access_path[-1][0].pos
-                    print self.access_path[-1][0].__dict__
-            raise RuntimeError("Visitor %r does not accept object: %s" % (self, obj))
-        #print "Caching " + cls.__name__
-        return handler_method
-
-class TreeVisitor(BasicVisitor):
+class TreeVisitor(object):
     """
     Base class for writing visitors for a Cython tree, contains utilities for
     recursing such trees using visitors. Each node is
@@ -96,9 +54,9 @@ class TreeVisitor(BasicVisitor):
     out 3
     out 0
     """
-    
     def __init__(self):
         super(TreeVisitor, self).__init__()
+        self.dispatch_table = {}
         self.access_path = []
 
     def dump_node(self, node, indent=0):
@@ -176,10 +134,47 @@ class TreeVisitor(BasicVisitor):
             last_node.pos, self.__class__.__name__,
             u'\n'.join(trace), e, stacktrace)
 
+    def find_handler(self, obj):
+        # to resolve, try entire hierarchy
+        cls = type(obj)
+        pattern = "visit_%s"
+        mro = inspect.getmro(cls)
+        handler_method = None
+        for mro_cls in mro:
+            if hasattr(self, pattern % mro_cls.__name__):
+                handler_method = getattr(self, pattern % mro_cls.__name__)
+                break
+        if handler_method is None:
+            print type(self), cls
+            if hasattr(self, 'access_path') and self.access_path:
+                print self.access_path
+                if self.access_path:
+                    print self.access_path[-1][0].pos
+                    print self.access_path[-1][0].__dict__
+            raise RuntimeError("Visitor %r does not accept object: %s" % (self, obj))
+        #print "Caching " + cls.__name__
+        return handler_method
+
+    def visit(self, obj):
+        return self._visit(obj)
+
+    def _visit(self, obj):
+        try:
+            handler_method = self.dispatch_table[type(obj)]
+        except KeyError:
+            handler_method = self.find_handler(obj)
+            self.dispatch_table[type(obj)] = handler_method
+        return handler_method(obj)
+
     def _visitchild(self, child, parent, attrname, idx):
         self.access_path.append((parent, attrname, idx))
         try:
-            result = self._visit(child)
+            try:
+                handler_method = self.dispatch_table[type(child)]
+            except KeyError:
+                handler_method = self.find_handler(child)
+                self.dispatch_table[type(child)] = handler_method
+            result = handler_method(child)
         except Errors.CompileError:
             raise
         except Exception, e: