To: vim_dev@googlegroups.com Subject: Patch 8.2.4225 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.4225 Problem: Vim9: depth argument of :lockvar not parsed in :def function. Solution: Parse the optional depth argument. (closes #9629) Fix that locking doesn't work for a non-materialize list. Files: src/vim9cmds.c, src/evalvars.c, src/structs.h, src/evalfunc.c, src/errors.h, src/vim9execute.c, src/testdir/test_vim9_cmd.vim, src/testdir/test_vim9_disassemble.vim *** ../vim-8.2.4224/src/vim9cmds.c 2022-01-22 12:27:00.823189193 +0000 --- src/vim9cmds.c 2022-01-26 19:38:41.386562788 +0000 *************** *** 178,184 **** lval_T *lvp, char_u *name_end, exarg_T *eap, ! int deep UNUSED, void *coookie) { cctx_T *cctx = coookie; --- 178,184 ---- lval_T *lvp, char_u *name_end, exarg_T *eap, ! int deep, void *coookie) { cctx_T *cctx = coookie; *************** *** 223,230 **** ret = FAIL; else { ! vim_snprintf((char *)buf, len, "%s %s", eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar", p); ret = generate_EXEC_copy(cctx, isn, buf); --- 223,231 ---- ret = FAIL; else { ! vim_snprintf((char *)buf, len, "%s %d %s", eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar", + deep, p); ret = generate_EXEC_copy(cctx, isn, buf); *************** *** 241,247 **** char_u * compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx) { ! ex_unletlock(eap, arg, 0, GLV_NO_AUTOLOAD | GLV_COMPILING, eap->cmdidx == CMD_unlet ? compile_unlet : compile_lock_unlock, cctx); return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd; --- 242,264 ---- char_u * compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx) { ! int deep = 0; ! char_u *p = arg; ! ! if (eap->cmdidx != CMD_unlet) ! { ! if (eap->forceit) ! deep = -1; ! else if (vim_isdigit(*p)) ! { ! deep = getdigits(&p); ! p = skipwhite(p); ! } ! else ! deep = 2; ! } ! ! ex_unletlock(eap, p, deep, GLV_NO_AUTOLOAD | GLV_COMPILING, eap->cmdidx == CMD_unlet ? compile_unlet : compile_lock_unlock, cctx); return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd; *** ../vim-8.2.4224/src/evalvars.c 2022-01-24 21:27:57.648085201 +0000 --- src/evalvars.c 2022-01-26 20:33:37.012692096 +0000 *************** *** 2060,2069 **** l->lv_lock |= VAR_LOCKED; else l->lv_lock &= ~VAR_LOCKED; ! if ((deep < 0 || deep > 1) && l->lv_first != &range_list_item) ! // recursive: lock/unlock the items the List contains ! FOR_ALL_LIST_ITEMS(l, li) ! item_lock(&li->li_tv, deep - 1, lock, check_refcount); } break; case VAR_DICT: --- 2060,2077 ---- l->lv_lock |= VAR_LOCKED; else l->lv_lock &= ~VAR_LOCKED; ! if (deep < 0 || deep > 1) ! { ! if (l->lv_first == &range_list_item) ! l->lv_lock |= VAR_ITEMS_LOCKED; ! else ! { ! // recursive: lock/unlock the items the List contains ! CHECK_LIST_MATERIALIZE(l); ! FOR_ALL_LIST_ITEMS(l, li) item_lock(&li->li_tv, ! deep - 1, lock, check_refcount); ! } ! } } break; case VAR_DICT: *** ../vim-8.2.4224/src/structs.h 2022-01-21 16:31:06.299109897 +0000 --- src/structs.h 2022-01-26 20:34:19.151837270 +0000 *************** *** 1464,1471 **** // allowed to mask existing functions // Values for "v_lock". ! #define VAR_LOCKED 1 // locked with lock(), can use unlock() ! #define VAR_FIXED 2 // locked forever /* * Structure to hold an item of a list: an internal variable without a name. --- 1464,1472 ---- // allowed to mask existing functions // Values for "v_lock". ! #define VAR_LOCKED 1 // locked with lock(), can use unlock() ! #define VAR_FIXED 2 // locked forever ! #define VAR_ITEMS_LOCKED 4 // items of non-materialized list locked /* * Structure to hold an item of a list: an internal variable without a name. *************** *** 1497,1503 **** */ struct listvar_S { ! listitem_T *lv_first; // first item, NULL if none listwatch_T *lv_watch; // first watcher, NULL if none union { struct { // used for non-materialized range list: --- 1498,1505 ---- */ struct listvar_S { ! listitem_T *lv_first; // first item, NULL if none, &range_list_item ! // for a non-materialized list listwatch_T *lv_watch; // first watcher, NULL if none union { struct { // used for non-materialized range list: *** ../vim-8.2.4224/src/evalfunc.c 2022-01-26 18:25:47.689295506 +0000 --- src/evalfunc.c 2022-01-26 20:44:59.098892455 +0000 *************** *** 7922,7928 **** { varnumber_T start = list->lv_u.nonmat.lv_start; varnumber_T end = list->lv_u.nonmat.lv_end; ! int stride = list->lv_u.nonmat.lv_stride; varnumber_T i; list->lv_first = NULL; --- 7922,7928 ---- { varnumber_T start = list->lv_u.nonmat.lv_start; varnumber_T end = list->lv_u.nonmat.lv_end; ! int stride = list->lv_u.nonmat.lv_stride; varnumber_T i; list->lv_first = NULL; *************** *** 7930,7937 **** --- 7930,7942 ---- list->lv_len = 0; list->lv_u.mat.lv_idx_item = NULL; for (i = start; stride > 0 ? i <= end : i >= end; i += stride) + { if (list_append_number(list, (varnumber_T)i) == FAIL) break; + if (list->lv_lock & VAR_ITEMS_LOCKED) + list->lv_u.mat.lv_last->li_tv.v_lock = VAR_LOCKED; + } + list->lv_lock &= ~VAR_ITEMS_LOCKED; } /* *** ../vim-8.2.4224/src/errors.h 2022-01-24 18:16:08.740970105 +0000 --- src/errors.h 2022-01-26 20:47:12.456200140 +0000 *************** *** 2859,2868 **** INIT(= N_("E1116: \"assert_fails()\" fifth argument must be a string")); EXTERN char e_cannot_use_bang_with_nested_def[] INIT(= N_("E1117: Cannot use ! with nested :def")); ! EXTERN char e_cannot_change_list[] ! INIT(= N_("E1118: Cannot change list")); ! EXTERN char e_cannot_change_list_item[] ! INIT(= N_("E1119: Cannot change list item")); EXTERN char e_cannot_change_dict[] INIT(= N_("E1120: Cannot change dict")); EXTERN char e_cannot_change_dict_item[] --- 2859,2868 ---- INIT(= N_("E1116: \"assert_fails()\" fifth argument must be a string")); EXTERN char e_cannot_use_bang_with_nested_def[] INIT(= N_("E1117: Cannot use ! with nested :def")); ! EXTERN char e_cannot_change_locked_list[] ! INIT(= N_("E1118: Cannot change locked list")); ! EXTERN char e_cannot_change_locked_list_item[] ! INIT(= N_("E1119: Cannot change locked list item")); EXTERN char e_cannot_change_dict[] INIT(= N_("E1120: Cannot change dict")); EXTERN char e_cannot_change_dict_item[] *** ../vim-8.2.4224/src/vim9execute.c 2022-01-25 15:51:52.430855187 +0000 --- src/vim9execute.c 2022-01-26 20:47:32.299799602 +0000 *************** *** 1754,1760 **** { listitem_T *li = list_find(list, lidx); ! if (error_if_locked(li->li_tv.v_lock, e_cannot_change_list_item)) return FAIL; // overwrite existing list item clear_tv(&li->li_tv); --- 1754,1761 ---- { listitem_T *li = list_find(list, lidx); ! if (error_if_locked(li->li_tv.v_lock, ! e_cannot_change_locked_list_item)) return FAIL; // overwrite existing list item clear_tv(&li->li_tv); *************** *** 1762,1768 **** } else { ! if (error_if_locked(list->lv_lock, e_cannot_change_list)) return FAIL; // append to list, only fails when out of memory if (list_append_tv(list, tv) == FAIL) --- 1763,1769 ---- } else { ! if (error_if_locked(list->lv_lock, e_cannot_change_locked_list)) return FAIL; // append to list, only fails when out of memory if (list_append_tv(list, tv) == FAIL) *** ../vim-8.2.4224/src/testdir/test_vim9_cmd.vim 2021-12-20 12:24:59.381293520 +0000 --- src/testdir/test_vim9_cmd.vim 2022-01-26 20:57:09.314273768 +0000 *************** *** 1396,1401 **** --- 1396,1430 ---- lockvar whatever endif + g:lockme = [1, 2, 3] + lockvar 1 g:lockme + g:lockme[1] = 77 + assert_equal([1, 77, 3], g:lockme) + + lockvar 2 g:lockme + var caught = false + try + g:lockme[1] = 99 + catch /E1119:/ + caught = true + endtry + assert_true(caught) + assert_equal([1, 77, 3], g:lockme) + unlet g:lockme + + # also for non-materialized list + g:therange = range(3) + lockvar 2 g:therange + caught = false + try + g:therange[1] = 99 + catch /E1119:/ + caught = true + endtry + assert_true(caught) + assert_equal([0, 1, 2], g:therange) + unlet g:therange + var d = {a: 1, b: 2} d.a = 3 d.b = 4 *** ../vim-8.2.4224/src/testdir/test_vim9_disassemble.vim 2022-01-25 15:51:52.430855187 +0000 --- src/testdir/test_vim9_disassemble.vim 2022-01-26 20:59:51.346676540 +0000 *************** *** 625,631 **** '\d STORE $0\_s*' .. 'lockvar d.a\_s*' .. '\d LOAD $0\_s*' .. ! '\d LOCKUNLOCK lockvar d.a\_s*', res) enddef --- 625,631 ---- '\d STORE $0\_s*' .. 'lockvar d.a\_s*' .. '\d LOAD $0\_s*' .. ! '\d LOCKUNLOCK lockvar 2 d.a\_s*', res) enddef *** ../vim-8.2.4224/src/version.c 2022-01-26 18:25:47.689295506 +0000 --- src/version.c 2022-01-26 20:47:54.535350813 +0000 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 4225, /**/ -- NEIL INNES PLAYED: THE FIRST SELF-DESTRUCTIVE MONK, ROBIN'S LEAST FAVORITE MINSTREL, THE PAGE CRUSHED BY A RABBIT, THE OWNER OF A DUCK "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///