diff options
author | Bram Moolenaar <Bram@vim.org> | 2022-01-26 21:01:15 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2022-01-26 21:01:15 +0000 |
commit | 70c43d84be98ab54d3723155dcc4232dc5a5f081 (patch) | |
tree | 31f3a580fe1bbfecc50e822e718696836d9cb95c | |
parent | 1080c48ec8d672d7e9fbefb5a1255c9df09a2884 (diff) | |
download | vim-git-70c43d84be98ab54d3723155dcc4232dc5a5f081.tar.gz |
patch 8.2.4225: Vim9: depth argument of :lockvar not parsed in :def functionv8.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.
-rw-r--r-- | src/errors.h | 8 | ||||
-rw-r--r-- | src/evalfunc.c | 7 | ||||
-rw-r--r-- | src/evalvars.c | 16 | ||||
-rw-r--r-- | src/structs.h | 8 | ||||
-rw-r--r-- | src/testdir/test_vim9_cmd.vim | 29 | ||||
-rw-r--r-- | src/testdir/test_vim9_disassemble.vim | 2 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9cmds.c | 23 | ||||
-rw-r--r-- | src/vim9execute.c | 5 |
9 files changed, 82 insertions, 18 deletions
diff --git a/src/errors.h b/src/errors.h index d89c27c22..dd1b9fcc8 100644 --- a/src/errors.h +++ b/src/errors.h @@ -2859,10 +2859,10 @@ EXTERN char e_assert_fails_fifth_argument[] 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_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[] diff --git a/src/evalfunc.c b/src/evalfunc.c index 4376318d0..169f972c2 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -7922,7 +7922,7 @@ range_list_materialize(list_T *list) { 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; + int stride = list->lv_u.nonmat.lv_stride; varnumber_T i; list->lv_first = NULL; @@ -7930,8 +7930,13 @@ range_list_materialize(list_T *list) 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; } /* diff --git a/src/evalvars.c b/src/evalvars.c index 496666e1e..c53cc87fb 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -2060,10 +2060,18 @@ item_lock(typval_T *tv, int deep, int lock, int check_refcount) 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); + 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: diff --git a/src/structs.h b/src/structs.h index e2f1de93a..a35361ecb 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1464,8 +1464,9 @@ typedef struct // 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_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,7 +1498,8 @@ struct listwatch_S */ struct listvar_S { - listitem_T *lv_first; // first item, NULL if none + 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: diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim index 6347a282a..7b2edfd1b 100644 --- a/src/testdir/test_vim9_cmd.vim +++ b/src/testdir/test_vim9_cmd.vim @@ -1396,6 +1396,35 @@ def Test_lockvar() 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 diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index 8731052aa..d3330908e 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -625,7 +625,7 @@ def Test_disassemble_locl_local() '\d STORE $0\_s*' .. 'lockvar d.a\_s*' .. '\d LOAD $0\_s*' .. - '\d LOCKUNLOCK lockvar d.a\_s*', + '\d LOCKUNLOCK lockvar 2 d.a\_s*', res) enddef diff --git a/src/version.c b/src/version.c index 9869aa0d8..7fbafc604 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 */ /**/ + 4225, +/**/ 4224, /**/ 4223, diff --git a/src/vim9cmds.c b/src/vim9cmds.c index 27322df1c..1af2a157e 100644 --- a/src/vim9cmds.c +++ b/src/vim9cmds.c @@ -178,7 +178,7 @@ compile_lock_unlock( lval_T *lvp, char_u *name_end, exarg_T *eap, - int deep UNUSED, + int deep, void *coookie) { cctx_T *cctx = coookie; @@ -223,8 +223,9 @@ compile_lock_unlock( ret = FAIL; else { - vim_snprintf((char *)buf, len, "%s %s", + vim_snprintf((char *)buf, len, "%s %d %s", eap->cmdidx == CMD_lockvar ? "lockvar" : "unlockvar", + deep, p); ret = generate_EXEC_copy(cctx, isn, buf); @@ -241,7 +242,23 @@ compile_lock_unlock( char_u * compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx) { - ex_unletlock(eap, arg, 0, GLV_NO_AUTOLOAD | GLV_COMPILING, + 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; diff --git a/src/vim9execute.c b/src/vim9execute.c index 1232b35bb..a45d7c553 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1754,7 +1754,8 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx) { listitem_T *li = list_find(list, lidx); - if (error_if_locked(li->li_tv.v_lock, e_cannot_change_list_item)) + 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,7 +1763,7 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx) } else { - if (error_if_locked(list->lv_lock, e_cannot_change_list)) + 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) |