From 8f854eae17fec66eedd24384cbc70cfe42af9f8c Mon Sep 17 00:00:00 2001 From: Robert Bradshaw Date: Thu, 1 Nov 2007 01:05:12 -0700 Subject: [PATCH] Fix cpdef after merge, change so one can still call super methods --- Cython/Compiler/ExprNodes.py | 7 +++++++ Cython/Compiler/Naming.py | 2 ++ Cython/Compiler/Nodes.py | 17 ++++++++++++----- Cython/Compiler/Symtab.py | 2 ++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 4c3b5004..cd1313e2 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -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 diff --git a/Cython/Compiler/Naming.py b/Cython/Compiler/Naming.py index bf395cb4..6ad9ae2a 100644 --- a/Cython/Compiler/Naming.py +++ b/Cython/Compiler/Naming.py @@ -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" diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index da668aa2..3a69f00f 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -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 = \ diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py index f1ae18ff..af4e2070 100644 --- a/Cython/Compiler/Symtab.py +++ b/Cython/Compiler/Symtab.py @@ -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 -- 2.26.2