isinstance uses PyObject_TypeCheck when second argument is a type
authorRobert Bradshaw <robertwb@math.washington.edu>
Tue, 23 Sep 2008 06:45:08 +0000 (23:45 -0700)
committerRobert Bradshaw <robertwb@math.washington.edu>
Tue, 23 Sep 2008 06:45:08 +0000 (23:45 -0700)
Cython/Compiler/Builtin.py
Cython/Compiler/Main.py
Cython/Compiler/Optimize.py
Cython/Compiler/Symtab.py
Cython/Includes/python_object.pxd

index 3d11eeb9de6ea367333308dd758ea2a48bf59d27..d1f54162487198d1cb7c7c33ae2fec06f1c9af04 100644 (file)
@@ -181,7 +181,8 @@ def init_builtins():
     init_builtin_funcs()
     init_builtin_types()
     init_builtin_structs()
-    global list_type, tuple_type, dict_type, unicode_type
+    global list_type, tuple_type, dict_type, unicode_type, type_type
+    type_type  = builtin_scope.lookup('type').type
     list_type  = builtin_scope.lookup('list').type
     tuple_type = builtin_scope.lookup('tuple').type
     dict_type  = builtin_scope.lookup('dict').type
index 138f5e3de9f534f1df46312006e1f69f37773a8a..6ed7fac626cfa9a5f63b21f3c39fbe2609938466 100644 (file)
@@ -81,7 +81,7 @@ class Context:
         from ParseTreeTransforms import CreateClosureClasses, MarkClosureVisitor, DecoratorTransform
         from ParseTreeTransforms import InterpretCompilerDirectives
         from AutoDocTransforms import EmbedSignature
-        from Optimize import FlattenInListTransform, SwitchTransform, OptimizeRefcounting
+        from Optimize import FlattenInListTransform, SwitchTransform, FinalOptimizePhase
         from Buffer import IntroduceBufferAuxiliaryVars
         from ModuleNode import check_c_classes
 
@@ -106,7 +106,7 @@ class Context:
             _check_c_classes,
             AnalyseExpressionsTransform(self),
             SwitchTransform(),
-            OptimizeRefcounting(self),
+            FinalOptimizePhase(self),
 #            SpecialFunctions(self),
             #        CreateClosureClasses(context),
             ]
index 9f4a46c8662c5108c3052996d50b9e50c015198c..64a410b9254c4a203a61099914c65f1f43f7f4aa 100644 (file)
@@ -140,7 +140,15 @@ class FlattenInListTransform(Visitor.VisitorTransform):
         return node
 
 
-class OptimizeRefcounting(Visitor.CythonTransform):
+class FinalOptimizePhase(Visitor.CythonTransform):
+    """
+    This visitor handles several commuting optimizations, and is run
+    just before the C code generation phase. 
+    
+    The optimizations currently implemented in this class are: 
+        - Eliminate None assignment and refcounting for first assignment. 
+        - isinstance -> typecheck for cdef types
+    """
     def visit_SingleAssignmentNode(self, node):
         if node.first:
             lhs = node.lhs
@@ -152,3 +160,22 @@ class OptimizeRefcounting(Visitor.CythonTransform):
                 lhs.skip_assignment_decref = True
         return node
 
+    def visit_SimpleCallNode(self, node):
+        self.visitchildren(node)
+        if node.function.type.is_cfunction:
+            if node.function.name == 'isinstance':
+                type_arg = node.args[1]
+                if type_arg.type.is_builtin_type and type_arg.type.name == 'type':
+                    object_module = self.context.find_module('python_object')
+                    node.function.entry = object_module.lookup('PyObject_TypeCheck')
+                    node.function.type = node.function.entry.type
+                    PyTypeObjectPtr = PyrexTypes.CPtrType(object_module.lookup('PyTypeObject').type)
+                    node.args[1] = ExprNodes.CastNode(node.args[1], PyTypeObjectPtr)
+                    # Remove when result_code stuff is put in its proper place...
+                    node.function.result_code = node.function.entry.cname
+                    node.args[1].result_code = node.args[1].arg.result_as(PyTypeObjectPtr)
+                    if node.is_temp:
+                        node.allocate_temp(None, node.result_code)
+                    else:
+                        node.allocate_temp(None)
+        return node
index 533a526f35a367402a5c62c8678764bcf51bbb4a..127d7c2487c731322c078edfe42951c846a883f7 100644 (file)
@@ -6,8 +6,7 @@ import re
 from Cython import Utils
 from Errors import warning, error, InternalError
 from StringEncoding import EncodedString
-import Options
-import Naming
+import Options, Naming
 import PyrexTypes
 from PyrexTypes import py_object_type
 import TypeSlots
@@ -711,7 +710,7 @@ class BuiltinScope(Scope):
         entry = self.declare_type(name, type, None, visibility='extern')
 
         var_entry = Entry(name = entry.name,
-            type = py_object_type,
+            type = self.lookup('type').type, # make sure "type" is the first type declared...
             pos = entry.pos,
             cname = "((PyObject*)%s)" % entry.type.typeptr_cname)
         var_entry.is_variable = 1
@@ -1110,8 +1109,9 @@ class ModuleScope(Scope):
         # variable entry attached to it. For the variable entry,
         # we use a read-only C global variable whose name is an
         # expression that refers to the type object.
+        import Builtin
         var_entry = Entry(name = entry.name,
-            type = py_object_type,
+            type = Builtin.type_type,
             pos = entry.pos,
             cname = "((PyObject*)%s)" % entry.type.typeptr_cname)
         var_entry.is_variable = 1
index fff3653f2d9a318ebb31103f11acb9cf530ab957..57ebc7c17c46012121bd1dc0e8886e7e5d24e191 100644 (file)
@@ -233,7 +233,7 @@ cdef extern from "Python.h":
     # pointer of type PyTypeObject*, except when the incremented
     # reference count is needed.
 
-    bint PyObject_TypeCheck(object o, object type) #   object o, PyTypeObject *type)
+    bint PyObject_TypeCheck(object o, PyTypeObject *type)
     # Return true if the object o is of type type or a subtype of
     # type. Both parameters must be non-NULL.