Patch 8.2.4332
Problem: Vim9: incomplete test for existing script variable in block.
Solution: Add a couple more tests. Fix uncovered problem.
Files: src/userfunc.c, src/vim9compile.c, src/proto/vim9compile.pro,
src/vim9script.c, src/vim9expr.c, src/testdir/test_vim9_func.vim
*** ../vim-8.2.4331/src/userfunc.c 2022-02-07 21:53:58.085529486 +0000
--- src/userfunc.c 2022-02-08 20:18:36.215334673 +0000
***************
*** 55,60 ****
--- 55,61 ----
* If "argtypes" is not NULL also get the type: "arg: type" (:def function).
* If "types_optional" is TRUE a missing type is OK, use "any".
* If "evalarg" is not NULL use it to check for an already declared name.
+ * If "eap" is not NULL use it to check for an already declared name.
* Return a pointer to after the type.
* When something is wrong return "arg".
*/
***************
*** 65,70 ****
--- 66,72 ----
garray_T *argtypes,
int types_optional,
evalarg_T *evalarg,
+ exarg_T *eap,
int is_vararg,
int skip)
{
***************
*** 87,93 ****
// Vim9 script: cannot use script var name for argument. In function: also
// check local vars and arguments.
if (!skip && argtypes != NULL && check_defined(arg, p - arg,
! evalarg == NULL ? NULL : evalarg->eval_cctx, TRUE) == FAIL)
return arg;
if (newargs != NULL && ga_grow(newargs, 1) == FAIL)
--- 89,96 ----
// Vim9 script: cannot use script var name for argument. In function: also
// check local vars and arguments.
if (!skip && argtypes != NULL && check_defined(arg, p - arg,
! evalarg == NULL ? NULL : evalarg->eval_cctx,
! eap == NULL ? NULL : eap->cstack, TRUE) == FAIL)
return arg;
if (newargs != NULL && ga_grow(newargs, 1) == FAIL)
***************
*** 210,216 ****
int *varargs,
garray_T *default_args,
int skip,
! exarg_T *eap,
garray_T *lines_to_free)
{
int mustend = FALSE;
--- 213,219 ----
int *varargs,
garray_T *default_args,
int skip,
! exarg_T *eap, // can be NULL
garray_T *lines_to_free)
{
int mustend = FALSE;
***************
*** 279,285 ****
arg = p;
p = one_function_arg(p, newargs, argtypes, types_optional,
! evalarg, TRUE, skip);
if (p == arg)
break;
if (*skipwhite(p) == '=')
--- 282,288 ----
arg = p;
p = one_function_arg(p, newargs, argtypes, types_optional,
! evalarg, eap, TRUE, skip);
if (p == arg)
break;
if (*skipwhite(p) == '=')
***************
*** 295,301 ****
arg = p;
p = one_function_arg(p, newargs, argtypes, types_optional,
! evalarg, FALSE, skip);
if (p == arg)
break;
--- 298,304 ----
arg = p;
p = one_function_arg(p, newargs, argtypes, types_optional,
! evalarg, eap, FALSE, skip);
if (p == arg)
break;
*** ../vim-8.2.4331/src/vim9compile.c 2022-02-07 21:53:58.085529486 +0000
--- src/vim9compile.c 2022-02-08 20:30:32.738346943 +0000
***************
*** 152,162 ****
* Lookup a script-local variable in the current script, possibly defined in a
* block that contains the function "cctx->ctx_ufunc".
* "cctx" is NULL at the script level.
* If "len" is <= 0 "name" must be NUL terminated.
* Return NULL when not found.
*/
static sallvar_T *
! find_script_var(char_u *name, size_t len, cctx_T *cctx)
{
scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
hashitem_T *hi;
--- 152,163 ----
* Lookup a script-local variable in the current script, possibly defined in a
* block that contains the function "cctx->ctx_ufunc".
* "cctx" is NULL at the script level.
+ * "cstack_T" is NULL in a function.
* If "len" is <= 0 "name" must be NUL terminated.
* Return NULL when not found.
*/
static sallvar_T *
! find_script_var(char_u *name, size_t len, cctx_T *cctx, cstack_T *cstack)
{
scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
hashitem_T *hi;
***************
*** 183,193 ****
if (cctx == NULL)
{
! // Not in a function scope, find variable with block id equal to or
! // smaller than the current block id.
while (sav != NULL)
{
! if (sav->sav_block_id <= si->sn_current_block_id)
break;
sav = sav->sav_next;
}
--- 184,205 ----
if (cctx == NULL)
{
! // Not in a function scope, find variable with block ID equal to or
! // smaller than the current block id. If "cstack" is not NULL go up
! // the block scopes (more accurate).
while (sav != NULL)
{
! if (cstack != NULL)
! {
! int idx;
!
! for (idx = cstack->cs_idx; idx >= 0; --idx)
! if (cstack->cs_block_id[idx] == sav->sav_block_id)
! break;
! if (idx >= 0)
! break;
! }
! else if (sav->sav_block_id <= si->sn_current_block_id)
break;
sav = sav->sav_next;
}
***************
*** 225,234 ****
/*
* Lookup a variable (without s: prefix) in the current script.
* "cctx" is NULL at the script level.
* Returns OK or FAIL.
*/
int
! script_var_exists(char_u *name, size_t len, cctx_T *cctx)
{
if (current_sctx.sc_sid <= 0)
return FAIL;
--- 237,247 ----
/*
* Lookup a variable (without s: prefix) in the current script.
* "cctx" is NULL at the script level.
+ * "cstack" is NULL in a function.
* Returns OK or FAIL.
*/
int
! script_var_exists(char_u *name, size_t len, cctx_T *cctx, cstack_T *cstack)
{
if (current_sctx.sc_sid <= 0)
return FAIL;
***************
*** 236,242 ****
{
// Check script variables that were visible where the function was
// defined.
! if (find_script_var(name, len, cctx) != NULL)
return OK;
}
else
--- 249,255 ----
{
// Check script variables that were visible where the function was
// defined.
! if (find_script_var(name, len, cctx, cstack) != NULL)
return OK;
}
else
***************
*** 267,273 ****
return (cctx != NULL
&& (lookup_local(name, len, NULL, cctx) == OK
|| arg_exists(name, len, NULL, NULL, NULL, cctx) == OK))
! || script_var_exists(name, len, cctx) == OK
|| find_imported(name, len, FALSE, cctx) != NULL;
}
--- 280,286 ----
return (cctx != NULL
&& (lookup_local(name, len, NULL, cctx) == OK
|| arg_exists(name, len, NULL, NULL, NULL, cctx) == OK))
! || script_var_exists(name, len, cctx, NULL) == OK
|| find_imported(name, len, FALSE, cctx) != NULL;
}
***************
*** 309,315 ****
* Return FAIL and give an error if it defined.
*/
int
! check_defined(char_u *p, size_t len, cctx_T *cctx, int is_arg)
{
int c = p[len];
ufunc_T *ufunc = NULL;
--- 322,333 ----
* Return FAIL and give an error if it defined.
*/
int
! check_defined(
! char_u *p,
! size_t len,
! cctx_T *cctx,
! cstack_T *cstack,
! int is_arg)
{
int c = p[len];
ufunc_T *ufunc = NULL;
***************
*** 318,324 ****
if (len == 1 && *p == '_')
return OK;
! if (script_var_exists(p, len, cctx) == OK)
{
if (is_arg)
semsg(_(e_argument_already_declared_in_script_str), p);
--- 336,342 ----
if (len == 1 && *p == '_')
return OK;
! if (script_var_exists(p, len, cctx, cstack) == OK)
{
if (is_arg)
semsg(_(e_argument_already_declared_in_script_str), p);
***************
*** 526,532 ****
return -1;
if (sid == current_sctx.sc_sid)
{
! sallvar_T *sav = find_script_var(name, 0, cctx);
if (sav == NULL)
return -2;
--- 544,550 ----
return -1;
if (sid == current_sctx.sc_sid)
{
! sallvar_T *sav = find_script_var(name, 0, cctx, NULL);
if (sav == NULL)
return -2;
***************
*** 884,890 ****
semsg(_(e_namespace_not_supported_str), name_start);
return NULL;
}
! if (check_defined(name_start, name_end - name_start, cctx, FALSE) == FAIL)
return NULL;
if (!ASCII_ISUPPER(is_global ? name_start[2] : name_start[0]))
{
--- 902,909 ----
semsg(_(e_namespace_not_supported_str), name_start);
return NULL;
}
! if (check_defined(name_start, name_end - name_start, cctx,
! NULL, FALSE) == FAIL)
return NULL;
if (!ASCII_ISUPPER(is_global ? name_start[2] : name_start[0]))
{
***************
*** 1356,1364 ****
&& STRNCMP(var_start, "s:", 2) == 0;
int script_var = (script_namespace
? script_var_exists(var_start + 2, lhs->lhs_varlen - 2,
! cctx)
: script_var_exists(var_start, lhs->lhs_varlen,
! cctx)) == OK;
imported_T *import =
find_imported(var_start, lhs->lhs_varlen, FALSE, cctx);
--- 1375,1383 ----
&& STRNCMP(var_start, "s:", 2) == 0;
int script_var = (script_namespace
? script_var_exists(var_start + 2, lhs->lhs_varlen - 2,
! cctx, NULL)
: script_var_exists(var_start, lhs->lhs_varlen,
! cctx, NULL)) == OK;
imported_T *import =
find_imported(var_start, lhs->lhs_varlen, FALSE, cctx);
***************
*** 1442,1449 ****
}
}
}
! else if (check_defined(var_start, lhs->lhs_varlen, cctx, FALSE)
! == FAIL)
return FAIL;
}
}
--- 1461,1468 ----
}
}
}
! else if (check_defined(var_start, lhs->lhs_varlen, cctx,
! NULL, FALSE) == FAIL)
return FAIL;
}
}
***************
*** 2470,2476 ****
for (i = 0; i < ufunc->uf_args.ga_len; ++i)
{
arg = ((char_u **)(ufunc->uf_args.ga_data))[i];
! if (check_defined(arg, STRLEN(arg), cctx, TRUE) == FAIL)
{
r = FAIL;
break;
--- 2489,2495 ----
for (i = 0; i < ufunc->uf_args.ga_len; ++i)
{
arg = ((char_u **)(ufunc->uf_args.ga_data))[i];
! if (check_defined(arg, STRLEN(arg), cctx, NULL, TRUE) == FAIL)
{
r = FAIL;
break;
*** ../vim-8.2.4331/src/proto/vim9compile.pro 2022-02-02 16:20:22.386554561
+0000
--- src/proto/vim9compile.pro 2022-02-08 20:29:00.926470151 +0000
***************
*** 2,9 ****
int lookup_local(char_u *name, size_t len, lvar_T *lvar, cctx_T *cctx);
int arg_exists(char_u *name, size_t len, int *idxp, type_T **type, int
*gen_load_outer, cctx_T *cctx);
int script_is_vim9(void);
! int script_var_exists(char_u *name, size_t len, cctx_T *cctx);
! int check_defined(char_u *p, size_t len, cctx_T *cctx, int is_arg);
int need_type_where(type_T *actual, type_T *expected, int offset, where_T
where, cctx_T *cctx, int silent, int actual_is_const);
int need_type(type_T *actual, type_T *expected, int offset, int arg_idx,
cctx_T *cctx, int silent, int actual_is_const);
lvar_T *reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst,
type_T *type);
--- 2,9 ----
int lookup_local(char_u *name, size_t len, lvar_T *lvar, cctx_T *cctx);
int arg_exists(char_u *name, size_t len, int *idxp, type_T **type, int
*gen_load_outer, cctx_T *cctx);
int script_is_vim9(void);
! int script_var_exists(char_u *name, size_t len, cctx_T *cctx, cstack_T
*cstack);
! int check_defined(char_u *p, size_t len, cctx_T *cctx, cstack_T *cstack, int
is_arg);
int need_type_where(type_T *actual, type_T *expected, int offset, where_T
where, cctx_T *cctx, int silent, int actual_is_const);
int need_type(type_T *actual, type_T *expected, int offset, int arg_idx,
cctx_T *cctx, int silent, int actual_is_const);
lvar_T *reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst,
type_T *type);
*** ../vim-8.2.4331/src/vim9script.c 2022-02-08 19:12:15.260593033 +0000
--- src/vim9script.c 2022-02-08 20:20:55.675136052 +0000
***************
*** 600,606 ****
goto erret;
}
else if (imported == NULL
! && check_defined(as_name, STRLEN(as_name), cctx, FALSE) == FAIL)
goto erret;
if (imported == NULL)
--- 600,607 ----
goto erret;
}
else if (imported == NULL
! && check_defined(as_name, STRLEN(as_name), cctx, NULL,
! FALSE) == FAIL)
goto erret;
if (imported == NULL)
*** ../vim-8.2.4331/src/vim9expr.c 2022-02-06 18:36:46.297746545 +0000
--- src/vim9expr.c 2022-02-08 20:23:39.622907487 +0000
***************
*** 501,507 ****
{
// "var" can be script-local even without using "s:" if it
// already exists in a Vim9 script or when it's imported.
! if (script_var_exists(*arg, len, cctx) == OK
|| find_imported(name, 0, FALSE, cctx) != NULL)
res = compile_load_scriptvar(cctx, name, *arg, &end, FALSE);
--- 501,507 ----
{
// "var" can be script-local even without using "s:" if it
// already exists in a Vim9 script or when it's imported.
! if (script_var_exists(*arg, len, cctx, NULL) == OK
|| find_imported(name, 0, FALSE, cctx) != NULL)
res = compile_load_scriptvar(cctx, name, *arg, &end, FALSE);
*** ../vim-8.2.4331/src/testdir/test_vim9_func.vim 2022-02-08
19:23:31.712319067 +0000
--- src/testdir/test_vim9_func.vim 2022-02-08 20:03:40.448780266 +0000
***************
*** 1057,1062 ****
--- 1057,1099 ----
END
v9.CheckScriptSuccess(lines)
+ # with another variable in another block
+ lines =<< trim END
+ vim9script
+ if true
+ var name = 'piet'
+ # define a function so that the variable isn't cleared
+ def GetItem(): string
+ return item
+ enddef
+ endif
+ if true
+ var name = 'peter'
+ def FuncOne(name: string)
+ echo name
+ enddef
+ endif
+ END
+ v9.CheckScriptFailure(lines, 'E1168:')
+
+ # only variable in another block is OK
+ lines =<< trim END
+ vim9script
+ if true
+ var name = 'piet'
+ # define a function so that the variable isn't cleared
+ def GetItem(): string
+ return item
+ enddef
+ endif
+ if true
+ def FuncOne(name: string)
+ echo name
+ enddef
+ endif
+ END
+ v9.CheckScriptSuccess(lines)
+
# argument name declared later is only found when compiling
lines =<< trim END
vim9script
*** ../vim-8.2.4331/src/version.c 2022-02-08 19:23:31.712319067 +0000
--- src/version.c 2022-02-08 20:00:27.981022674 +0000
***************
*** 748,749 ****
--- 748,751 ----
{ /* Add new patch number below this line */
+ /**/
+ 4332,
/**/
--
How To Keep A Healthy Level Of Insanity:
3. Every time someone asks you to do something, ask if they want fries
with that.
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/20220208203611.137501C1905%40moolenaar.net.