return "<error>"
formal_args = func_type.args
arg_list_code = []
- for (formal_arg, actual_arg) in \
- zip(formal_args, self.args):
+ args = zip(formal_args, self.args)
+ max_nargs = len(func_type.args)
+ expected_nargs = max_nargs - func_type.optional_arg_count
+ actual_nargs = len(self.args)
+ for formal_arg, actual_arg in args[:expected_nargs]:
arg_code = actual_arg.result_as(formal_arg.type)
arg_list_code.append(arg_code)
if func_type.optional_arg_count:
- for formal_arg in formal_args[len(self.args):]:
- arg_list_code.append(formal_arg.type.cast_code('0'))
- arg_list_code.append(str(max(0, len(formal_args) - len(self.args))))
+ if expected_nargs == actual_nargs:
+ arg_list_code.append(func_type.op_args.cast_code('NULL'))
+ else:
+ optional_arg_code = [str(actual_nargs - expected_nargs)]
+ for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
+ arg_code = actual_arg.result_as(formal_arg.type)
+ optional_arg_code.append(arg_code)
+# for formal_arg in formal_args[actual_nargs:max_nargs]:
+# optional_arg_code.append(formal_arg.type.cast_code('0'))
+ optional_arg_struct = '{%s}' % ','.join(optional_arg_code)
+ arg_list_code.append('&' + func_type.op_args.base_type.cast_code(optional_arg_struct))
for actual_arg in self.args[len(formal_args):]:
arg_list_code.append(actual_arg.result_code)
result = "%s(%s)" % (self.function.result_code,
PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
if arg_node.default:
self.optional_arg_count += 1
+
+ if self.optional_arg_count:
+ scope = StructOrUnionScope()
+ scope.declare_var('n', PyrexTypes.c_int_type, self.pos)
+ for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
+ scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
+ struct_cname = Naming.opt_arg_prefix + self.base.name
+ self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
+ kind = 'struct',
+ scope = scope,
+ typedef_flag = 0,
+ pos = self.pos,
+ cname = struct_cname)
+ self.op_args_struct.used = 1
+
exc_val = None
exc_check = 0
if return_type.is_pyobject \
exception_value = exc_val, exception_check = exc_check,
calling_convention = self.base.calling_convention,
nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
+ if self.optional_arg_count:
+ func_type.op_args = PyrexTypes.c_ptr_type(self.op_args_struct.type)
return self.base.analyse(func_type, env)
# is_kw_only boolean Is a keyword-only argument
is_self_arg = 0
-
+ is_generic = 1
+
def analyse(self, env):
#print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
base_type = self.base_type.analyse(env)
# from the base type of an extension type.
self.type = type
type.is_overridable = self.overridable
+ for formal_arg, type_arg in zip(self.declarator.args, type.args):
+ formal_arg.type = type_arg.type
+ formal_arg.cname = type_arg.cname
name = name_declarator.name
cname = name_declarator.cname
self.entry = env.declare_cfunction(
defining = self.body is not None,
api = self.api)
self.return_type = type.return_type
-
+
if self.overridable:
import ExprNodes
arg_names = [arg.name for arg in self.type.args]
arg_decls = []
type = self.type
visibility = self.entry.visibility
- for arg in type.args:
+ for arg in type.args[:len(type.args)-type.optional_arg_count]:
arg_decls.append(arg.declaration_code())
if type.optional_arg_count:
- arg_decls.append("int %s" % Naming.optional_count_cname)
+ arg_decls.append(type.op_args.declaration_code(Naming.optional_args_cname))
if type.has_varargs:
arg_decls.append("...")
if not arg_decls:
arg_decls = ["void"]
entity = type.function_header_code(self.entry.func_cname,
- string.join(arg_decls, ","))
+ string.join(arg_decls, ", "))
if visibility == 'public':
dll_linkage = "DL_EXPORT"
else:
header))
def generate_argument_declarations(self, env, code):
- # Arguments already declared in function header
- pass
-
+ for arg in self.declarator.args:
+ if arg.default:
+ code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_entry.cname))
+
def generate_keyword_list(self, code):
pass
def generate_argument_parsing_code(self, code):
- rev_args = zip(self.declarator.args, self.type.args)
- rev_args.reverse()
+ rev_args = self.declarator.args
i = 0
- for darg, targ in rev_args:
- if darg.default:
- code.putln('if (%s > %s) {' % (Naming.optional_count_cname, i))
- code.putln('%s = %s;' % (targ.cname, darg.default_entry.cname))
- i += 1
- for _ in range(i):
+ if self.type.optional_arg_count:
+ code.putln('if (%s) {' % Naming.optional_args_cname)
+ for arg in rev_args:
+ if arg.default:
+ code.putln('if (%s->n > %s) {' % (Naming.optional_args_cname, i))
+ code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, arg.declarator.name))
+ i += 1
+ for _ in range(self.type.optional_arg_count):
+ code.putln('}')
code.putln('}')
- code.putln('/* defaults */')
def generate_argument_conversion_code(self, code):
pass
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
arg_decl_list = []
- for arg in self.args:
+ for arg in self.args[:len(self.args)-self.optional_arg_count]:
arg_decl_list.append(
arg.type.declaration_code("", for_display, pyrex = pyrex))
if self.optional_arg_count:
- arg_decl_list.append("int %s" % Naming.optional_count_cname)
+ arg_decl_list.append(self.op_args.declaration_code(Naming.optional_args_cname))
if self.has_varargs:
arg_decl_list.append("...")
- arg_decl_code = string.join(arg_decl_list, ",")
+ arg_decl_code = string.join(arg_decl_list, ", ")
if not arg_decl_code and not pyrex:
arg_decl_code = "void"
exc_clause = ""
Scope.__init__(self, "?", None, None)
def declare_var(self, name, type, pos,
- cname = None, visibility = 'private', is_cdef = 0):
+ cname = None, visibility = 'private', is_cdef = 0, allow_pyobject = 0):
# Add an entry for an attribute.
if not cname:
cname = name
entry = self.declare(name, cname, type, pos)
entry.is_variable = 1
self.var_entries.append(entry)
- if type.is_pyobject:
+ if type.is_pyobject and not allow_pyobject:
error(pos,
"C struct/union member cannot be a Python object")
if visibility <> 'private':