To: vim_dev@googlegroups.com Subject: Patch 8.2.1465 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.1465 Problem: Vim9: subscript not handled properly. Solution: Adjust error message. Remove dead code. Disallow string to number conversion in scripts. Files: src/errors.h, src/vim9compile.c, src/vim9execute.c, src/eval.c, src/typval.c, src/list.c, src/testdir/test_vim9_expr.vim, src/testdir/test_vim9_script.vim *** ../vim-8.2.1464/src/errors.h 2020-08-15 21:09:03.277675809 +0200 --- src/errors.h 2020-08-16 13:06:22.544377819 +0200 *************** *** 228,235 **** 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_item_not_found_str[] INIT(= N_("E1108: Item not found: %s")); #endif --- 228,235 ---- INIT(= N_("E1106: one argument too many")); EXTERN char e_nr_arguments_too_many[] INIT(= N_("E1106: %d arguments too many")); ! 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 *** ../vim-8.2.1464/src/vim9compile.c 2020-08-15 22:14:49.051890442 +0200 --- src/vim9compile.c 2020-08-16 14:34:04.259515059 +0200 *************** *** 3067,3072 **** --- 3067,3073 ---- { garray_T *stack = &cctx->ctx_type_stack; type_T **typep; + type_T *valtype; vartype_T vtype; int is_slice = FALSE; *************** *** 3127,3139 **** typep = ((type_T **)stack->ga_data) + stack->ga_len - (is_slice ? 3 : 2); vtype = (*typep)->tt_type; ! if (*typep == &t_any) { ! type_T *valtype = ((type_T **)stack->ga_data) ! [stack->ga_len - 1]; ! if (valtype == &t_string) ! vtype = VAR_DICT; } if (vtype == VAR_DICT) { if (is_slice) --- 3128,3149 ---- typep = ((type_T **)stack->ga_data) + stack->ga_len - (is_slice ? 3 : 2); vtype = (*typep)->tt_type; ! 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) { ! 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,3174 **** --- 3179,3188 ---- } 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,3190 **** } else { ! emsg(_(e_list_dict_or_blob_required)); return FAIL; } } --- 3198,3204 ---- } else { ! emsg(_(e_string_list_dict_or_blob_required)); return FAIL; } } *** ../vim-8.2.1464/src/vim9execute.c 2020-08-15 22:48:41.201724597 +0200 --- src/vim9execute.c 2020-08-16 13:23:58.010889306 +0200 *************** *** 2241,2273 **** // 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; --- 2241,2253 ---- *************** *** 2296,2328 **** // 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); } --- 2276,2290 ---- *** ../vim-8.2.1464/src/eval.c 2020-08-15 22:14:49.055890417 +0200 --- src/eval.c 2020-08-16 13:58:52.752122773 +0200 *************** *** 2142,2148 **** { int error = FALSE; ! if (tv_get_number_chk(rettv, &error) != 0) result = TRUE; clear_tv(rettv); if (error) --- 2142,2150 ---- { int error = FALSE; ! if (in_vim9script()) ! result = tv2bool(rettv); ! else if (tv_get_number_chk(rettv, &error) != 0) result = TRUE; clear_tv(rettv); if (error) *** ../vim-8.2.1464/src/typval.c 2020-07-21 21:30:55.011536496 +0200 --- src/typval.c 2020-08-16 14:16:13.945756387 +0200 *************** *** 204,209 **** --- 204,214 ---- 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,221 **** --- 221,231 ---- 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,1469 **** linenr_T tv_get_lnum(typval_T *argvars) { ! linenr_T lnum; ! lnum = (linenr_T)tv_get_number_chk(&argvars[0], NULL); if (lnum == 0) // no valid number, try using arg like line() { int fnum; --- 1471,1480 ---- linenr_T tv_get_lnum(typval_T *argvars) { ! linenr_T lnum = 0; ! 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; *** ../vim-8.2.1464/src/list.c 2020-08-15 22:14:49.055890417 +0200 --- src/list.c 2020-08-16 14:10:08.751786355 +0200 *************** *** 1909,1915 **** int error = FALSE; // filter(): when expr is zero remove the item ! *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(). --- 1909,1918 ---- int error = FALSE; // filter(): when expr is zero remove the item ! 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(). *** ../vim-8.2.1464/src/testdir/test_vim9_expr.vim 2020-08-15 22:14:49.055890417 +0200 --- src/testdir/test_vim9_expr.vim 2020-08-16 14:36:20.574699460 +0200 *************** *** 384,395 **** call CheckDefFailure(["let x = 1&& 2"], msg) endfunc let atrue = v:true let afalse = v:false let anone = v:none let anull = v:null let anint = 10 ! let alsoint = 4 if has('float') let afloat = 0.1 endif --- 384,397 ---- 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 theone = 1 ! let thefour = 4 if has('float') let afloat = 0.1 endif *************** *** 901,917 **** assert_equal(66, 60 + 6) assert_equal(70, 60 + g:anint) ! assert_equal(9, g:alsoint + 5) ! assert_equal(14, g:alsoint + 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 - 5) ! assert_equal(-6, g:alsoint - g:anint) assert_equal('hello', 'hel' .. 'lo') assert_equal('hello 123', 'hello ' .. --- 903,919 ---- assert_equal(66, 60 + 6) assert_equal(70, 60 + g:anint) ! assert_equal(9, g:thefour + 5) ! 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:thefour - 5) ! assert_equal(-6, g:thefour - g:anint) assert_equal('hello', 'hel' .. 'lo') assert_equal('hello 123', 'hello ' .. *************** *** 1136,1159 **** def Test_expr6() assert_equal(36, 6 * 6) assert_equal(24, 6 * ! g:alsoint) ! assert_equal(24, g:alsoint * 6) ! assert_equal(40, g:anint * g:alsoint) assert_equal(10, 60 / 6) assert_equal(6, 60 / g:anint) assert_equal(1, g:anint / 6) assert_equal(2, g:anint ! / g:alsoint) assert_equal(5, 11 % 6) assert_equal(4, g:anint % 6) assert_equal(3, 13 % g:anint) assert_equal(2, g:anint ! % g:alsoint) assert_equal(4, 6 * 4 / 6) --- 1138,1161 ---- def Test_expr6() assert_equal(36, 6 * 6) assert_equal(24, 6 * ! g:thefour) ! assert_equal(24, g:thefour * 6) ! 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:thefour) assert_equal(5, 11 % 6) assert_equal(4, g:anint % 6) assert_equal(3, 13 % g:anint) assert_equal(2, g:anint ! % g:thefour) assert_equal(4, 6 * 4 / 6) *************** *** 1323,1329 **** " type casts def Test_expr7t() let ls: list = ['a', g:string_empty] ! let ln: list = [g:anint, g:alsoint] let nr = 234 assert_equal(234, nr) --- 1325,1331 ---- " type casts def Test_expr7t() let ls: list = ['a', g:string_empty] ! let ln: list = [g:anint, g:thefour] let nr = 234 assert_equal(234, nr) *************** *** 1448,1460 **** let mixed: list = [1, 'b', false,] assert_equal(g:list_mixed, mixed) ! assert_equal('b', g:list_mixed[1]) echo [1, 2] [3, 4] ! call CheckDefExecFailure(["let x = g:anint[3]"], 'E714:') call CheckDefFailure(["let x = g:list_mixed[xxx]"], 'E1001:') call CheckDefFailure(["let x = [1,2,3]"], 'E1069:') --- 1450,1464 ---- let mixed: list = [1, 'b', false,] assert_equal(g:list_mixed, mixed) ! assert_equal('b', mixed[1]) echo [1, 2] [3, 4] ! 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,2141 **** --- 2140,2146 ---- 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,2152 **** --- 2152,2161 ---- 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() *** ../vim-8.2.1464/src/testdir/test_vim9_script.vim 2020-08-15 16:33:24.501747305 +0200 --- src/testdir/test_vim9_script.vim 2020-08-16 14:41:44.496755033 +0200 *************** *** 793,811 **** endtry assert_equal(99, n) try n = g:astring[3] ! catch /E714:/ n = 77 endtry assert_equal(77, n) try n = l[g:astring] ! catch /E39:/ ! n = 77 endtry ! assert_equal(77, n) try n = s:does_not_exist --- 793,812 ---- endtry assert_equal(99, n) + # TODO: this will change when index on "any" works try n = g:astring[3] ! catch /E1029:/ n = 77 endtry assert_equal(77, n) try n = l[g:astring] ! catch /E1029:/ ! n = 88 endtry ! assert_equal(88, n) try n = s:does_not_exist *** ../vim-8.2.1464/src/version.c 2020-08-15 22:48:41.201724597 +0200 --- src/version.c 2020-08-16 14:40:32.525187662 +0200 *************** *** 756,757 **** --- 756,759 ---- { /* Add new patch number below this line */ + /**/ + 1465, /**/ -- 'Psychologist' -- Someone who looks at everyone else when an attractive woman enters the room. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///