From f9dc278946d52235a0025fd347bd9ff571258470 Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Thu, 11 May 2023 15:02:56 +0100 Subject: patch 9.0.1540: reverse() on string doesn't work in compiled function Problem: reverse() on string doesn't work in compiled function. Solution: Accept string in argument type check. (Yegappan Lakshmanan, closes #12377) --- src/evalfunc.c | 15 +++++++++++++-- src/list.c | 6 ++---- src/optionstr.c | 2 +- src/testdir/test_functions.vim | 17 ++++++++++------- src/testdir/test_listdict.vim | 2 +- src/testdir/test_method.vim | 2 +- src/testdir/test_vim9_builtin.vim | 3 +-- src/version.c | 2 ++ 8 files changed, 31 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/evalfunc.c b/src/evalfunc.c index 05734d25ac..8f20ebee17 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -756,6 +756,17 @@ arg_string_list_or_blob(type_T *type, type_T *decl_type UNUSED, argcontext_T *co return FAIL; } +/* + * Check "type" is a modifiable list of 'any' or a blob or a string. + */ + static int +arg_string_list_or_blob_mod(type_T *type, type_T *decl_type, argcontext_T *context) +{ + if (arg_string_list_or_blob(type, decl_type, context) == FAIL) + return FAIL; + return arg_type_modifiable(type, context->arg_idx + 1); +} + /* * Check "type" is a job. */ @@ -1010,7 +1021,7 @@ static argcheck_T arg1_float_or_nr[] = {arg_float_or_nr}; static argcheck_T arg1_job[] = {arg_job}; static argcheck_T arg1_list_any[] = {arg_list_any}; static argcheck_T arg1_list_number[] = {arg_list_number}; -static argcheck_T arg1_list_or_blob_mod[] = {arg_list_or_blob_mod}; +static argcheck_T arg1_string_or_list_or_blob_mod[] = {arg_string_list_or_blob_mod}; static argcheck_T arg1_list_or_dict[] = {arg_list_or_dict}; static argcheck_T arg1_list_string[] = {arg_list_string}; static argcheck_T arg1_string_or_list_or_dict[] = {arg_string_or_list_or_dict}; @@ -2413,7 +2424,7 @@ static funcentry_T global_functions[] = ret_repeat, f_repeat}, {"resolve", 1, 1, FEARG_1, arg1_string, ret_string, f_resolve}, - {"reverse", 1, 1, FEARG_1, arg1_list_or_blob_mod, + {"reverse", 1, 1, FEARG_1, arg1_string_or_list_or_blob_mod, ret_first_arg, f_reverse}, {"round", 1, 1, FEARG_1, arg1_float_or_nr, ret_float, f_round}, diff --git a/src/list.c b/src/list.c index 7042965ba3..d52c23dea1 100644 --- a/src/list.c +++ b/src/list.c @@ -2994,16 +2994,14 @@ list_reverse(list_T *l, typval_T *rettv) void f_reverse(typval_T *argvars, typval_T *rettv) { - if (in_vim9script() && check_for_list_or_blob_arg(argvars, 0) == FAIL) + if (check_for_string_or_list_or_blob_arg(argvars, 0) == FAIL) return; if (argvars[0].v_type == VAR_BLOB) blob_reverse(argvars[0].vval.v_blob, rettv); else if (argvars[0].v_type == VAR_STRING) string_reverse(argvars[0].vval.v_string, rettv); - else if (argvars[0].v_type != VAR_LIST) - semsg(_(e_argument_of_str_must_be_list_or_blob), "reverse()"); - else + else if (argvars[0].v_type == VAR_LIST) list_reverse(argvars[0].vval.v_list, rettv); } diff --git a/src/optionstr.c b/src/optionstr.c index 311b069d27..cfbcf3acba 100644 --- a/src/optionstr.c +++ b/src/optionstr.c @@ -134,7 +134,7 @@ didset_string_options(void) (void)opt_strings_flags(p_swb, p_swb_values, &swb_flags, TRUE); } -#if defined(FEAT_EVAL) +#if defined(FEAT_EVAL) || defined(PROTO) /* * Trigger the OptionSet autocommand. * "opt_idx" is the index of the option being set. diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index 4529a5e8d5..8664724b5c 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -3475,13 +3475,16 @@ endfunc " Test for the reverse() function with a string func Test_string_reverse() - call assert_equal('', reverse(test_null_string())) - for [s1, s2] in [['', ''], ['a', 'a'], ['ab', 'ba'], ['abc', 'cba'], - \ ['abcd', 'dcba'], ['«-«-»-»', '»-»-«-«'], - \ ['🇦', '🇦'], ['🇦🇧', '🇧🇦'], ['🇦🇧🇨', '🇨🇧🇦'], - \ ['🇦«🇧-🇨»🇩', '🇩»🇨-🇧«🇦']] - call assert_equal(s2, reverse(s1)) - endfor + let lines =<< trim END + call assert_equal('', reverse(test_null_string())) + for [s1, s2] in [['', ''], ['a', 'a'], ['ab', 'ba'], ['abc', 'cba'], + \ ['abcd', 'dcba'], ['«-«-»-»', '»-»-«-«'], + \ ['🇦', '🇦'], ['🇦🇧', '🇧🇦'], ['🇦🇧🇨', '🇨🇧🇦'], + \ ['🇦«🇧-🇨»🇩', '🇩»🇨-🇧«🇦']] + call assert_equal(s2, reverse(s1)) + endfor + END + call v9.CheckLegacyAndVim9Success(lines) " test in latin1 encoding let save_enc = &encoding diff --git a/src/testdir/test_listdict.vim b/src/testdir/test_listdict.vim index e29c351f41..877bb80739 100644 --- a/src/testdir/test_listdict.vim +++ b/src/testdir/test_listdict.vim @@ -981,7 +981,7 @@ func Test_reverse_sort_uniq() END call v9.CheckLegacyAndVim9Success(lines) - call assert_fails('call reverse({})', 'E899:') + call assert_fails('call reverse({})', 'E1252:') call assert_fails('call uniq([1, 2], {x, y -> []})', 'E745:') call assert_fails("call sort([1, 2], function('min'), 1)", "E1206:") call assert_fails("call sort([1, 2], function('invalid_func'))", "E700:") diff --git a/src/testdir/test_method.vim b/src/testdir/test_method.vim index 2ca66fd77e..120fadecbc 100644 --- a/src/testdir/test_method.vim +++ b/src/testdir/test_method.vim @@ -62,7 +62,7 @@ func Test_dict_method() call assert_equal(2, d->remove("two")) let d.two = 2 call assert_fails('let x = d->repeat(2)', 'E731:') - call assert_fails('let x = d->reverse()', 'E899:') + call assert_fails('let x = d->reverse()', 'E1252:') call assert_fails('let x = d->sort()', 'E686:') call assert_equal("{'one': 1, 'two': 2, 'three': 3}", d->string()) call assert_equal(v:t_dict, d->type()) diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim index b8500c5e61..8cf16a2cf6 100644 --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -3459,8 +3459,7 @@ def Test_resolve() enddef def Test_reverse() - v9.CheckDefAndScriptFailure(['reverse(10)'], ['E1013: Argument 1: type mismatch, expected list but got number', 'E1226: List or Blob required for argument 1']) - v9.CheckDefAndScriptFailure(['reverse("abc")'], ['E1013: Argument 1: type mismatch, expected list but got string', 'E1226: List or Blob required for argument 1']) + v9.CheckDefAndScriptFailure(['reverse(10)'], ['E1013: Argument 1: type mismatch, expected list but got number', 'E1252: String, List or Blob required for argument 1']) enddef def Test_reverse_return_type() diff --git a/src/version.c b/src/version.c index 5d55e4c5ff..e5f4afa70a 100644 --- a/src/version.c +++ b/src/version.c @@ -695,6 +695,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1540, /**/ 1539, /**/ -- cgit v1.2.3