Commit ed4b9d51 authored by Stefan Behnel's avatar Stefan Behnel

merge

parents 5aeb0139 592be47b
...@@ -550,6 +550,8 @@ class AtomicExprNode(ExprNode): ...@@ -550,6 +550,8 @@ class AtomicExprNode(ExprNode):
class PyConstNode(AtomicExprNode): class PyConstNode(AtomicExprNode):
# Abstract base class for constant Python values. # Abstract base class for constant Python values.
is_literal = 1
def is_simple(self): def is_simple(self):
return 1 return 1
...@@ -571,6 +573,24 @@ class NoneNode(PyConstNode): ...@@ -571,6 +573,24 @@ class NoneNode(PyConstNode):
def compile_time_value(self, denv): def compile_time_value(self, denv):
return None return None
class BoolNode(PyConstNode):
# The constant value True or False
def compile_time_value(self, denv):
return None
def calculate_result_code(self):
if self.value:
return "Py_True"
else:
return "Py_False"
def coerce_to(self, dst_type, env):
value = self.value
if dst_type.is_numeric:
return IntNode(self.pos, value=self.value).coerce_to(dst_type, env)
else:
return PyConstNode.coerce_to(self, dst_type, env)
class EllipsisNode(PyConstNode): class EllipsisNode(PyConstNode):
# '...' in a subscript list. # '...' in a subscript list.
...@@ -1514,13 +1534,19 @@ class SimpleCallNode(ExprNode): ...@@ -1514,13 +1534,19 @@ class SimpleCallNode(ExprNode):
self.result_code = "<error>" self.result_code = "<error>"
return return
# Check no. of args # Check no. of args
expected_nargs = len(func_type.args) max_nargs = len(func_type.args)
expected_nargs = max_nargs - func_type.optional_arg_count
actual_nargs = len(self.args) actual_nargs = len(self.args)
if actual_nargs < expected_nargs \ if actual_nargs < expected_nargs \
or (not func_type.has_varargs and actual_nargs > expected_nargs): or (not func_type.has_varargs and actual_nargs > max_nargs):
expected_str = str(expected_nargs) expected_str = str(expected_nargs)
if func_type.has_varargs: if func_type.has_varargs:
expected_str = "at least " + expected_str expected_str = "at least " + expected_str
elif func_type.optional_arg_count:
if actual_nargs < max_nargs:
expected_str = "at least " + expected_str
else:
expected_str = "at most " + str(max_nargs)
error(self.pos, error(self.pos,
"Call with wrong number of arguments (expected %s, got %s)" "Call with wrong number of arguments (expected %s, got %s)"
% (expected_str, actual_nargs)) % (expected_str, actual_nargs))
...@@ -1529,10 +1555,10 @@ class SimpleCallNode(ExprNode): ...@@ -1529,10 +1555,10 @@ class SimpleCallNode(ExprNode):
self.result_code = "<error>" self.result_code = "<error>"
return return
# Coerce arguments # Coerce arguments
for i in range(expected_nargs): for i in range(min(max_nargs, actual_nargs)):
formal_type = func_type.args[i].type formal_type = func_type.args[i].type
self.args[i] = self.args[i].coerce_to(formal_type, env) self.args[i] = self.args[i].coerce_to(formal_type, env)
for i in range(expected_nargs, actual_nargs): for i in range(max_nargs, actual_nargs):
if self.args[i].type.is_pyobject: if self.args[i].type.is_pyobject:
error(self.args[i].pos, error(self.args[i].pos,
"Python object cannot be passed as a varargs parameter") "Python object cannot be passed as a varargs parameter")
...@@ -1554,14 +1580,33 @@ class SimpleCallNode(ExprNode): ...@@ -1554,14 +1580,33 @@ class SimpleCallNode(ExprNode):
return "<error>" return "<error>"
formal_args = func_type.args formal_args = func_type.args
arg_list_code = [] arg_list_code = []
for (formal_arg, actual_arg) in \ args = zip(formal_args, self.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_code = actual_arg.result_as(formal_arg.type)
arg_list_code.append(arg_code) arg_list_code.append(arg_code)
if func_type.optional_arg_count:
if expected_nargs == actual_nargs:
optional_args = '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)
optional_args = PyrexTypes.c_void_ptr_type.cast_code(
'&' + func_type.op_arg_struct.base_type.cast_code(optional_arg_struct))
arg_list_code.append(optional_args)
for actual_arg in self.args[len(formal_args):]: for actual_arg in self.args[len(formal_args):]:
arg_list_code.append(actual_arg.result_code) arg_list_code.append(actual_arg.result_code)
result = "%s(%s)" % (self.function.result_code, result = "%s(%s)" % (self.function.result_code,
join(arg_list_code, ",")) join(arg_list_code, ", "))
if self.wrapper_call or \ if self.wrapper_call or \
self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable: self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result) result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
...@@ -2123,6 +2168,7 @@ class TupleNode(SequenceNode): ...@@ -2123,6 +2168,7 @@ class TupleNode(SequenceNode):
if len(self.args) == 0: if len(self.args) == 0:
self.type = py_object_type self.type = py_object_type
self.is_temp = 0 self.is_temp = 0
self.is_literal = 1
else: else:
SequenceNode.analyse_types(self, env) SequenceNode.analyse_types(self, env)
...@@ -3539,6 +3585,9 @@ class PyTypeTestNode(CoercionNode): ...@@ -3539,6 +3585,9 @@ class PyTypeTestNode(CoercionNode):
self.result_ctype = arg.ctype() self.result_ctype = arg.ctype()
env.use_utility_code(type_test_utility_code) env.use_utility_code(type_test_utility_code)
def analyse_types(self, env):
pass
def result_in_temp(self): def result_in_temp(self):
return self.arg.result_in_temp() return self.arg.result_in_temp()
...@@ -3552,7 +3601,7 @@ class PyTypeTestNode(CoercionNode): ...@@ -3552,7 +3601,7 @@ class PyTypeTestNode(CoercionNode):
if self.type.typeobj_is_available(): if self.type.typeobj_is_available():
code.putln( code.putln(
"if (!__Pyx_TypeTest(%s, %s)) %s" % ( "if (!__Pyx_TypeTest(%s, %s)) %s" % (
self.arg.py_result(), self.arg.py_result(),
self.type.typeptr_cname, self.type.typeptr_cname,
code.error_goto(self.pos))) code.error_goto(self.pos)))
else: else:
......
...@@ -32,6 +32,7 @@ var_prefix = pyrex_prefix + "v_" ...@@ -32,6 +32,7 @@ var_prefix = pyrex_prefix + "v_"
vtable_prefix = pyrex_prefix + "vtable_" vtable_prefix = pyrex_prefix + "vtable_"
vtabptr_prefix = pyrex_prefix + "vtabptr_" vtabptr_prefix = pyrex_prefix + "vtabptr_"
vtabstruct_prefix = pyrex_prefix + "vtabstruct_" vtabstruct_prefix = pyrex_prefix + "vtabstruct_"
opt_arg_prefix = pyrex_prefix + "opt_args_"
args_cname = pyrex_prefix + "args" args_cname = pyrex_prefix + "args"
kwdlist_cname = pyrex_prefix + "argnames" kwdlist_cname = pyrex_prefix + "argnames"
...@@ -60,6 +61,8 @@ gilstate_cname = pyrex_prefix + "state" ...@@ -60,6 +61,8 @@ gilstate_cname = pyrex_prefix + "state"
skip_dispatch_cname = pyrex_prefix + "skip_dispatch" skip_dispatch_cname = pyrex_prefix + "skip_dispatch"
empty_tuple = pyrex_prefix + "empty_tuple" empty_tuple = pyrex_prefix + "empty_tuple"
cleanup_cname = pyrex_prefix + "module_cleanup" cleanup_cname = pyrex_prefix + "module_cleanup"
optional_args_cname = pyrex_prefix + "optional_args"
no_opt_args = pyrex_prefix + "no_opt_args"
extern_c_macro = pyrex_prefix.upper() + "EXTERN_C" extern_c_macro = pyrex_prefix.upper() + "EXTERN_C"
......
...@@ -316,6 +316,7 @@ class CFuncDeclaratorNode(CDeclaratorNode): ...@@ -316,6 +316,7 @@ class CFuncDeclaratorNode(CDeclaratorNode):
# with_gil boolean Acquire gil around function body # with_gil boolean Acquire gil around function body
overridable = 0 overridable = 0
optional_arg_count = 0
def analyse(self, return_type, env): def analyse(self, return_type, env):
func_type_args = [] func_type_args = []
...@@ -337,7 +338,25 @@ class CFuncDeclaratorNode(CDeclaratorNode): ...@@ -337,7 +338,25 @@ class CFuncDeclaratorNode(CDeclaratorNode):
func_type_args.append( func_type_args.append(
PyrexTypes.CFuncTypeArg(name, type, arg_node.pos)) PyrexTypes.CFuncTypeArg(name, type, arg_node.pos))
if arg_node.default: if arg_node.default:
error(arg_node.pos, "C function argument cannot have default value") self.optional_arg_count += 1
elif self.optional_arg_count:
error(self.pos, "Non-default argument follows default argument")
if self.optional_arg_count:
scope = StructOrUnionScope()
scope.declare_var('%sn' % Naming.pyrex_prefix, 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 = env.mangle(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.defined_in_pxd = 1
self.op_args_struct.used = 1
exc_val = None exc_val = None
exc_check = 0 exc_check = 0
if return_type.is_pyobject \ if return_type.is_pyobject \
...@@ -363,9 +382,12 @@ class CFuncDeclaratorNode(CDeclaratorNode): ...@@ -363,9 +382,12 @@ class CFuncDeclaratorNode(CDeclaratorNode):
"Function cannot return a function") "Function cannot return a function")
func_type = PyrexTypes.CFuncType( func_type = PyrexTypes.CFuncType(
return_type, func_type_args, self.has_varargs, return_type, func_type_args, self.has_varargs,
optional_arg_count = self.optional_arg_count,
exception_value = exc_val, exception_check = exc_check, exception_value = exc_val, exception_check = exc_check,
calling_convention = self.base.calling_convention, calling_convention = self.base.calling_convention,
nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable) nogil = self.nogil, with_gil = self.with_gil, is_overridable = self.overridable)
if self.optional_arg_count:
func_type.op_arg_struct = PyrexTypes.c_ptr_type(self.op_args_struct.type)
return self.base.analyse(func_type, env) return self.base.analyse(func_type, env)
...@@ -377,11 +399,13 @@ class CArgDeclNode(Node): ...@@ -377,11 +399,13 @@ class CArgDeclNode(Node):
# not_none boolean Tagged with 'not None' # not_none boolean Tagged with 'not None'
# default ExprNode or None # default ExprNode or None
# default_entry Symtab.Entry Entry for the variable holding the default value # default_entry Symtab.Entry Entry for the variable holding the default value
# default_result_code string cname or code fragment for default value
# is_self_arg boolean Is the "self" arg of an extension type method # is_self_arg boolean Is the "self" arg of an extension type method
# is_kw_only boolean Is a keyword-only argument # is_kw_only boolean Is a keyword-only argument
is_self_arg = 0 is_self_arg = 0
is_generic = 1
def analyse(self, env): def analyse(self, env):
#print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ### #print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
base_type = self.base_type.analyse(env) base_type = self.base_type.analyse(env)
...@@ -439,6 +463,8 @@ class CSimpleBaseTypeNode(CBaseTypeNode): ...@@ -439,6 +463,8 @@ class CSimpleBaseTypeNode(CBaseTypeNode):
scope = None scope = None
break break
if scope: if scope:
if scope.is_c_class_scope:
scope = scope.global_scope()
entry = scope.find(self.name, self.pos) entry = scope.find(self.name, self.pos)
if entry and entry.is_type: if entry and entry.is_type:
type = entry.type type = entry.type
...@@ -609,10 +635,31 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -609,10 +635,31 @@ class FuncDefNode(StatNode, BlockNode):
# entry Symtab.Entry # entry Symtab.Entry
py_func = None py_func = None
assmt = None
def analyse_default_values(self, env):
genv = env.global_scope()
for arg in self.args:
if arg.default:
if arg.is_generic:
if not hasattr(arg, 'default_entry'):
arg.default.analyse_types(genv)
arg.default = arg.default.coerce_to(arg.type, genv)
if arg.default.is_literal:
arg.default_entry = arg.default
arg.default_result_code = arg.default.calculate_result_code()
if arg.default.type != arg.type and not arg.type.is_int:
arg.default_result_code = arg.type.cast_code(arg.default_result_code)
else:
arg.default.allocate_temps(genv)
arg.default_entry = genv.add_default_value(arg.type)
arg.default_entry.used = 1
arg.default_result_code = arg.default_entry.cname
else:
error(arg.pos,
"This argument cannot have a default value")
arg.default = None
def analyse_expressions(self, env):
pass
def need_gil_acquisition(self, lenv): def need_gil_acquisition(self, lenv):
return 0 return 0
...@@ -729,6 +776,7 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -729,6 +776,7 @@ class FuncDefNode(StatNode, BlockNode):
# ----- Python version # ----- Python version
if self.py_func: if self.py_func:
self.py_func.generate_function_definitions(env, code) self.py_func.generate_function_definitions(env, code)
self.generate_optarg_wrapper_function(env, code)
def put_stararg_decrefs(self, code): def put_stararg_decrefs(self, code):
pass pass
...@@ -748,9 +796,30 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -748,9 +796,30 @@ class FuncDefNode(StatNode, BlockNode):
for entry in env.arg_entries: for entry in env.arg_entries:
code.put_var_incref(entry) code.put_var_incref(entry)
def generate_execution_code(self, code): def generate_optarg_wrapper_function(self, env, code):
pass pass
def generate_execution_code(self, code):
# Evaluate and store argument default values
for arg in self.args:
default = arg.default
if default:
if not default.is_literal:
default.generate_evaluation_code(code)
default.make_owned_reference(code)
code.putln(
"%s = %s;" % (
arg.default_entry.cname,
default.result_as(arg.default_entry.type)))
if default.is_temp and default.type.is_pyobject:
code.putln(
"%s = 0;" %
default.result_code)
# For Python class methods, create and store function object
if self.assmt:
self.assmt.generate_execution_code(code)
class CFuncDefNode(FuncDefNode): class CFuncDefNode(FuncDefNode):
# C function definition. # C function definition.
...@@ -780,6 +849,13 @@ class CFuncDefNode(FuncDefNode): ...@@ -780,6 +849,13 @@ class CFuncDefNode(FuncDefNode):
# from the base type of an extension type. # from the base type of an extension type.
self.type = type self.type = type
type.is_overridable = self.overridable type.is_overridable = self.overridable
declarator = self.declarator
while not hasattr(declarator, 'args'):
declarator = declarator.base
self.args = declarator.args
for formal_arg, type_arg in zip(self.args, type.args):
formal_arg.type = type_arg.type
formal_arg.cname = type_arg.cname
name = name_declarator.name name = name_declarator.name
cname = name_declarator.cname cname = name_declarator.cname
self.entry = env.declare_cfunction( self.entry = env.declare_cfunction(
...@@ -788,14 +864,10 @@ class CFuncDefNode(FuncDefNode): ...@@ -788,14 +864,10 @@ class CFuncDefNode(FuncDefNode):
defining = self.body is not None, defining = self.body is not None,
api = self.api) api = self.api)
self.return_type = type.return_type self.return_type = type.return_type
if self.overridable: if self.overridable:
import ExprNodes import ExprNodes
arg_names = [arg.name for arg in self.type.args] py_func_body = self.call_self_node()
self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.declarator.base.name)
c_call = ExprNodes.SimpleCallNode(self.pos, function=cfunc, args=[ExprNodes.NameNode(self.pos, name=n) for n in arg_names[1:]], wrapper_call=True)
py_func_body = ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
self.py_func = DefNode(pos = self.pos, self.py_func = DefNode(pos = self.pos,
name = self.declarator.base.name, name = self.declarator.base.name,
args = self.declarator.args, args = self.declarator.args,
...@@ -810,7 +882,17 @@ class CFuncDefNode(FuncDefNode): ...@@ -810,7 +882,17 @@ class CFuncDefNode(FuncDefNode):
self.py_func.interned_attr_cname = env.intern(self.py_func.entry.name) self.py_func.interned_attr_cname = env.intern(self.py_func.entry.name)
self.override = OverrideCheckNode(self.pos, py_func = self.py_func) self.override = OverrideCheckNode(self.pos, py_func = self.py_func)
self.body = StatListNode(self.pos, stats=[self.override, self.body]) self.body = StatListNode(self.pos, stats=[self.override, self.body])
def call_self_node(self, omit_optional_args=0):
import ExprNodes
args = self.type.args
if omit_optional_args:
args = args[:len(args) - self.type.optional_arg_count]
arg_names = [arg.name for arg in args]
self_arg = ExprNodes.NameNode(self.pos, name=arg_names[0])
cfunc = ExprNodes.AttributeNode(self.pos, obj=self_arg, attribute=self.declarator.base.name)
c_call = ExprNodes.SimpleCallNode(self.pos, function=cfunc, args=[ExprNodes.NameNode(self.pos, name=n) for n in arg_names[1:]], wrapper_call=True)
return ReturnStatNode(pos=self.pos, return_type=PyrexTypes.py_object_type, value=c_call)
def declare_arguments(self, env): def declare_arguments(self, env):
for arg in self.type.args: for arg in self.type.args:
...@@ -826,18 +908,27 @@ class CFuncDefNode(FuncDefNode): ...@@ -826,18 +908,27 @@ class CFuncDefNode(FuncDefNode):
error(self.pos, "Function declared nogil has Python locals or temporaries") error(self.pos, "Function declared nogil has Python locals or temporaries")
return with_gil return with_gil
def generate_function_header(self, code, with_pymethdef): def analyse_expressions(self, env):
self.analyse_default_values(env)
if self.overridable:
self.py_func.analyse_expressions(env)
def generate_function_header(self, code, with_pymethdef, with_opt_args = 1):
arg_decls = [] arg_decls = []
type = self.type type = self.type
visibility = self.entry.visibility 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()) arg_decls.append(arg.declaration_code())
if type.optional_arg_count and with_opt_args:
arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
if type.has_varargs: if type.has_varargs:
arg_decls.append("...") arg_decls.append("...")
if not arg_decls: if not arg_decls:
arg_decls = ["void"] arg_decls = ["void"]
entity = type.function_header_code(self.entry.func_cname, cname = self.entry.func_cname
string.join(arg_decls, ",")) if not with_opt_args:
cname += Naming.no_opt_args
entity = type.function_header_code(cname, string.join(arg_decls, ", "))
if visibility == 'public': if visibility == 'public':
dll_linkage = "DL_EXPORT" dll_linkage = "DL_EXPORT"
else: else:
...@@ -854,14 +945,28 @@ class CFuncDefNode(FuncDefNode): ...@@ -854,14 +945,28 @@ class CFuncDefNode(FuncDefNode):
header)) header))
def generate_argument_declarations(self, env, code): def generate_argument_declarations(self, env, code):
# Arguments already declared in function header for arg in self.args:
pass if arg.default:
code.putln('%s = %s;' % (arg.type.declaration_code(arg.cname), arg.default_result_code))
def generate_keyword_list(self, code): def generate_keyword_list(self, code):
pass pass
def generate_argument_parsing_code(self, env, code): def generate_argument_parsing_code(self, env, code):
pass i = 0
if self.type.optional_arg_count:
code.putln('if (%s) {' % Naming.optional_args_cname)
for arg in self.args:
if arg.default:
code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i))
declarator = arg.declarator
while not hasattr(declarator, 'name'):
declarator = declarator.base
code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, declarator.name))
i += 1
for _ in range(self.type.optional_arg_count):
code.putln('}')
code.putln('}')
def generate_argument_conversion_code(self, code): def generate_argument_conversion_code(self, code):
pass pass
...@@ -899,6 +1004,19 @@ class CFuncDefNode(FuncDefNode): ...@@ -899,6 +1004,19 @@ class CFuncDefNode(FuncDefNode):
def caller_will_check_exceptions(self): def caller_will_check_exceptions(self):
return self.entry.type.exception_check return self.entry.type.exception_check
def generate_optarg_wrapper_function(self, env, code):
if self.type.optional_arg_count and \
self.type.original_sig and not self.type.original_sig.optional_arg_count:
code.putln()
self.generate_function_header(code, 0, with_opt_args = 0)
if not self.return_type.is_void:
code.put('return ')
args = self.type.args
arglist = [arg.cname for arg in args[:len(args)-self.type.optional_arg_count]]
arglist.append('NULL')
code.putln('%s(%s);' % (self.entry.func_cname, ', '.join(arglist)))
code.putln('}')
class PyArgDeclNode(Node): class PyArgDeclNode(Node):
# Argument which must be a Python object (used # Argument which must be a Python object (used
...@@ -1114,21 +1232,6 @@ class DefNode(FuncDefNode): ...@@ -1114,21 +1232,6 @@ class DefNode(FuncDefNode):
if env.is_py_class_scope: if env.is_py_class_scope:
self.synthesize_assignment_node(env) self.synthesize_assignment_node(env)
def analyse_default_values(self, env):
genv = env.global_scope()
for arg in self.args:
if arg.default:
if arg.is_generic:
arg.default.analyse_types(genv)
arg.default = arg.default.coerce_to(arg.type, genv)
arg.default.allocate_temps(genv)
arg.default_entry = genv.add_default_value(arg.type)
arg.default_entry.used = 1
else:
error(arg.pos,
"This argument cannot have a default value")
arg.default = None
def synthesize_assignment_node(self, env): def synthesize_assignment_node(self, env):
import ExprNodes import ExprNodes
self.assmt = SingleAssignmentNode(self.pos, self.assmt = SingleAssignmentNode(self.pos,
...@@ -1239,7 +1342,7 @@ class DefNode(FuncDefNode): ...@@ -1239,7 +1342,7 @@ class DefNode(FuncDefNode):
code.putln( code.putln(
"%s = %s;" % ( "%s = %s;" % (
arg_entry.cname, arg_entry.cname,
arg.default_entry.cname)) arg.default_result_code))
if not default_seen: if not default_seen:
arg_formats.append("|") arg_formats.append("|")
default_seen = 1 default_seen = 1
...@@ -1546,25 +1649,6 @@ class DefNode(FuncDefNode): ...@@ -1546,25 +1649,6 @@ class DefNode(FuncDefNode):
error(arg.pos, "Cannot test type of extern C class " error(arg.pos, "Cannot test type of extern C class "
"without type object name specification") "without type object name specification")
def generate_execution_code(self, code):
# Evaluate and store argument default values
for arg in self.args:
default = arg.default
if default:
default.generate_evaluation_code(code)
default.make_owned_reference(code)
code.putln(
"%s = %s;" % (
arg.default_entry.cname,
default.result_as(arg.default_entry.type)))
if default.is_temp and default.type.is_pyobject:
code.putln(
"%s = 0;" %
default.result_code)
# For Python class methods, create and store function object
if self.assmt:
self.assmt.generate_execution_code(code)
def error_value(self): def error_value(self):
return self.entry.signature.error_value return self.entry.signature.error_value
...@@ -2954,7 +3038,8 @@ class ExceptClauseNode(Node): ...@@ -2954,7 +3038,8 @@ class ExceptClauseNode(Node):
"}") "}")
def annotate(self, code): def annotate(self, code):
self.pattern.annotate(code) if self.pattern:
self.pattern.annotate(code)
if self.target: if self.target:
self.target.annotate(code) self.target.annotate(code)
self.body.annotate(code) self.body.annotate(code)
......
...@@ -468,6 +468,10 @@ def p_atom(s): ...@@ -468,6 +468,10 @@ def p_atom(s):
s.next() s.next()
if name == "None": if name == "None":
return ExprNodes.NoneNode(pos) return ExprNodes.NoneNode(pos)
elif name == "True":
return ExprNodes.BoolNode(pos, value=1)
elif name == "False":
return ExprNodes.BoolNode(pos, value=0)
else: else:
return p_name(s, name) return p_name(s, name)
elif sy == 'NULL': elif sy == 'NULL':
...@@ -1325,6 +1329,7 @@ def p_statement(s, level, cdef_flag = 0, visibility = 'private', api = 0): ...@@ -1325,6 +1329,7 @@ def p_statement(s, level, cdef_flag = 0, visibility = 'private', api = 0):
if cdef_flag: if cdef_flag:
if level not in ('module', 'module_pxd', 'function', 'c_class', 'c_class_pxd'): if level not in ('module', 'module_pxd', 'function', 'c_class', 'c_class_pxd'):
s.error('cdef statement not allowed here') s.error('cdef statement not allowed here')
s.level = level
return p_cdef_statement(s, level, visibility = visibility, return p_cdef_statement(s, level, visibility = visibility,
api = api, overridable = overridable) api = api, overridable = overridable)
# elif s.sy == 'cpdef': # elif s.sy == 'cpdef':
...@@ -1336,6 +1341,7 @@ def p_statement(s, level, cdef_flag = 0, visibility = 'private', api = 0): ...@@ -1336,6 +1341,7 @@ def p_statement(s, level, cdef_flag = 0, visibility = 'private', api = 0):
elif s.sy == 'def': elif s.sy == 'def':
if level not in ('module', 'class', 'c_class', 'property'): if level not in ('module', 'class', 'c_class', 'property'):
s.error('def statement not allowed here') s.error('def statement not allowed here')
s.level = level
return p_def_statement(s) return p_def_statement(s)
elif s.sy == 'class': elif s.sy == 'class':
if level <> 'module': if level <> 'module':
...@@ -1692,7 +1698,13 @@ def p_c_arg_decl(s, in_pyfunc, cmethod_flag = 0, nonempty = 0, kw_only = 0): ...@@ -1692,7 +1698,13 @@ def p_c_arg_decl(s, in_pyfunc, cmethod_flag = 0, nonempty = 0, kw_only = 0):
not_none = 1 not_none = 1
if s.sy == '=': if s.sy == '=':
s.next() s.next()
default = p_simple_expr(s) if 'pxd' in s.level:
if s.sy not in ['*', '?']:
error(pos, "default values cannot be specified in pxd files, use ? or *")
default = 1
s.next()
else:
default = p_simple_expr(s)
return Nodes.CArgDeclNode(pos, return Nodes.CArgDeclNode(pos,
base_type = base_type, base_type = base_type,
declarator = declarator, declarator = declarator,
......
...@@ -584,13 +584,15 @@ class CFuncType(CType): ...@@ -584,13 +584,15 @@ class CFuncType(CType):
# with_gil boolean Acquire gil around function body # with_gil boolean Acquire gil around function body
is_cfunction = 1 is_cfunction = 1
original_sig = None
def __init__(self, return_type, args, has_varargs = 0, def __init__(self, return_type, args, has_varargs = 0,
exception_value = None, exception_check = 0, calling_convention = "", exception_value = None, exception_check = 0, calling_convention = "",
nogil = 0, with_gil = 0, is_overridable = 0): nogil = 0, with_gil = 0, is_overridable = 0, optional_arg_count = 0):
self.return_type = return_type self.return_type = return_type
self.args = args self.args = args
self.has_varargs = has_varargs self.has_varargs = has_varargs
self.optional_arg_count = optional_arg_count
self.exception_value = exception_value self.exception_value = exception_value
self.exception_check = exception_check self.exception_check = exception_check
self.calling_convention = calling_convention self.calling_convention = calling_convention
...@@ -625,7 +627,7 @@ class CFuncType(CType): ...@@ -625,7 +627,7 @@ class CFuncType(CType):
return 1 return 1
if not other_type.is_cfunction: if not other_type.is_cfunction:
return 0 return 0
if self.is_overridable != other_type.is_overridable: if not self.is_overridable and other_type.is_overridable:
return 0 return 0
nargs = len(self.args) nargs = len(self.args)
if nargs <> len(other_type.args): if nargs <> len(other_type.args):
...@@ -639,12 +641,51 @@ class CFuncType(CType): ...@@ -639,12 +641,51 @@ class CFuncType(CType):
return 0 return 0
if self.has_varargs <> other_type.has_varargs: if self.has_varargs <> other_type.has_varargs:
return 0 return 0
if self.optional_arg_count <> other_type.optional_arg_count:
return 0
if not self.return_type.same_as(other_type.return_type):
return 0
if not self.same_calling_convention_as(other_type):
return 0
return 1
def compatible_signature_with(self, other_type, as_cmethod = 0):
return self.compatible_signature_with_resolved_type(other_type.resolve(), as_cmethod)
def compatible_signature_with_resolved_type(self, other_type, as_cmethod):
#print "CFuncType.same_c_signature_as_resolved_type:", \
# self, other_type, "as_cmethod =", as_cmethod ###
if other_type is error_type:
return 1
if not other_type.is_cfunction:
return 0
if not self.is_overridable and other_type.is_overridable:
return 0
nargs = len(self.args)
if nargs - self.optional_arg_count != len(other_type.args) - other_type.optional_arg_count:
return 0
if self.optional_arg_count < other_type.optional_arg_count:
return 0
# When comparing C method signatures, the first argument
# is exempt from compatibility checking (the proper check
# is performed elsewhere).
for i in range(as_cmethod, len(other_type.args)):
if not self.args[i].type.same_as(
other_type.args[i].type):
return 0
if self.has_varargs != other_type.has_varargs:
return 0
if not self.return_type.same_as(other_type.return_type): if not self.return_type.same_as(other_type.return_type):
return 0 return 0
if not self.same_calling_convention_as(other_type): if not self.same_calling_convention_as(other_type):
return 0 return 0
self.original_sig = other_type.original_sig or other_type
if as_cmethod:
self.args[0] = other_type.args[0]
return 1 return 1
def narrower_c_signature_than(self, other_type, as_cmethod = 0): def narrower_c_signature_than(self, other_type, as_cmethod = 0):
return self.narrower_c_signature_than_resolved_type(other_type.resolve(), as_cmethod) return self.narrower_c_signature_than_resolved_type(other_type.resolve(), as_cmethod)
...@@ -664,6 +705,8 @@ class CFuncType(CType): ...@@ -664,6 +705,8 @@ class CFuncType(CType):
or not self.args[i].type.same_as(other_type.args[i].type) or not self.args[i].type.same_as(other_type.args[i].type)
if self.has_varargs <> other_type.has_varargs: if self.has_varargs <> other_type.has_varargs:
return 0 return 0
if self.optional_arg_count <> other_type.optional_arg_count:
return 0
if not self.return_type.subtype_of_resolved_type(other_type.return_type): if not self.return_type.subtype_of_resolved_type(other_type.return_type):
return 0 return 0
return 1 return 1
...@@ -688,12 +731,14 @@ class CFuncType(CType): ...@@ -688,12 +731,14 @@ class CFuncType(CType):
def declaration_code(self, entity_code, def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0): for_display = 0, dll_linkage = None, pyrex = 0):
arg_decl_list = [] 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_decl_list.append(
arg.type.declaration_code("", for_display, pyrex = pyrex)) arg.type.declaration_code("", for_display, pyrex = pyrex))
if self.optional_arg_count:
arg_decl_list.append(self.op_arg_struct.declaration_code(Naming.optional_args_cname))
if self.has_varargs: if self.has_varargs:
arg_decl_list.append("...") 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: if not arg_decl_code and not pyrex:
arg_decl_code = "void" arg_decl_code = "void"
exc_clause = "" exc_clause = ""
......
...@@ -1058,14 +1058,14 @@ class StructOrUnionScope(Scope): ...@@ -1058,14 +1058,14 @@ class StructOrUnionScope(Scope):
Scope.__init__(self, "?", None, None) Scope.__init__(self, "?", None, None)
def declare_var(self, name, type, pos, 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. # Add an entry for an attribute.
if not cname: if not cname:
cname = name cname = name
entry = self.declare(name, cname, type, pos) entry = self.declare(name, cname, type, pos)
entry.is_variable = 1 entry.is_variable = 1
self.var_entries.append(entry) self.var_entries.append(entry)
if type.is_pyobject: if type.is_pyobject and not allow_pyobject:
error(pos, error(pos,
"C struct/union member cannot be a Python object") "C struct/union member cannot be a Python object")
if visibility <> 'private': if visibility <> 'private':
...@@ -1275,6 +1275,21 @@ class CClassScope(ClassScope): ...@@ -1275,6 +1275,21 @@ class CClassScope(ClassScope):
#print "CClassScope.declare_cfunction: checking signature" ### #print "CClassScope.declare_cfunction: checking signature" ###
if type.same_c_signature_as(entry.type, as_cmethod = 1): if type.same_c_signature_as(entry.type, as_cmethod = 1):
pass pass
elif type.compatible_signature_with(entry.type, as_cmethod = 1):
if type.optional_arg_count and not type.original_sig.optional_arg_count:
# Need to put a wrapper taking no optional arguments
# into the method table.
wrapper_func_cname = self.mangle(Naming.func_prefix, name) + Naming.no_opt_args
wrapper_func_name = name + Naming.no_opt_args
if entry.type.optional_arg_count:
old_entry = self.lookup_here(wrapper_func_name)
old_entry.func_cname = wrapper_func_cname
else:
entry.func_cname = wrapper_func_cname
entry.name = wrapper_func_name
entry = self.add_cfunction(name, type, pos, cname or name, visibility)
defining = 1
entry.type = type
# if type.narrower_c_signature_than(entry.type, as_cmethod = 1): # if type.narrower_c_signature_than(entry.type, as_cmethod = 1):
# entry.type = type # entry.type = type
else: else:
......
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