From e6978a4e26a17ef473e2aad78662d3bf29638578 Mon Sep 17 00:00:00 2001 From: Delio Brignoli Date: Thu, 17 Sep 2015 12:07:06 +0200 Subject: [PATCH] py: Fix call args when a stararg is followed by keyword args. --- py/compile.c | 13 +++++++++++-- tests/basics/fun_kwvarargs.py | 12 ++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/py/compile.c b/py/compile.c index 34f377fb0c..9ac37c6d95 100644 --- a/py/compile.c +++ b/py/compile.c @@ -2203,6 +2203,7 @@ STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_ar int n_positional = n_positional_extra; uint n_keyword = 0; uint star_flags = 0; + mp_parse_node_struct_t *star_args_node = NULL, *dblstar_args_node = NULL; for (int i = 0; i < n_args; i++) { if (MP_PARSE_NODE_IS_STRUCT(args[i])) { mp_parse_node_struct_t *pns_arg = (mp_parse_node_struct_t*)args[i]; @@ -2212,14 +2213,14 @@ STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_ar return; } star_flags |= MP_EMIT_STAR_FLAG_SINGLE; - compile_node(comp, pns_arg->nodes[0]); + star_args_node = pns_arg; } else if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_arglist_dbl_star) { if (star_flags & MP_EMIT_STAR_FLAG_DOUBLE) { compile_syntax_error(comp, (mp_parse_node_t)pns_arg, "can't have multiple **x"); return; } star_flags |= MP_EMIT_STAR_FLAG_DOUBLE; - compile_node(comp, pns_arg->nodes[0]); + dblstar_args_node = pns_arg; } else if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_argument) { assert(MP_PARSE_NODE_IS_STRUCT(pns_arg->nodes[1])); // should always be mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns_arg->nodes[1]; @@ -2250,6 +2251,14 @@ STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_ar } } + // compile the star/double-star arguments if we had them + if (star_args_node != NULL) { + compile_node(comp, star_args_node->nodes[0]); + } + if (dblstar_args_node != NULL) { + compile_node(comp, dblstar_args_node->nodes[0]); + } + // emit the function/method call if (is_method_call) { EMIT_ARG(call_method, n_positional, n_keyword, star_flags); diff --git a/tests/basics/fun_kwvarargs.py b/tests/basics/fun_kwvarargs.py index 6350d20d6b..2b6893f24f 100644 --- a/tests/basics/fun_kwvarargs.py +++ b/tests/basics/fun_kwvarargs.py @@ -17,3 +17,15 @@ f3(1) f3(1, 2) f3(1, b=2) f3(1, 2, b=3) + +def f4(*vargs, **kwargs): + print(vargs, kwargs) +f4(*(1, 2)) +f4(kw_arg=3) +f4(*(1, 2), kw_arg=3) + +# test evaluation order of arguments (in CPy 3.4 it's actually backwards) +def print_ret(x): + print(x) + return x +f4(*print_ret(['a', 'b']), kw_arg=print_ret(None))