Commit c228cfff authored by Vitja Makarov's avatar Vitja Makarov

CyFunction's support for classmethod and staticmethod

parent ddd48329
...@@ -5832,6 +5832,7 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin): ...@@ -5832,6 +5832,7 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
# pymethdef_cname string PyMethodDef structure # pymethdef_cname string PyMethodDef structure
# self_object ExprNode or None # self_object ExprNode or None
# binding bool # binding bool
# def_node DefNode the Python function node
# module_name EncodedString Name of defining module # module_name EncodedString Name of defining module
# code_object CodeObjectNode the PyCodeObject creator node # code_object CodeObjectNode the PyCodeObject creator node
...@@ -5840,6 +5841,7 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin): ...@@ -5840,6 +5841,7 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
self_object = None self_object = None
code_object = None code_object = None
binding = False binding = False
def_node = None
type = py_object_type type = py_object_type
is_temp = 1 is_temp = 1
...@@ -5873,25 +5875,50 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin): ...@@ -5873,25 +5875,50 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
def generate_result_code(self, code): def generate_result_code(self, code):
if self.binding: if self.binding:
if self.specialized_cpdefs: self.generate_cyfunction_code(code)
constructor = "__pyx_FusedFunction_NewEx" else:
else: self.generate_pycfunction_code(code)
constructor = "__Pyx_CyFunction_NewEx"
if self.code_object: def generate_pycfunction_code(self, code):
code_object_result = ', ' + self.code_object.py_result() py_mod_name = self.get_py_mod_name(code)
else: code.putln(
code_object_result = ', NULL' '%s = PyCFunction_NewEx(&%s, %s, %s); %s' % (
self.result(),
self.pymethdef_cname,
self.self_result_code(),
py_mod_name,
code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.py_result())
def generate_cyfunction_code(self, code):
if self.specialized_cpdefs:
constructor = "__pyx_FusedFunction_NewEx"
else: else:
constructor = "PyCFunction_NewEx" constructor = "__Pyx_CyFunction_NewEx"
code_object_result = ''
if self.code_object:
code_object_result = self.code_object.py_result()
else:
code_object_result = 'NULL'
flags = []
if self.def_node.is_staticmethod:
flags.append('__Pyx_CYFUNCTION_STATICMETHOD')
elif self.def_node.is_classmethod:
flags.append('__Pyx_CYFUNCTION_CLASSMETHOD')
if flags:
flags = ' | '.join(flags)
else:
flags = '0'
py_mod_name = self.get_py_mod_name(code) py_mod_name = self.get_py_mod_name(code)
code.putln( code.putln(
'%s = %s(&%s, %s, %s%s); %s' % ( '%s = %s(&%s, %s, %s, %s, %s); %s' % (
self.result(), self.result(),
constructor, constructor,
self.pymethdef_cname, self.pymethdef_cname,
flags,
self.self_result_code(), self.self_result_code(),
py_mod_name, py_mod_name,
code_object_result, code_object_result,
...@@ -5900,9 +5927,9 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin): ...@@ -5900,9 +5927,9 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
code.put_gotref(self.py_result()) code.put_gotref(self.py_result())
if self.specialized_cpdefs: if self.specialized_cpdefs:
self.generate_fused_cpdef(code, code_object_result) self.generate_fused_cpdef(code, code_object_result, flags)
def generate_fused_cpdef(self, code, code_object_result): def generate_fused_cpdef(self, code, code_object_result, flags):
""" """
Generate binding function objects for all specialized cpdefs, and the Generate binding function objects for all specialized cpdefs, and the
original fused one. The fused function gets a dict __signatures__ original fused one. The fused function gets a dict __signatures__
...@@ -5924,6 +5951,7 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin): ...@@ -5924,6 +5951,7 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
py_mod_name=self.get_py_mod_name(code), py_mod_name=self.get_py_mod_name(code),
self=self.self_result_code(), self=self.self_result_code(),
code=code_object_result, code=code_object_result,
flags=flags,
func=code.funcstate.allocate_temp(py_object_type, func=code.funcstate.allocate_temp(py_object_type,
manage_ref=True), manage_ref=True),
signature=code.funcstate.allocate_temp(py_object_type, signature=code.funcstate.allocate_temp(py_object_type,
...@@ -5945,7 +5973,7 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin): ...@@ -5945,7 +5973,7 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
'"%(signature_string)s")') '"%(signature_string)s")')
goto_err("%(func)s = __pyx_FusedFunction_NewEx(" goto_err("%(func)s = __pyx_FusedFunction_NewEx("
"&%(pymethdef_cname)s, %(self)s, %(py_mod_name)s %(code)s)") "&%(pymethdef_cname)s, %(flags)s, %(self)s, %(py_mod_name)s, %(code)s)")
s = "PyDict_SetItem(%(sigdict)s, %(signature)s, %(func)s)" s = "PyDict_SetItem(%(sigdict)s, %(signature)s, %(func)s)"
code.put_error_if_neg(self.pos, s % fmt_dict) code.put_error_if_neg(self.pos, s % fmt_dict)
...@@ -6040,7 +6068,6 @@ class LambdaNode(InnerFunctionNode): ...@@ -6040,7 +6068,6 @@ class LambdaNode(InnerFunctionNode):
child_attrs = ['def_node'] child_attrs = ['def_node']
def_node = None
name = StringEncoding.EncodedString('<lambda>') name = StringEncoding.EncodedString('<lambda>')
def analyse_declarations(self, env): def analyse_declarations(self, env):
......
...@@ -2994,21 +2994,20 @@ class DefNode(FuncDefNode): ...@@ -2994,21 +2994,20 @@ class DefNode(FuncDefNode):
if genv.is_closure_scope: if genv.is_closure_scope:
rhs = self.py_cfunc_node = ExprNodes.InnerFunctionNode( rhs = self.py_cfunc_node = ExprNodes.InnerFunctionNode(
self.pos, pymethdef_cname = self.entry.pymethdef_cname, self.pos, def_node=self,
code_object = ExprNodes.CodeObjectNode(self)) pymethdef_cname=self.entry.pymethdef_cname,
code_object=ExprNodes.CodeObjectNode(self))
else: else:
rhs = ExprNodes.PyCFunctionNode( rhs = ExprNodes.PyCFunctionNode(
self.pos, self.pos,
pymethdef_cname=self.entry.pymethdef_cname, def_node=self,
binding=env.directives['binding'], pymethdef_cname=self.entry.pymethdef_cname,
specialized_cpdefs=self.specialized_cpdefs, binding=env.directives['binding'],
code_object=ExprNodes.CodeObjectNode(self)) specialized_cpdefs=self.specialized_cpdefs,
code_object=ExprNodes.CodeObjectNode(self))
if env.is_py_class_scope: if env.is_py_class_scope:
if not self.is_staticmethod and not self.is_classmethod: rhs.binding = True
rhs.binding = True
else:
rhs.binding = False
if self.decorators: if self.decorators:
for decorator in self.decorators[::-1]: for decorator in self.decorators[::-1]:
......
...@@ -4,8 +4,12 @@ ...@@ -4,8 +4,12 @@
#define __Pyx_CyFunction_USED 1 #define __Pyx_CyFunction_USED 1
#include <structmember.h> #include <structmember.h>
#define __Pyx_CYFUNCTION_STATICMETHOD 0x01
#define __Pyx_CYFUNCTION_CLASSMETHOD 0x02
typedef struct { typedef struct {
PyCFunctionObject func; PyCFunctionObject func;
int flags;
PyObject *func_dict; PyObject *func_dict;
PyObject *func_weakreflist; PyObject *func_weakreflist;
PyObject *func_name; PyObject *func_name;
...@@ -15,8 +19,13 @@ typedef struct { ...@@ -15,8 +19,13 @@ typedef struct {
static PyTypeObject *__pyx_CyFunctionType = 0; static PyTypeObject *__pyx_CyFunctionType = 0;
#define __Pyx_CyFunction_NewEx(ml, self, module, code) __Pyx_CyFunction_New(__pyx_CyFunctionType, ml, self, module, code) #define __Pyx_CyFunction_NewEx(ml, flags, self, module, code) \
static PyObject *__Pyx_CyFunction_New(PyTypeObject *, PyMethodDef *ml, PyObject *self, PyObject *module, PyObject* code); __Pyx_CyFunction_New(__pyx_CyFunctionType, ml, flags, self, module, code)
static PyObject *__Pyx_CyFunction_New(PyTypeObject *,
PyMethodDef *ml, int flags,
PyObject *self, PyObject *module,
PyObject* code);
static int __Pyx_CyFunction_init(void); static int __Pyx_CyFunction_init(void);
...@@ -209,10 +218,12 @@ static PyMethodDef __pyx_CyFunction_methods[] = { ...@@ -209,10 +218,12 @@ static PyMethodDef __pyx_CyFunction_methods[] = {
}; };
static PyObject *__Pyx_CyFunction_New(PyTypeObject *type, PyMethodDef *ml, PyObject *self, PyObject *module, PyObject* code) { static PyObject *__Pyx_CyFunction_New(PyTypeObject *type, PyMethodDef *ml, int flags,
PyObject *self, PyObject *module, PyObject* code) {
__pyx_CyFunctionObject *op = PyObject_GC_New(__pyx_CyFunctionObject, type); __pyx_CyFunctionObject *op = PyObject_GC_New(__pyx_CyFunctionObject, type);
if (op == NULL) if (op == NULL)
return NULL; return NULL;
op->flags = flags;
op->func_weakreflist = NULL; op->func_weakreflist = NULL;
op->func.m_ml = ml; op->func.m_ml = ml;
Py_XINCREF(self); Py_XINCREF(self);
...@@ -262,6 +273,20 @@ static int __Pyx_CyFunction_traverse(__pyx_CyFunctionObject *m, visitproc visit, ...@@ -262,6 +273,20 @@ static int __Pyx_CyFunction_traverse(__pyx_CyFunctionObject *m, visitproc visit,
static PyObject *__Pyx_CyFunction_descr_get(PyObject *func, PyObject *obj, PyObject *type) static PyObject *__Pyx_CyFunction_descr_get(PyObject *func, PyObject *obj, PyObject *type)
{ {
__pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func;
if (m->flags & __Pyx_CYFUNCTION_STATICMETHOD) {
Py_INCREF(func);
return func;
}
if (m->flags & __Pyx_CYFUNCTION_CLASSMETHOD) {
if (type == NULL)
type = (PyObject *)(Py_TYPE(obj));
return PyMethod_New(func,
type, (PyObject *)(Py_TYPE(type)));
}
if (obj == Py_None) if (obj == Py_None)
obj = NULL; obj = NULL;
return PyMethod_New(func, obj, type); return PyMethod_New(func, obj, type);
...@@ -356,9 +381,10 @@ typedef struct { ...@@ -356,9 +381,10 @@ typedef struct {
PyObject *self; PyObject *self;
} __pyx_FusedFunctionObject; } __pyx_FusedFunctionObject;
#define __pyx_FusedFunction_NewEx(ml, self, module, code) \ #define __pyx_FusedFunction_NewEx(ml, flags, self, module, code) \
__pyx_FusedFunction_New(__pyx_FusedFunctionType, ml, self, module, code) __pyx_FusedFunction_New(__pyx_FusedFunctionType, ml, flags, self, module, code)
static PyObject *__pyx_FusedFunction_New(PyTypeObject *type, PyMethodDef *ml, static PyObject *__pyx_FusedFunction_New(PyTypeObject *type,
PyMethodDef *ml, int flags,
PyObject *self, PyObject *module, PyObject *self, PyObject *module,
PyObject *code); PyObject *code);
...@@ -369,12 +395,12 @@ static int __pyx_FusedFunction_init(void); ...@@ -369,12 +395,12 @@ static int __pyx_FusedFunction_init(void);
//////////////////// FusedFunction //////////////////// //////////////////// FusedFunction ////////////////////
static PyObject * static PyObject *
__pyx_FusedFunction_New(PyTypeObject *type, PyMethodDef *ml, PyObject *self, __pyx_FusedFunction_New(PyTypeObject *type, PyMethodDef *ml, int flags, PyObject *self,
PyObject *module, PyObject *code) PyObject *module, PyObject *code)
{ {
__pyx_FusedFunctionObject *fusedfunc = \ __pyx_FusedFunctionObject *fusedfunc =
(__pyx_FusedFunctionObject *) __Pyx_CyFunction_New(type, ml, self, (__pyx_FusedFunctionObject *) __Pyx_CyFunction_New(type, ml, flags,
module, code); self, module, code);
if (!fusedfunc) if (!fusedfunc)
return NULL; return NULL;
...@@ -429,6 +455,7 @@ __pyx_FusedFunction_descr_get(PyObject *self, PyObject *obj, PyObject *type) ...@@ -429,6 +455,7 @@ __pyx_FusedFunction_descr_get(PyObject *self, PyObject *obj, PyObject *type)
meth = (__pyx_FusedFunctionObject *) __pyx_FusedFunction_NewEx( meth = (__pyx_FusedFunctionObject *) __pyx_FusedFunction_NewEx(
((PyCFunctionObject *) func)->m_ml, ((PyCFunctionObject *) func)->m_ml,
((__pyx_CyFunctionObject *) func)->flags,
((PyCFunctionObject *) func)->m_self, ((PyCFunctionObject *) func)->m_self,
((PyCFunctionObject *) func)->m_module, ((PyCFunctionObject *) func)->m_module,
((__pyx_CyFunctionObject *) func)->func_code); ((__pyx_CyFunctionObject *) func)->func_code);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment