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 -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20220126210201.CE1541C05DA%40moolenaar.net.

Raspunde prin e-mail lui