To: vim_dev@googlegroups.com Subject: Patch 8.2.2449 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.2449 Problem: Vim9: flatten() always changes the list type. Solution: Disallow using flatten() and add flattennew(). Files: runtime/doc/eval.txt, runtime/doc/usr_41.txt, src/evalfunc.c, src/list.c, src/proto/list.pro, src/errors.h, src/vim9compile.c, src/testdir/test_flatten.vim, src/testdir/test_vim9_builtin.vim *** ../vim-8.2.2448/runtime/doc/eval.txt 2021-01-31 17:02:06.250490190 +0100 --- runtime/doc/eval.txt 2021-02-01 19:48:59.899320314 +0100 *************** *** 2549,2554 **** --- 2549,2556 ---- findfile({name} [, {path} [, {count}]]) String find file {name} in {path} flatten({list} [, {maxdepth}]) List flatten {list} up to {maxdepth} levels + flattennew({list} [, {maxdepth}]) + List flatten a copy of {list} float2nr({expr}) Number convert Float {expr} to a Number floor({expr}) Float round {expr} down fmod({expr1}, {expr2}) Float remainder of {expr1} / {expr2} *************** *** 4712,4719 **** Flatten {list} up to {maxdepth} levels. Without {maxdepth} the result is a |List| without nesting, as if {maxdepth} is a very large number. ! The {list} is changed in place, make a copy first if you do not want that. *E900* {maxdepth} means how deep in nested lists changes are made. {list} is not modified when {maxdepth} is 0. --- 4714,4723 ---- Flatten {list} up to {maxdepth} levels. Without {maxdepth} the result is a |List| without nesting, as if {maxdepth} is a very large number. ! The {list} is changed in place, use |flattennew()| if you do not want that. + In Vim9 script flatten() cannot be used, you must always use + |flattennew()|. *E900* {maxdepth} means how deep in nested lists changes are made. {list} is not modified when {maxdepth} is 0. *************** *** 4727,4732 **** --- 4731,4740 ---- :echo flatten([1, [2, [3, 4]], 5], 1) < [1, 2, [3, 4], 5] + flattennew({list} [, {maxdepth}]) *flattennew()* + Like |flatten()| but first make a copy of {list}. + + float2nr({expr}) *float2nr()* Convert {expr} to a Number by omitting the part after the decimal point. *** ../vim-8.2.2448/runtime/doc/usr_41.txt 2021-01-31 17:02:06.266490126 +0100 --- runtime/doc/usr_41.txt 2021-02-01 19:49:35.455237261 +0100 *************** *** 665,670 **** --- 665,671 ---- count() count number of times a value appears in a List repeat() repeat a List multiple times flatten() flatten a List + flattennew() flatten a copy of a List Dictionary manipulation: *dict-functions* get() get an entry without an error for a wrong key *** ../vim-8.2.2448/src/evalfunc.c 2021-01-31 20:48:55.162175817 +0100 --- src/evalfunc.c 2021-02-01 19:50:24.523120307 +0100 *************** *** 954,959 **** --- 954,961 ---- 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, *** ../vim-8.2.2448/src/list.c 2021-01-31 17:48:26.358330166 +0100 --- src/list.c 2021-02-01 20:03:02.281100687 +0100 *************** *** 740,746 **** * It does nothing if "maxdepth" is 0. * Returns FAIL when out of memory. */ ! static int list_flatten(list_T *list, long maxdepth) { listitem_T *item; --- 740,746 ---- * It does nothing if "maxdepth" is 0. * Returns FAIL when out of memory. */ ! static void list_flatten(list_T *list, long maxdepth) { listitem_T *item; *************** *** 748,754 **** int n; if (maxdepth == 0) ! return OK; CHECK_LIST_MATERIALIZE(list); n = 0; --- 748,754 ---- int n; if (maxdepth == 0) ! return; CHECK_LIST_MATERIALIZE(list); n = 0; *************** *** 757,763 **** { fast_breakcheck(); if (got_int) ! return FAIL; if (item->li_tv.v_type == VAR_LIST) { --- 757,763 ---- { fast_breakcheck(); if (got_int) ! return; if (item->li_tv.v_type == VAR_LIST) { *************** *** 765,771 **** vimlist_remove(list, item, item); if (list_extend(list, item->li_tv.vval.v_list, next) == FAIL) ! return FAIL; clear_tv(&item->li_tv); tofree = item; --- 765,771 ---- vimlist_remove(list, item, item); if (list_extend(list, item->li_tv.vval.v_list, next) == FAIL) ! return; clear_tv(&item->li_tv); tofree = item; *************** *** 787,801 **** item = item->li_next; } } - - return OK; } /* ! * "flatten(list[, {maxdepth}])" function */ ! void ! f_flatten(typval_T *argvars, typval_T *rettv) { list_T *l; long maxdepth; --- 787,799 ---- item = item->li_next; } } } /* ! * "flatten()" and "flattennew()" functions */ ! static void ! flatten_common(typval_T *argvars, typval_T *rettv, int make_copy) { list_T *l; long maxdepth; *************** *** 822,831 **** } 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); } /* --- 820,867 ---- } l = argvars[0].vval.v_list; ! 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); } /* *** ../vim-8.2.2448/src/proto/list.pro 2021-01-13 21:46:53.832589880 +0100 --- src/proto/list.pro 2021-02-01 19:54:08.770557406 +0100 *************** *** 31,36 **** --- 31,37 ---- 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); *** ../vim-8.2.2448/src/errors.h 2021-01-31 22:18:21.977811108 +0100 --- src/errors.h 2021-02-01 19:54:23.870518098 +0100 *************** *** 351,353 **** --- 351,355 ---- 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")); *** ../vim-8.2.2448/src/vim9compile.c 2021-01-31 21:47:39.036783041 +0100 --- src/vim9compile.c 2021-02-01 20:11:35.063630218 +0100 *************** *** 2900,2905 **** --- 2900,2911 ---- 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; *** ../vim-8.2.2448/src/testdir/test_flatten.vim 2020-08-12 18:50:31.879655802 +0200 --- src/testdir/test_flatten.vim 2021-02-01 20:06:39.924481595 +0100 *************** *** 81,84 **** --- 81,93 ---- 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 *** ../vim-8.2.2448/src/testdir/test_vim9_builtin.vim 2021-01-31 20:48:55.162175817 +0100 --- src/testdir/test_vim9_builtin.vim 2021-02-01 20:09:18.728024772 +0100 *************** *** 382,387 **** --- 382,404 ---- 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")']) *** ../vim-8.2.2448/src/version.c 2021-02-01 19:31:43.969603658 +0100 --- src/version.c 2021-02-01 19:51:03.851024757 +0100 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 2449, /**/ -- Facepalm reply #9: "Speed up, you can drive 80 here" "Why, the cars behind us are also driving 60" /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///