cython-devel
changeset 912:fe3d5f426ff2
Fix optional cdef arguments for c++, possible optimization when not all args are used.
| author | Robert Bradshaw <robertwb@math.washington.edu> |
|---|---|
| date | Sun Aug 03 04:02:45 2008 -0700 (3 years ago) |
| parents | 464b7f41f688 |
| children | f69dab8c46d8 |
| files | Cython/Compiler/ExprNodes.py Demos/Setup.py tests/run/cdefoptargs.pyx |
line diff
1.1 --- a/Cython/Compiler/ExprNodes.py Sun Aug 03 09:47:55 2008 +0200
1.2 +++ b/Cython/Compiler/ExprNodes.py Sun Aug 03 04:02:45 2008 -0700
1.3 @@ -1680,6 +1680,7 @@
1.4 # self ExprNode or None used internally
1.5 # coerced_self ExprNode or None used internally
1.6 # wrapper_call bool used internally
1.7 + # has_optional_args bool used internally
1.8
1.9 subexprs = ['self', 'coerced_self', 'function', 'args', 'arg_tuple']
1.10
1.11 @@ -1687,6 +1688,7 @@
1.12 coerced_self = None
1.13 arg_tuple = None
1.14 wrapper_call = False
1.15 + has_optional_args = False
1.16
1.17 def compile_time_value(self, denv):
1.18 function = self.function.compile_time_value(denv)
1.19 @@ -1773,6 +1775,11 @@
1.20 self.type = PyrexTypes.error_type
1.21 self.result_code = "<error>"
1.22 return
1.23 + if func_type.optional_arg_count and expected_nargs != actual_nargs:
1.24 + self.has_optional_args = 1
1.25 + self.is_temp = 1
1.26 + self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
1.27 + env.release_temp(self.opt_arg_struct)
1.28 # Coerce arguments
1.29 for i in range(min(max_nargs, actual_nargs)):
1.30 formal_type = func_type.args[i].type
1.31 @@ -1818,15 +1825,7 @@
1.32 if expected_nargs == actual_nargs:
1.33 optional_args = 'NULL'
1.34 else:
1.35 - optional_arg_code = [str(actual_nargs - expected_nargs)]
1.36 - for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
1.37 - arg_code = actual_arg.result_as(formal_arg.type)
1.38 - optional_arg_code.append(arg_code)
1.39 -# for formal_arg in formal_args[actual_nargs:max_nargs]:
1.40 -# optional_arg_code.append(formal_arg.type.cast_code('0'))
1.41 - optional_arg_struct = '{%s}' % ','.join(optional_arg_code)
1.42 - optional_args = PyrexTypes.c_void_ptr_type.cast_code(
1.43 - '&' + func_type.op_arg_struct.base_type.cast_code(optional_arg_struct))
1.44 + optional_args = "&%s" % self.opt_arg_struct
1.45 arg_list_code.append(optional_args)
1.46
1.47 for actual_arg in self.args[len(formal_args):]:
1.48 @@ -1849,6 +1848,19 @@
1.49 arg_code,
1.50 code.error_goto_if_null(self.result_code, self.pos)))
1.51 elif func_type.is_cfunction:
1.52 + if self.has_optional_args:
1.53 + actual_nargs = len(self.args)
1.54 + expected_nargs = len(func_type.args) - func_type.optional_arg_count
1.55 + code.putln("%s.%s = %s;" % (
1.56 + self.opt_arg_struct,
1.57 + Naming.pyrex_prefix + "n",
1.58 + len(self.args) - expected_nargs))
1.59 + args = zip(func_type.args, self.args)
1.60 + for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
1.61 + code.putln("%s.%s = %s;" % (
1.62 + self.opt_arg_struct,
1.63 + formal_arg.name,
1.64 + actual_arg.result_as(formal_arg.type)))
1.65 exc_checks = []
1.66 if self.type.is_pyobject:
1.67 exc_checks.append("!%s" % self.result_code)
1.68 @@ -1883,12 +1895,12 @@
1.69 rhs,
1.70 raise_py_exception,
1.71 code.error_goto(self.pos)))
1.72 - return
1.73 - code.putln(
1.74 - "%s%s; %s" % (
1.75 - lhs,
1.76 - rhs,
1.77 - code.error_goto_if(" && ".join(exc_checks), self.pos)))
1.78 + else:
1.79 + if exc_checks:
1.80 + goto_error = code.error_goto_if(" && ".join(exc_checks), self.pos)
1.81 + else:
1.82 + goto_error = ""
1.83 + code.putln("%s%s; %s" % (lhs, rhs, goto_error))
1.84
1.85 class GeneralCallNode(CallNode):
1.86 # General Python function call, including keyword,
2.1 --- a/Demos/Setup.py Sun Aug 03 09:47:55 2008 +0200
2.2 +++ b/Demos/Setup.py Sun Aug 03 04:02:45 2008 -0700
2.3 @@ -7,7 +7,6 @@
2.4 ext_modules=[
2.5 Extension("primes", ["primes.pyx"]),
2.6 Extension("spam", ["spam.pyx"]),
2.7 -# Extension("optargs", ["optargs.pyx"], language = "c++"),
2.8 ]
2.9
2.10 for file in glob.glob("*.pyx"):
3.1 --- a/tests/run/cdefoptargs.pyx Sun Aug 03 09:47:55 2008 +0200
3.2 +++ b/tests/run/cdefoptargs.pyx Sun Aug 03 04:02:45 2008 -0700
3.3 @@ -2,6 +2,11 @@
3.4 >>> call2()
3.5 >>> call3()
3.6 >>> call4()
3.7 + >>> test_foo()
3.8 + 2
3.9 + 3
3.10 + 7
3.11 + 26
3.12 """
3.13
3.14 # the calls:
3.15 @@ -19,3 +24,13 @@
3.16
3.17 cdef b(a, b, c=1, d=2):
3.18 pass
3.19 +
3.20 +
3.21 +cdef int foo(int a, int b=1, int c=1):
3.22 + return a+b*c
3.23 +
3.24 +def test_foo():
3.25 + print foo(1)
3.26 + print foo(1, 2)
3.27 + print foo(1, 2, 3)
3.28 + print foo(1, foo(2, 3), foo(4))
