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):
# pymethdef_cname string PyMethodDef structure
# self_object ExprNode or None
# binding bool
# def_node DefNode the Python function node
# module_name EncodedString Name of defining module
# code_object CodeObjectNode the PyCodeObject creator node
......@@ -5840,6 +5841,7 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
self_object = None
code_object = None
binding = False
def_node = None
type = py_object_type
is_temp = 1
......@@ -5873,25 +5875,50 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
def generate_result_code(self, code):
if self.binding:
self.generate_cyfunction_code(code)
else:
self.generate_pycfunction_code(code)
def generate_pycfunction_code(self, code):
py_mod_name = self.get_py_mod_name(code)
code.putln(
'%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:
constructor = "__Pyx_CyFunction_NewEx"
if self.code_object:
code_object_result = ', ' + self.code_object.py_result()
code_object_result = self.code_object.py_result()
else:
code_object_result = ', NULL'
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:
constructor = "PyCFunction_NewEx"
code_object_result = ''
flags = '0'
py_mod_name = self.get_py_mod_name(code)
code.putln(
'%s = %s(&%s, %s, %s%s); %s' % (
'%s = %s(&%s, %s, %s, %s, %s); %s' % (
self.result(),
constructor,
self.pymethdef_cname,
flags,
self.self_result_code(),
py_mod_name,
code_object_result,
......@@ -5900,9 +5927,9 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
code.put_gotref(self.py_result())
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
original fused one. The fused function gets a dict __signatures__
......@@ -5924,6 +5951,7 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
py_mod_name=self.get_py_mod_name(code),
self=self.self_result_code(),
code=code_object_result,
flags=flags,
func=code.funcstate.allocate_temp(py_object_type,
manage_ref=True),
signature=code.funcstate.allocate_temp(py_object_type,
......@@ -5945,7 +5973,7 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
'"%(signature_string)s")')
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)"
code.put_error_if_neg(self.pos, s % fmt_dict)
......@@ -6040,7 +6068,6 @@ class LambdaNode(InnerFunctionNode):
child_attrs = ['def_node']
def_node = None
name = StringEncoding.EncodedString('<lambda>')
def analyse_declarations(self, env):
......
......@@ -2994,21 +2994,20 @@ class DefNode(FuncDefNode):
if genv.is_closure_scope:
rhs = self.py_cfunc_node = ExprNodes.InnerFunctionNode(
self.pos, pymethdef_cname = self.entry.pymethdef_cname,
code_object = ExprNodes.CodeObjectNode(self))
self.pos, def_node=self,
pymethdef_cname=self.entry.pymethdef_cname,
code_object=ExprNodes.CodeObjectNode(self))
else:
rhs = ExprNodes.PyCFunctionNode(
self.pos,
def_node=self,
pymethdef_cname=self.entry.pymethdef_cname,
binding=env.directives['binding'],
specialized_cpdefs=self.specialized_cpdefs,
code_object=ExprNodes.CodeObjectNode(self))
if env.is_py_class_scope:
if not self.is_staticmethod and not self.is_classmethod:
rhs.binding = True
else:
rhs.binding = False
if self.decorators:
for decorator in self.decorators[::-1]:
......
......@@ -4,8 +4,12 @@
#define __Pyx_CyFunction_USED 1
#include <structmember.h>
#define __Pyx_CYFUNCTION_STATICMETHOD 0x01
#define __Pyx_CYFUNCTION_CLASSMETHOD 0x02
typedef struct {
PyCFunctionObject func;
int flags;
PyObject *func_dict;
PyObject *func_weakreflist;
PyObject *func_name;
......@@ -15,8 +19,13 @@ typedef struct {
static PyTypeObject *__pyx_CyFunctionType = 0;
#define __Pyx_CyFunction_NewEx(ml, self, module, code) __Pyx_CyFunction_New(__pyx_CyFunctionType, ml, self, module, code)
static PyObject *__Pyx_CyFunction_New(PyTypeObject *, PyMethodDef *ml, PyObject *self, PyObject *module, PyObject* code);
#define __Pyx_CyFunction_NewEx(ml, flags, self, module, 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);
......@@ -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);
if (op == NULL)
return NULL;
op->flags = flags;
op->func_weakreflist = NULL;
op->func.m_ml = ml;
Py_XINCREF(self);
......@@ -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)
{
__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)
obj = NULL;
return PyMethod_New(func, obj, type);
......@@ -356,9 +381,10 @@ typedef struct {
PyObject *self;
} __pyx_FusedFunctionObject;
#define __pyx_FusedFunction_NewEx(ml, self, module, code) \
__pyx_FusedFunction_New(__pyx_FusedFunctionType, ml, self, module, code)
static PyObject *__pyx_FusedFunction_New(PyTypeObject *type, PyMethodDef *ml,
#define __pyx_FusedFunction_NewEx(ml, flags, self, module, code) \
__pyx_FusedFunction_New(__pyx_FusedFunctionType, ml, flags, self, module, code)
static PyObject *__pyx_FusedFunction_New(PyTypeObject *type,
PyMethodDef *ml, int flags,
PyObject *self, PyObject *module,
PyObject *code);
......@@ -369,12 +395,12 @@ static int __pyx_FusedFunction_init(void);
//////////////////// FusedFunction ////////////////////
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)
{
__pyx_FusedFunctionObject *fusedfunc = \
(__pyx_FusedFunctionObject *) __Pyx_CyFunction_New(type, ml, self,
module, code);
__pyx_FusedFunctionObject *fusedfunc =
(__pyx_FusedFunctionObject *) __Pyx_CyFunction_New(type, ml, flags,
self, module, code);
if (!fusedfunc)
return NULL;
......@@ -429,6 +455,7 @@ __pyx_FusedFunction_descr_get(PyObject *self, PyObject *obj, PyObject *type)
meth = (__pyx_FusedFunctionObject *) __pyx_FusedFunction_NewEx(
((PyCFunctionObject *) func)->m_ml,
((__pyx_CyFunctionObject *) func)->flags,
((PyCFunctionObject *) func)->m_self,
((PyCFunctionObject *) func)->m_module,
((__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