]> granicus.if.org Git - vim/commitdiff
patch 8.2.3423: Vim9: list += list creates a new list in :def function v8.2.3423
authorBram Moolenaar <Bram@vim.org>
Thu, 9 Sep 2021 21:01:14 +0000 (23:01 +0200)
committerBram Moolenaar <Bram@vim.org>
Thu, 9 Sep 2021 21:01:14 +0000 (23:01 +0200)
Problem:    Vim9: list += list creates a new list in :def function.
Solution:   Append to the existing list.

src/structs.h
src/testdir/test_vim9_assign.vim
src/version.c
src/vim9compile.c
src/vim9execute.c

index 5d1496f59074f3d80b31c792990f2f9aa7ef399c..8a94fc115586501f2b53aef612c9f1a806ef2fa0 100644 (file)
@@ -4106,6 +4106,9 @@ typedef enum
     EXPR_MULT,         // *
     EXPR_DIV,          // /
     EXPR_REM,          // %
+    // used with ISN_ADDLIST
+    EXPR_COPY,         // create new list
+    EXPR_APPEND,       // append to first list
 } exprtype_T;
 
 /*
index 6b6311a56ae5a9eb0db6bcdba7a38661a8645565..0d07e07eb71ef6f04ca411ea12b0fcbebb8d806f 100644 (file)
@@ -557,20 +557,21 @@ enddef
 
 def Test_extend_list()
   var lines =<< trim END
-      vim9script
-      var l: list<number>
-      l += [123]
-      assert_equal([123], l)
+      var l1: list<number>
+      var l2 = l1
+      assert_true(l1 is l2)
+      l1 += [123]
+      assert_equal([123], l1)
+      assert_true(l1 is l2)
   END
-  CheckScriptSuccess(lines)
+  CheckDefAndScriptSuccess(lines)
 
   lines =<< trim END
-      vim9script
       var list: list<string>
       extend(list, ['x'])
       assert_equal(['x'], list)
   END
-  CheckScriptSuccess(lines)
+  CheckDefAndScriptSuccess(lines)
 
   # appending to NULL list from a function
   lines =<< trim END
index 8cd295c1bbbf986040071ee47155b4b8ca41ac1e..9f4ea7613151bf805639a4b834dd59891ca6eaf0 100644 (file)
@@ -755,6 +755,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    3423,
 /**/
     3422,
 /**/
index a4d8423fca0173bb737ca7d04daf0b0e68dad372..e7c7c07a6926944f480af3d82bd77e3b0593c768 100644 (file)
@@ -690,12 +690,16 @@ check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
     return OK;
 }
 
+/*
+ * Generate instruction for "+".  For a list this creates a new list.
+ */
     static int
 generate_add_instr(
        cctx_T *cctx,
        vartype_T vartype,
        type_T *type1,
-       type_T *type2)
+       type_T *type2,
+       exprtype_T expr_type)
 {
     garray_T   *stack = &cctx->ctx_type_stack;
     isn_T      *isn = generate_instr_drop(cctx,
@@ -715,7 +719,12 @@ generate_add_instr(
        return FAIL;
 
     if (isn != NULL)
-       isn->isn_arg.op.op_type = EXPR_ADD;
+    {
+       if (isn->isn_type == ISN_ADDLIST)
+           isn->isn_arg.op.op_type = expr_type;
+       else
+           isn->isn_arg.op.op_type = EXPR_ADD;
+    }
 
     // When concatenating two lists with different member types the member type
     // becomes "any".
@@ -769,7 +778,8 @@ generate_two_op(cctx_T *cctx, char_u *op)
     switch (*op)
     {
        case '+':
-                 if (generate_add_instr(cctx, vartype, type1, type2) == FAIL)
+                 if (generate_add_instr(cctx, vartype, type1, type2,
+                                                           EXPR_COPY) == FAIL)
                      return FAIL;
                  break;
 
@@ -7186,7 +7196,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
            {
                if (generate_add_instr(cctx,
                            operator_type(lhs.lhs_member_type, stacktype),
-                                      lhs.lhs_member_type, stacktype) == FAIL)
+                                      lhs.lhs_member_type, stacktype,
+                                                         EXPR_APPEND) == FAIL)
                    goto theend;
            }
            else if (generate_two_op(cctx, op) == FAIL)
index fdca9771450e692c79388ae1027789d8cee724a7..9fc942d3796b46cb96cd61fb243dca6c51bee339 100644 (file)
@@ -3677,7 +3677,14 @@ exec_instructions(ectx_T *ectx)
 
                    // add two lists or blobs
                    if (iptr->isn_type == ISN_ADDLIST)
-                       eval_addlist(tv1, tv2);
+                   {
+                       if (iptr->isn_arg.op.op_type == EXPR_APPEND
+                                                  && tv1->vval.v_list != NULL)
+                           list_extend(tv1->vval.v_list, tv2->vval.v_list,
+                                                                        NULL);
+                       else
+                           eval_addlist(tv1, tv2);
+                   }
                    else
                        eval_addblob(tv1, tv2);
                    clear_tv(tv2);