Commit fc581b12 authored by Vitja Makarov's avatar Vitja Makarov

Implement CyFunction.__defaults__

parent d9dc3496
......@@ -6087,7 +6087,7 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
# module_name EncodedString Name of defining module
# code_object CodeObjectNode the PyCodeObject creator node
subexprs = ['code_object']
subexprs = ['code_object', 'defaults_tuple']
self_object = None
code_object = None
......@@ -6096,6 +6096,7 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
defaults = None
defaults_struct = None
defaults_pyobjects = 0
defaults_tuple = None
type = py_object_type
is_temp = 1
......@@ -6122,13 +6123,16 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
"""
nonliteral_objects = []
nonliteral_other = []
default_args = []
for arg in self.def_node.args:
if arg.default and not arg.default.is_literal:
arg.is_dynamic = True
if arg.type.is_pyobject:
nonliteral_objects.append(arg)
else:
nonliteral_other.append(arg)
if arg.default:
if not arg.default.is_literal:
arg.is_dynamic = True
if arg.type.is_pyobject:
nonliteral_objects.append(arg)
else:
nonliteral_other.append(arg)
default_args.append(arg)
if nonliteral_objects or nonliteral_objects:
module_scope = env.global_scope()
cname = module_scope.next_id(Naming.defaults_struct_prefix)
......@@ -6153,6 +6157,12 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
Naming.dynamic_args_cname, entry.cname)
self.def_node.defaults_struct = self.defaults_struct.name
if default_args:
if self.defaults_struct is None:
self.defaults_tuple = TupleNode(self.pos, args=[
arg.default for arg in default_args])
self.defaults_tuple.analyse_types(env)
def may_be_none(self):
return False
......@@ -6245,6 +6255,10 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
arg.generate_assignment_code(code, target='%s->%s' % (
defaults, entry.cname))
if self.defaults_tuple:
code.putln('__Pyx_CyFunction_SetDefaultsTuple(%s, %s);' % (
self.result(), self.defaults_tuple.py_result()))
if self.specialized_cpdefs:
self.generate_fused_cpdef(code, code_object_result, flags)
......
......@@ -31,6 +31,9 @@ typedef struct {
/* Dynamic default args*/
void *defaults;
int defaults_pyobjects;
/* Defaults info */
PyObject *defaults_tuple; /* Const defaults tuple */
} __pyx_CyFunctionObject;
static PyTypeObject *__pyx_CyFunctionType = 0;
......@@ -46,6 +49,8 @@ static PyObject *__Pyx_CyFunction_New(PyTypeObject *,
static CYTHON_INLINE void *__Pyx_CyFunction_InitDefaults(PyObject *m,
size_t size,
int pyobjects);
static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsTuple(PyObject *m,
PyObject *tuple);
static int __Pyx_CyFunction_init(void);
......@@ -197,6 +202,18 @@ __Pyx_CyFunction_get_code(__pyx_CyFunctionObject *op)
return result;
}
static PyObject *
__Pyx_CyFunction_get_defaults(__pyx_CyFunctionObject *op)
{
if (op->defaults_tuple) {
Py_INCREF(op->defaults_tuple);
return op->defaults_tuple;
}
Py_INCREF(Py_None);
return Py_None;
}
static PyGetSetDef __pyx_CyFunction_getsets[] = {
{(char *) "func_doc", (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0},
{(char *) "__doc__", (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0},
......@@ -211,6 +228,8 @@ static PyGetSetDef __pyx_CyFunction_getsets[] = {
{(char *) "__closure__", (getter)__Pyx_CyFunction_get_closure, 0, 0, 0},
{(char *) "func_code", (getter)__Pyx_CyFunction_get_code, 0, 0, 0},
{(char *) "__code__", (getter)__Pyx_CyFunction_get_code, 0, 0, 0},
{(char *) "func_defaults", (getter)__Pyx_CyFunction_get_defaults, 0, 0, 0},
{(char *) "__defaults__", (getter)__Pyx_CyFunction_get_defaults, 0, 0, 0},
{0, 0, 0, 0, 0}
};
......@@ -261,6 +280,7 @@ static PyObject *__Pyx_CyFunction_New(PyTypeObject *type, PyMethodDef *ml, int f
/* Dynamic Default args */
op->defaults_pyobjects = 0;
op->defaults = NULL;
op->defaults_tuple = NULL;
PyObject_GC_Track(op);
return (PyObject *) op;
}
......@@ -275,6 +295,7 @@ __Pyx_CyFunction_clear(__pyx_CyFunctionObject *m)
Py_CLEAR(m->func_doc);
Py_CLEAR(m->func_code);
Py_CLEAR(m->func_classobj);
Py_CLEAR(m->defaults_tuple);
if (m->defaults) {
PyObject **pydefaults = __Pyx_CyFunction_Defaults(PyObject *, m);
......@@ -308,6 +329,7 @@ static int __Pyx_CyFunction_traverse(__pyx_CyFunctionObject *m, visitproc visit,
Py_VISIT(m->func_doc);
Py_VISIT(m->func_code);
Py_VISIT(m->func_classobj);
Py_VISIT(m->defaults_tuple);
if (m->defaults) {
PyObject **pydefaults = __Pyx_CyFunction_Defaults(PyObject *, m);
......@@ -431,6 +453,13 @@ void *__Pyx_CyFunction_InitDefaults(PyObject *func, size_t size, int pyobjects)
m->defaults_pyobjects = pyobjects;
return m->defaults;
}
static void __Pyx_CyFunction_SetDefaultsTuple(PyObject *func, PyObject *tuple)
{
__pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func;
m->defaults_tuple = tuple;
Py_INCREF(tuple);
}
//////////////////// CyFunctionClassCell.proto ////////////////////
static CYTHON_INLINE void __Pyx_CyFunction_InitClassCell(PyObject *cyfunctions,
PyObject *classobj);
......
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