Mercurial > vim
diff src/vim9execute.c @ 24272:cabed216cc2f v8.2.2677
patch 8.2.2677: Vim9: cannot use only some of the default arguments
Commit: https://github.com/vim/vim/commit/38a3bfa9a2931729a5e0c28dc087f745b68988ef
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Mar 29 22:14:55 2021 +0200
patch 8.2.2677: Vim9: cannot use only some of the default arguments
Problem: Vim9: cannot use only some of the default arguments.
Solution: Use v:none to use default argument value. Remove
uf_def_arg_idx[], use JUMP_IF_ARG_SET. (closes #6504)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 29 Mar 2021 22:15:03 +0200 |
parents | 7ffc795288dd |
children | bbf4b3185554 |
line wrap: on
line diff
--- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -97,35 +97,6 @@ ufunc_argcount(ufunc_T *ufunc) } /* - * Set the instruction index, depending on omitted arguments, where the default - * values are to be computed. If all optional arguments are present, start - * with the function body. - * The expression evaluation is at the start of the instructions: - * 0 -> EVAL default1 - * STORE arg[-2] - * 1 -> EVAL default2 - * STORE arg[-1] - * 2 -> function body - */ - static void -init_instr_idx(ufunc_T *ufunc, int argcount, ectx_T *ectx) -{ - if (ufunc->uf_def_args.ga_len == 0) - ectx->ec_iidx = 0; - else - { - int defcount = ufunc->uf_args.ga_len - argcount; - - // If there is a varargs argument defcount can be negative, no defaults - // to evaluate then. - if (defcount < 0) - defcount = 0; - ectx->ec_iidx = ufunc->uf_def_arg_idx[ - ufunc->uf_def_args.ga_len - defcount]; - } -} - -/* * Create a new list from "count" items at the bottom of the stack. * When "count" is zero an empty list is added to the stack. */ @@ -363,8 +334,8 @@ call_dfunc( current_sctx.sc_sid = ufunc->uf_script_ctx.sc_sid; } - // Decide where to start execution, handles optional arguments. - init_instr_idx(ufunc, argcount, ectx); + // Start execution at the first instruction. + ectx->ec_iidx = 0; return OK; } @@ -1367,11 +1338,21 @@ call_def_function( && (ufunc->uf_va_name != NULL || idx < ufunc->uf_args.ga_len); ++idx) { - if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len - && check_typval_arg_type(ufunc->uf_arg_types[idx], &argv[idx], - idx + 1) == FAIL) - goto failed_early; - copy_tv(&argv[idx], STACK_TV_BOT(0)); + 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) + { + // Use the default value. + STACK_TV_BOT(0)->v_type = VAR_UNKNOWN; + } + else + { + if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len + && check_typval_arg_type( + ufunc->uf_arg_types[idx], &argv[idx], idx + 1) == FAIL) + goto failed_early; + copy_tv(&argv[idx], STACK_TV_BOT(0)); + } ++ectx.ec_stack.ga_len; } @@ -1505,8 +1486,8 @@ call_def_function( where.wt_index = 0; where.wt_variable = FALSE; - // Decide where to start execution, handles optional arguments. - init_instr_idx(ufunc, argc, &ectx); + // Start execution at the first instruction. + ectx.ec_iidx = 0; for (;;) { @@ -2738,6 +2719,16 @@ call_def_function( } break; + // Jump if an argument with a default value was already set and not + // v:none. + case ISN_JUMP_IF_ARG_SET: + tv = STACK_TV_VAR(iptr->isn_arg.jumparg.jump_arg_off); + if (tv->v_type != VAR_UNKNOWN + && !(tv->v_type == VAR_SPECIAL + && tv->vval.v_number == VVAL_NONE)) + ectx.ec_iidx = iptr->isn_arg.jumparg.jump_where; + break; + // top of a for loop case ISN_FOR: { @@ -4517,6 +4508,12 @@ ex_disassemble(exarg_T *eap) } break; + case ISN_JUMP_IF_ARG_SET: + smsg("%4d JUMP_IF_ARG_SET arg[%d] -> %d", current, + iptr->isn_arg.jumparg.jump_arg_off + STACK_FRAME_SIZE, + iptr->isn_arg.jump.jump_where); + break; + case ISN_FOR: { forloop_T *forloop = &iptr->isn_arg.forloop;