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 -- Br...@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 ///