Patch 8.1.1539
Problem: Not easy to define a variable and lock it.
Solution: Add ":const".
Files: runtime/doc/eval.txt, src/eval.c, src/ex_cmdidxs.h, src/ex_cmds.h,
src/proto/
eval.pro, src/testdir/Make_all.mak,
src/testdir/test_const.vim
*** ../vim-8.1.1538/runtime/doc/eval.txt 2019-06-14 14:39:44.553975948 +0200
--- runtime/doc/eval.txt 2019-06-15 15:28:41.781334766 +0200
***************
*** 11596,11603 ****
No error message is given for a non-existing
variable, also without !.
If the system does not support deleting an environment
! variable, it is made emtpy.
:lockv[ar][!] [depth] {name} ... *:lockvar* *:lockv*
Lock the internal variable {name}. Locking means that
it can no longer be changed (until it is unlocked).
--- 11596,11626 ----
No error message is given for a non-existing
variable, also without !.
If the system does not support deleting an environment
! variable, it is made empty.
+ *:cons* *:const* *E996*
+ :cons[t] {var-name} = {expr1}
+ :cons[t] [{name1}, {name2}, ...] = {expr1}
+ :cons[t] [{name1}, {name2}, ...] .= {expr1}
+ :cons[t] [{name}, ..., ; {lastname}] = {expr1}
+ :cons[t] {var-name} =<< [trim] {marker}
+ text...
+ text...
+ {marker}
+ Similar to |:let|, but additionally lock the variable
+ after setting the value. This is the same as locking
+ the variable with |:lockvar| just after |:let|, thus: >
+ :const x = 1
+ < is equivalent to: >
+ :let x = 1
+ :lockvar 1 x
+ < This is useful if you want to make sure the variable
+ is not modified.
+ *E995*
+ |:const| does not allow to for changing a variable. >
+ :let x = 1
+ :const x = 2 " Error!
+ <
:lockv[ar][!] [depth] {name} ... *:lockvar* *:lockv*
Lock the internal variable {name}. Locking means that
it can no longer be changed (until it is unlocked).
*** ../vim-8.1.1538/src/eval.c 2019-06-14 14:39:44.553975948 +0200
--- src/eval.c 2019-06-15 15:42:11.467153821 +0200
***************
*** 28,33 ****
--- 28,34 ----
static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary");
static char *e_letwrong = N_("E734: Wrong variable type for %s=");
static char *e_illvar = N_("E461: Illegal variable name: %s");
+ static char *e_cannot_mod = N_("E995: Cannot modify existing variable");
#ifdef FEAT_FLOAT
static char *e_float_as_string = N_("E806: using Float as a String");
#endif
***************
*** 212,218 ****
static dictitem_T vimvars_var; /* variable used for v: */
#define vimvarht vimvardict.dv_hashtab
! static int ex_let_vars(char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, char_u *nextchars);
static char_u *skip_var_list(char_u *arg, int *var_count, int *semicolon);
static char_u *skip_var_one(char_u *arg);
static void list_glob_vars(int *first);
--- 213,220 ----
static dictitem_T vimvars_var; /* variable used for v: */
#define vimvarht vimvardict.dv_hashtab
! static void ex_let_const(exarg_T *eap, int is_const);
! static int ex_let_vars(char_u *arg, typval_T *tv, int copy, int semicolon, int var_count, int is_const, char_u *nextchars);
static char_u *skip_var_list(char_u *arg, int *var_count, int *semicolon);
static char_u *skip_var_one(char_u *arg);
static void list_glob_vars(int *first);
***************
*** 222,229 ****
static void list_vim_vars(int *first);
static void list_script_vars(int *first);
static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first);
! static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, char_u *endchars, char_u *op);
! static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op);
static int tv_op(typval_T *tv1, typval_T *tv2, char_u *op);
static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep);
static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit);
--- 224,231 ----
static void list_vim_vars(int *first);
static void list_script_vars(int *first);
static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first);
! static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, int is_const, char_u *endchars, char_u *op);
! static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, int is_const, char_u *op);
static int tv_op(typval_T *tv1, typval_T *tv2, char_u *op);
static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep);
static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit);
***************
*** 248,253 ****
--- 250,256 ----
static void delete_var(hashtab_T *ht, hashitem_T *hi);
static void list_one_var(dictitem_T *v, char *prefix, int *first);
static void list_one_var_a(char *prefix, char_u *name, int type, char_u *string, int *first);
+ static void set_var_const(char_u *name, typval_T *tv, int copy, int is_const);
static int tv_check_lock(typval_T *tv, char_u *name, int use_gettext);
static char_u *find_option_end(char_u **arg, int *opt_flags);
***************
*** 526,534 ****
tv.v_type = VAR_STRING;
tv.vval.v_string = (char_u *)"";
if (append)
! set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)".");
else
! set_var_lval(redir_lval, redir_endp, &tv, TRUE, (char_u *)"=");
clear_lval(redir_lval);
err = did_emsg;
did_emsg |= save_emsg;
--- 529,537 ----
tv.v_type = VAR_STRING;
tv.vval.v_string = (char_u *)"";
if (append)
! set_var_lval(redir_lval, redir_endp, &tv, TRUE, FALSE, (char_u *)".");
else
! set_var_lval(redir_lval, redir_endp, &tv, TRUE, FALSE, (char_u *)"=");
clear_lval(redir_lval);
err = did_emsg;
did_emsg |= save_emsg;
***************
*** 601,607 ****
redir_endp = get_lval(redir_varname, NULL, redir_lval,
FALSE, FALSE, 0, FNE_CHECK_START);
if (redir_endp != NULL && redir_lval->ll_name != NULL)
! set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)".");
clear_lval(redir_lval);
}
--- 604,611 ----
redir_endp = get_lval(redir_varname, NULL, redir_lval,
FALSE, FALSE, 0, FNE_CHECK_START);
if (redir_endp != NULL && redir_lval->ll_name != NULL)
! set_var_lval(redir_lval, redir_endp, &tv, FALSE, FALSE,
! (char_u *)".");
clear_lval(redir_lval);
}
***************
*** 1338,1343 ****
--- 1342,1365 ----
void
ex_let(exarg_T *eap)
{
+ ex_let_const(eap, FALSE);
+ }
+
+ /*
+ * ":const" list all variable values
+ * ":const var1 var2" list variable values
+ * ":const var = expr" assignment command.
+ * ":const [var1, var2] = expr" unpack list.
+ */
+ void
+ ex_const(exarg_T *eap)
+ {
+ ex_let_const(eap, TRUE);
+ }
+
+ static void
+ ex_let_const(exarg_T *eap, int is_const)
+ {
char_u *arg = eap->arg;
char_u *expr = NULL;
typval_T rettv;
***************
*** 1396,1402 ****
op[0] = '=';
op[1] = NUL;
(void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
! op);
clear_tv(&rettv);
}
}
--- 1418,1424 ----
op[0] = '=';
op[1] = NUL;
(void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
! is_const, op);
clear_tv(&rettv);
}
}
***************
*** 1429,1435 ****
else if (i != FAIL)
{
(void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
! op);
clear_tv(&rettv);
}
}
--- 1451,1457 ----
else if (i != FAIL)
{
(void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
! is_const, op);
clear_tv(&rettv);
}
}
***************
*** 1447,1455 ****
ex_let_vars(
char_u *arg_start,
typval_T *tv,
! int copy, /* copy values from "tv", don't move */
! int semicolon, /* from skip_var_list() */
! int var_count, /* from skip_var_list() */
char_u *nextchars)
{
char_u *arg = arg_start;
--- 1469,1478 ----
ex_let_vars(
char_u *arg_start,
typval_T *tv,
! int copy, // copy values from "tv", don't move
! int semicolon, // from skip_var_list()
! int var_count, // from skip_var_list()
! int is_const, // lock variables for const
char_u *nextchars)
{
char_u *arg = arg_start;
***************
*** 1463,1469 ****
/*
* ":let var = expr" or ":for var in list"
*/
! if (ex_let_one(arg, tv, copy, nextchars, nextchars) == NULL)
return FAIL;
return OK;
}
--- 1486,1492 ----
/*
* ":let var = expr" or ":for var in list"
*/
! if (ex_let_one(arg, tv, copy, is_const, nextchars, nextchars) == NULL)
return FAIL;
return OK;
}
***************
*** 1493,1499 ****
while (*arg != ']')
{
arg = skipwhite(arg + 1);
! arg = ex_let_one(arg, &item->li_tv, TRUE, (char_u *)",;]", nextchars);
item = item->li_next;
if (arg == NULL)
return FAIL;
--- 1516,1523 ----
while (*arg != ']')
{
arg = skipwhite(arg + 1);
! arg = ex_let_one(arg, &item->li_tv, TRUE, is_const,
! (char_u *)",;]", nextchars);
item = item->li_next;
if (arg == NULL)
return FAIL;
***************
*** 1517,1524 ****
ltv.vval.v_list = l;
l->lv_refcount = 1;
! arg = ex_let_one(skipwhite(arg + 1), <v, FALSE,
! (char_u *)"]", nextchars);
clear_tv(<v);
if (arg == NULL)
return FAIL;
--- 1541,1548 ----
ltv.vval.v_list = l;
l->lv_refcount = 1;
! arg = ex_let_one(skipwhite(arg + 1), <v, FALSE, is_const,
! (char_u *)"]", nextchars);
clear_tv(<v);
if (arg == NULL)
return FAIL;
***************
*** 1805,1815 ****
*/
static char_u *
ex_let_one(
! char_u *arg, /* points to variable name */
! typval_T *tv, /* value to assign to variable */
! int copy, /* copy value from "tv" */
! char_u *endchars, /* valid chars after variable name or NULL */
! char_u *op) /* "+", "-", "." or NULL*/
{
int c1;
char_u *name;
--- 1829,1840 ----
*/
static char_u *
ex_let_one(
! char_u *arg, // points to variable name
! typval_T *tv, // value to assign to variable
! int copy, // copy value from "tv"
! int is_const, // lock variable for const
! char_u *endchars, // valid chars after variable name or NULL
! char_u *op) // "+", "-", "." or NULL
{
int c1;
char_u *name;
***************
*** 1824,1829 ****
--- 1849,1859 ----
*/
if (*arg == '$')
{
+ if (is_const)
+ {
+ emsg(_("E996: Cannot lock an environment variable"));
+ return NULL;
+ }
/* Find the end of the name. */
++arg;
name = arg;
***************
*** 1879,1884 ****
--- 1909,1919 ----
*/
else if (*arg == '&')
{
+ if (is_const)
+ {
+ emsg(_("E996: Cannot lock an option"));
+ return NULL;
+ }
/* Find the end of the name. */
p = find_option_end(&arg, &opt_flags);
if (p == NULL || (endchars != NULL
***************
*** 1943,1948 ****
--- 1978,1988 ----
*/
else if (*arg == '@')
{
+ if (is_const)
+ {
+ emsg(_("E996: Cannot lock a register"));
+ return NULL;
+ }
++arg;
if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL)
semsg(_(e_letwrong), op);
***************
*** 1988,1994 ****
emsg(_(e_letunexp));
else
{
! set_var_lval(&lv, p, tv, copy, op);
arg_end = p;
}
}
--- 2028,2034 ----
emsg(_(e_letunexp));
else
{
! set_var_lval(&lv, p, tv, copy, is_const, op);
arg_end = p;
}
}
***************
*** 2430,2435 ****
--- 2470,2476 ----
char_u *endp,
typval_T *rettv,
int copy,
+ int is_const, // Disallow to modify existing variable for :const
char_u *op)
{
int cc;
***************
*** 2495,2500 ****
--- 2536,2548 ----
{
typval_T tv;
+ if (is_const)
+ {
+ emsg(_(e_cannot_mod));
+ *endp = cc;
+ return;
+ }
+
// handle +=, -=, *=, /=, %= and .=
di = NULL;
if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
***************
*** 2509,2515 ****
}
}
else
! set_var(lp->ll_name, rettv, copy);
*endp = cc;
}
else if (var_check_lock(lp->ll_newkey == NULL
--- 2557,2563 ----
}
}
else
! set_var_const(lp->ll_name, rettv, copy, is_const);
*endp = cc;
}
else if (var_check_lock(lp->ll_newkey == NULL
***************
*** 2521,2526 ****
--- 2569,2580 ----
listitem_T *ll_li = lp->ll_li;
int ll_n1 = lp->ll_n1;
+ if (is_const)
+ {
+ emsg(_("E996: Cannot lock a range"));
+ return;
+ }
+
/*
* Check whether any of the list items is locked
*/
***************
*** 2574,2579 ****
--- 2628,2638 ----
/*
* Assign to a List or Dictionary item.
*/
+ if (is_const)
+ {
+ emsg(_("E996: Cannot lock a list or dict"));
+ return;
+ }
if (lp->ll_newkey != NULL)
{
if (op != NULL && *op != '=')
***************
*** 2860,2867 ****
tv.v_lock = VAR_FIXED;
tv.vval.v_number = blob_get(fi->fi_blob, fi->fi_bi);
++fi->fi_bi;
! return ex_let_vars(arg, &tv, TRUE,
! fi->fi_semicolon, fi->fi_varcount, NULL) == OK;
}
item = fi->fi_lw.lw_item;
--- 2919,2926 ----
tv.v_lock = VAR_FIXED;
tv.vval.v_number = blob_get(fi->fi_blob, fi->fi_bi);
++fi->fi_bi;
! return ex_let_vars(arg, &tv, TRUE, fi->fi_semicolon,
! fi->fi_varcount, FALSE, NULL) == OK;
}
item = fi->fi_lw.lw_item;
***************
*** 2870,2877 ****
else
{
fi->fi_lw.lw_item = item->li_next;
! result = (ex_let_vars(arg, &item->li_tv, TRUE,
! fi->fi_semicolon, fi->fi_varcount, NULL) == OK);
}
return result;
}
--- 2929,2936 ----
else
{
fi->fi_lw.lw_item = item->li_next;
! result = (ex_let_vars(arg, &item->li_tv, TRUE, fi->fi_semicolon,
! fi->fi_varcount, FALSE, NULL) == OK);
}
return result;
}
***************
*** 8051,8057 ****
set_var(
char_u *name,
typval_T *tv,
! int copy) /* make copy of value in "tv" */
{
dictitem_T *v;
char_u *varname;
--- 8110,8131 ----
set_var(
char_u *name,
typval_T *tv,
! int copy) // make copy of value in "tv"
! {
! set_var_const(name, tv, copy, FALSE);
! }
!
! /*
! * Set variable "name" to value in "tv".
! * If the variable already exists and "is_const" is FALSE the value is updated.
! * Otherwise the variable is created.
! */
! static void
! set_var_const(
! char_u *name,
! typval_T *tv,
! int copy, // make copy of value in "tv"
! int is_const) // disallow to modify existing variable
{
dictitem_T *v;
char_u *varname;
***************
*** 8075,8080 ****
--- 8149,8160 ----
if (v != NULL)
{
+ if (is_const)
+ {
+ emsg(_(e_cannot_mod));
+ return;
+ }
+
/* existing variable, need to clear the value */
if (var_check_ro(v->di_flags, name, FALSE)
|| var_check_lock(v->di_tv.v_lock, name, FALSE))
***************
*** 8152,8157 ****
--- 8232,8239 ----
return;
}
v->di_flags = DI_FLAGS_ALLOC;
+ if (is_const)
+ v->di_flags |= DI_FLAGS_LOCK;
}
if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT)
***************
*** 8162,8167 ****
--- 8244,8252 ----
v->di_tv.v_lock = 0;
init_tv(tv);
}
+
+ if (is_const)
+ v->di_tv.v_lock |= VAR_LOCKED;
}
/*
*** ../vim-8.1.1538/src/ex_cmdidxs.h 2019-06-10 13:10:45.370588270 +0200
--- src/ex_cmdidxs.h 2019-06-15 14:46:27.993733724 +0200
***************
*** 8,36 ****
/* a */ 0,
/* b */ 19,
/* c */ 42,
! /* d */ 107,
! /* e */ 129,
! /* f */ 149,
! /* g */ 165,
! /* h */ 171,
! /* i */ 180,
! /* j */ 198,
! /* k */ 200,
! /* l */ 205,
! /* m */ 267,
! /* n */ 285,
! /* o */ 305,
! /* p */ 317,
! /* q */ 356,
! /* r */ 359,
! /* s */ 379,
! /* t */ 447,
! /* u */ 492,
! /* v */ 503,
! /* w */ 521,
! /* x */ 535,
! /* y */ 545,
! /* z */ 546
};
/*
--- 8,36 ----
/* a */ 0,
/* b */ 19,
/* c */ 42,
! /* d */ 108,
! /* e */ 130,
! /* f */ 150,
! /* g */ 166,
! /* h */ 172,
! /* i */ 181,
! /* j */ 199,
! /* k */ 201,
! /* l */ 206,
! /* m */ 268,
! /* n */ 286,
! /* o */ 306,
! /* p */ 318,
! /* q */ 357,
! /* r */ 360,
! /* s */ 380,
! /* t */ 448,
! /* u */ 493,
! /* v */ 504,
! /* w */ 522,
! /* x */ 536,
! /* y */ 546,
! /* z */ 547
};
/*
***************
*** 43,49 ****
{ /* a b c d e f g h i j k l m n o p q r s t u v w x y z */
/* a */ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 0, 0, 0, 7, 15, 0, 16, 0, 0, 0, 0, 0 },
/* b */ { 2, 0, 0, 4, 5, 7, 0, 0, 0, 0, 0, 8, 9, 10, 11, 12, 0, 13, 0, 0, 0, 0, 22, 0, 0, 0 },
! /* c */ { 3, 12, 16, 18, 20, 22, 25, 0, 0, 0, 0, 33, 37, 40, 46, 55, 57, 58, 59, 0, 61, 0, 64, 0, 0, 0 },
/* d */ { 0, 0, 0, 0, 0, 0, 0, 0, 6, 15, 0, 16, 0, 0, 17, 0, 0, 19, 20, 0, 0, 0, 0, 0, 0, 0 },
/* e */ { 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0 },
/* f */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0 },
--- 43,49 ----
{ /* a b c d e f g h i j k l m n o p q r s t u v w x y z */
/* a */ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 6, 0, 0, 0, 7, 15, 0, 16, 0, 0, 0, 0, 0 },
/* b */ { 2, 0, 0, 4, 5, 7, 0, 0, 0, 0, 0, 8, 9, 10, 11, 12, 0, 13, 0, 0, 0, 0, 22, 0, 0, 0 },
! /* c */ { 3, 12, 16, 18, 20, 22, 25, 0, 0, 0, 0, 33, 37, 40, 46, 56, 58, 59, 60, 0, 62, 0, 65, 0, 0, 0 },
/* d */ { 0, 0, 0, 0, 0, 0, 0, 0, 6, 15, 0, 16, 0, 0, 17, 0, 0, 19, 20, 0, 0, 0, 0, 0, 0, 0 },
/* e */ { 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0 },
/* f */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0 },
***************
*** 69,72 ****
/* z */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
! static const int command_count = 559;
--- 69,72 ----
/* z */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
! static const int command_count = 560;
*** ../vim-8.1.1538/src/ex_cmds.h 2019-06-10 13:10:45.370588270 +0200
--- src/ex_cmds.h 2019-06-15 14:46:27.993733724 +0200
***************
*** 401,406 ****
--- 401,409 ----
EX(CMD_confirm, "confirm", ex_wrongmodifier,
NEEDARG|EXTRA|NOTRLCOM|CMDWIN,
ADDR_NONE),
+ EX(CMD_const, "const", ex_const,
+ EXTRA|NOTRLCOM|SBOXOK|CMDWIN,
+ ADDR_NONE),
EX(CMD_copen, "copen", ex_copen,
RANGE|COUNT|TRLBAR,
ADDR_OTHER),
*** ../vim-8.1.1538/src/proto/
eval.pro 2019-04-27 20:36:52.534303564 +0200
--- src/proto/
eval.pro 2019-06-15 15:42:33.471067677 +0200
***************
*** 28,33 ****
--- 28,34 ----
void *call_func_retlist(char_u *func, int argc, typval_T *argv);
int eval_foldexpr(char_u *arg, int *cp);
void ex_let(exarg_T *eap);
+ void ex_const(exarg_T *eap);
void list_hashtable_vars(hashtab_T *ht, char *prefix, int empty, int *first);
char_u *get_lval(char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int flags, int fne_flags);
void clear_lval(lval_T *lp);
*** ../vim-8.1.1538/src/testdir/Make_all.mak 2019-06-09 13:42:36.428522167 +0200
--- src/testdir/Make_all.mak 2019-06-15 14:46:27.993733724 +0200
***************
*** 87,92 ****
--- 87,93 ----
test_comparators \
test_compiler \
test_conceal \
+ test_const \
test_crypt \
test_cscope \
test_cursor_func \
***************
*** 312,317 ****
--- 313,319 ----
test_command_count.res \
test_comparators.res \
test_conceal.res \
+ test_const.res \
test_crypt.res \
test_cscope.res \
test_curswant.res \
*** ../vim-8.1.1538/src/testdir/test_const.vim 2019-06-15 15:35:38.776519171 +0200
--- src/testdir/test_const.vim 2019-06-15 15:28:09.557352213 +0200
***************
*** 0 ****
--- 1,228 ----
+ " Test for :const
+
+ func s:noop()
+ endfunc
+
+ func Test_define_var_with_lock()
+ const i = 1
+ const f = 1.1
+ const s = 'vim'
+ const F = funcref('s:noop')
+ const l = [1, 2, 3]
+ const d = {'foo': 10}
+ if has('channel')
+ const j = test_null_job()
+ const c = test_null_channel()
+ endif
+ const b = v:true
+ const n = v:null
+ const bl = 0zC0FFEE
+ const here =<< trim EOS
+ hello
+ EOS
+
+ call assert_fails('let i = 1', 'E741:')
+ call assert_fails('let f = 1.1', 'E741:')
+ call assert_fails('let s = "vim"', 'E741:')
+ call assert_fails('let F = funcref("s:noop")', 'E741:')
+ call assert_fails('let l = [1, 2, 3]', 'E741:')
+ call assert_fails('let d = {"foo": 10}', 'E741:')
+ if has('channel')
+ call assert_fails('let j = test_null_job()', 'E741:')
+ call assert_fails('let c = test_null_channel()', 'E741:')
+ endif
+ call assert_fails('let b = v:true', 'E741:')
+ call assert_fails('let n = v:null', 'E741:')
+ call assert_fails('let bl = 0zC0FFEE', 'E741:')
+ call assert_fails('let here = "xxx"', 'E741:')
+
+ " Unlet
+ unlet i
+ unlet f
+ unlet s
+ unlet F
+ unlet l
+ unlet d
+ unlet j
+ unlet c
+ unlet b
+ unlet n
+ unlet bl
+ unlet here
+ endfunc
+
+ func Test_define_l_var_with_lock()
+ " With l: prefix
+ const l:i = 1
+ const l:f = 1.1
+ const l:s = 'vim'
+ const l:F = funcref('s:noop')
+ const l:l = [1, 2, 3]
+ const l:d = {'foo': 10}
+ if has('channel')
+ const l:j = test_null_job()
+ const l:c = test_null_channel()
+ endif
+ const l:b = v:true
+ const l:n = v:null
+ const l:bl = 0zC0FFEE
+ const l:here =<< trim EOS
+ hello
+ EOS
+
+ call assert_fails('let l:i = 1', 'E741:')
+ call assert_fails('let l:f = 1.1', 'E741:')
+ call assert_fails('let l:s = "vim"', 'E741:')
+ call assert_fails('let l:F = funcref("s:noop")', 'E741:')
+ call assert_fails('let l:l = [1, 2, 3]', 'E741:')
+ call assert_fails('let l:d = {"foo": 10}', 'E741:')
+ if has('channel')
+ call assert_fails('let l:j = test_null_job()', 'E741:')
+ call assert_fails('let l:c = test_null_channel()', 'E741:')
+ endif
+ call assert_fails('let l:b = v:true', 'E741:')
+ call assert_fails('let l:n = v:null', 'E741:')
+ call assert_fails('let l:bl = 0zC0FFEE', 'E741:')
+ call assert_fails('let l:here = "xxx"', 'E741:')
+
+ " Unlet
+ unlet l:i
+ unlet l:f
+ unlet l:s
+ unlet l:F
+ unlet l:l
+ unlet l:d
+ unlet l:j
+ unlet l:c
+ unlet l:b
+ unlet l:n
+ unlet l:bl
+ unlet l:here
+ endfunc
+
+ func Test_define_script_var_with_lock()
+ const s:x = 0
+ call assert_fails('let s:x = 1', 'E741:')
+ unlet s:x
+ endfunc
+
+ func Test_descructuring_with_lock()
+ const [a, b, c] = [1, 1.1, 'vim']
+
+ call assert_fails('let a = 1', 'E741:')
+ call assert_fails('let b = 1.1', 'E741:')
+ call assert_fails('let c = "vim"', 'E741:')
+
+ const [d; e] = [1, 1.1, 'vim']
+ call assert_fails('let d = 1', 'E741:')
+ call assert_fails('let e = [2.2, "a"]', 'E741:')
+ endfunc
+
+ func Test_cannot_modify_existing_variable()
+ let i = 1
+ let f = 1.1
+ let s = 'vim'
+ let F = funcref('s:noop')
+ let l = [1, 2, 3]
+ let d = {'foo': 10}
+ if has('channel')
+ let j = test_null_job()
+ let c = test_null_channel()
+ endif
+ let b = v:true
+ let n = v:null
+ let bl = 0zC0FFEE
+
+ call assert_fails('const i = 1', 'E995:')
+ call assert_fails('const f = 1.1', 'E995:')
+ call assert_fails('const s = "vim"', 'E995:')
+ call assert_fails('const F = funcref("s:noop")', 'E995:')
+ call assert_fails('const l = [1, 2, 3]', 'E995:')
+ call assert_fails('const d = {"foo": 10}', 'E995:')
+ if has('channel')
+ call assert_fails('const j = test_null_job()', 'E995:')
+ call assert_fails('const c = test_null_channel()', 'E995:')
+ endif
+ call assert_fails('const b = v:true', 'E995:')
+ call assert_fails('const n = v:null', 'E995:')
+ call assert_fails('const bl = 0zC0FFEE', 'E995:')
+ call assert_fails('const [i, f, s] = [1, 1.1, "vim"]', 'E995:')
+
+ const i2 = 1
+ const f2 = 1.1
+ const s2 = 'vim'
+ const F2 = funcref('s:noop')
+ const l2 = [1, 2, 3]
+ const d2 = {'foo': 10}
+ if has('channel')
+ const j2 = test_null_job()
+ const c2 = test_null_channel()
+ endif
+ const b2 = v:true
+ const n2 = v:null
+ const bl2 = 0zC0FFEE
+
+ call assert_fails('const i2 = 1', 'E995:')
+ call assert_fails('const f2 = 1.1', 'E995:')
+ call assert_fails('const s2 = "vim"', 'E995:')
+ call assert_fails('const F2 = funcref("s:noop")', 'E995:')
+ call assert_fails('const l2 = [1, 2, 3]', 'E995:')
+ call assert_fails('const d2 = {"foo": 10}', 'E995:')
+ if has('channel')
+ call assert_fails('const j2 = test_null_job()', 'E995:')
+ call assert_fails('const c2 = test_null_channel()', 'E995:')
+ endif
+ call assert_fails('const b2 = v:true', 'E995:')
+ call assert_fails('const n2 = v:null', 'E995:')
+ call assert_fails('const bl2 = 0zC0FFEE', 'E995:')
+ call assert_fails('const [i2, f2, s2] = [1, 1.1, "vim"]', 'E995:')
+ endfunc
+
+ func Test_const_with_index_access()
+ let l = [1, 2, 3]
+ call assert_fails('const l[0] = 4', 'E996:')
+ call assert_fails('const l[0:1] = [1, 2]', 'E996:')
+
+ let d = {'aaa': 0}
+ call assert_fails("const d['aaa'] = 4", 'E996:')
+ call assert_fails("const d.aaa = 4", 'E996:')
+ endfunc
+
+ func Test_const_with_compound_assign()
+ let i = 0
+ call assert_fails('const i += 4', 'E995:')
+ call assert_fails('const i -= 4', 'E995:')
+ call assert_fails('const i *= 4', 'E995:')
+ call assert_fails('const i /= 4', 'E995:')
+ call assert_fails('const i %= 4', 'E995:')
+
+ let s = 'a'
+ call assert_fails('const s .= "b"', 'E995:')
+
+ let [a, b, c] = [1, 2, 3]
+ call assert_fails('const [a, b, c] += [4, 5, 6]', 'E995:')
+
+ let [d; e] = [1, 2, 3]
+ call assert_fails('const [d; e] += [4, 5, 6]', 'E995:')
+ endfunc
+
+ func Test_const_with_special_variables()
+ call assert_fails('const $FOO = "hello"', 'E996:')
+ call assert_fails('const @a = "hello"', 'E996:')
+ call assert_fails('const &filetype = "vim"', 'E996:')
+ call assert_fails('const &l:filetype = "vim"', 'E996:')
+ call assert_fails('const &g:encoding = "utf-8"', 'E996:')
+ endfunc
+
+ func Test_lock_depth_is_1()
+ const l = [1, 2, 3]
+ const d = {'foo': 10}
+
+ " Modify list
+ call add(l, 4)
+ let l[0] = 42
+
+ " Modify dict
+ let d['bar'] = 'hello'
+ let d.foo = 44
+ endfunc
*** ../vim-8.1.1538/src/version.c 2019-06-15 14:31:33.774185476 +0200
--- src/version.c 2019-06-15 15:35:00.596628638 +0200
***************
*** 779,780 ****
--- 779,782 ----
{ /* Add new patch number below this line */
+ /**/
+ 1539,
/**/
--
A bad peace is better than a good war. - Yiddish Proverb
/// Bram Moolenaar -- Br...@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 ///