summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-06-27 15:04:05 +0200
committerBram Moolenaar <Bram@vim.org>2021-06-27 15:04:05 +0200
commite65081d1b591f16dc6e380a830d87565c5eb7b03 (patch)
treeea8c2e725d7dcd81f3b0f83dfab33ee1936ee692
parent65aee0b714e809b9f19862f3decd35055ed4de10 (diff)
patch 8.2.3064: Vim9: in script cannot set item in uninitialized listv8.2.3064
Problem: Vim9: in script cannot set item in uninitialized list. Solution: When a list is NULL allocate an empty one. (closes #8461)
-rw-r--r--src/eval.c33
-rw-r--r--src/testdir/test_vim9_assign.vim39
-rw-r--r--src/version.c2
3 files changed, 51 insertions, 23 deletions
diff --git a/src/eval.c b/src/eval.c
index 7704d46e98..7990c23f00 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -932,15 +932,22 @@ get_lval(
semsg(_(e_dot_can_only_be_used_on_dictionary_str), name);
return NULL;
}
- if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL)
- && !(lp->ll_tv->v_type == VAR_DICT)
- && !(lp->ll_tv->v_type == VAR_BLOB
- && lp->ll_tv->vval.v_blob != NULL))
+ if (lp->ll_tv->v_type != VAR_LIST
+ && lp->ll_tv->v_type != VAR_DICT
+ && lp->ll_tv->v_type != VAR_BLOB)
{
if (!quiet)
emsg(_("E689: Can only index a List, Dictionary or Blob"));
return NULL;
}
+
+ // a NULL list/blob works like an empty list/blob, allocate one now.
+ if (lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list == NULL)
+ rettv_list_alloc(lp->ll_tv);
+ else if (lp->ll_tv->v_type == VAR_BLOB
+ && lp->ll_tv->vval.v_blob == NULL)
+ rettv_blob_alloc(lp->ll_tv);
+
if (lp->ll_range)
{
if (!quiet)
@@ -1201,10 +1208,20 @@ get_lval(
lp->ll_li = list_find_index(lp->ll_list, &lp->ll_n1);
if (lp->ll_li == NULL)
{
- clear_tv(&var2);
- if (!quiet)
- semsg(_(e_listidx), lp->ll_n1);
- return NULL;
+ // Vim9: Allow for adding an item at the end.
+ if (in_vim9script() && lp->ll_n1 == lp->ll_list->lv_len
+ && lp->ll_list->lv_lock == 0)
+ {
+ list_append_number(lp->ll_list, 0);
+ lp->ll_li = list_find_index(lp->ll_list, &lp->ll_n1);
+ }
+ if (lp->ll_li == NULL)
+ {
+ clear_tv(&var2);
+ if (!quiet)
+ semsg(_(e_listidx), lp->ll_n1);
+ return NULL;
+ }
}
if (lp->ll_valtype != NULL)
diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim
index 230ddc50c6..86f890ea09 100644
--- a/src/testdir/test_vim9_assign.vim
+++ b/src/testdir/test_vim9_assign.vim
@@ -1102,21 +1102,30 @@ def Test_assignment_failure()
enddef
def Test_assign_list()
- var l: list<string> = []
- l[0] = 'value'
- assert_equal('value', l[0])
-
- l[1] = 'asdf'
- assert_equal('value', l[0])
- assert_equal('asdf', l[1])
- assert_equal('asdf', l[-1])
- assert_equal('value', l[-2])
-
- var nrl: list<number> = []
- for i in range(5)
- nrl[i] = i
- endfor
- assert_equal([0, 1, 2, 3, 4], nrl)
+ var lines =<< trim END
+ var l: list<string> = []
+ l[0] = 'value'
+ assert_equal('value', l[0])
+
+ l[1] = 'asdf'
+ assert_equal('value', l[0])
+ assert_equal('asdf', l[1])
+ assert_equal('asdf', l[-1])
+ assert_equal('value', l[-2])
+
+ var nrl: list<number> = []
+ for i in range(5)
+ nrl[i] = i
+ endfor
+ assert_equal([0, 1, 2, 3, 4], nrl)
+
+ var ul: list<any>
+ ul[0] = 1
+ ul[1] = 2
+ ul[2] = 3
+ assert_equal([1, 2, 3], ul)
+ END
+ CheckDefAndScriptSuccess(lines)
CheckDefFailure(["var l: list<number> = ['', true]"], 'E1012: Type mismatch; expected list<number> but got list<any>', 1)
CheckDefFailure(["var l: list<list<number>> = [['', true]]"], 'E1012: Type mismatch; expected list<list<number>> but got list<list<any>>', 1)
diff --git a/src/version.c b/src/version.c
index 1238a4976b..12f6648195 100644
--- 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 */
/**/
+ 3064,
+/**/
3063,
/**/
3062,