Patch 8.2.1465
Problem:    Vim9: subscript not handled properly.
Solution:   Adjust error message.  Remove dead code.  Disallow string to
            number conversion in scripts.
Files:      src/errors.h, src/vim9compile.c, src/vim9execute.c, src/eval.c,
            src/typval.c, src/list.c, src/testdir/test_vim9_expr.vim,
            src/testdir/test_vim9_script.vim


*** ../vim-8.2.1464/src/errors.h        2020-08-15 21:09:03.277675809 +0200
--- src/errors.h        2020-08-16 13:06:22.544377819 +0200
***************
*** 228,235 ****
        INIT(= N_("E1106: one argument too many"));
  EXTERN char e_nr_arguments_too_many[]
        INIT(= N_("E1106: %d arguments too many"));
! EXTERN char e_list_dict_or_blob_required[]
!       INIT(= N_("E1107: List, Dict or Blob required"));
  EXTERN char e_item_not_found_str[]
        INIT(= N_("E1108: Item not found: %s"));
  #endif
--- 228,235 ----
        INIT(= N_("E1106: one argument too many"));
  EXTERN char e_nr_arguments_too_many[]
        INIT(= N_("E1106: %d arguments too many"));
! EXTERN char e_string_list_dict_or_blob_required[]
!       INIT(= N_("E1107: String, List, Dict or Blob required"));
  EXTERN char e_item_not_found_str[]
        INIT(= N_("E1108: Item not found: %s"));
  #endif
*** ../vim-8.2.1464/src/vim9compile.c   2020-08-15 22:14:49.051890442 +0200
--- src/vim9compile.c   2020-08-16 14:34:04.259515059 +0200
***************
*** 3067,3072 ****
--- 3067,3073 ----
        {
            garray_T    *stack = &cctx->ctx_type_stack;
            type_T      **typep;
+           type_T      *valtype;
            vartype_T   vtype;
            int         is_slice = FALSE;
  
***************
*** 3127,3139 ****
            typep = ((type_T **)stack->ga_data) + stack->ga_len
                                                          - (is_slice ? 3 : 2);
            vtype = (*typep)->tt_type;
!           if (*typep == &t_any)
            {
!               type_T *valtype = ((type_T **)stack->ga_data)
!                                                          [stack->ga_len - 1];
!               if (valtype == &t_string)
!                   vtype = VAR_DICT;
            }
            if (vtype == VAR_DICT)
            {
                if (is_slice)
--- 3128,3149 ----
            typep = ((type_T **)stack->ga_data) + stack->ga_len
                                                          - (is_slice ? 3 : 2);
            vtype = (*typep)->tt_type;
!           valtype = ((type_T **)stack->ga_data)[stack->ga_len - 1];
!           // If the index is a string, the variable must be a Dict.
!           if (*typep == &t_any && valtype == &t_string)
!               vtype = VAR_DICT;
!           if (vtype == VAR_STRING || vtype == VAR_LIST || vtype == VAR_BLOB)
            {
!               if (need_type(valtype, &t_number, -1, cctx, FALSE) == FAIL)
!                   return FAIL;
!               if (is_slice)
!               {
!                   valtype = ((type_T **)stack->ga_data)[stack->ga_len - 2];
!                   if (need_type(valtype, &t_number, -2, cctx, FALSE) == FAIL)
!                       return FAIL;
!               }
            }
+ 
            if (vtype == VAR_DICT)
            {
                if (is_slice)
***************
*** 3169,3174 ****
--- 3179,3188 ----
            }
            else if (vtype == VAR_LIST || *typep == &t_any)
            {
+               // TODO: any requires runtime code
+               if (*typep == &t_any && need_type(*typep, &t_list_any,
+                                     is_slice ? -3 : -2, cctx, FALSE) == FAIL)
+                   return FAIL;
                if (is_slice)
                {
                    if (generate_instr_drop(cctx, ISN_LISTSLICE, 2) == FAIL)
***************
*** 3184,3190 ****
            }
            else
            {
!               emsg(_(e_list_dict_or_blob_required));
                return FAIL;
            }
        }
--- 3198,3204 ----
            }
            else
            {
!               emsg(_(e_string_list_dict_or_blob_required));
                return FAIL;
            }
        }
*** ../vim-8.2.1464/src/vim9execute.c   2020-08-15 22:48:41.201724597 +0200
--- src/vim9execute.c   2020-08-16 13:23:58.010889306 +0200
***************
*** 2241,2273 ****
                    // string index: string is at stack-2, index at stack-1
                    // string slice: string is at stack-3, first index at
                    // stack-2, second index at stack-1
-                   tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2);
-                   if (tv->v_type != VAR_STRING)
-                   {
-                       SOURCING_LNUM = iptr->isn_lnum;
-                       emsg(_(e_stringreq));
-                       goto on_error;
-                   }
- 
                    if (is_slice)
                    {
                        tv = STACK_TV_BOT(-2);
-                       if (tv->v_type != VAR_NUMBER)
-                       {
-                           SOURCING_LNUM = iptr->isn_lnum;
-                           emsg(_(e_number_exp));
-                           goto on_error;
-                       }
                        n1 = tv->vval.v_number;
                    }
  
                    tv = STACK_TV_BOT(-1);
-                   if (tv->v_type != VAR_NUMBER)
-                   {
-                       SOURCING_LNUM = iptr->isn_lnum;
-                       emsg(_(e_number_exp));
-                       goto on_error;
-                   }
                    n2 = tv->vval.v_number;
  
                    ectx.ec_stack.ga_len -= is_slice ? 2 : 1;
--- 2241,2253 ----
***************
*** 2296,2328 ****
                    // list slice: list is at stack-3, indexes at stack-2 and
                    // stack-1
                    tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2);
-                   if (tv->v_type != VAR_LIST)
-                   {
-                       SOURCING_LNUM = iptr->isn_lnum;
-                       emsg(_(e_listreq));
-                       goto on_error;
-                   }
                    list = tv->vval.v_list;
  
                    tv = STACK_TV_BOT(-1);
-                   if (tv->v_type != VAR_NUMBER)
-                   {
-                       SOURCING_LNUM = iptr->isn_lnum;
-                       emsg(_(e_number_exp));
-                       goto on_error;
-                   }
                    n1 = n2 = tv->vval.v_number;
                    clear_tv(tv);
  
                    if (is_slice)
                    {
                        tv = STACK_TV_BOT(-2);
-                       if (tv->v_type != VAR_NUMBER)
-                       {
-                           SOURCING_LNUM = iptr->isn_lnum;
-                           emsg(_(e_number_exp));
-                           goto on_error;
-                       }
                        n1 = tv->vval.v_number;
                        clear_tv(tv);
                    }
--- 2276,2290 ----
*** ../vim-8.2.1464/src/eval.c  2020-08-15 22:14:49.055890417 +0200
--- src/eval.c  2020-08-16 13:58:52.752122773 +0200
***************
*** 2142,2148 ****
        {
            int         error = FALSE;
  
!           if (tv_get_number_chk(rettv, &error) != 0)
                result = TRUE;
            clear_tv(rettv);
            if (error)
--- 2142,2150 ----
        {
            int         error = FALSE;
  
!           if (in_vim9script())
!               result = tv2bool(rettv);
!           else if (tv_get_number_chk(rettv, &error) != 0)
                result = TRUE;
            clear_tv(rettv);
            if (error)
*** ../vim-8.2.1464/src/typval.c        2020-07-21 21:30:55.011536496 +0200
--- src/typval.c        2020-08-16 14:16:13.945756387 +0200
***************
*** 204,209 ****
--- 204,214 ----
            emsg(_("E703: Using a Funcref as a Number"));
            break;
        case VAR_STRING:
+           if (in_vim9script())
+           {
+               emsg(_(e_using_string_as_number));
+               break;
+           }
            if (varp->vval.v_string != NULL)
                vim_str2nr(varp->vval.v_string, NULL, NULL,
                                            STR2NR_ALL, &n, NULL, 0, FALSE);
***************
*** 216,221 ****
--- 221,231 ----
            break;
        case VAR_BOOL:
        case VAR_SPECIAL:
+           if (in_vim9script())
+           {
+               emsg(_("E611: Using a Special as a Number"));
+               break;
+           }
            return varp->vval.v_number == VVAL_TRUE ? 1 : 0;
        case VAR_JOB:
  #ifdef FEAT_JOB_CHANNEL
***************
*** 1461,1469 ****
      linenr_T
  tv_get_lnum(typval_T *argvars)
  {
!     linenr_T  lnum;
  
!     lnum = (linenr_T)tv_get_number_chk(&argvars[0], NULL);
      if (lnum == 0)  // no valid number, try using arg like line()
      {
        int     fnum;
--- 1471,1480 ----
      linenr_T
  tv_get_lnum(typval_T *argvars)
  {
!     linenr_T  lnum = 0;
  
!     if (argvars[0].v_type != VAR_STRING || !in_vim9script())
!       lnum = (linenr_T)tv_get_number_chk(&argvars[0], NULL);
      if (lnum == 0)  // no valid number, try using arg like line()
      {
        int     fnum;
*** ../vim-8.2.1464/src/list.c  2020-08-15 22:14:49.055890417 +0200
--- src/list.c  2020-08-16 14:10:08.751786355 +0200
***************
*** 1909,1915 ****
        int         error = FALSE;
  
        // filter(): when expr is zero remove the item
!       *remp = (tv_get_number_chk(&rettv, &error) == 0);
        clear_tv(&rettv);
        // On type error, nothing has been removed; return FAIL to stop the
        // loop.  The error message was given by tv_get_number_chk().
--- 1909,1918 ----
        int         error = FALSE;
  
        // filter(): when expr is zero remove the item
!       if (in_vim9script())
!           *remp = !tv2bool(&rettv);
!       else
!           *remp = (tv_get_number_chk(&rettv, &error) == 0);
        clear_tv(&rettv);
        // On type error, nothing has been removed; return FAIL to stop the
        // loop.  The error message was given by tv_get_number_chk().
*** ../vim-8.2.1464/src/testdir/test_vim9_expr.vim      2020-08-15 
22:14:49.055890417 +0200
--- src/testdir/test_vim9_expr.vim      2020-08-16 14:36:20.574699460 +0200
***************
*** 384,395 ****
    call CheckDefFailure(["let x = 1&& 2"], msg)
  endfunc
  
  let atrue = v:true
  let afalse = v:false
  let anone = v:none
  let anull = v:null
  let anint = 10
! let alsoint = 4
  if has('float')
    let afloat = 0.1
  endif
--- 384,397 ----
    call CheckDefFailure(["let x = 1&& 2"], msg)
  endfunc
  
+ " global variables to use for tests with the "any" type
  let atrue = v:true
  let afalse = v:false
  let anone = v:none
  let anull = v:null
  let anint = 10
! let theone = 1
! let thefour = 4
  if has('float')
    let afloat = 0.1
  endif
***************
*** 901,917 ****
    assert_equal(66, 60 + 6)
    assert_equal(70, 60 +
                        g:anint)
!   assert_equal(9, g:alsoint
                        + 5)
!   assert_equal(14, g:alsoint + g:anint)
    assert_equal([1, 2, 3, 4], [1] + g:alist)
  
    assert_equal(54, 60 - 6)
    assert_equal(50, 60 -
                    g:anint)
!   assert_equal(-1, g:alsoint
                        - 5)
!   assert_equal(-6, g:alsoint - g:anint)
  
    assert_equal('hello', 'hel' .. 'lo')
    assert_equal('hello 123', 'hello ' ..
--- 903,919 ----
    assert_equal(66, 60 + 6)
    assert_equal(70, 60 +
                        g:anint)
!   assert_equal(9, g:thefour
                        + 5)
!   assert_equal(14, g:thefour + g:anint)
    assert_equal([1, 2, 3, 4], [1] + g:alist)
  
    assert_equal(54, 60 - 6)
    assert_equal(50, 60 -
                    g:anint)
!   assert_equal(-1, g:thefour
                        - 5)
!   assert_equal(-6, g:thefour - g:anint)
  
    assert_equal('hello', 'hel' .. 'lo')
    assert_equal('hello 123', 'hello ' ..
***************
*** 1136,1159 ****
  def Test_expr6()
    assert_equal(36, 6 * 6)
    assert_equal(24, 6 *
!                       g:alsoint)
!   assert_equal(24, g:alsoint
                        * 6)
!   assert_equal(40, g:anint * g:alsoint)
  
    assert_equal(10, 60 / 6)
    assert_equal(6, 60 /
                        g:anint)
    assert_equal(1, g:anint / 6)
    assert_equal(2, g:anint
!                       / g:alsoint)
  
    assert_equal(5, 11 % 6)
    assert_equal(4, g:anint % 6)
    assert_equal(3, 13 %
                        g:anint)
    assert_equal(2, g:anint
!                       % g:alsoint)
  
    assert_equal(4, 6 * 4 / 6)
  
--- 1138,1161 ----
  def Test_expr6()
    assert_equal(36, 6 * 6)
    assert_equal(24, 6 *
!                       g:thefour)
!   assert_equal(24, g:thefour
                        * 6)
!   assert_equal(40, g:anint * g:thefour)
  
    assert_equal(10, 60 / 6)
    assert_equal(6, 60 /
                        g:anint)
    assert_equal(1, g:anint / 6)
    assert_equal(2, g:anint
!                       / g:thefour)
  
    assert_equal(5, 11 % 6)
    assert_equal(4, g:anint % 6)
    assert_equal(3, 13 %
                        g:anint)
    assert_equal(2, g:anint
!                       % g:thefour)
  
    assert_equal(4, 6 * 4 / 6)
  
***************
*** 1323,1329 ****
  " type casts
  def Test_expr7t()
    let ls: list<string> = ['a', <string>g:string_empty]
!   let ln: list<number> = [<number>g:anint, <number>g:alsoint]
    let nr = <number>234
    assert_equal(234, nr)
  
--- 1325,1331 ----
  " type casts
  def Test_expr7t()
    let ls: list<string> = ['a', <string>g:string_empty]
!   let ln: list<number> = [<number>g:anint, <number>g:thefour]
    let nr = <number>234
    assert_equal(234, nr)
  
***************
*** 1448,1460 ****
  
    let mixed: list<any> = [1, 'b', false,]
    assert_equal(g:list_mixed, mixed)
!   assert_equal('b', g:list_mixed[1])
  
    echo [1,
        2] [3,
                4]
  
!   call CheckDefExecFailure(["let x = g:anint[3]"], 'E714:')
    call CheckDefFailure(["let x = g:list_mixed[xxx]"], 'E1001:')
  
    call CheckDefFailure(["let x = [1,2,3]"], 'E1069:')
--- 1450,1464 ----
  
    let mixed: list<any> = [1, 'b', false,]
    assert_equal(g:list_mixed, mixed)
!   assert_equal('b', mixed[1])
  
    echo [1,
        2] [3,
                4]
  
!   call CheckDefFailure(["let x = 1234[3]"], 'E1107:')
!   call CheckDefExecFailure(["let x = g:anint[3]"], 'E1029:')
! 
    call CheckDefFailure(["let x = g:list_mixed[xxx]"], 'E1001:')
  
    call CheckDefFailure(["let x = [1,2,3]"], 'E1069:')
***************
*** 2136,2141 ****
--- 2140,2146 ----
      assert_equal([4], list[4:-1])
      assert_equal([], list[5:-1])
      assert_equal([], list[999:-1])
+     assert_equal([1, 2, 3, 4], list[g:theone:g:thefour])
  
      assert_equal([0, 1, 2, 3], list[0:3])
      assert_equal([0], list[0:0])
***************
*** 2147,2152 ****
--- 2152,2161 ----
    END
    CheckDefSuccess(lines)
    CheckScriptSuccess(['vim9script'] + lines)
+ 
+   lines = ['let l = [0, 1, 2]', 'echo l[g:astring : g:theone]']
+   CheckDefExecFailure(lines, 'E1029:')
+   CheckScriptFailure(['vim9script'] + lines, 'E1030:')
  enddef
  
  def Test_expr7_subscript_linebreak()
*** ../vim-8.2.1464/src/testdir/test_vim9_script.vim    2020-08-15 
16:33:24.501747305 +0200
--- src/testdir/test_vim9_script.vim    2020-08-16 14:41:44.496755033 +0200
***************
*** 793,811 ****
    endtry
    assert_equal(99, n)
  
    try
      n = g:astring[3]
!   catch /E714:/
      n = 77
    endtry
    assert_equal(77, n)
  
    try
      n = l[g:astring]
!   catch /E39:/
!     n = 77
    endtry
!   assert_equal(77, n)
  
    try
      n = s:does_not_exist
--- 793,812 ----
    endtry
    assert_equal(99, n)
  
+   # TODO: this will change when index on "any" works
    try
      n = g:astring[3]
!   catch /E1029:/
      n = 77
    endtry
    assert_equal(77, n)
  
    try
      n = l[g:astring]
!   catch /E1029:/
!     n = 88
    endtry
!   assert_equal(88, n)
  
    try
      n = s:does_not_exist
*** ../vim-8.2.1464/src/version.c       2020-08-15 22:48:41.201724597 +0200
--- src/version.c       2020-08-16 14:40:32.525187662 +0200
***************
*** 756,757 ****
--- 756,759 ----
  {   /* Add new patch number below this line */
+ /**/
+     1465,
  /**/

-- 
'Psychologist' -- Someone who looks at everyone else when
an attractive woman enters the room.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            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/202008161248.07GCmiJx561256%40masaka.moolenaar.net.

Raspunde prin e-mail lui