Mercurial > vim
comparison src/evalvars.c @ 24440:d2f9bdd938fa v8.2.2760
patch 8.2.2760: Vim9: no error for changing a for loop variable
Commit: https://github.com/vim/vim/commit/f6a8d420a8d2924737f713de046947dcb487550c
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Apr 13 21:48:03 2021 +0200
patch 8.2.2760: Vim9: no error for changing a for loop variable
Problem: Vim9: no error for changing a for loop variable.
Solution: Make the loop variable read-only. (issue https://github.com/vim/vim/issues/8102)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 13 Apr 2021 22:00:05 +0200 |
parents | 78343859f42d |
children | f388a033e568 |
comparison
equal
deleted
inserted
replaced
24439:21feee770b96 | 24440:d2f9bdd938fa |
---|---|
1313 } | 1313 } |
1314 | 1314 |
1315 // ":let $VAR = expr": Set environment variable. | 1315 // ":let $VAR = expr": Set environment variable. |
1316 if (*arg == '$') | 1316 if (*arg == '$') |
1317 { | 1317 { |
1318 if (flags & (ASSIGN_CONST | ASSIGN_FINAL)) | 1318 if ((flags & (ASSIGN_CONST | ASSIGN_FINAL)) |
1319 && (flags & ASSIGN_FOR_LOOP) == 0) | |
1319 { | 1320 { |
1320 emsg(_("E996: Cannot lock an environment variable")); | 1321 emsg(_("E996: Cannot lock an environment variable")); |
1321 return NULL; | 1322 return NULL; |
1322 } | 1323 } |
1323 | 1324 |
1363 } | 1364 } |
1364 | 1365 |
1365 // ":let &option = expr": Set option value. | 1366 // ":let &option = expr": Set option value. |
1366 // ":let &l:option = expr": Set local option value. | 1367 // ":let &l:option = expr": Set local option value. |
1367 // ":let &g:option = expr": Set global option value. | 1368 // ":let &g:option = expr": Set global option value. |
1369 // ":for &ts in range(8)": Set option value for for loop | |
1368 else if (*arg == '&') | 1370 else if (*arg == '&') |
1369 { | 1371 { |
1370 if (flags & (ASSIGN_CONST | ASSIGN_FINAL)) | 1372 if ((flags & (ASSIGN_CONST | ASSIGN_FINAL)) |
1373 && (flags & ASSIGN_FOR_LOOP) == 0) | |
1371 { | 1374 { |
1372 emsg(_(e_const_option)); | 1375 emsg(_(e_const_option)); |
1373 return NULL; | 1376 return NULL; |
1374 } | 1377 } |
1375 // Find the end of the name. | 1378 // Find the end of the name. |
1464 } | 1467 } |
1465 | 1468 |
1466 // ":let @r = expr": Set register contents. | 1469 // ":let @r = expr": Set register contents. |
1467 else if (*arg == '@') | 1470 else if (*arg == '@') |
1468 { | 1471 { |
1469 if (flags & (ASSIGN_CONST | ASSIGN_FINAL)) | 1472 if ((flags & (ASSIGN_CONST | ASSIGN_FINAL)) |
1473 && (flags & ASSIGN_FOR_LOOP) == 0) | |
1470 { | 1474 { |
1471 emsg(_("E996: Cannot lock a register")); | 1475 emsg(_("E996: Cannot lock a register")); |
1472 return NULL; | 1476 return NULL; |
1473 } | 1477 } |
1474 ++arg; | 1478 ++arg; |
3156 set_var_const( | 3160 set_var_const( |
3157 char_u *name, | 3161 char_u *name, |
3158 type_T *type, | 3162 type_T *type, |
3159 typval_T *tv_arg, | 3163 typval_T *tv_arg, |
3160 int copy, // make copy of value in "tv" | 3164 int copy, // make copy of value in "tv" |
3161 int flags, // ASSIGN_CONST, ASSIGN_FINAL, etc. | 3165 int flags_arg, // ASSIGN_CONST, ASSIGN_FINAL, etc. |
3162 int var_idx) // index for ":let [a, b] = list" | 3166 int var_idx) // index for ":let [a, b] = list" |
3163 { | 3167 { |
3164 typval_T *tv = tv_arg; | 3168 typval_T *tv = tv_arg; |
3165 typval_T bool_tv; | 3169 typval_T bool_tv; |
3166 dictitem_T *di; | 3170 dictitem_T *di; |
3167 char_u *varname; | 3171 char_u *varname; |
3168 hashtab_T *ht; | 3172 hashtab_T *ht; |
3169 int is_script_local; | 3173 int is_script_local; |
3170 int vim9script = in_vim9script(); | 3174 int vim9script = in_vim9script(); |
3171 int var_in_vim9script; | 3175 int var_in_vim9script; |
3176 int flags = flags_arg; | |
3172 | 3177 |
3173 ht = find_var_ht(name, &varname); | 3178 ht = find_var_ht(name, &varname); |
3174 if (ht == NULL || *varname == NUL) | 3179 if (ht == NULL || *varname == NUL) |
3175 { | 3180 { |
3176 semsg(_(e_illvar), name); | 3181 semsg(_(e_illvar), name); |
3185 && name[1] == ':') | 3190 && name[1] == ':') |
3186 { | 3191 { |
3187 vim9_declare_error(name); | 3192 vim9_declare_error(name); |
3188 goto failed; | 3193 goto failed; |
3189 } | 3194 } |
3195 if ((flags & ASSIGN_FOR_LOOP) && name[1] == ':' | |
3196 && vim_strchr((char_u *)"gwbt", name[0]) != NULL) | |
3197 // Do not make g:var, w:var, b:var or t:var final. | |
3198 flags &= ~ASSIGN_FINAL; | |
3199 | |
3190 var_in_vim9script = is_script_local && current_script_is_vim9(); | 3200 var_in_vim9script = is_script_local && current_script_is_vim9(); |
3191 if (var_in_vim9script && name[0] == '_' && name[1] == NUL) | 3201 if (var_in_vim9script && name[0] == '_' && name[1] == NUL) |
3192 { | 3202 { |
3193 // For "[a, _] = list" the underscore is ignored. | 3203 // For "[a, _] = list" the underscore is ignored. |
3194 if ((flags & ASSIGN_UNPACK) == 0) | 3204 if ((flags & ASSIGN_UNPACK) == 0) |
3218 if (di != NULL) | 3228 if (di != NULL) |
3219 { | 3229 { |
3220 // Item already exists. Allowed to replace when reloading. | 3230 // Item already exists. Allowed to replace when reloading. |
3221 if ((di->di_flags & DI_FLAGS_RELOAD) == 0) | 3231 if ((di->di_flags & DI_FLAGS_RELOAD) == 0) |
3222 { | 3232 { |
3223 if (flags & (ASSIGN_CONST | ASSIGN_FINAL)) | 3233 if ((flags & (ASSIGN_CONST | ASSIGN_FINAL)) |
3234 && (flags & ASSIGN_FOR_LOOP) == 0) | |
3224 { | 3235 { |
3225 emsg(_(e_cannot_mod)); | 3236 emsg(_(e_cannot_mod)); |
3226 goto failed; | 3237 goto failed; |
3227 } | 3238 } |
3228 | 3239 |
3253 di->di_flags &= ~DI_FLAGS_RELOAD; | 3264 di->di_flags &= ~DI_FLAGS_RELOAD; |
3254 | 3265 |
3255 // A Vim9 script-local variable is also present in sn_all_vars and | 3266 // A Vim9 script-local variable is also present in sn_all_vars and |
3256 // sn_var_vals. It may set "type" from "tv". | 3267 // sn_var_vals. It may set "type" from "tv". |
3257 if (var_in_vim9script) | 3268 if (var_in_vim9script) |
3258 update_vim9_script_var(FALSE, di, flags, tv, &type); | 3269 update_vim9_script_var(FALSE, di, flags, tv, &type, |
3270 (flags & ASSIGN_NO_MEMBER_TYPE) == 0); | |
3259 } | 3271 } |
3260 | 3272 |
3261 // existing variable, need to clear the value | 3273 // existing variable, need to clear the value |
3262 | 3274 |
3263 // Handle setting internal di: variables separately where needed to | 3275 // Handle setting internal di: variables separately where needed to |
3351 di->di_flags |= DI_FLAGS_LOCK; | 3363 di->di_flags |= DI_FLAGS_LOCK; |
3352 | 3364 |
3353 // A Vim9 script-local variable is also added to sn_all_vars and | 3365 // A Vim9 script-local variable is also added to sn_all_vars and |
3354 // sn_var_vals. It may set "type" from "tv". | 3366 // sn_var_vals. It may set "type" from "tv". |
3355 if (var_in_vim9script) | 3367 if (var_in_vim9script) |
3356 update_vim9_script_var(TRUE, di, flags, tv, &type); | 3368 update_vim9_script_var(TRUE, di, flags, tv, &type, |
3369 (flags & ASSIGN_NO_MEMBER_TYPE) == 0); | |
3357 } | 3370 } |
3358 | 3371 |
3359 if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT) | 3372 if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT) |
3360 copy_tv(tv, &di->di_tv); | 3373 copy_tv(tv, &di->di_tv); |
3361 else | 3374 else |