Commit d97bdff5 authored by Stefan Behnel's avatar Stefan Behnel

merge

parents 46f2563c 1d5644c7
...@@ -628,7 +628,7 @@ class BoolNode(ConstNode): ...@@ -628,7 +628,7 @@ class BoolNode(ConstNode):
return self.value return self.value
def calculate_result_code(self): def calculate_result_code(self):
return int(self.value) return str(int(self.value))
class NullNode(ConstNode): class NullNode(ConstNode):
type = PyrexTypes.c_null_ptr_type type = PyrexTypes.c_null_ptr_type
...@@ -1680,6 +1680,7 @@ class SimpleCallNode(CallNode): ...@@ -1680,6 +1680,7 @@ class SimpleCallNode(CallNode):
# self ExprNode or None used internally # self ExprNode or None used internally
# coerced_self ExprNode or None used internally # coerced_self ExprNode or None used internally
# wrapper_call bool used internally # wrapper_call bool used internally
# has_optional_args bool used internally
subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple'] subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
...@@ -1687,6 +1688,7 @@ class SimpleCallNode(CallNode): ...@@ -1687,6 +1688,7 @@ class SimpleCallNode(CallNode):
coerced_self = None coerced_self = None
arg_tuple = None arg_tuple = None
wrapper_call = False wrapper_call = False
has_optional_args = False
def compile_time_value(self, denv): def compile_time_value(self, denv):
function = self.function.compile_time_value(denv) function = self.function.compile_time_value(denv)
...@@ -1773,6 +1775,11 @@ class SimpleCallNode(CallNode): ...@@ -1773,6 +1775,11 @@ class SimpleCallNode(CallNode):
self.type = PyrexTypes.error_type self.type = PyrexTypes.error_type
self.result_code = "<error>" self.result_code = "<error>"
return return
if func_type.optional_arg_count and expected_nargs != actual_nargs:
self.has_optional_args = 1
self.is_temp = 1
self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
env.release_temp(self.opt_arg_struct)
# Coerce arguments # Coerce arguments
for i in range(min(max_nargs, actual_nargs)): for i in range(min(max_nargs, actual_nargs)):
formal_type = func_type.args[i].type formal_type = func_type.args[i].type
...@@ -1818,15 +1825,7 @@ class SimpleCallNode(CallNode): ...@@ -1818,15 +1825,7 @@ class SimpleCallNode(CallNode):
if expected_nargs == actual_nargs: if expected_nargs == actual_nargs:
optional_args = 'NULL' optional_args = 'NULL'
else: else:
optional_arg_code = [str(actual_nargs - expected_nargs)] optional_args = "&%s" % self.opt_arg_struct
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) arg_list_code.append(optional_args)
for actual_arg in self.args[len(formal_args):]: for actual_arg in self.args[len(formal_args):]:
...@@ -1849,6 +1848,19 @@ class SimpleCallNode(CallNode): ...@@ -1849,6 +1848,19 @@ class SimpleCallNode(CallNode):
arg_code, arg_code,
code.error_goto_if_null(self.result_code, self.pos))) code.error_goto_if_null(self.result_code, self.pos)))
elif func_type.is_cfunction: elif func_type.is_cfunction:
if self.has_optional_args:
actual_nargs = len(self.args)
expected_nargs = len(func_type.args) - func_type.optional_arg_count
code.putln("%s.%s = %s;" % (
self.opt_arg_struct,
Naming.pyrex_prefix + "n",
len(self.args) - expected_nargs))
args = zip(func_type.args, self.args)
for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
code.putln("%s.%s = %s;" % (
self.opt_arg_struct,
formal_arg.name,
actual_arg.result_as(formal_arg.type)))
exc_checks = [] exc_checks = []
if self.type.is_pyobject: if self.type.is_pyobject:
exc_checks.append("!%s" % self.result_code) exc_checks.append("!%s" % self.result_code)
...@@ -1883,12 +1895,12 @@ class SimpleCallNode(CallNode): ...@@ -1883,12 +1895,12 @@ class SimpleCallNode(CallNode):
rhs, rhs,
raise_py_exception, raise_py_exception,
code.error_goto(self.pos))) code.error_goto(self.pos)))
return else:
code.putln( if exc_checks:
"%s%s; %s" % ( goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
lhs, else:
rhs, goto_error = ""
code.error_goto_if(" && ".join(exc_checks), self.pos))) code.putln("%s%s; %s" % (lhs, rhs, goto_error))
class GeneralCallNode(CallNode): class GeneralCallNode(CallNode):
# General Python function call, including keyword, # General Python function call, including keyword,
......
...@@ -1467,7 +1467,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1467,7 +1467,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
entry.is_identifier entry.is_identifier
)) ))
code.putln( code.putln(
"{0, 0, 0, 0, 0}") "{0, 0, 0, 0, 0, 0}")
code.putln( code.putln(
"};") "};")
......
...@@ -362,8 +362,13 @@ class CNameDeclaratorNode(CDeclaratorNode): ...@@ -362,8 +362,13 @@ class CNameDeclaratorNode(CDeclaratorNode):
def analyse(self, base_type, env, nonempty = 0): def analyse(self, base_type, env, nonempty = 0):
if nonempty and self.name == '': if nonempty and self.name == '':
# Must have mistaken the name for the type. raise RuntimeError
self.name = base_type.name # May have mistaken the name for the type.
if base_type.is_ptr or base_type.is_array or base_type.is_buffer:
error(self.pos, "Missing argument name.")
elif base_type.is_void:
error(self.pos, "Use spam() rather than spam(void) to declare a function with no arguments.")
self.name = base_type.declaration_code("", for_display=1, pyrex=1)
base_type = py_object_type base_type = py_object_type
self.type = base_type self.type = base_type
return self, base_type return self, base_type
...@@ -424,7 +429,7 @@ class CFuncDeclaratorNode(CDeclaratorNode): ...@@ -424,7 +429,7 @@ class CFuncDeclaratorNode(CDeclaratorNode):
def analyse(self, return_type, env, nonempty = 0): def analyse(self, return_type, env, nonempty = 0):
func_type_args = [] func_type_args = []
for arg_node in self.args: for arg_node in self.args:
name_declarator, type = arg_node.analyse(env, nonempty = nonempty) name_declarator, type = arg_node.analyse(env)
name = name_declarator.name name = name_declarator.name
if name_declarator.cname: if name_declarator.cname:
error(self.pos, error(self.pos,
......
...@@ -1620,15 +1620,19 @@ def p_c_simple_base_type(s, self_flag, nonempty): ...@@ -1620,15 +1620,19 @@ def p_c_simple_base_type(s, self_flag, nonempty):
# Treat trailing [] on type as buffer access # Treat trailing [] on type as buffer access
if not is_basic and s.sy == '[': if s.sy == '[':
return p_buffer_access(s, type_node) return p_buffer_access(s, type_node)
else: else:
return type_node return type_node
def p_buffer_access(s, type_node): def p_buffer_access(s, base_type_node):
# s.sy == '[' # s.sy == '['
pos = s.position() pos = s.position()
s.next() s.next()
if s.sy == ']':
# not buffer, could be [] on C type nameless array arguments
s.put_back('[', '[')
return base_type_node
positional_args, keyword_args = ( positional_args, keyword_args = (
p_positional_and_keyword_args(s, (']',), (0,), ('dtype',)) p_positional_and_keyword_args(s, (']',), (0,), ('dtype',))
) )
...@@ -1643,7 +1647,7 @@ def p_buffer_access(s, type_node): ...@@ -1643,7 +1647,7 @@ def p_buffer_access(s, type_node):
result = Nodes.CBufferAccessTypeNode(pos, result = Nodes.CBufferAccessTypeNode(pos,
positional_args = positional_args, positional_args = positional_args,
keyword_args = keyword_dict, keyword_args = keyword_dict,
base_type_node = type_node) base_type_node = base_type_node)
return result return result
......
...@@ -58,6 +58,7 @@ class TestBufferOptions(CythonTest): ...@@ -58,6 +58,7 @@ class TestBufferOptions(CythonTest):
self.assert_(self.expect_error) self.assert_(self.expect_error)
def parse_opts(self, opts, expect_error=False): def parse_opts(self, opts, expect_error=False):
assert opts != ""
s = u"def f():\n cdef object[%s] x" % opts s = u"def f():\n cdef object[%s] x" % opts
self.expect_error = expect_error self.expect_error = expect_error
root = self.fragment(s, pipeline=[NormalizeTree(self), PostParse(self)]).root root = self.fragment(s, pipeline=[NormalizeTree(self), PostParse(self)]).root
...@@ -89,9 +90,6 @@ class TestBufferOptions(CythonTest): ...@@ -89,9 +90,6 @@ class TestBufferOptions(CythonTest):
self.assert_(buf.dtype_node.signed == 0 and buf.dtype_node.longness == -1) self.assert_(buf.dtype_node.signed == 0 and buf.dtype_node.longness == -1)
self.assertEqual(3, buf.ndim) self.assertEqual(3, buf.ndim)
def test_dtype(self):
self.non_parse(ERR_BUF_MISSING % 'dtype', u"")
def test_ndim(self): def test_ndim(self):
self.parse_opts(u"int, 2") self.parse_opts(u"int, 2")
self.non_parse(ERR_BUF_INT % 'ndim', u"int, 'a'") self.non_parse(ERR_BUF_INT % 'ndim', u"int, 'a'")
......
...@@ -7,7 +7,6 @@ from Cython.Distutils import build_ext ...@@ -7,7 +7,6 @@ from Cython.Distutils import build_ext
ext_modules=[ ext_modules=[
Extension("primes", ["primes.pyx"]), Extension("primes", ["primes.pyx"]),
Extension("spam", ["spam.pyx"]), Extension("spam", ["spam.pyx"]),
# Extension("optargs", ["optargs.pyx"], language = "c++"),
] ]
for file in glob.glob("*.pyx"): for file in glob.glob("*.pyx"):
......
PYTHON?=python PYTHON?=python
all: local
local:
${PYTHON} setup.py build_ext --inplace
clean: clean:
@echo Cleaning Source @echo Cleaning Source
@rm -fr build @rm -fr build
@rm -f *.pyc */*.pyc */*/*.pyc @rm -f *.pyc */*.pyc */*/*.pyc
@rm -f *~ */*~ */*/*~ @rm -f *~ */*~ */*/*~
@rm -f core */core @rm -f core */core
@rm -f Cython/Plex/Scanners.{so,pyd}
@(cd Demos; $(MAKE) clean) @(cd Demos; $(MAKE) clean)
testclean: testclean:
......
cdef extern from *:
cdef void foo(int[])
ctypedef int MyInt
cdef void foo(MyInt[])
struct MyStruct:
pass
cdef void bar(MyStruct[])
ctypedef MyStruct* MyStructP
cdef void baz(MyStructP[])
def f(obj, int i, float f, char *s1, char s2[]): def f(obj, int i, float f, char *s1, char s2[]):
pass pass
\ No newline at end of file cdef g(obj, int i, float f, char *s1, char s2[]):
pass
cdef do_g(object (*func)(object, int, float, char*, char*)):
return func(1, 2, 3.14159, "a", "b")
do_g(&g)
__doc__ = u"""
>>> e = ExtClass()
>>> e.get()
5
"""
cdef class ExtClass:
cdef int _attribute = 2
def get(self):
return self._attribute
_attribute = 5 # FIXME: this is not currently handled!!!
_ERRORS = u"""
8:13: Cannot assign default value to cdef class attributes
"""
"""
>>> call_test()
False
True
False
True
True
True
True
"""
cdef test(bint value):
print value
def call_test():
test(False)
test(True)
test(0)
test(234)
test(-1)
x = True
test(x)
x = 3242
test(x)
__doc__ = u"""
>>> test_c(u'abc')
fileabc
typeabc
>>> print test_file_py(u'abc')
abc
>>> print range(u'abc')
rangeabc
"""
def test_file_py(file):
return file
cdef test_file_c(file):
return u'file' + file
def range(arg):
return u'range' + arg
cdef type(arg):
return u'type' + arg
def test_c(arg):
print test_file_c(arg)
print type(arg)
...@@ -2,6 +2,11 @@ __doc__ = u""" ...@@ -2,6 +2,11 @@ __doc__ = u"""
>>> call2() >>> call2()
>>> call3() >>> call3()
>>> call4() >>> call4()
>>> test_foo()
2
3
7
26
""" """
# the calls: # the calls:
...@@ -19,3 +24,13 @@ def call4(): ...@@ -19,3 +24,13 @@ def call4():
cdef b(a, b, c=1, d=2): cdef b(a, b, c=1, d=2):
pass pass
cdef int foo(int a, int b=1, int c=1):
return a+b*c
def test_foo():
print foo(1)
print foo(1, 2)
print foo(1, 2, 3)
print foo(1, foo(2, 3), foo(4))
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