Fix cpdef after merge, change so one can still call super methods
authorRobert Bradshaw <robertwb@math.washington.edu>
Thu, 1 Nov 2007 08:05:12 +0000 (01:05 -0700)
committerRobert Bradshaw <robertwb@math.washington.edu>
Thu, 1 Nov 2007 08:05:12 +0000 (01:05 -0700)
Cython/Compiler/ExprNodes.py
Cython/Compiler/Naming.py
Cython/Compiler/Nodes.py
Cython/Compiler/Symtab.py

index 4c3b50040991e468ca842d310fac9753512e2d8d..cd1313e24620446c081b91e6f6f144f036e81eb4 100644 (file)
@@ -1434,12 +1434,14 @@ class SimpleCallNode(ExprNode):
     #  arg_tuple      ExprNode or None     used internally
     #  self           ExprNode or None     used internally
     #  coerced_self   ExprNode or None     used internally
+    #  wrapper_call   bool                 used internally
     
     subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
     
     self = None
     coerced_self = None
     arg_tuple = None
+    wrapper_call = False
     
     def compile_time_value(self, denv):
         function = self.function.compile_time_value(denv)
@@ -1547,6 +1549,9 @@ class SimpleCallNode(ExprNode):
             arg_list_code.append(actual_arg.result_code)
         result = "%s(%s)" % (self.function.result_code,
             join(arg_list_code, ","))
+        if self.wrapper_call or \
+                self.function.entry.is_unbound_cmethod and self.function.entry.is_overridable:
+            result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
         return result
     
     def generate_result_code(self, code):
@@ -1764,6 +1769,8 @@ class AttributeNode(ExprNode):
                     entry.type)
                 ubcm_entry.is_cfunction = 1
                 ubcm_entry.func_cname = entry.func_cname
+                ubcm_entry.is_unbound_cmethod = 1
+                ubcm_entry.is_overridable = entry.is_overridable
                 self.mutate_into_name_node(env, ubcm_entry, None)
                 return 1
         return 0
index bf395cb489235a23627cd47e26121cebc644f34a..6ad9ae2a882ee3ae7a62438be261db0f5ed5e674 100644 (file)
@@ -13,6 +13,7 @@ arg_prefix        = pyrex_prefix + "arg_"
 funcdoc_prefix    = pyrex_prefix + "doc_"
 enum_prefix       = pyrex_prefix + "e_"
 func_prefix       = pyrex_prefix + "f_"
+pyfunc_prefix     = pyrex_prefix + "pf_"
 gstab_prefix      = pyrex_prefix + "getsets_"
 prop_get_prefix   = pyrex_prefix + "getprop_"
 const_prefix      = pyrex_prefix + "k"
@@ -56,6 +57,7 @@ stringtab_cname  = pyrex_prefix + "string_tab"
 vtabslot_cname   = pyrex_prefix + "vtab"
 c_api_tab_cname  = pyrex_prefix + "c_api_tab"
 gilstate_cname   = pyrex_prefix + "state"
+skip_dispatch_cname = pyrex_prefix + "skip_dispatch"
 
 extern_c_macro  = pyrex_prefix.upper() + "EXTERN_C"
 
index da668aa2ae08262ccada9ac19621e5e09006f04c..3a69f00ffc45512c5df00fb76347e814c0a5b4f6 100644 (file)
@@ -768,6 +768,7 @@ class CFuncDefNode(FuncDefNode):
             cname = cname, visibility = self.visibility,
             defining = self.body is not None,
             api = self.api)
+        self.entry.is_overridable = self.overridable
         self.return_type = type.return_type
 
         if self.overridable:
@@ -775,7 +776,7 @@ class CFuncDefNode(FuncDefNode):
             arg_names = [arg.name for arg in self.type.args]
             self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
             cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.declarator.base.name)
-            c_call = ExprNodes.SimpleCallNode(self.pos, function=cfunc, args=[ExprNodes.NameNode(self.pos, name=n) for n in arg_names[1:]])
+            c_call = ExprNodes.SimpleCallNode(self.pos, function=cfunc, args=[ExprNodes.NameNode(self.pos, name=n) for n in arg_names[1:]], wrapper_call=True)
             py_func_body = ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
             self.py_func = DefNode(pos = self.pos, 
                                    name = self.declarator.base.name,
@@ -790,7 +791,7 @@ class CFuncDefNode(FuncDefNode):
             if Options.intern_names:
                 self.py_func.interned_attr_cname = env.intern(self.py_func.entry.name)
             self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
-            self.body.stats.insert(0, self.override)
+            self.body = StatListNode(self.pos, stats=[self.override, self.body])
             
                     
     def declare_arguments(self, env):
@@ -1020,7 +1021,7 @@ class DefNode(FuncDefNode):
         self.entry = entry
         prefix = env.scope_prefix
         entry.func_cname = \
-            Naming.func_prefix + prefix + name
+            Naming.pyfunc_prefix + prefix + name
         entry.pymethdef_cname = \
             Naming.pymethdef_prefix + prefix + name
         if not entry.is_special:
@@ -1389,8 +1390,10 @@ class OverrideCheckNode(StatNode):
     def generate_execution_code(self, code):
         # Check to see if we are an extension type
         self_arg = "((PyObject *)%s)" % self.args[0].cname
+        code.putln("/* Check if called by wrapper */")
+        code.putln("if (unlikely(%s)) %s = 0;" % (Naming.skip_dispatch_cname, Naming.skip_dispatch_cname))
         code.putln("/* Check if overriden in Python */")
-        code.putln("if (unlikely(%s->ob_type->tp_dictoffset != 0)) {" % self_arg)
+        code.putln("else if (unlikely(%s->ob_type->tp_dictoffset != 0)) {" % self_arg)
         err = code.error_goto_if_null(self_arg, self.pos)
         # need to get attribute manually--scope would return cdef method
         if Options.intern_names:
@@ -2950,7 +2953,11 @@ static INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
    else return PyObject_IsTrue(x);
 }
 
-""" 
+""" + """
+
+static int %(skip_dispatch_cname)s = 0;
+
+""" % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
 
 if Options.gcc_branch_hints:
     branch_prediction_macros = \
index f1ae18ff3badebf2f95055c3d3466e638d145de4..af4e20706eb52c6bc13cbd99238abe696f190eec 100644 (file)
@@ -34,6 +34,7 @@ class Entry:
     # is_variable      boolean    Is a variable
     # is_cfunction     boolean    Is a C function
     # is_cmethod       boolean    Is a C method of an extension type
+    # is_unbound_cmethod boolean  Is an unbound C method of an extension type
     # is_type          boolean    Is a type definition
     # is_const         boolean    Is a constant
     # is_property      boolean    Is a property of an extension type:
@@ -81,6 +82,7 @@ class Entry:
     is_variable = 0
     is_cfunction = 0
     is_cmethod = 0
+    is_unbound_cmethod = 0
     is_type = 0
     is_const = 0
     is_property = 0