Mercurial > vim
changeset 26238:14b4c778b61e v8.2.3650
patch 8.2.3650: Vim9: for loop variable can be a list member
Commit: https://github.com/vim/vim/commit/3b3755fe19e9ded2a1c45f14b2c6fa065bcaf2c6
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Nov 22 20:10:18 2021 +0000
patch 8.2.3650: Vim9: for loop variable can be a list member
Problem: Vim9: for loop variable can be a list member.
Solution: Check for valid variable name. (closes https://github.com/vim/vim/issues/9179)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 22 Nov 2021 21:15:03 +0100 |
parents | 83c695dd5355 |
children | 5187470e768c |
files | src/dict.c src/eval.c src/evalvars.c src/proto/evalvars.pro src/testdir/test_vim9_script.vim src/version.c src/vim9compile.c |
diffstat | 7 files changed, 38 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/src/dict.c +++ b/src/dict.c @@ -1102,7 +1102,7 @@ dict_extend(dict_T *d1, dict_T *d2, char && HI2DI(hi2)->di_tv.v_type == VAR_FUNC && var_wrong_func_name(hi2->hi_key, di1 == NULL)) break; - if (!valid_varname(hi2->hi_key, TRUE)) + if (!valid_varname(hi2->hi_key, -1, TRUE)) break; }
--- a/src/eval.c +++ b/src/eval.c @@ -1128,7 +1128,7 @@ get_lval( wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE && rettv->v_type == VAR_FUNC && var_wrong_func_name(key, lp->ll_di == NULL)) - || !valid_varname(key, TRUE); + || !valid_varname(key, -1, TRUE); if (len != -1) key[len] = prevval; if (wrong)
--- a/src/evalvars.c +++ b/src/evalvars.c @@ -3431,7 +3431,7 @@ set_var_const( // Make sure the variable name is valid. In Vim9 script an autoload // variable must be prefixed with "g:". - if (!valid_varname(varname, !vim9script + if (!valid_varname(varname, -1, !vim9script || STRNCMP(name, "g:", 2) == 0)) goto failed; @@ -3631,14 +3631,15 @@ value_check_lock(int lock, char_u *name, /* * Check if a variable name is valid. When "autoload" is true "#" is allowed. + * If "len" is -1 use all of "varname", otherwise up to "varname[len]". * Return FALSE and give an error if not. */ int -valid_varname(char_u *varname, int autoload) +valid_varname(char_u *varname, int len, int autoload) { char_u *p; - for (p = varname; *p != NUL; ++p) + for (p = varname; len < 0 ? *p != NUL : p < varname + len; ++p) if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p)) && !(autoload && *p == AUTOLOAD_CHAR)) {
--- a/src/proto/evalvars.pro +++ b/src/proto/evalvars.pro @@ -78,7 +78,7 @@ int var_check_lock(int flags, char_u *na int var_check_fixed(int flags, char_u *name, int use_gettext); int var_wrong_func_name(char_u *name, int new_var); int value_check_lock(int lock, char_u *name, int use_gettext); -int valid_varname(char_u *varname, int autoload); +int valid_varname(char_u *varname, int len, int autoload); void reset_v_option_vars(void); void assert_error(garray_T *gap); int var_exists(char_u *var);
--- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -2865,11 +2865,35 @@ def Test_for_loop_fails() endfor END CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected job but got string', 2) + + lines =<< trim END + var i = 0 + for i in [1, 2, 3] + echo i + endfor + END + CheckDefExecAndScriptFailure2(lines, 'E1017:', 'E1041:') + + lines =<< trim END + var l = [0] + for l[0] in [1, 2, 3] + echo l[0] + endfor + END + CheckDefExecAndScriptFailure2(lines, 'E461:', 'E1017:') + + lines =<< trim END + var d = {x: 0} + for d.x in [1, 2, 3] + echo d.x + endfor + END + CheckDefExecAndScriptFailure2(lines, 'E461:', 'E1017:') enddef def Test_for_loop_script_var() # cannot use s:var in a :def function - CheckDefFailure(['for s:var in range(3)', 'echo 3'], 'E1101:') + CheckDefFailure(['for s:var in range(3)', 'echo 3'], 'E461:') # can use s:var in Vim9 script, with or without s: var lines =<< trim END
--- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3650, +/**/ 3649, /**/ 3648,
--- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -8220,8 +8220,8 @@ compile_for(char_u *arg_start, cctx_T *c for (idx = 0; idx < var_count; ++idx) { assign_dest_T dest = dest_local; - int opt_flags = 0; - int vimvaridx = -1; + int opt_flags = 0; + int vimvaridx = -1; type_T *type = &t_any; type_T *lhs_type = &t_any; where_T where = WHERE_INIT; @@ -8255,6 +8255,8 @@ compile_for(char_u *arg_start, cctx_T *c } else { + if (!valid_varname(arg, varlen, FALSE)) + goto failed; if (lookup_local(arg, varlen, NULL, cctx) == OK) { semsg(_(e_variable_already_declared), arg);