Mercurial > vim
diff src/vim9execute.c @ 30138:6575d0bf6061 v9.0.0405
patch 9.0.0405: arguments in a partial not used by a :def function
Commit: https://github.com/vim/vim/commit/c9c967da09d9faf5ba989c943352274fea365841
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Sep 7 16:48:46 2022 +0100
patch 9.0.0405: arguments in a partial not used by a :def function
Problem: Arguments in a partial not used by a :def function.
Solution: Put the partial arguments on the stack.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 07 Sep 2022 18:00:04 +0200 |
parents | 01408b56f093 |
children | 9f8b1f584395 |
line wrap: on
line diff
--- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -5272,16 +5272,21 @@ call_def_function( ufunc_T *ufunc, int argc_arg, // nr of arguments typval_T *argv, // arguments + int flags, // DEF_ flags partial_T *partial, // optional partial for context funccall_T *funccal, typval_T *rettv) // return value { ectx_T ectx; // execution context int argc = argc_arg; + int partial_argc = partial == NULL + || (flags & DEF_USE_PT_ARGV) == 0 + ? 0 : partial->pt_argc; + int total_argc = argc + partial_argc; typval_T *tv; int idx; int ret = FAIL; - int defcount = ufunc->uf_args.ga_len - argc; + int defcount = ufunc->uf_args.ga_len - total_argc; sctx_T save_current_sctx = current_sctx; int did_emsg_before = did_emsg_cumul + did_emsg; int save_suppress_errthrow = suppress_errthrow; @@ -5345,14 +5350,14 @@ call_def_function( ectx.ec_did_emsg_before = did_emsg_before; ++ex_nesting_level; - idx = argc - ufunc->uf_args.ga_len; + idx = total_argc - ufunc->uf_args.ga_len; if (idx > 0 && ufunc->uf_va_name == NULL) { semsg(NGETTEXT(e_one_argument_too_many, e_nr_arguments_too_many, - idx), idx); + idx), idx); goto failed_early; } - idx = argc - ufunc->uf_args.ga_len + ufunc->uf_def_args.ga_len; + idx = total_argc - ufunc->uf_args.ga_len + ufunc->uf_def_args.ga_len; if (idx < 0) { semsg(NGETTEXT(e_one_argument_too_few, e_nr_arguments_too_few, @@ -5360,15 +5365,19 @@ call_def_function( goto failed_early; } - // Put arguments on the stack, but no more than what the function expects. - // A lambda can be called with more arguments than it uses. - for (idx = 0; idx < argc + // Put values from the partial and arguments on the stack, but no more than + // what the function expects. A lambda can be called with more arguments + // than it uses. + for (idx = 0; idx < total_argc && (ufunc->uf_va_name != NULL || idx < ufunc->uf_args.ga_len); ++idx) { + int argv_idx = idx - partial_argc; + + tv = idx < partial_argc ? partial->pt_argv + idx : argv + argv_idx; if (idx >= ufunc->uf_args.ga_len - ufunc->uf_def_args.ga_len - && argv[idx].v_type == VAR_SPECIAL - && argv[idx].vval.v_number == VVAL_NONE) + && tv->v_type == VAR_SPECIAL + && tv->vval.v_number == VVAL_NONE) { // Use the default value. STACK_TV_BOT(0)->v_type = VAR_UNKNOWN; @@ -5377,10 +5386,10 @@ call_def_function( { if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len && check_typval_arg_type( - ufunc->uf_arg_types[idx], &argv[idx], - NULL, idx + 1) == FAIL) + ufunc->uf_arg_types[idx], tv, + NULL, argv_idx + 1) == FAIL) goto failed_early; - copy_tv(&argv[idx], STACK_TV_BOT(0)); + copy_tv(tv, STACK_TV_BOT(0)); } ++ectx.ec_stack.ga_len; }