diff options
author | Bram Moolenaar <Bram@vim.org> | 2021-02-01 20:14:51 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2021-02-01 20:14:51 +0100 |
commit | 3b690069730805a147d45d92eaca4dc838272d1d (patch) | |
tree | 47e970336167b1b23d8fac9e97b12cb76f159dd7 /src | |
parent | 9d20daffc296b9eb901fb14bdd83620ea55d440a (diff) | |
download | vim-git-3b690069730805a147d45d92eaca4dc838272d1d.tar.gz |
patch 8.2.2449: Vim9: flatten() always changes the list typev8.2.2449
Problem: Vim9: flatten() always changes the list type.
Solution: Disallow using flatten() and add flattennew().
Diffstat (limited to 'src')
-rw-r--r-- | src/errors.h | 2 | ||||
-rw-r--r-- | src/evalfunc.c | 2 | ||||
-rw-r--r-- | src/list.c | 62 | ||||
-rw-r--r-- | src/proto/list.pro | 1 | ||||
-rw-r--r-- | src/testdir/test_flatten.vim | 9 | ||||
-rw-r--r-- | src/testdir/test_vim9_builtin.vim | 17 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9compile.c | 6 |
8 files changed, 88 insertions, 13 deletions
diff --git a/src/errors.h b/src/errors.h index 990fb86ee..e6d7ab26c 100644 --- a/src/errors.h +++ b/src/errors.h @@ -351,3 +351,5 @@ EXTERN char e_cannot_change_arglist_recursively[] INIT(= N_("E1156: Cannot change the argument list recursively")); EXTERN char e_missing_return_type[] INIT(= N_("E1157: Missing return type")); +EXTERN char e_cannot_use_flatten_in_vim9_script[] + INIT(= N_("E1158: Cannot use flatten() in Vim9 script")); diff --git a/src/evalfunc.c b/src/evalfunc.c index f0a15f98c..0b4b5021a 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -954,6 +954,8 @@ static funcentry_T global_functions[] = ret_string, f_findfile}, {"flatten", 1, 2, FEARG_1, NULL, ret_list_any, f_flatten}, + {"flattennew", 1, 2, FEARG_1, NULL, + ret_list_any, f_flattennew}, {"float2nr", 1, 1, FEARG_1, NULL, ret_number, FLOAT_FUNC(f_float2nr)}, {"floor", 1, 1, FEARG_1, NULL, diff --git a/src/list.c b/src/list.c index ca6e469c4..c51c99bc9 100644 --- a/src/list.c +++ b/src/list.c @@ -740,7 +740,7 @@ list_insert(list_T *l, listitem_T *ni, listitem_T *item) * It does nothing if "maxdepth" is 0. * Returns FAIL when out of memory. */ - static int + static void list_flatten(list_T *list, long maxdepth) { listitem_T *item; @@ -748,7 +748,7 @@ list_flatten(list_T *list, long maxdepth) int n; if (maxdepth == 0) - return OK; + return; CHECK_LIST_MATERIALIZE(list); n = 0; @@ -757,7 +757,7 @@ list_flatten(list_T *list, long maxdepth) { fast_breakcheck(); if (got_int) - return FAIL; + return; if (item->li_tv.v_type == VAR_LIST) { @@ -765,7 +765,7 @@ list_flatten(list_T *list, long maxdepth) vimlist_remove(list, item, item); if (list_extend(list, item->li_tv.vval.v_list, next) == FAIL) - return FAIL; + return; clear_tv(&item->li_tv); tofree = item; @@ -787,15 +787,13 @@ list_flatten(list_T *list, long maxdepth) item = item->li_next; } } - - return OK; } /* - * "flatten(list[, {maxdepth}])" function + * "flatten()" and "flattennew()" functions */ - void -f_flatten(typval_T *argvars, typval_T *rettv) + static void +flatten_common(typval_T *argvars, typval_T *rettv, int make_copy) { list_T *l; long maxdepth; @@ -822,10 +820,48 @@ f_flatten(typval_T *argvars, typval_T *rettv) } l = argvars[0].vval.v_list; - if (l != NULL && !value_check_lock(l->lv_lock, - (char_u *)N_("flatten() argument"), TRUE) - && list_flatten(l, maxdepth) == OK) - copy_tv(&argvars[0], rettv); + rettv->v_type = VAR_LIST; + rettv->vval.v_list = l; + if (l == NULL) + return; + + if (make_copy) + { + l = list_copy(l, TRUE, get_copyID()); + rettv->vval.v_list = l; + if (l == NULL) + return; + } + else + { + if (value_check_lock(l->lv_lock, + (char_u *)N_("flatten() argument"), TRUE)) + return; + ++l->lv_refcount; + } + + list_flatten(l, maxdepth); +} + +/* + * "flatten(list[, {maxdepth}])" function + */ + void +f_flatten(typval_T *argvars, typval_T *rettv) +{ + if (in_vim9script()) + emsg(_(e_cannot_use_flatten_in_vim9_script)); + else + flatten_common(argvars, rettv, FALSE); +} + +/* + * "flattennew(list[, {maxdepth}])" function + */ + void +f_flattennew(typval_T *argvars, typval_T *rettv) +{ + flatten_common(argvars, rettv, TRUE); } /* diff --git a/src/proto/list.pro b/src/proto/list.pro index 7c9ddaef1..4ccc89780 100644 --- a/src/proto/list.pro +++ b/src/proto/list.pro @@ -31,6 +31,7 @@ int list_append_number(list_T *l, varnumber_T n); int list_insert_tv(list_T *l, typval_T *tv, listitem_T *item); void list_insert(list_T *l, listitem_T *ni, listitem_T *item); void f_flatten(typval_T *argvars, typval_T *rettv); +void f_flattennew(typval_T *argvars, typval_T *rettv); int list_extend(list_T *l1, list_T *l2, listitem_T *bef); int list_concat(list_T *l1, list_T *l2, typval_T *tv); list_T *list_slice(list_T *ol, long n1, long n2); diff --git a/src/testdir/test_flatten.vim b/src/testdir/test_flatten.vim index 34431f892..7d321f7c1 100644 --- a/src/testdir/test_flatten.vim +++ b/src/testdir/test_flatten.vim @@ -81,4 +81,13 @@ func Test_flatten() call assert_equal([2, l:x], l:y) endfunc +func Test_flattennew() + let l = [1, [2, [3, 4]], 5] + call assert_equal([1, 2, 3, 4, 5], flattennew(l)) + call assert_equal([1, [2, [3, 4]], 5], l) + + call assert_equal([1, 2, [3, 4], 5], flattennew(l, 1)) + call assert_equal([1, [2, [3, 4]], 5], l) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim index 5fd510f57..5e678fa6d 100644 --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -382,6 +382,23 @@ def Test_findfile() CheckDefExecFailure(['echo findfile("")'], 'E1142:') enddef +def Test_flattennew() + var lines =<< trim END + var l = [1, [2, [3, 4]], 5] + call assert_equal([1, 2, 3, 4, 5], flattennew(l)) + call assert_equal([1, [2, [3, 4]], 5], l) + + call assert_equal([1, 2, [3, 4], 5], flattennew(l, 1)) + call assert_equal([1, [2, [3, 4]], 5], l) + END + CheckDefAndScriptSuccess(lines) + + lines =<< trim END + echo flatten([1, 2, 3]) + END + CheckDefAndScriptFailure(lines, 'E1158:') +enddef + def Test_fnamemodify() CheckDefSuccess(['echo fnamemodify(test_null_string(), ":p")']) CheckDefSuccess(['echo fnamemodify("", ":p")']) diff --git a/src/version.c b/src/version.c index 5a8993360..d34839c48 100644 --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2449, +/**/ 2448, /**/ 2447, diff --git a/src/vim9compile.c b/src/vim9compile.c index a9edc802d..5718efdf8 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -2900,6 +2900,12 @@ compile_call( idx = find_internal_func(name); if (idx >= 0) { + if (STRCMP(name, "flatten") == 0) + { + emsg(_(e_cannot_use_flatten_in_vim9_script)); + goto theend; + } + if (STRCMP(name, "add") == 0 && argcount == 2) { garray_T *stack = &cctx->ctx_type_stack; |