Commit ed4b9d51 authored by Stefan Behnel's avatar Stefan Behnel

merge

parents 5aeb0139 592be47b
......@@ -550,6 +550,8 @@ class AtomicExprNode(ExprNode):
class PyConstNode(AtomicExprNode):
# Abstract base class for constant Python values.
is_literal = 1
def is_simple(self):
return 1
......@@ -571,6 +573,24 @@ class NoneNode(PyConstNode):
def compile_time_value(self, denv):
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):
# '...' in a subscript list.
......@@ -1514,13 +1534,19 @@ class SimpleCallNode(ExprNode):
self.result_code = "<error>"
return
# 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)
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)
if func_type.has_varargs:
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,
"Call with wrong number of arguments (expected %s, got %s)"
% (expected_str, actual_nargs))
......@@ -1529,10 +1555,10 @@ class SimpleCallNode(ExprNode):
self.result_code = "<error>"
return
# Coerce arguments
for i in range(expected_nargs):
for i in range(min(max_nargs, actual_nargs)):
formal_type = func_type.args[i].type
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:
error(self.args[i].pos,
"Python object cannot be passed as a varargs parameter")
......@@ -1554,14 +1580,33 @@ class SimpleCallNode(ExprNode):
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:
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):]:
arg_list_code.append(actual_arg.result_code)
result = "%s(%s)" % (self.function.result_code,
join(arg_list_code, ","))
join(arg_list_code, ", "))
if self.wrapper_call or \
self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
......@@ -2123,6 +2168,7 @@ class TupleNode(SequenceNode):
if len(self.args) == 0:
self.type = py_object_type
self.is_temp = 0
self.is_literal = 1
else:
SequenceNode.analyse_types(self, env)
......@@ -3539,6 +3585,9 @@ class PyTypeTestNode(CoercionNode):
self.result_ctype = arg.ctype()
env.use_utility_code(type_test_utility_code)
def analyse_types(self, env):
pass
def result_in_temp(self):
return self.arg.result_in_temp()
......
......@@ -32,6 +32,7 @@ var_prefix = pyrex_prefix + "v_"
vtable_prefix = pyrex_prefix + "vtable_"
vtabptr_prefix = pyrex_prefix + "vtabptr_"
vtabstruct_prefix = pyrex_prefix + "vtabstruct_"
opt_arg_prefix = pyrex_prefix + "opt_args_"
args_cname = pyrex_prefix + "args"
kwdlist_cname = pyrex_prefix + "argnames"
......@@ -60,6 +61,8 @@ gilstate_cname = pyrex_prefix + "state"
skip_dispatch_cname = pyrex_prefix + "skip_dispatch"
empty_tuple = pyrex_prefix + "empty_tuple"
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"
......
This diff is collapsed.
......@@ -468,6 +468,10 @@ def p_atom(s):
s.next()
if name == "None":
return ExprNodes.NoneNode(pos)
elif name == "True":
return ExprNodes.BoolNode(pos, value=1)
elif name == "False":
return ExprNodes.BoolNode(pos, value=0)
else:
return p_name(s, name)
elif sy == 'NULL':
......@@ -1325,6 +1329,7 @@ def p_statement(s, level, cdef_flag = 0, visibility = 'private', api = 0):
if cdef_flag:
if level not in ('module', 'module_pxd', 'function', 'c_class', 'c_class_pxd'):
s.error('cdef statement not allowed here')
s.level = level
return p_cdef_statement(s, level, visibility = visibility,
api = api, overridable = overridable)
# elif s.sy == 'cpdef':
......@@ -1336,6 +1341,7 @@ def p_statement(s, level, cdef_flag = 0, visibility = 'private', api = 0):
elif s.sy == 'def':
if level not in ('module', 'class', 'c_class', 'property'):
s.error('def statement not allowed here')
s.level = level
return p_def_statement(s)
elif s.sy == 'class':
if level <> 'module':
......@@ -1692,6 +1698,12 @@ def p_c_arg_decl(s, in_pyfunc, cmethod_flag = 0, nonempty = 0, kw_only = 0):
not_none = 1
if s.sy == '=':
s.next()
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,
base_type = base_type,
......
......@@ -584,13 +584,15 @@ class CFuncType(CType):
# with_gil boolean Acquire gil around function body
is_cfunction = 1
original_sig = None
def __init__(self, return_type, args, has_varargs = 0,
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.args = args
self.has_varargs = has_varargs
self.optional_arg_count = optional_arg_count
self.exception_value = exception_value
self.exception_check = exception_check
self.calling_convention = calling_convention
......@@ -625,7 +627,7 @@ class CFuncType(CType):
return 1
if not other_type.is_cfunction:
return 0
if self.is_overridable != other_type.is_overridable:
if not self.is_overridable and other_type.is_overridable:
return 0
nargs = len(self.args)
if nargs <> len(other_type.args):
......@@ -639,12 +641,51 @@ class CFuncType(CType):
return 0
if self.has_varargs <> other_type.has_varargs:
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):
return 0
if not self.same_calling_convention_as(other_type):
return 0
self.original_sig = other_type.original_sig or other_type
if as_cmethod:
self.args[0] = other_type.args[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)
......@@ -664,6 +705,8 @@ class CFuncType(CType):
or not self.args[i].type.same_as(other_type.args[i].type)
if self.has_varargs <> other_type.has_varargs:
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):
return 0
return 1
......@@ -688,12 +731,14 @@ class CFuncType(CType):
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(self.op_arg_struct.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 = ""
......
......@@ -1058,14 +1058,14 @@ class StructOrUnionScope(Scope):
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':
......@@ -1275,6 +1275,21 @@ class CClassScope(ClassScope):
#print "CClassScope.declare_cfunction: checking signature" ###
if type.same_c_signature_as(entry.type, as_cmethod = 1):
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):
# entry.type = type
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