diff options
Diffstat (limited to 'src/vim9compile.c')
-rw-r--r-- | src/vim9compile.c | 51 |
1 files changed, 42 insertions, 9 deletions
diff --git a/src/vim9compile.c b/src/vim9compile.c index e27bf29c6..43bda5f0b 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2195,8 +2195,13 @@ push_default_value( * Return "arg" if it does not look like a variable list. */ static char_u * -compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) +compile_assignment( + char_u *arg_start, + exarg_T *eap, + cmdidx_T cmdidx, + cctx_T *cctx) { + char_u *arg = arg_start; char_u *var_start; char_u *p; char_u *end = arg; @@ -2206,6 +2211,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) int semicolon = 0; int did_generate_slice = FALSE; garray_T *instr = &cctx->ctx_instr; + int jump_instr_idx = instr->ga_len; char_u *op; int oplen = 0; int heredoc = FALSE; @@ -2216,6 +2222,23 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) lhs_T lhs; long start_lnum = SOURCING_LNUM; + int has_arg_is_set_prefix = STRNCMP(arg, "ifargisset ", 11) == 0; + if (has_arg_is_set_prefix) + { + arg += 11; + int def_idx = getdigits(&arg); + arg = skipwhite(arg); + + // Use a JUMP_IF_ARG_NOT_SET instruction to skip if the value was not + // given and the default value is "v:none". + int off = STACK_FRAME_SIZE + (cctx->ctx_ufunc->uf_va_name != NULL + ? 1 : 0); + int count = cctx->ctx_ufunc->uf_def_args.ga_len; + if (generate_JUMP_IF_ARG(cctx, ISN_JUMP_IF_ARG_NOT_SET, + def_idx - count - off) == FAIL) + goto theend; + } + // Skip over the "varname" or "[varname, varname]" to get to any "=". p = skip_var_list(arg, TRUE, &var_count, &semicolon, TRUE); if (p == NULL) @@ -2636,6 +2659,13 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx) if (var_idx + 1 < var_count) var_start = skipwhite(lhs.lhs_end + 1); + + if (has_arg_is_set_prefix) + { + // set instruction index in JUMP_IF_ARG_SET to here + isn_T *isn = ((isn_T *)instr->ga_data) + jump_instr_idx; + isn->isn_arg.jumparg.jump_where = instr->ga_len; + } } // For "[var, var] = expr" drop the "expr" value. @@ -2711,9 +2741,9 @@ may_compile_assignment(exarg_T *eap, char_u **line, cctx_T *cctx) } } - if (*eap->cmd == '[') + // might be "[var, var] = expr" or "ifargisset this.member = expr" + if (*eap->cmd == '[' || STRNCMP(eap->cmd, "ifargisset ", 11) == 0) { - // might be "[var, var] = expr" *line = compile_assignment(eap->cmd, eap, CMD_SIZE, cctx); if (*line == NULL) return FAIL; @@ -2994,7 +3024,6 @@ compile_def_function( int count = ufunc->uf_def_args.ga_len; int first_def_arg = ufunc->uf_args.ga_len - count; int i; - char_u *arg; int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0); int did_set_arg_type = FALSE; @@ -3002,23 +3031,27 @@ compile_def_function( SOURCING_LNUM = 0; // line number unknown for (i = 0; i < count; ++i) { + char_u *arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i]; + if (STRCMP(arg, "v:none") == 0) + // "arg = v:none" means the argument is optional without + // setting a value when the argument is missing. + continue; + type_T *val_type; int arg_idx = first_def_arg + i; where_T where = WHERE_INIT; - int r; int jump_instr_idx = instr->ga_len; isn_T *isn; // Use a JUMP_IF_ARG_SET instruction to skip if the value was given. - if (generate_JUMP_IF_ARG_SET(&cctx, i - count - off) == FAIL) + if (generate_JUMP_IF_ARG(&cctx, ISN_JUMP_IF_ARG_SET, + i - count - off) == FAIL) goto erret; // Make sure later arguments are not found. ufunc->uf_args_visible = arg_idx; - arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i]; - r = compile_expr0(&arg, &cctx); - + int r = compile_expr0(&arg, &cctx); if (r == FAIL) goto erret; |