Patch 8.2.2780
Problem:    Vim9: for loop over blob doesn't work.
Solution:   Make it work.
Files:      src/vim9compile.c, src/vim9execute.c, src/testdir/test_blob.vim


*** ../vim-8.2.2779/src/vim9compile.c   2021-04-17 20:44:52.438520729 +0200
--- src/vim9compile.c   2021-04-18 13:10:48.610166634 +0200
***************
*** 7508,7520 ****
      }
      arg_end = arg;
  
!     // If we know the type of "var" and it is a not a list or string we can
      // give an error now.
      vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
      if (vartype->tt_type != VAR_LIST && vartype->tt_type != VAR_STRING
!                                               && vartype->tt_type != VAR_ANY)
      {
-       // TODO: support Blob
        semsg(_(e_for_loop_on_str_not_supported),
                                               vartype_name(vartype->tt_type));
        drop_scope(cctx);
--- 7508,7519 ----
      }
      arg_end = arg;
  
!     // If we know the type of "var" and it is a not a supported type we can
      // give an error now.
      vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
      if (vartype->tt_type != VAR_LIST && vartype->tt_type != VAR_STRING
!               && vartype->tt_type != VAR_BLOB && vartype->tt_type != VAR_ANY)
      {
        semsg(_(e_for_loop_on_str_not_supported),
                                               vartype_name(vartype->tt_type));
        drop_scope(cctx);
***************
*** 7523,7528 ****
--- 7522,7529 ----
  
      if (vartype->tt_type == VAR_STRING)
        item_type = &t_string;
+     else if (vartype->tt_type == VAR_BLOB)
+       item_type = &t_number;
      else if (vartype->tt_type == VAR_LIST
                                     && vartype->tt_member->tt_type != VAR_ANY)
      {
***************
*** 7530,7536 ****
            item_type = vartype->tt_member;
        else if (vartype->tt_member->tt_type == VAR_LIST
                      && vartype->tt_member->tt_member->tt_type != VAR_ANY)
!           // TODO: should get the type from 
            item_type = vartype->tt_member->tt_member;
      }
  
--- 7531,7537 ----
            item_type = vartype->tt_member;
        else if (vartype->tt_member->tt_type == VAR_LIST
                      && vartype->tt_member->tt_member->tt_type != VAR_ANY)
!           // TODO: should get the type for each lhs
            item_type = vartype->tt_member->tt_member;
      }
  
*** ../vim-8.2.2779/src/vim9execute.c   2021-04-17 20:44:52.442520718 +0200
--- src/vim9execute.c   2021-04-18 13:14:50.845114758 +0200
***************
*** 2900,2907 ****
                    {
                        char_u  *str = ltv->vval.v_string;
  
!                       // Push the next character from the string.  The index
!                       // is for the last byte of the previous character.
                        ++idxtv->vval.v_number;
                        if (str == NULL || str[idxtv->vval.v_number] == NUL)
                        {
--- 2900,2907 ----
                    {
                        char_u  *str = ltv->vval.v_string;
  
!                       // The index is for the last byte of the previous
!                       // character.
                        ++idxtv->vval.v_number;
                        if (str == NULL || str[idxtv->vval.v_number] == NUL)
                        {
***************
*** 2913,2918 ****
--- 2913,2919 ----
                        {
                            int clen = mb_ptr2len(str + idxtv->vval.v_number);
  
+                           // Push the next character from the string.
                            tv = STACK_TV_BOT(0);
                            tv->v_type = VAR_STRING;
                            tv->vval.v_string = vim_strnsave(
***************
*** 2921,2929 ****
                            idxtv->vval.v_number += clen - 1;
                        }
                    }
                    else
                    {
-                       // TODO: support Blob
                        semsg(_(e_for_loop_on_str_not_supported),
                                                    vartype_name(ltv->v_type));
                        goto failed;
--- 2922,2962 ----
                            idxtv->vval.v_number += clen - 1;
                        }
                    }
+                   else if (ltv->v_type == VAR_BLOB)
+                   {
+                       blob_T  *blob = ltv->vval.v_blob;
+ 
+                       // When we get here the first time make a copy of the
+                       // blob, so that the iteration still works when it is
+                       // changed.
+                       if (idxtv->vval.v_number == -1 && blob != NULL)
+                       {
+                           blob_copy(blob, ltv);
+                           blob_unref(blob);
+                           blob = ltv->vval.v_blob;
+                       }
+ 
+                       // The index is for the previous byte.
+                       ++idxtv->vval.v_number;
+                       if (blob == NULL
+                                    || idxtv->vval.v_number >= blob_len(blob))
+                       {
+                           // past the end of the blob, jump to "endfor"
+                           ectx.ec_iidx = iptr->isn_arg.forloop.for_end;
+                           may_restore_cmdmod(&funclocal);
+                       }
+                       else
+                       {
+                           // Push the next byte from the blob.
+                           tv = STACK_TV_BOT(0);
+                           tv->v_type = VAR_NUMBER;
+                           tv->vval.v_number = blob_get(blob,
+                                                        idxtv->vval.v_number);
+                           ++ectx.ec_stack.ga_len;
+                       }
+                   }
                    else
                    {
                        semsg(_(e_for_loop_on_str_not_supported),
                                                    vartype_name(ltv->v_type));
                        goto failed;
*** ../vim-8.2.2779/src/testdir/test_blob.vim   2021-04-17 20:44:52.442520718 
+0200
--- src/testdir/test_blob.vim   2021-04-18 13:01:39.892653660 +0200
***************
*** 283,315 ****
  endfunc
  
  func Test_blob_for_loop()
!   let blob = 0z00010203
!   let i = 0
!   for byte in blob
!     call assert_equal(i, byte)
!     let i += 1
!   endfor
!     call assert_equal(4, i)
  
!   let blob = 0z00
!   call remove(blob, 0)
!   call assert_equal(0, len(blob))
!   for byte in blob
!     call assert_error('loop over empty blob')
!   endfor
! 
!   let blob = 0z0001020304
!   let i = 0
!   for byte in blob
!     call assert_equal(i, byte)
!     if i == 1
        call remove(blob, 0)
!     elseif i == 3
!       call remove(blob, 3)
!     endif
!     let i += 1
!   endfor
!   call assert_equal(5, i)
  endfunc
  
  func Test_blob_concatenate()
--- 283,318 ----
  endfunc
  
  func Test_blob_for_loop()
!   let lines =<< trim END
!       VAR blob = 0z00010203
!       VAR i = 0
!       for byte in blob
!         call assert_equal(i, byte)
!         LET i += 1
!       endfor
!       call assert_equal(4, i)
  
!       LET blob = 0z00
        call remove(blob, 0)
!       call assert_equal(0, len(blob))
!       for byte in blob
!         call assert_report('loop over empty blob')
!       endfor
! 
!       LET blob = 0z0001020304
!       LET i = 0
!       for byte in blob
!         call assert_equal(i, byte)
!         if i == 1
!           call remove(blob, 0)
!         elseif i == 3
!           call remove(blob, 3)
!         endif
!         LET i += 1
!       endfor
!       call assert_equal(5, i)
!   END
!   call CheckLegacyAndVim9Success(lines)
  endfunc
  
  func Test_blob_concatenate()
*** ../vim-8.2.2779/src/version.c       2021-04-17 21:22:46.351232494 +0200
--- src/version.c       2021-04-18 12:53:17.195236010 +0200
***************
*** 752,753 ****
--- 752,755 ----
  {   /* Add new patch number below this line */
+ /**/
+     2780,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
117. You are more comfortable typing in html.

 /// 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/202104181116.13IBGqKl293369%40masaka.moolenaar.net.

Raspunde prin e-mail lui