Mercurial > vim
comparison 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 |
comparison
equal
deleted
inserted
replaced
30137:a207126c5111 | 30138:6575d0bf6061 |
---|---|
5270 int | 5270 int |
5271 call_def_function( | 5271 call_def_function( |
5272 ufunc_T *ufunc, | 5272 ufunc_T *ufunc, |
5273 int argc_arg, // nr of arguments | 5273 int argc_arg, // nr of arguments |
5274 typval_T *argv, // arguments | 5274 typval_T *argv, // arguments |
5275 int flags, // DEF_ flags | |
5275 partial_T *partial, // optional partial for context | 5276 partial_T *partial, // optional partial for context |
5276 funccall_T *funccal, | 5277 funccall_T *funccal, |
5277 typval_T *rettv) // return value | 5278 typval_T *rettv) // return value |
5278 { | 5279 { |
5279 ectx_T ectx; // execution context | 5280 ectx_T ectx; // execution context |
5280 int argc = argc_arg; | 5281 int argc = argc_arg; |
5282 int partial_argc = partial == NULL | |
5283 || (flags & DEF_USE_PT_ARGV) == 0 | |
5284 ? 0 : partial->pt_argc; | |
5285 int total_argc = argc + partial_argc; | |
5281 typval_T *tv; | 5286 typval_T *tv; |
5282 int idx; | 5287 int idx; |
5283 int ret = FAIL; | 5288 int ret = FAIL; |
5284 int defcount = ufunc->uf_args.ga_len - argc; | 5289 int defcount = ufunc->uf_args.ga_len - total_argc; |
5285 sctx_T save_current_sctx = current_sctx; | 5290 sctx_T save_current_sctx = current_sctx; |
5286 int did_emsg_before = did_emsg_cumul + did_emsg; | 5291 int did_emsg_before = did_emsg_cumul + did_emsg; |
5287 int save_suppress_errthrow = suppress_errthrow; | 5292 int save_suppress_errthrow = suppress_errthrow; |
5288 msglist_T **saved_msg_list = NULL; | 5293 msglist_T **saved_msg_list = NULL; |
5289 msglist_T *private_msg_list = NULL; | 5294 msglist_T *private_msg_list = NULL; |
5343 ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10); | 5348 ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10); |
5344 ga_init2(&ectx.ec_funcrefs, sizeof(partial_T *), 10); | 5349 ga_init2(&ectx.ec_funcrefs, sizeof(partial_T *), 10); |
5345 ectx.ec_did_emsg_before = did_emsg_before; | 5350 ectx.ec_did_emsg_before = did_emsg_before; |
5346 ++ex_nesting_level; | 5351 ++ex_nesting_level; |
5347 | 5352 |
5348 idx = argc - ufunc->uf_args.ga_len; | 5353 idx = total_argc - ufunc->uf_args.ga_len; |
5349 if (idx > 0 && ufunc->uf_va_name == NULL) | 5354 if (idx > 0 && ufunc->uf_va_name == NULL) |
5350 { | 5355 { |
5351 semsg(NGETTEXT(e_one_argument_too_many, e_nr_arguments_too_many, | 5356 semsg(NGETTEXT(e_one_argument_too_many, e_nr_arguments_too_many, |
5352 idx), idx); | 5357 idx), idx); |
5353 goto failed_early; | 5358 goto failed_early; |
5354 } | 5359 } |
5355 idx = argc - ufunc->uf_args.ga_len + ufunc->uf_def_args.ga_len; | 5360 idx = total_argc - ufunc->uf_args.ga_len + ufunc->uf_def_args.ga_len; |
5356 if (idx < 0) | 5361 if (idx < 0) |
5357 { | 5362 { |
5358 semsg(NGETTEXT(e_one_argument_too_few, e_nr_arguments_too_few, | 5363 semsg(NGETTEXT(e_one_argument_too_few, e_nr_arguments_too_few, |
5359 -idx), -idx); | 5364 -idx), -idx); |
5360 goto failed_early; | 5365 goto failed_early; |
5361 } | 5366 } |
5362 | 5367 |
5363 // Put arguments on the stack, but no more than what the function expects. | 5368 // Put values from the partial and arguments on the stack, but no more than |
5364 // A lambda can be called with more arguments than it uses. | 5369 // what the function expects. A lambda can be called with more arguments |
5365 for (idx = 0; idx < argc | 5370 // than it uses. |
5371 for (idx = 0; idx < total_argc | |
5366 && (ufunc->uf_va_name != NULL || idx < ufunc->uf_args.ga_len); | 5372 && (ufunc->uf_va_name != NULL || idx < ufunc->uf_args.ga_len); |
5367 ++idx) | 5373 ++idx) |
5368 { | 5374 { |
5375 int argv_idx = idx - partial_argc; | |
5376 | |
5377 tv = idx < partial_argc ? partial->pt_argv + idx : argv + argv_idx; | |
5369 if (idx >= ufunc->uf_args.ga_len - ufunc->uf_def_args.ga_len | 5378 if (idx >= ufunc->uf_args.ga_len - ufunc->uf_def_args.ga_len |
5370 && argv[idx].v_type == VAR_SPECIAL | 5379 && tv->v_type == VAR_SPECIAL |
5371 && argv[idx].vval.v_number == VVAL_NONE) | 5380 && tv->vval.v_number == VVAL_NONE) |
5372 { | 5381 { |
5373 // Use the default value. | 5382 // Use the default value. |
5374 STACK_TV_BOT(0)->v_type = VAR_UNKNOWN; | 5383 STACK_TV_BOT(0)->v_type = VAR_UNKNOWN; |
5375 } | 5384 } |
5376 else | 5385 else |
5377 { | 5386 { |
5378 if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len | 5387 if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len |
5379 && check_typval_arg_type( | 5388 && check_typval_arg_type( |
5380 ufunc->uf_arg_types[idx], &argv[idx], | 5389 ufunc->uf_arg_types[idx], tv, |
5381 NULL, idx + 1) == FAIL) | 5390 NULL, argv_idx + 1) == FAIL) |
5382 goto failed_early; | 5391 goto failed_early; |
5383 copy_tv(&argv[idx], STACK_TV_BOT(0)); | 5392 copy_tv(tv, STACK_TV_BOT(0)); |
5384 } | 5393 } |
5385 ++ectx.ec_stack.ga_len; | 5394 ++ectx.ec_stack.ga_len; |
5386 } | 5395 } |
5387 | 5396 |
5388 // Turn varargs into a list. Empty list if no args. | 5397 // Turn varargs into a list. Empty list if no args. |