summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-02-01 20:14:51 +0100
committerBram Moolenaar <Bram@vim.org>2021-02-01 20:14:51 +0100
commit3b690069730805a147d45d92eaca4dc838272d1d (patch)
tree47e970336167b1b23d8fac9e97b12cb76f159dd7 /src
parent9d20daffc296b9eb901fb14bdd83620ea55d440a (diff)
downloadvim-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.h2
-rw-r--r--src/evalfunc.c2
-rw-r--r--src/list.c62
-rw-r--r--src/proto/list.pro1
-rw-r--r--src/testdir/test_flatten.vim9
-rw-r--r--src/testdir/test_vim9_builtin.vim17
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c6
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;