diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-08-18 06:13:37 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-18 06:13:37 +0800 |
commit | 7dcbe74234cae6192d11c25dbcd801d35e604eb0 (patch) | |
tree | 4d6b898cb67d3d1aec5d3cd49acdb0be7be07ada | |
parent | 88887a7be707773f908dd6e597f0293d3c1a0faa (diff) | |
parent | bb29ef40084e1cea1f35cbbcbac794f41f46d5f8 (diff) | |
download | rneovim-7dcbe74234cae6192d11c25dbcd801d35e604eb0.tar.gz rneovim-7dcbe74234cae6192d11c25dbcd801d35e604eb0.tar.bz2 rneovim-7dcbe74234cae6192d11c25dbcd801d35e604eb0.zip |
Merge pull request #24766 from zeertzjq/vim-9.0.1722
vim-patch:9.0.{1722,1723}
-rw-r--r-- | src/nvim/eval.c | 36 | ||||
-rw-r--r-- | src/nvim/eval/funcs.c | 18 | ||||
-rw-r--r-- | test/old/testdir/test_functions.vim | 3 | ||||
-rw-r--r-- | test/old/testdir/test_listdict.vim | 6 |
4 files changed, 39 insertions, 24 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 9baf3209a2..08c5ef743b 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -820,36 +820,44 @@ bool eval_expr_valid_arg(const typval_T *const tv) && (tv->v_type != VAR_STRING || (tv->vval.v_string != NULL && *tv->vval.v_string != NUL)); } -int eval_expr_typval(const typval_T *expr, typval_T *argv, int argc, typval_T *rettv) - FUNC_ATTR_NONNULL_ARG(1, 2, 4) +/// Evaluate an expression, which can be a function, partial or string. +/// Pass arguments "argv[argc]". +/// Return the result in "rettv" and OK or FAIL. +/// +/// @param want_func if true, treat a string as a function name, not an expression +int eval_expr_typval(const typval_T *expr, bool want_func, typval_T *argv, int argc, + typval_T *rettv) + FUNC_ATTR_NONNULL_ALL { + char buf[NUMBUFLEN]; funcexe_T funcexe = FUNCEXE_INIT; - if (expr->v_type == VAR_FUNC) { - const char *const s = expr->vval.v_string; + if (expr->v_type == VAR_PARTIAL) { + partial_T *const partial = expr->vval.v_partial; + if (partial == NULL) { + return FAIL; + } + const char *const s = partial_name(partial); if (s == NULL || *s == NUL) { return FAIL; } funcexe.fe_evaluate = true; + funcexe.fe_partial = partial; if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL) { return FAIL; } - } else if (expr->v_type == VAR_PARTIAL) { - partial_T *const partial = expr->vval.v_partial; - if (partial == NULL) { - return FAIL; - } - const char *const s = partial_name(partial); + } else if (expr->v_type == VAR_FUNC || want_func) { + const char *const s = (expr->v_type == VAR_FUNC + ? expr->vval.v_string + : tv_get_string_buf_chk(expr, buf)); if (s == NULL || *s == NUL) { return FAIL; } funcexe.fe_evaluate = true; - funcexe.fe_partial = partial; if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL) { return FAIL; } } else { - char buf[NUMBUFLEN]; char *s = (char *)tv_get_string_buf_chk(expr, buf); if (s == NULL) { return FAIL; @@ -874,7 +882,7 @@ bool eval_expr_to_bool(const typval_T *expr, bool *error) { typval_T argv, rettv; - if (eval_expr_typval(expr, &argv, 0, &rettv) == FAIL) { + if (eval_expr_typval(expr, false, &argv, 0, &rettv) == FAIL) { *error = true; return false; } @@ -5352,7 +5360,7 @@ static int filter_map_one(typval_T *tv, typval_T *expr, const filtermap_T filter tv_copy(tv, &vimvars[VV_VAL].vv_tv); argv[0] = vimvars[VV_KEY].vv_tv; argv[1] = vimvars[VV_VAL].vv_tv; - if (eval_expr_typval(expr, argv, 2, newtv) == FAIL) { + if (eval_expr_typval(expr, false, argv, 2, newtv) == FAIL) { goto theend; } if (filtermap == FILTERMAP_FILTER) { diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index b0e0fffe5c..e8224671dc 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -147,6 +147,8 @@ PRAGMA_DIAG_POP static const char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob"); static const char *e_invalwindow = N_("E957: Invalid window number"); +static const char e_argument_of_str_must_be_list_string_or_dictionary[] + = N_("E706: Argument of %s must be a List, String or Dictionary"); static const char e_invalid_submatch_number_nr[] = N_("E935: Invalid submatch number: %d"); static const char *e_reduceempty = N_("E998: Reduce of an empty %s with no initial value"); @@ -997,8 +999,8 @@ static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) n = count_dict(argvars[0].vval.v_dict, &argvars[1], ic); } } - } else { - semsg(_(e_listdictarg), "count()"); + } else if (!error) { + semsg(_(e_argument_of_str_must_be_list_string_or_dictionary), "count()"); } rettv->vval.v_number = n; } @@ -2951,7 +2953,7 @@ static void f_wait(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) const int called_emsg_before = called_emsg; LOOP_PROCESS_EVENTS_UNTIL(&main_loop, main_loop.events, timeout, - eval_expr_typval(&expr, &argv, 0, &exprval) != OK + eval_expr_typval(&expr, false, &argv, 0, &exprval) != OK || tv_get_number_chk(&exprval, &error) || called_emsg > called_emsg_before || error || got_int); @@ -3513,7 +3515,7 @@ static varnumber_T indexof_eval_expr(typval_T *expr) typval_T newtv; newtv.v_type = VAR_UNKNOWN; - if (eval_expr_typval(expr, argv, 2, &newtv) == FAIL) { + if (eval_expr_typval(expr, false, argv, 2, &newtv) == FAIL) { return false; } @@ -5535,7 +5537,7 @@ static varnumber_T readdir_checkitem(void *context, const char *name) argv[0].vval.v_string = (char *)name; typval_T rettv; - if (eval_expr_typval(expr, argv, 1, &rettv) == FAIL) { + if (eval_expr_typval(expr, false, argv, 1, &rettv) == FAIL) { goto theend; } @@ -6257,7 +6259,7 @@ static void reduce_list(typval_T *argvars, typval_T *expr, typval_T *rettv) argv[1] = *TV_LIST_ITEM_TV(li); rettv->v_type = VAR_UNKNOWN; - const int r = eval_expr_typval(expr, argv, 2, rettv); + const int r = eval_expr_typval(expr, true, argv, 2, rettv); tv_clear(&argv[0]); if (r == FAIL || called_emsg != called_emsg_start) { @@ -6304,7 +6306,7 @@ static void reduce_string(typval_T *argvars, typval_T *expr, typval_T *rettv) .vval.v_string = xstrnsave(p, (size_t)len), }; - const int r = eval_expr_typval(expr, argv, 2, rettv); + const int r = eval_expr_typval(expr, true, argv, 2, rettv); tv_clear(&argv[0]); tv_clear(&argv[1]); @@ -6352,7 +6354,7 @@ static void reduce_blob(typval_T *argvars, typval_T *expr, typval_T *rettv) .vval.v_number = tv_blob_get(b, i), }; - const int r = eval_expr_typval(expr, argv, 2, rettv); + const int r = eval_expr_typval(expr, true, argv, 2, rettv); if (r == FAIL || called_emsg != called_emsg_start) { return; diff --git a/test/old/testdir/test_functions.vim b/test/old/testdir/test_functions.vim index 74f9143ca0..e286090018 100644 --- a/test/old/testdir/test_functions.vim +++ b/test/old/testdir/test_functions.vim @@ -1627,7 +1627,8 @@ func Test_count() call assert_equal(2, count("fooooo", "oo")) call assert_equal(0, count("foo", "")) - call assert_fails('call count(0, 0)', 'E712:') + call assert_fails('call count(0, 0)', 'E706:') + call assert_fails('call count("", "", {})', ['E728:', 'E728:']) endfunc func Test_changenr() diff --git a/test/old/testdir/test_listdict.vim b/test/old/testdir/test_listdict.vim index abb7f88a7b..354d987c79 100644 --- a/test/old/testdir/test_listdict.vim +++ b/test/old/testdir/test_listdict.vim @@ -944,6 +944,10 @@ func Test_reduce() call assert_equal('Å,s,t,r,ö,m', reduce('Åström', LSTART acc, val LMIDDLE acc .. ',' .. val LEND)) call assert_equal('Å,s,t,r,ö,m', reduce('Åström', LSTART acc, val LMIDDLE acc .. ',' .. val LEND)) call assert_equal(',a,b,c', reduce('abc', LSTART acc, val LMIDDLE acc .. ',' .. val LEND, v:_null_string)) + + call assert_equal(0x7d, reduce([0x30, 0x25, 0x08, 0x61], 'or')) + call assert_equal(0x7d, reduce(0z30250861, 'or')) + call assert_equal('β', reduce('ββββ', 'matchstr')) END call CheckLegacyAndVim9Success(lines) @@ -958,7 +962,7 @@ func Test_reduce() call assert_fails("call reduce({}, { acc, val -> acc + val }, 1)", 'E1098:') call assert_fails("call reduce(0, { acc, val -> acc + val }, 1)", 'E1098:') - call assert_fails("call reduce([1, 2], 'Xdoes_not_exist')", 'E121:') + call assert_fails("call reduce([1, 2], 'Xdoes_not_exist')", 'E117:') call assert_fails("echo reduce(0z01, { acc, val -> 2 * acc + val }, '')", 'E1210:') " call assert_fails("vim9 reduce(0, (acc, val) => (acc .. val), '')", 'E1252:') |