diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-08-16 14:48:19 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-08-16 14:48:19 +0200 |
commit | 56acb0943ede35cd9d2f6667cde2442819ccbf59 (patch) | |
tree | d35aa5928ec6d46f07ea1ed4f1e5fb2f00bfa7dc /src | |
parent | 829ac868b7615d73dbfb536f7fcd44fc7c5b7c1d (diff) | |
download | vim-git-56acb0943ede35cd9d2f6667cde2442819ccbf59.tar.gz |
patch 8.2.1465: Vim9: subscript not handled properlyv8.2.1465
Problem: Vim9: subscript not handled properly.
Solution: Adjust error message. Remove dead code. Disallow string to
number conversion in scripts.
Diffstat (limited to 'src')
-rw-r--r-- | src/errors.h | 4 | ||||
-rw-r--r-- | src/eval.c | 4 | ||||
-rw-r--r-- | src/list.c | 5 | ||||
-rw-r--r-- | src/testdir/test_vim9_expr.vim | 35 | ||||
-rw-r--r-- | src/testdir/test_vim9_script.vim | 9 | ||||
-rw-r--r-- | src/typval.c | 15 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9compile.c | 26 | ||||
-rw-r--r-- | src/vim9execute.c | 38 |
9 files changed, 71 insertions, 67 deletions
diff --git a/src/errors.h b/src/errors.h index 3f9607146..0622042a8 100644 --- a/src/errors.h +++ b/src/errors.h @@ -228,8 +228,8 @@ EXTERN char e_one_argument_too_many[] INIT(= N_("E1106: one argument too many")); EXTERN char e_nr_arguments_too_many[] INIT(= N_("E1106: %d arguments too many")); -EXTERN char e_list_dict_or_blob_required[] - INIT(= N_("E1107: List, Dict or Blob required")); +EXTERN char e_string_list_dict_or_blob_required[] + INIT(= N_("E1107: String, List, Dict or Blob required")); EXTERN char e_item_not_found_str[] INIT(= N_("E1108: Item not found: %s")); #endif diff --git a/src/eval.c b/src/eval.c index 8f685eda4..02b5623fc 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2142,7 +2142,9 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg) { int error = FALSE; - if (tv_get_number_chk(rettv, &error) != 0) + if (in_vim9script()) + result = tv2bool(rettv); + else if (tv_get_number_chk(rettv, &error) != 0) result = TRUE; clear_tv(rettv); if (error) diff --git a/src/list.c b/src/list.c index 955272c37..b09e87f5f 100644 --- a/src/list.c +++ b/src/list.c @@ -1909,7 +1909,10 @@ filter_map_one(typval_T *tv, typval_T *expr, int map, int *remp) int error = FALSE; // filter(): when expr is zero remove the item - *remp = (tv_get_number_chk(&rettv, &error) == 0); + if (in_vim9script()) + *remp = !tv2bool(&rettv); + else + *remp = (tv_get_number_chk(&rettv, &error) == 0); clear_tv(&rettv); // On type error, nothing has been removed; return FAIL to stop the // loop. The error message was given by tv_get_number_chk(). diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim index 6f3cedf90..720f2307f 100644 --- a/src/testdir/test_vim9_expr.vim +++ b/src/testdir/test_vim9_expr.vim @@ -384,12 +384,14 @@ func Test_expr3_fails() call CheckDefFailure(["let x = 1&& 2"], msg) endfunc +" global variables to use for tests with the "any" type let atrue = v:true let afalse = v:false let anone = v:none let anull = v:null let anint = 10 -let alsoint = 4 +let theone = 1 +let thefour = 4 if has('float') let afloat = 0.1 endif @@ -901,17 +903,17 @@ def Test_expr5() assert_equal(66, 60 + 6) assert_equal(70, 60 + g:anint) - assert_equal(9, g:alsoint + assert_equal(9, g:thefour + 5) - assert_equal(14, g:alsoint + g:anint) + assert_equal(14, g:thefour + g:anint) assert_equal([1, 2, 3, 4], [1] + g:alist) assert_equal(54, 60 - 6) assert_equal(50, 60 - g:anint) - assert_equal(-1, g:alsoint + assert_equal(-1, g:thefour - 5) - assert_equal(-6, g:alsoint - g:anint) + assert_equal(-6, g:thefour - g:anint) assert_equal('hello', 'hel' .. 'lo') assert_equal('hello 123', 'hello ' .. @@ -1136,24 +1138,24 @@ endfunc def Test_expr6() assert_equal(36, 6 * 6) assert_equal(24, 6 * - g:alsoint) - assert_equal(24, g:alsoint + g:thefour) + assert_equal(24, g:thefour * 6) - assert_equal(40, g:anint * g:alsoint) + assert_equal(40, g:anint * g:thefour) assert_equal(10, 60 / 6) assert_equal(6, 60 / g:anint) assert_equal(1, g:anint / 6) assert_equal(2, g:anint - / g:alsoint) + / g:thefour) assert_equal(5, 11 % 6) assert_equal(4, g:anint % 6) assert_equal(3, 13 % g:anint) assert_equal(2, g:anint - % g:alsoint) + % g:thefour) assert_equal(4, 6 * 4 / 6) @@ -1323,7 +1325,7 @@ let $TESTVAR = 'testvar' " type casts def Test_expr7t() let ls: list<string> = ['a', <string>g:string_empty] - let ln: list<number> = [<number>g:anint, <number>g:alsoint] + let ln: list<number> = [<number>g:anint, <number>g:thefour] let nr = <number>234 assert_equal(234, nr) @@ -1448,13 +1450,15 @@ def Test_expr7_list() let mixed: list<any> = [1, 'b', false,] assert_equal(g:list_mixed, mixed) - assert_equal('b', g:list_mixed[1]) + assert_equal('b', mixed[1]) echo [1, 2] [3, 4] - call CheckDefExecFailure(["let x = g:anint[3]"], 'E714:') + call CheckDefFailure(["let x = 1234[3]"], 'E1107:') + call CheckDefExecFailure(["let x = g:anint[3]"], 'E1029:') + call CheckDefFailure(["let x = g:list_mixed[xxx]"], 'E1001:') call CheckDefFailure(["let x = [1,2,3]"], 'E1069:') @@ -2136,6 +2140,7 @@ def Test_expr7_list_subscript() 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]) @@ -2147,6 +2152,10 @@ def Test_expr7_list_subscript() END CheckDefSuccess(lines) CheckScriptSuccess(['vim9script'] + lines) + + lines = ['let l = [0, 1, 2]', 'echo l[g:astring : g:theone]'] + CheckDefExecFailure(lines, 'E1029:') + CheckScriptFailure(['vim9script'] + lines, 'E1030:') enddef def Test_expr7_subscript_linebreak() diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 832835ec5..1e265be0d 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -793,19 +793,20 @@ def Test_try_catch() endtry assert_equal(99, n) + # TODO: this will change when index on "any" works try n = g:astring[3] - catch /E714:/ + catch /E1029:/ n = 77 endtry assert_equal(77, n) try n = l[g:astring] - catch /E39:/ - n = 77 + catch /E1029:/ + n = 88 endtry - assert_equal(77, n) + assert_equal(88, n) try n = s:does_not_exist diff --git a/src/typval.c b/src/typval.c index e87f91096..406a193be 100644 --- a/src/typval.c +++ b/src/typval.c @@ -204,6 +204,11 @@ tv_get_number_chk(typval_T *varp, int *denote) emsg(_("E703: Using a Funcref as a Number")); break; case VAR_STRING: + if (in_vim9script()) + { + emsg(_(e_using_string_as_number)); + break; + } if (varp->vval.v_string != NULL) vim_str2nr(varp->vval.v_string, NULL, NULL, STR2NR_ALL, &n, NULL, 0, FALSE); @@ -216,6 +221,11 @@ tv_get_number_chk(typval_T *varp, int *denote) break; case VAR_BOOL: case VAR_SPECIAL: + if (in_vim9script()) + { + emsg(_("E611: Using a Special as a Number")); + break; + } return varp->vval.v_number == VVAL_TRUE ? 1 : 0; case VAR_JOB: #ifdef FEAT_JOB_CHANNEL @@ -1461,9 +1471,10 @@ eval_env_var(char_u **arg, typval_T *rettv, int evaluate) linenr_T tv_get_lnum(typval_T *argvars) { - linenr_T lnum; + linenr_T lnum = 0; - lnum = (linenr_T)tv_get_number_chk(&argvars[0], NULL); + if (argvars[0].v_type != VAR_STRING || !in_vim9script()) + lnum = (linenr_T)tv_get_number_chk(&argvars[0], NULL); if (lnum == 0) // no valid number, try using arg like line() { int fnum; diff --git a/src/version.c b/src/version.c index 4554fc4bb..7a6fcbfff 100644 --- a/src/version.c +++ b/src/version.c @@ -755,6 +755,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1465, +/**/ 1464, /**/ 1463, diff --git a/src/vim9compile.c b/src/vim9compile.c index da44770f3..cdc63cfe1 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -3067,6 +3067,7 @@ compile_subscript( { garray_T *stack = &cctx->ctx_type_stack; type_T **typep; + type_T *valtype; vartype_T vtype; int is_slice = FALSE; @@ -3127,13 +3128,22 @@ compile_subscript( typep = ((type_T **)stack->ga_data) + stack->ga_len - (is_slice ? 3 : 2); vtype = (*typep)->tt_type; - if (*typep == &t_any) + valtype = ((type_T **)stack->ga_data)[stack->ga_len - 1]; + // If the index is a string, the variable must be a Dict. + if (*typep == &t_any && valtype == &t_string) + vtype = VAR_DICT; + if (vtype == VAR_STRING || vtype == VAR_LIST || vtype == VAR_BLOB) { - type_T *valtype = ((type_T **)stack->ga_data) - [stack->ga_len - 1]; - if (valtype == &t_string) - vtype = VAR_DICT; + if (need_type(valtype, &t_number, -1, cctx, FALSE) == FAIL) + return FAIL; + if (is_slice) + { + valtype = ((type_T **)stack->ga_data)[stack->ga_len - 2]; + if (need_type(valtype, &t_number, -2, cctx, FALSE) == FAIL) + return FAIL; + } } + if (vtype == VAR_DICT) { if (is_slice) @@ -3169,6 +3179,10 @@ compile_subscript( } else if (vtype == VAR_LIST || *typep == &t_any) { + // TODO: any requires runtime code + if (*typep == &t_any && need_type(*typep, &t_list_any, + is_slice ? -3 : -2, cctx, FALSE) == FAIL) + return FAIL; if (is_slice) { if (generate_instr_drop(cctx, ISN_LISTSLICE, 2) == FAIL) @@ -3184,7 +3198,7 @@ compile_subscript( } else { - emsg(_(e_list_dict_or_blob_required)); + emsg(_(e_string_list_dict_or_blob_required)); return FAIL; } } diff --git a/src/vim9execute.c b/src/vim9execute.c index 5670a7c3c..02a895ecb 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -2241,33 +2241,13 @@ call_def_function( // string index: string is at stack-2, index at stack-1 // string slice: string is at stack-3, first index at // stack-2, second index at stack-1 - tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2); - if (tv->v_type != VAR_STRING) - { - SOURCING_LNUM = iptr->isn_lnum; - emsg(_(e_stringreq)); - goto on_error; - } - if (is_slice) { tv = STACK_TV_BOT(-2); - if (tv->v_type != VAR_NUMBER) - { - SOURCING_LNUM = iptr->isn_lnum; - emsg(_(e_number_exp)); - goto on_error; - } n1 = tv->vval.v_number; } tv = STACK_TV_BOT(-1); - if (tv->v_type != VAR_NUMBER) - { - SOURCING_LNUM = iptr->isn_lnum; - emsg(_(e_number_exp)); - goto on_error; - } n2 = tv->vval.v_number; ectx.ec_stack.ga_len -= is_slice ? 2 : 1; @@ -2296,33 +2276,15 @@ call_def_function( // list slice: list is at stack-3, indexes at stack-2 and // stack-1 tv = is_slice ? STACK_TV_BOT(-3) : STACK_TV_BOT(-2); - if (tv->v_type != VAR_LIST) - { - SOURCING_LNUM = iptr->isn_lnum; - emsg(_(e_listreq)); - goto on_error; - } list = tv->vval.v_list; tv = STACK_TV_BOT(-1); - if (tv->v_type != VAR_NUMBER) - { - SOURCING_LNUM = iptr->isn_lnum; - emsg(_(e_number_exp)); - goto on_error; - } n1 = n2 = tv->vval.v_number; clear_tv(tv); if (is_slice) { tv = STACK_TV_BOT(-2); - if (tv->v_type != VAR_NUMBER) - { - SOURCING_LNUM = iptr->isn_lnum; - emsg(_(e_number_exp)); - goto on_error; - } n1 = tv->vval.v_number; clear_tv(tv); } |