# HG changeset patch # User Bram Moolenaar # Date 1631222104 -7200 # Node ID f31cf0388eab8dbe84b2c511f47ba2b3a4a8d3dc # Parent 90bcb4296e14d792b10c94e99a6f6c0f4e702e48 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 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. diff --git a/src/structs.h b/src/structs.h --- 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; /* diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim --- 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 - l += [123] - assert_equal([123], l) + var l1: list + 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 extend(list, ['x']) assert_equal(['x'], list) END - CheckScriptSuccess(lines) + CheckDefAndScriptSuccess(lines) # appending to NULL list from a function lines =<< trim END diff --git a/src/version.c b/src/version.c --- 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, diff --git a/src/vim9compile.c b/src/vim9compile.c --- 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) diff --git a/src/vim9execute.c b/src/vim9execute.c --- 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);