# HG changeset patch # User Bram Moolenaar # Date 1609357503 -3600 # Node ID 9bd3873b13e28022e1844d291f0e007a8e473a77 # Parent 490f599d5bbcfc991eaa903fad1f79442267b30a patch 8.2.2250: Vim9: sublist is ambiguous Commit: https://github.com/vim/vim/commit/de4f95b04134f6dfd10f60051a5078fd903a297d Author: Bram Moolenaar Date: Wed Dec 30 20:39:21 2020 +0100 patch 8.2.2250: Vim9: sublist is ambiguous Problem: Vim9: sublist is ambiguous. Solution: Require white space around the colon. (closes https://github.com/vim/vim/issues/7409) diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -3725,6 +3725,7 @@ eval_index( int range = FALSE; char_u *key = NULL; int keylen = -1; + int vim9 = in_vim9script(); if (check_can_index(rettv, evaluate, verbose) == FAIL) return FAIL; @@ -3755,6 +3756,12 @@ eval_index( empty1 = TRUE; else if (eval1(arg, &var1, evalarg) == FAIL) // recursive! return FAIL; + else if (vim9 && **arg == ':') + { + semsg(_(e_white_space_required_before_and_after_str), ":"); + clear_tv(&var1); + return FAIL; + } else if (evaluate && tv_get_string_chk(&var1) == NULL) { // not a number or string @@ -3769,7 +3776,15 @@ eval_index( if (**arg == ':') { range = TRUE; - *arg = skipwhite_and_linebreak(*arg + 1, evalarg); + ++*arg; + if (!IS_WHITE_OR_NUL(**arg) && **arg != ']') + { + semsg(_(e_white_space_required_before_and_after_str), ":"); + if (!empty1) + clear_tv(&var1); + return FAIL; + } + *arg = skipwhite_and_linebreak(*arg, evalarg); if (**arg == ']') empty2 = TRUE; else if (eval1(arg, &var2, evalarg) == FAIL) // recursive! diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -1285,7 +1285,7 @@ enddef def StringSlice(): string var s = "abcd" - var res = s[1:8] + var res = s[1 : 8] return res enddef @@ -1295,7 +1295,7 @@ def Test_disassemble_string_slice() 'var s = "abcd"\_s*' .. '\d PUSHS "abcd"\_s*' .. '\d STORE $0\_s*' .. - 'var res = s\[1:8]\_s*' .. + 'var res = s\[1 : 8]\_s*' .. '\d LOAD $0\_s*' .. '\d PUSHNR 1\_s*' .. '\d PUSHNR 8\_s*' .. @@ -1331,7 +1331,7 @@ enddef def ListSlice(): list var l = [1, 2, 3] - var res = l[1:8] + var res = l[1 : 8] return res enddef @@ -1344,7 +1344,7 @@ def Test_disassemble_list_slice() '\d PUSHNR 3\_s*' .. '\d NEWLIST size 3\_s*' .. '\d STORE $0\_s*' .. - 'var res = l\[1:8]\_s*' .. + 'var res = l\[1 : 8]\_s*' .. '\d LOAD $0\_s*' .. '\d PUSHNR 1\_s*' .. '\d PUSHNR 8\_s*' .. @@ -1405,14 +1405,14 @@ def Test_disassemble_any_index() enddef def AnySlice(): list - var res = g:somelist[1:3] + var res = g:somelist[1 : 3] return res enddef def Test_disassemble_any_slice() var instr = execute('disassemble AnySlice') assert_match('AnySlice\_s*' .. - 'var res = g:somelist\[1:3\]\_s*' .. + 'var res = g:somelist\[1 : 3\]\_s*' .. '\d LOADG g:somelist\_s*' .. '\d PUSHNR 1\_s*' .. '\d PUSHNR 3\_s*' .. diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -1718,6 +1718,15 @@ def Test_expr7_list() Main() END CheckScriptFailure(lines, 'E1127:') + + lines =<< trim END + var numbers = [1, 2, 3, 4] + var a = 1 + var b = 2 + END + CheckDefAndScriptFailure(lines + ['echo numbers[1:b]'], 'E1004:', 4) + CheckDefAndScriptFailure(lines + ['echo numbers[1: b]'], 'E1004:', 4) + CheckDefAndScriptFailure(lines + ['echo numbers[a :b]'], 'E1004:', 4) enddef def Test_expr7_list_vim9script() @@ -2274,13 +2283,13 @@ def Test_expr7_any_index_slice() assert_equal('', g:teststring[-1]) assert_equal('', g:teststring[99]) - assert_equal('b', g:teststring[1:1]) - assert_equal('bcdef', g:teststring[1:]) - assert_equal('abcd', g:teststring[:3]) - assert_equal('cdef', g:teststring[-4:]) - assert_equal('abcdef', g:teststring[-9:]) - assert_equal('abcd', g:teststring[:-3]) - assert_equal('', g:teststring[:-9]) + assert_equal('b', g:teststring[1 : 1]) + assert_equal('bcdef', g:teststring[1 :]) + assert_equal('abcd', g:teststring[: 3]) + assert_equal('cdef', g:teststring[-4 :]) + assert_equal('abcdef', g:teststring[-9 :]) + assert_equal('abcd', g:teststring[: -3]) + assert_equal('', g:teststring[: -9]) # blob index cannot be out of range g:testblob = 0z01ab @@ -2290,13 +2299,13 @@ def Test_expr7_any_index_slice() assert_equal(0x01, g:testblob[-2]) # blob slice accepts out of range - assert_equal(0z01ab, g:testblob[0:1]) - assert_equal(0z01, g:testblob[0:0]) - assert_equal(0z01, g:testblob[-2:-2]) - assert_equal(0zab, g:testblob[1:1]) - assert_equal(0zab, g:testblob[-1:-1]) - assert_equal(0z, g:testblob[2:2]) - assert_equal(0z, g:testblob[0:-3]) + assert_equal(0z01ab, g:testblob[0 : 1]) + assert_equal(0z01, g:testblob[0 : 0]) + assert_equal(0z01, g:testblob[-2 : -2]) + assert_equal(0zab, g:testblob[1 : 1]) + assert_equal(0zab, g:testblob[-1 : -1]) + assert_equal(0z, g:testblob[2 : 2]) + assert_equal(0z, g:testblob[0 : -3]) # list index cannot be out of range g:testlist = [0, 1, 2, 3] @@ -2308,19 +2317,19 @@ def Test_expr7_any_index_slice() assert_equal(1, g:testlist[g:theone]) # list slice accepts out of range - assert_equal([0], g:testlist[0:0]) - assert_equal([3], g:testlist[3:3]) - assert_equal([0, 1], g:testlist[0:1]) - assert_equal([0, 1, 2, 3], g:testlist[0:3]) - assert_equal([0, 1, 2, 3], g:testlist[0:9]) - assert_equal([], g:testlist[-1:1]) - assert_equal([1], g:testlist[-3:1]) - assert_equal([0, 1], g:testlist[-4:1]) - assert_equal([0, 1], g:testlist[-9:1]) - assert_equal([1, 2, 3], g:testlist[1:-1]) - assert_equal([1], g:testlist[1:-3]) - assert_equal([], g:testlist[1:-4]) - assert_equal([], g:testlist[1:-9]) + assert_equal([0], g:testlist[0 : 0]) + assert_equal([3], g:testlist[3 : 3]) + assert_equal([0, 1], g:testlist[0 : 1]) + assert_equal([0, 1, 2, 3], g:testlist[0 : 3]) + assert_equal([0, 1, 2, 3], g:testlist[0 : 9]) + assert_equal([], g:testlist[-1 : 1]) + assert_equal([1], g:testlist[-3 : 1]) + assert_equal([0, 1], g:testlist[-4 : 1]) + assert_equal([0, 1], g:testlist[-9 : 1]) + assert_equal([1, 2, 3], g:testlist[1 : -1]) + assert_equal([1], g:testlist[1 : -3]) + assert_equal([], g:testlist[1 : -4]) + assert_equal([], g:testlist[1 : -9]) g:testdict = {a: 1, b: 2} assert_equal(1, g:testdict['a']) @@ -2340,8 +2349,8 @@ def Test_expr7_any_index_slice() CheckDefExecFailure(['echo g:testlist[-5]'], 'E684:', 1) CheckScriptFailure(['vim9script', 'echo g:testlist[-5]'], 'E684:', 2) - CheckDefExecFailure(['echo g:testdict["a":"b"]'], 'E719:', 1) - CheckScriptFailure(['vim9script', 'echo g:testdict["a":"b"]'], 'E719:', 2) + CheckDefExecFailure(['echo g:testdict["a" : "b"]'], 'E719:', 1) + CheckScriptFailure(['vim9script', 'echo g:testdict["a" : "b"]'], 'E719:', 2) CheckDefExecFailure(['echo g:testdict[1]'], 'E716:', 1) CheckScriptFailure(['vim9script', 'echo g:testdict[1]'], 'E716:', 2) @@ -2746,45 +2755,45 @@ def Test_expr7_string_subscript() assert_equal('', text[6]) assert_equal('', text[999]) - assert_equal('ábçdëf', text[0:-1]) - assert_equal('ábçdëf', text[0 :-1]) - assert_equal('ábçdëf', text[0: -1]) + assert_equal('ábçdëf', text[0 : -1]) + assert_equal('ábçdëf', text[0 : -1]) + assert_equal('ábçdëf', text[0 : -1]) assert_equal('ábçdëf', text[0 : -1]) assert_equal('ábçdëf', text[0 - :-1]) - assert_equal('ábçdëf', text[0: + : -1]) + assert_equal('ábçdëf', text[0 : -1]) assert_equal('ábçdëf', text[0 : -1 ]) - assert_equal('bçdëf', text[1:-1]) - assert_equal('çdëf', text[2:-1]) - assert_equal('dëf', text[3:-1]) - assert_equal('ëf', text[4:-1]) - assert_equal('f', text[5:-1]) - assert_equal('', text[6:-1]) - assert_equal('', text[999:-1]) - - assert_equal('ábçd', text[:3]) - assert_equal('bçdëf', text[1:]) + assert_equal('bçdëf', text[1 : -1]) + assert_equal('çdëf', text[2 : -1]) + assert_equal('dëf', text[3 : -1]) + assert_equal('ëf', text[4 : -1]) + assert_equal('f', text[5 : -1]) + assert_equal('', text[6 : -1]) + assert_equal('', text[999 : -1]) + + assert_equal('ábçd', text[: 3]) + assert_equal('bçdëf', text[1 :]) assert_equal('ábçdëf', text[:]) END CheckDefSuccess(lines) CheckScriptSuccess(['vim9script'] + lines) lines =<< trim END - var d = 'asdf'[1: + var d = 'asdf'[1 : END CheckDefFailure(lines, 'E1097:', 3) lines =<< trim END - var d = 'asdf'[1:xxx] + var d = 'asdf'[1 : xxx] END CheckDefFailure(lines, 'E1001:', 1) lines =<< trim END - var d = 'asdf'[1:2 + var d = 'asdf'[1 : 2 END CheckDefFailure(lines, 'E1097:', 3) lines =<< trim END - var d = 'asdf'[1:2 + var d = 'asdf'[1 : 2 echo d END CheckDefFailure(lines, 'E111:', 2) @@ -2794,12 +2803,12 @@ def Test_expr7_string_subscript() END CheckDefFailure(lines, 'E1012: Type mismatch; expected number but got string', 1) lines =<< trim END - var d = 'asdf'['1':2] + var d = 'asdf'['1' : 2] echo d END CheckDefFailure(lines, 'E1012: Type mismatch; expected number but got string', 1) lines =<< trim END - var d = 'asdf'[1:'2'] + var d = 'asdf'[1 : '2'] echo d END CheckDefFailure(lines, 'E1012: Type mismatch; expected number but got string', 1) @@ -2813,22 +2822,22 @@ def Test_expr7_list_subscript() assert_equal(4, list[-1]) assert_equal(0, list[-5]) - assert_equal([0, 1, 2, 3, 4], list[0:4]) + assert_equal([0, 1, 2, 3, 4], list[0 : 4]) assert_equal([0, 1, 2, 3, 4], list[:]) - assert_equal([1, 2, 3, 4], list[1:]) - assert_equal([2, 3, 4], list[2:-1]) - assert_equal([4], list[4:-1]) - assert_equal([], list[5:-1]) - assert_equal([], list[999:-1]) - assert_equal([1, 2, 3, 4], list[g:theone:g:thefour]) - - assert_equal([0, 1, 2, 3], list[0:3]) - assert_equal([0], list[0:0]) - assert_equal([0, 1, 2, 3, 4], list[0:-1]) - assert_equal([0, 1, 2], list[0:-3]) - assert_equal([0], list[0:-5]) - assert_equal([], list[0:-6]) - assert_equal([], list[0:-99]) + assert_equal([1, 2, 3, 4], list[1 :]) + assert_equal([2, 3, 4], list[2 : -1]) + assert_equal([4], list[4 : -1]) + assert_equal([], list[5 : -1]) + assert_equal([], list[999 : -1]) + assert_equal([1, 2, 3, 4], list[g:theone : g:thefour]) + + assert_equal([0, 1, 2, 3], list[0 : 3]) + assert_equal([0], list[0 : 0]) + assert_equal([0, 1, 2, 3, 4], list[0 : -1]) + assert_equal([0, 1, 2], list[0 : -3]) + assert_equal([0], list[0 : -5]) + assert_equal([], list[0 : -6]) + assert_equal([], list[0 : -99]) END CheckDefSuccess(lines) CheckScriptSuccess(['vim9script'] + lines) diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2250, +/**/ 2249, /**/ 2248, diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -3695,19 +3695,33 @@ compile_subscript( if (may_get_next_line_error(p, arg, cctx) == FAIL) return FAIL; if (**arg == ':') + { // missing first index is equal to zero generate_PUSHNR(cctx, 0); + } else { if (compile_expr0(arg, cctx) == FAIL) return FAIL; + if (**arg == ':') + { + semsg(_(e_white_space_required_before_and_after_str), ":"); + return FAIL; + } if (may_get_next_line_error(p, arg, cctx) == FAIL) return FAIL; *arg = skipwhite(*arg); } if (**arg == ':') { - *arg = skipwhite(*arg + 1); + is_slice = TRUE; + ++*arg; + if (!IS_WHITE_OR_NUL(**arg) && **arg != ']') + { + semsg(_(e_white_space_required_before_and_after_str), ":"); + return FAIL; + } + *arg = skipwhite(*arg); if (may_get_next_line_error(p, arg, cctx) == FAIL) return FAIL; if (**arg == ']') @@ -3721,7 +3735,6 @@ compile_subscript( return FAIL; *arg = skipwhite(*arg); } - is_slice = TRUE; } if (**arg != ']')