for arg in self.type.args:
if not arg.name:
error(arg.pos, "Missing argument name")
- self.declare_argument(env, arg)
+ arg.entry = self.declare_argument(env, arg)
def generate_function_header(self, code, with_pymethdef):
arg_decls = []
pass
def generate_argument_type_tests(self, code):
- pass
+ # Generate type tests for args whose type in a parent
+ # class is a supertype of the declared type.
+ for arg in self.type.args:
+ if arg.needs_type_test:
+ self.generate_arg_type_test(arg, code)
+
+ def generate_arg_type_test(self, arg, code):
+ # Generate type test for one argument.
+ if arg.type.typeobj_is_available():
+ typeptr_cname = arg.type.typeptr_cname
+ arg_code = "((PyObject *)%s)" % arg.entry.cname
+ code.putln(
+ 'if (!__Pyx_ArgTypeTest(%s, %s, %d, "%s")) %s' % (
+ arg_code,
+ typeptr_cname,
+ not arg.not_none,
+ arg.name,
+ code.error_goto(arg.pos)))
+ else:
+ error(arg.pos, "Cannot test type of extern C class "
+ "without type object name specification")
def error_value(self):
if self.return_type.is_pyobject:
static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *name, char *modname); /*proto*/
static int __Pyx_InternStrings(__Pyx_InternTabEntry *t); /*proto*/
static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
+
+#DEFINE __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False))
+#DEFINE __Pyx_PyObject_IsTrue(x) ({PyObject *_x = (x); _x == Py_True ? 1 : (_x) == Py_False ? 0 : PyObject_IsTrue(_x)})
"""
get_name_predeclaration = \
# TODO: this should be a macro "(__ ? Py_True : Py_False)"
# and no error checking should be needed (just an incref).
- to_py_function = "PyBool_FromLong"
- from_py_function = "PyObject_IsTrue"
+ to_py_function = "__Pyx_PyBool_FromLong"
+ from_py_function = "__Pyx_PyObject_IsTrue"
class CPySSizeTType(CIntType):
if not self.return_type.same_as(other_type.return_type):
return 0
return 1
+
+ def narrower_c_signature_than(self, other_type, as_cmethod = 0):
+ return self.narrower_c_signature_than_resolved_type(other_type.resolve(), as_cmethod)
+
+ def narrower_c_signature_than_resolved_type(self, other_type, as_cmethod):
+ if other_type is error_type:
+ return 1
+ if not other_type.is_cfunction:
+ return 0
+ nargs = len(self.args)
+ if nargs <> len(other_type.args):
+ return 0
+ for i in range(as_cmethod, nargs):
+ if not self.args[i].type.subtype_of_resolved_type(other_type.args[i].type):
+ return 0
+ else:
+ self.args[i].needs_type_test = other_type.args[i].needs_type_test \
+ or not self.args[i].type.same_as(other_type.args[i].type)
+ if self.has_varargs <> other_type.has_varargs:
+ return 0
+ if not self.return_type.subtype_of_resolved_type(other_type.return_type):
+ return 0
+ return 1
+
def same_exception_signature_as(self, other_type):
return self.same_exception_signature_as_resolved_type(
self.cname = Naming.var_prefix + name
self.type = type
self.pos = pos
+ self.not_none = False
+ self.needs_type_test = False # TODO: should these defaults be set in analyse_types()?
def __repr__(self):
return "%s:%s" % (self.name, repr(self.type))
if defining and entry.func_cname:
error(pos, "'%s' already defined" % name)
if not entry.type.same_as(type, as_cmethod = 1):
- error(pos, "Signature does not match previous declaration")
+ old_type = entry.type
+ if type.narrower_c_signature_than(entry.type, as_cmethod = 1):
+ entry.type = type
+ else:
+ error(pos, "Signature not compatible with previous declaration")
else:
if self.defined:
error(pos,