Patch 8.2.2760

6 views
Skip to first unread message

Bram Moolenaar

unread,
Apr 13, 2021, 3:48:49 PM4/13/21
to vim...@googlegroups.com

Patch 8.2.2760
Problem: Vim9: no error for changing a for loop variable.
Solution: Make the loop variable read-only. (issue #8102)
Files: src/eval.c, src/evalvars.c, src/vim9compile.c, src/vim.h,
src/testdir/test_vim9_script.vim


*** ../vim-8.2.2759/src/eval.c 2021-04-12 21:20:58.634708976 +0200
--- src/eval.c 2021-04-13 21:33:38.330057046 +0200
***************
*** 1351,1357 ****
{
typval_T tv;

! if (flags & (ASSIGN_CONST | ASSIGN_FINAL))
{
emsg(_(e_cannot_mod));
*endp = cc;
--- 1351,1358 ----
{
typval_T tv;

! if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
! && (flags & ASSIGN_FOR_LOOP) == 0)
{
emsg(_(e_cannot_mod));
*endp = cc;
***************
*** 1390,1396 ****
listitem_T *ll_li = lp->ll_li;
int ll_n1 = lp->ll_n1;

! if (flags & (ASSIGN_CONST | ASSIGN_FINAL))
{
emsg(_("E996: Cannot lock a range"));
return;
--- 1391,1398 ----
listitem_T *ll_li = lp->ll_li;
int ll_n1 = lp->ll_n1;

! if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
! && (flags & ASSIGN_FOR_LOOP) == 0)
{
emsg(_("E996: Cannot lock a range"));
return;
***************
*** 1449,1455 ****
/*
* Assign to a List or Dictionary item.
*/
! if (flags & (ASSIGN_CONST | ASSIGN_FINAL))
{
emsg(_("E996: Cannot lock a list or dict"));
return;
--- 1451,1458 ----
/*
* Assign to a List or Dictionary item.
*/
! if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
! && (flags & ASSIGN_FOR_LOOP) == 0)
{
emsg(_("E996: Cannot lock a list or dict"));
return;
***************
*** 1775,1781 ****
{
forinfo_T *fi = (forinfo_T *)fi_void;
int result;
! int flag = in_vim9script() ? ASSIGN_DECL : 0;
listitem_T *item;

if (fi->fi_blob != NULL)
--- 1778,1786 ----
{
forinfo_T *fi = (forinfo_T *)fi_void;
int result;
! int flag = ASSIGN_FOR_LOOP | (in_vim9script()
! ? (ASSIGN_FINAL | ASSIGN_DECL | ASSIGN_NO_MEMBER_TYPE)
! : 0);
listitem_T *item;

if (fi->fi_blob != NULL)
*** ../vim-8.2.2759/src/evalvars.c 2021-04-10 22:35:40.487360271 +0200
--- src/evalvars.c 2021-04-13 21:44:23.604852104 +0200
***************
*** 1315,1321 ****
// ":let $VAR = expr": Set environment variable.
if (*arg == '$')
{
! if (flags & (ASSIGN_CONST | ASSIGN_FINAL))
{
emsg(_("E996: Cannot lock an environment variable"));
return NULL;
--- 1315,1322 ----
// ":let $VAR = expr": Set environment variable.
if (*arg == '$')
{
! if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
! && (flags & ASSIGN_FOR_LOOP) == 0)
{
emsg(_("E996: Cannot lock an environment variable"));
return NULL;
***************
*** 1365,1373 ****
// ":let &option = expr": Set option value.
// ":let &l:option = expr": Set local option value.
// ":let &g:option = expr": Set global option value.
else if (*arg == '&')
{
! if (flags & (ASSIGN_CONST | ASSIGN_FINAL))
{
emsg(_(e_const_option));
return NULL;
--- 1366,1376 ----
// ":let &option = expr": Set option value.
// ":let &l:option = expr": Set local option value.
// ":let &g:option = expr": Set global option value.
+ // ":for &ts in range(8)": Set option value for for loop
else if (*arg == '&')
{
! if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
! && (flags & ASSIGN_FOR_LOOP) == 0)
{
emsg(_(e_const_option));
return NULL;
***************
*** 1466,1472 ****
// ":let @r = expr": Set register contents.
else if (*arg == '@')
{
! if (flags & (ASSIGN_CONST | ASSIGN_FINAL))
{
emsg(_("E996: Cannot lock a register"));
return NULL;
--- 1469,1476 ----
// ":let @r = expr": Set register contents.
else if (*arg == '@')
{
! if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
! && (flags & ASSIGN_FOR_LOOP) == 0)
{
emsg(_("E996: Cannot lock a register"));
return NULL;
***************
*** 3158,3164 ****
type_T *type,
typval_T *tv_arg,
int copy, // make copy of value in "tv"
! int flags, // ASSIGN_CONST, ASSIGN_FINAL, etc.
int var_idx) // index for ":let [a, b] = list"
{
typval_T *tv = tv_arg;
--- 3162,3168 ----
type_T *type,
typval_T *tv_arg,
int copy, // make copy of value in "tv"
! int flags_arg, // ASSIGN_CONST, ASSIGN_FINAL, etc.
int var_idx) // index for ":let [a, b] = list"
{
typval_T *tv = tv_arg;
***************
*** 3169,3174 ****
--- 3173,3179 ----
int is_script_local;
int vim9script = in_vim9script();
int var_in_vim9script;
+ int flags = flags_arg;

ht = find_var_ht(name, &varname);
if (ht == NULL || *varname == NUL)
***************
*** 3187,3192 ****
--- 3192,3202 ----
vim9_declare_error(name);
goto failed;
}
+ if ((flags & ASSIGN_FOR_LOOP) && name[1] == ':'
+ && vim_strchr((char_u *)"gwbt", name[0]) != NULL)
+ // Do not make g:var, w:var, b:var or t:var final.
+ flags &= ~ASSIGN_FINAL;
+
var_in_vim9script = is_script_local && current_script_is_vim9();
if (var_in_vim9script && name[0] == '_' && name[1] == NUL)
{
***************
*** 3220,3226 ****
// Item already exists. Allowed to replace when reloading.
if ((di->di_flags & DI_FLAGS_RELOAD) == 0)
{
! if (flags & (ASSIGN_CONST | ASSIGN_FINAL))
{
emsg(_(e_cannot_mod));
goto failed;
--- 3230,3237 ----
// Item already exists. Allowed to replace when reloading.
if ((di->di_flags & DI_FLAGS_RELOAD) == 0)
{
! if ((flags & (ASSIGN_CONST | ASSIGN_FINAL))
! && (flags & ASSIGN_FOR_LOOP) == 0)
{
emsg(_(e_cannot_mod));
goto failed;
***************
*** 3255,3261 ****
// A Vim9 script-local variable is also present in sn_all_vars and
// sn_var_vals. It may set "type" from "tv".
if (var_in_vim9script)
! update_vim9_script_var(FALSE, di, flags, tv, &type);
}

// existing variable, need to clear the value
--- 3266,3273 ----
// A Vim9 script-local variable is also present in sn_all_vars and
// sn_var_vals. It may set "type" from "tv".
if (var_in_vim9script)
! update_vim9_script_var(FALSE, di, flags, tv, &type,
! (flags & ASSIGN_NO_MEMBER_TYPE) == 0);
}

// existing variable, need to clear the value
***************
*** 3353,3359 ****
// A Vim9 script-local variable is also added to sn_all_vars and
// sn_var_vals. It may set "type" from "tv".
if (var_in_vim9script)
! update_vim9_script_var(TRUE, di, flags, tv, &type);
}

if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT)
--- 3365,3372 ----
// A Vim9 script-local variable is also added to sn_all_vars and
// sn_var_vals. It may set "type" from "tv".
if (var_in_vim9script)
! update_vim9_script_var(TRUE, di, flags, tv, &type,
! (flags & ASSIGN_NO_MEMBER_TYPE) == 0);
}

if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT)
*** ../vim-8.2.2759/src/vim9compile.c 2021-04-12 21:20:58.634708976 +0200
--- src/vim9compile.c 2021-04-13 21:17:49.447983964 +0200
***************
*** 7590,7596 ****

// Reserve a variable to store "var".
// TODO: check for type
! var_lvar = reserve_local(cctx, arg, varlen, FALSE, &t_any);
if (var_lvar == NULL)
// out of memory or used as an argument
goto failed;
--- 7590,7596 ----

// Reserve a variable to store "var".
// TODO: check for type
! var_lvar = reserve_local(cctx, arg, varlen, TRUE, &t_any);
if (var_lvar == NULL)
// out of memory or used as an argument
goto failed;
*** ../vim-8.2.2759/src/vim.h 2021-04-13 20:53:09.846201149 +0200
--- src/vim.h 2021-04-13 21:27:01.150065988 +0200
***************
*** 2158,2163 ****
--- 2158,2164 ----
#define ASSIGN_DECL 0x08 // may declare variable if it does not exist
#define ASSIGN_UNPACK 0x10 // using [a, b] = list
#define ASSIGN_NO_MEMBER_TYPE 0x20 // use "any" for list and dict member type
+ #define ASSIGN_FOR_LOOP 0x40 // assigning to loop variable

#include "ex_cmds.h" // Ex command defines
#include "spell.h" // spell checking stuff
*** ../vim-8.2.2759/src/testdir/test_vim9_script.vim 2021-04-13 20:53:09.846201149 +0200
--- src/testdir/test_vim9_script.vim 2021-04-13 21:19:45.107564578 +0200
***************
*** 2393,2398 ****
--- 2393,2406 ----
g:adict = {a: 1}
CheckDefExecFailure(['for i in g:adict', 'echo 3', 'endfor'], 'E1177: For loop on dict not supported')
unlet g:adict
+
+ var lines =<< trim END
+ var d: list<dict<any>> = [{a: 0}]
+ for e in d
+ e = {a: 0, b: ''}
+ endfor
+ END
+ CheckDefAndScriptFailure2(lines, 'E1018:', 'E46:', 3)
enddef

def Test_for_loop_script_var()
*** ../vim-8.2.2759/src/version.c 2021-04-13 20:53:09.846201149 +0200
--- src/version.c 2021-04-13 21:14:18.864756079 +0200
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 2760,
/**/

--
From "know your smileys":
:-| :-| Deja' vu!

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
Reply all
Reply to author
Forward
0 new messages