changeset 25776:f31cf0388eab v8.2.3423

patch 8.2.3423: Vim9: list += list creates a new list in :def function Commit: https://github.com/vim/vim/commit/07802044b90b2cbcc64b2dfe235f019d7c37589c Author: Bram Moolenaar <Bram@vim.org> Date: Thu Sep 9 23:01:14 2021 +0200 patch 8.2.3423: Vim9: list += list creates a new list in :def function Problem: Vim9: list += list creates a new list in :def function. Solution: Append to the existing list.
author Bram Moolenaar <Bram@vim.org>
date Thu, 09 Sep 2021 23:15:04 +0200
parents 90bcb4296e14
children 584b2206c6d4
files src/structs.h src/testdir/test_vim9_assign.vim src/version.c src/vim9compile.c src/vim9execute.c
diffstat 5 files changed, 36 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/structs.h
+++ b/src/structs.h
@@ -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;
 
 /*
--- a/src/testdir/test_vim9_assign.vim
+++ b/src/testdir/test_vim9_assign.vim
@@ -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
--- a/src/version.c
+++ b/src/version.c
@@ -756,6 +756,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    3423,
+/**/
     3422,
 /**/
     3421,
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -690,12 +690,16 @@ check_number_or_float(vartype_T type1, v
     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 
 	    {
 		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)
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -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);