]> granicus.if.org Git - vim/commitdiff
patch 8.2.1244: Vim9: in lambda index assumes a list v8.2.1244
authorBram Moolenaar <Bram@vim.org>
Sun, 19 Jul 2020 13:49:49 +0000 (15:49 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 19 Jul 2020 13:49:49 +0000 (15:49 +0200)
Problem:    Vim9: in lambda index assumes a list.
Solution:   Use the value type to decide about list or dict. (closes #6479)

src/testdir/test_vim9_expr.vim
src/version.c
src/vim9compile.c

index 4c8e6e169f086589de468c2c79c3736b0da55ed6..a92254375bdfde64fa4453bdd1155fd278a491e5 100644 (file)
@@ -1115,7 +1115,7 @@ def Test_expr7_list()
   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:')
-  call CheckDefExecFailure(["let x = g:list_mixed['xx']"], 'E39:')
+  call CheckDefExecFailure(["let x = g:list_mixed['xx']"], 'E1029:')
   call CheckDefFailure(["let x = g:list_mixed["], 'E1097:')
   call CheckDefFailure(["let x = g:list_mixed[0"], 'E1097:')
   call CheckDefExecFailure(["let x = g:list_empty[3]"], 'E684:')
@@ -1173,6 +1173,9 @@ def Test_expr7_lambda()
        })
   assert_equal([111, 222, 111], ll)
 
+  let dl = [{'key': 0}, {'key': 22}]->filter({ _, v -> v['key'] })
+  assert_equal([{'key': 22}], dl)
+
   call CheckDefFailure(["filter([1, 2], {k,v -> 1})"], 'E1069:')
 enddef
 
index fb8fbe34607ceb69d000cf2888ccf793d7d51b56..c8dab652158890e9c6115a9cf4059e8b7e732ebc 100644 (file)
@@ -754,6 +754,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1244,
 /**/
     1243,
 /**/
index ed400769b1b1678792b6d0b2cd91f3bd9e23c4c7..4b569f92f91fbfa598a03a7dcc11ccb9a91a62ab 100644 (file)
@@ -3748,6 +3748,7 @@ compile_subscript(
        {
            garray_T    *stack = &cctx->ctx_type_stack;
            type_T      **typep;
+           vartype_T   vtype;
 
            // list index: list[123]
            // dict member: dict[key]
@@ -3773,22 +3774,38 @@ compile_subscript(
            }
            *arg = *arg + 1;
 
+           // We can index a list and a dict.  If we don't know the type
+           // we can use the index value type.
+           // TODO: If we don't know use an instruction to figure it out at
+           // runtime.
            typep = ((type_T **)stack->ga_data) + stack->ga_len - 2;
-           if ((*typep)->tt_type == VAR_LIST || (*typep) == &t_any)
+           vtype = (*typep)->tt_type;
+           if (*typep == &t_any)
            {
-               if ((*typep)->tt_type == VAR_LIST)
-                   *typep = (*typep)->tt_member;
-               if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
-                   return FAIL;
+               type_T *valtype = ((type_T **)stack->ga_data)
+                                                          [stack->ga_len - 1];
+               if (valtype == &t_string)
+                   vtype = VAR_DICT;
            }
-           else if ((*typep)->tt_type == VAR_DICT)
+           if (vtype == VAR_DICT)
            {
-               *typep = (*typep)->tt_member;
+               if ((*typep)->tt_type == VAR_DICT)
+                   *typep = (*typep)->tt_member;
+               else if (need_type(*typep, &t_dict_any, -2, cctx, FALSE)
+                                                                      == FAIL)
+                   return FAIL;
                if (may_generate_2STRING(-1, cctx) == FAIL)
                    return FAIL;
                if (generate_instr_drop(cctx, ISN_MEMBER, 1) == FAIL)
                    return FAIL;
            }
+           else if (vtype == VAR_LIST || *typep == &t_any)
+           {
+               if ((*typep)->tt_type == VAR_LIST)
+                   *typep = (*typep)->tt_member;
+               if (generate_instr_drop(cctx, ISN_INDEX, 1) == FAIL)
+                   return FAIL;
+           }
            else
            {
                emsg(_(e_listdictblobreq));
@@ -5386,7 +5403,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
                }
 
                stacktype = stack->ga_len == 0 ? &t_void
-                         : ((type_T **)stack->ga_data)[stack->ga_len - 1];
+                             : ((type_T **)stack->ga_data)[stack->ga_len - 1];
                if (lvar != NULL && (is_decl || !has_type))
                {
                    if (new_local && !has_type)