mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.2.2162: Vim9: Cannot load or store autoload variables
Problem: Vim9: Cannot load or store autoload variables. Solution: Add ISN_LOADAUTO and ISN_STOREAUTO. (closes #7485)
This commit is contained in:
@@ -1073,7 +1073,7 @@ dict_extend(dict_T *d1, dict_T *d2, char_u *action)
|
|||||||
&& HI2DI(hi2)->di_tv.v_type == VAR_FUNC
|
&& HI2DI(hi2)->di_tv.v_type == VAR_FUNC
|
||||||
&& var_wrong_func_name(hi2->hi_key, di1 == NULL))
|
&& var_wrong_func_name(hi2->hi_key, di1 == NULL))
|
||||||
break;
|
break;
|
||||||
if (!valid_varname(hi2->hi_key))
|
if (!valid_varname(hi2->hi_key, TRUE))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (di1 == NULL)
|
if (di1 == NULL)
|
||||||
|
@@ -1049,7 +1049,7 @@ get_lval(
|
|||||||
wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE
|
wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE
|
||||||
&& rettv->v_type == VAR_FUNC
|
&& rettv->v_type == VAR_FUNC
|
||||||
&& var_wrong_func_name(key, lp->ll_di == NULL))
|
&& var_wrong_func_name(key, lp->ll_di == NULL))
|
||||||
|| !valid_varname(key);
|
|| !valid_varname(key, TRUE);
|
||||||
if (len != -1)
|
if (len != -1)
|
||||||
key[len] = prevval;
|
key[len] = prevval;
|
||||||
if (wrong)
|
if (wrong)
|
||||||
|
@@ -3195,8 +3195,10 @@ set_var_const(
|
|||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the variable name is valid.
|
// Make sure the variable name is valid. In Vim9 script an autoload
|
||||||
if (!valid_varname(varname))
|
// variable must be prefixed with "g:".
|
||||||
|
if (!valid_varname(varname, !vim9script
|
||||||
|
|| STRNCMP(name, "g:", 2) == 0))
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
||||||
di = alloc(sizeof(dictitem_T) + STRLEN(varname));
|
di = alloc(sizeof(dictitem_T) + STRLEN(varname));
|
||||||
@@ -3349,17 +3351,17 @@ value_check_lock(int lock, char_u *name, int use_gettext)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if a variable name is valid.
|
* Check if a variable name is valid. When "autoload" is true "#" is allowed.
|
||||||
* Return FALSE and give an error if not.
|
* Return FALSE and give an error if not.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
valid_varname(char_u *varname)
|
valid_varname(char_u *varname, int autoload)
|
||||||
{
|
{
|
||||||
char_u *p;
|
char_u *p;
|
||||||
|
|
||||||
for (p = varname; *p != NUL; ++p)
|
for (p = varname; *p != NUL; ++p)
|
||||||
if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p))
|
if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p))
|
||||||
&& *p != AUTOLOAD_CHAR)
|
&& !(autoload && *p == AUTOLOAD_CHAR))
|
||||||
{
|
{
|
||||||
semsg(_(e_illvar), varname);
|
semsg(_(e_illvar), varname);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@@ -75,7 +75,7 @@ int var_check_lock(int flags, char_u *name, int use_gettext);
|
|||||||
int var_check_fixed(int flags, char_u *name, int use_gettext);
|
int var_check_fixed(int flags, char_u *name, int use_gettext);
|
||||||
int var_wrong_func_name(char_u *name, int new_var);
|
int var_wrong_func_name(char_u *name, int new_var);
|
||||||
int value_check_lock(int lock, char_u *name, int use_gettext);
|
int value_check_lock(int lock, char_u *name, int use_gettext);
|
||||||
int valid_varname(char_u *varname);
|
int valid_varname(char_u *varname, int autoload);
|
||||||
void reset_v_option_vars(void);
|
void reset_v_option_vars(void);
|
||||||
void assert_error(garray_T *gap);
|
void assert_error(garray_T *gap);
|
||||||
int var_exists(char_u *var);
|
int var_exists(char_u *var);
|
||||||
|
@@ -23,6 +23,7 @@ def s:ScriptFuncLoad(arg: string)
|
|||||||
echo s:scriptvar
|
echo s:scriptvar
|
||||||
echo g:globalvar
|
echo g:globalvar
|
||||||
echo get(g:, "global")
|
echo get(g:, "global")
|
||||||
|
echo g:auto#var
|
||||||
echo b:buffervar
|
echo b:buffervar
|
||||||
echo get(b:, "buffer")
|
echo get(b:, "buffer")
|
||||||
echo w:windowvar
|
echo w:windowvar
|
||||||
@@ -68,8 +69,14 @@ def Test_disassemble_load()
|
|||||||
'echo get(g:, "global")\_s*' ..
|
'echo get(g:, "global")\_s*' ..
|
||||||
'\d\+ LOAD g:\_s*' ..
|
'\d\+ LOAD g:\_s*' ..
|
||||||
'\d\+ PUSHS "global"\_s*' ..
|
'\d\+ PUSHS "global"\_s*' ..
|
||||||
'\d\+ BCALL get(argc 2).*' ..
|
'\d\+ BCALL get(argc 2)\_s*' ..
|
||||||
' LOADB b:buffervar.*' ..
|
'\d\+ ECHO 1\_s*' ..
|
||||||
|
'echo g:auto#var\_s*' ..
|
||||||
|
'\d\+ LOADAUTO g:auto#var\_s*' ..
|
||||||
|
'\d\+ ECHO 1\_s*' ..
|
||||||
|
'echo b:buffervar\_s*' ..
|
||||||
|
'\d\+ LOADB b:buffervar\_s*' ..
|
||||||
|
'\d\+ ECHO 1\_s*' ..
|
||||||
'echo get(b:, "buffer")\_s*' ..
|
'echo get(b:, "buffer")\_s*' ..
|
||||||
'\d\+ LOAD b:\_s*' ..
|
'\d\+ LOAD b:\_s*' ..
|
||||||
'\d\+ PUSHS "buffer"\_s*' ..
|
'\d\+ PUSHS "buffer"\_s*' ..
|
||||||
@@ -197,6 +204,7 @@ def s:ScriptFuncStore()
|
|||||||
v:char = 'abc'
|
v:char = 'abc'
|
||||||
s:scriptvar = 'sv'
|
s:scriptvar = 'sv'
|
||||||
g:globalvar = 'gv'
|
g:globalvar = 'gv'
|
||||||
|
g:auto#var = 'av'
|
||||||
b:buffervar = 'bv'
|
b:buffervar = 'bv'
|
||||||
w:windowvar = 'wv'
|
w:windowvar = 'wv'
|
||||||
t:tabpagevar = 'tv'
|
t:tabpagevar = 'tv'
|
||||||
@@ -220,6 +228,8 @@ def Test_disassemble_store()
|
|||||||
' STORES s:scriptvar in .*test_vim9_disassemble.vim.*' ..
|
' STORES s:scriptvar in .*test_vim9_disassemble.vim.*' ..
|
||||||
'g:globalvar = ''gv''.*' ..
|
'g:globalvar = ''gv''.*' ..
|
||||||
' STOREG g:globalvar.*' ..
|
' STOREG g:globalvar.*' ..
|
||||||
|
'g:auto#var = ''av''.*' ..
|
||||||
|
' STOREAUTO g:auto#var.*' ..
|
||||||
'b:buffervar = ''bv''.*' ..
|
'b:buffervar = ''bv''.*' ..
|
||||||
' STOREB b:buffervar.*' ..
|
' STOREB b:buffervar.*' ..
|
||||||
'w:windowvar = ''wv''.*' ..
|
'w:windowvar = ''wv''.*' ..
|
||||||
|
@@ -2779,8 +2779,32 @@ def Test_vim9_copen()
|
|||||||
quit
|
quit
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
" test using a vim9script that is auto-loaded from an autocmd
|
" test using an auto-loaded function and variable
|
||||||
def Test_vim9_autoload()
|
def Test_vim9_autoload()
|
||||||
|
var lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
def some#gettest(): string
|
||||||
|
return 'test'
|
||||||
|
enddef
|
||||||
|
g:some#name = 'name'
|
||||||
|
END
|
||||||
|
|
||||||
|
mkdir('Xdir/autoload', 'p')
|
||||||
|
writefile(lines, 'Xdir/autoload/some.vim')
|
||||||
|
var save_rtp = &rtp
|
||||||
|
exe 'set rtp^=' .. getcwd() .. '/Xdir'
|
||||||
|
|
||||||
|
assert_equal('test', g:some#gettest())
|
||||||
|
assert_equal('name', g:some#name)
|
||||||
|
g:some#other = 'other'
|
||||||
|
assert_equal('other', g:some#other)
|
||||||
|
|
||||||
|
delete('Xdir', 'rf')
|
||||||
|
&rtp = save_rtp
|
||||||
|
enddef
|
||||||
|
|
||||||
|
" test using a vim9script that is auto-loaded from an autocmd
|
||||||
|
def Test_vim9_aucmd_autoload()
|
||||||
var lines =<< trim END
|
var lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
def foo#test()
|
def foo#test()
|
||||||
@@ -2842,6 +2866,12 @@ def Test_vim9_autoload_error()
|
|||||||
delete('Xdidit')
|
delete('Xdidit')
|
||||||
delete('Xscript')
|
delete('Xscript')
|
||||||
delete('Xruntime', 'rf')
|
delete('Xruntime', 'rf')
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
var foo#bar = 'asdf'
|
||||||
|
END
|
||||||
|
CheckScriptFailure(lines, 'E461: Illegal variable name: foo#bar', 2)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_script_var_in_autocmd()
|
def Test_script_var_in_autocmd()
|
||||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2162,
|
||||||
/**/
|
/**/
|
||||||
2161,
|
2161,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -24,6 +24,7 @@ typedef enum {
|
|||||||
ISN_LOAD, // push local variable isn_arg.number
|
ISN_LOAD, // push local variable isn_arg.number
|
||||||
ISN_LOADV, // push v: variable isn_arg.number
|
ISN_LOADV, // push v: variable isn_arg.number
|
||||||
ISN_LOADG, // push g: variable isn_arg.string
|
ISN_LOADG, // push g: variable isn_arg.string
|
||||||
|
ISN_LOADAUTO, // push g: autoload variable isn_arg.string
|
||||||
ISN_LOADB, // push b: variable isn_arg.string
|
ISN_LOADB, // push b: variable isn_arg.string
|
||||||
ISN_LOADW, // push w: variable isn_arg.string
|
ISN_LOADW, // push w: variable isn_arg.string
|
||||||
ISN_LOADT, // push t: variable isn_arg.string
|
ISN_LOADT, // push t: variable isn_arg.string
|
||||||
@@ -41,6 +42,7 @@ typedef enum {
|
|||||||
ISN_STORE, // pop into local variable isn_arg.number
|
ISN_STORE, // pop into local variable isn_arg.number
|
||||||
ISN_STOREV, // pop into v: variable isn_arg.number
|
ISN_STOREV, // pop into v: variable isn_arg.number
|
||||||
ISN_STOREG, // pop into global variable isn_arg.string
|
ISN_STOREG, // pop into global variable isn_arg.string
|
||||||
|
ISN_STOREAUTO, // pop into global autoload variable isn_arg.string
|
||||||
ISN_STOREB, // pop into buffer-local variable isn_arg.string
|
ISN_STOREB, // pop into buffer-local variable isn_arg.string
|
||||||
ISN_STOREW, // pop into window-local variable isn_arg.string
|
ISN_STOREW, // pop into window-local variable isn_arg.string
|
||||||
ISN_STORET, // pop into tab-local variable isn_arg.string
|
ISN_STORET, // pop into tab-local variable isn_arg.string
|
||||||
|
@@ -2535,7 +2535,17 @@ compile_load(
|
|||||||
case 's': res = compile_load_scriptvar(cctx, name,
|
case 's': res = compile_load_scriptvar(cctx, name,
|
||||||
NULL, NULL, error);
|
NULL, NULL, error);
|
||||||
break;
|
break;
|
||||||
case 'g': isn_type = ISN_LOADG; break;
|
case 'g': if (vim_strchr(name, AUTOLOAD_CHAR) == NULL)
|
||||||
|
isn_type = ISN_LOADG;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isn_type = ISN_LOADAUTO;
|
||||||
|
vim_free(name);
|
||||||
|
name = vim_strnsave(*arg, end - *arg);
|
||||||
|
if (name == NULL)
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'w': isn_type = ISN_LOADW; break;
|
case 'w': isn_type = ISN_LOADW; break;
|
||||||
case 't': isn_type = ISN_LOADT; break;
|
case 't': isn_type = ISN_LOADT; break;
|
||||||
case 'b': isn_type = ISN_LOADB; break;
|
case 'b': isn_type = ISN_LOADB; break;
|
||||||
@@ -2738,7 +2748,7 @@ compile_call(
|
|||||||
if (compile_arguments(arg, cctx, &argcount) == FAIL)
|
if (compile_arguments(arg, cctx, &argcount) == FAIL)
|
||||||
goto theend;
|
goto theend;
|
||||||
|
|
||||||
is_autoload = vim_strchr(name, '#') != NULL;
|
is_autoload = vim_strchr(name, AUTOLOAD_CHAR) != NULL;
|
||||||
if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload)
|
if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload)
|
||||||
{
|
{
|
||||||
int idx;
|
int idx;
|
||||||
@@ -4986,7 +4996,10 @@ generate_loadvar(
|
|||||||
generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
|
generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
|
||||||
break;
|
break;
|
||||||
case dest_global:
|
case dest_global:
|
||||||
|
if (vim_strchr(name, AUTOLOAD_CHAR) == NULL)
|
||||||
generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
|
generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
|
||||||
|
else
|
||||||
|
generate_LOAD(cctx, ISN_LOADAUTO, 0, name, type);
|
||||||
break;
|
break;
|
||||||
case dest_buffer:
|
case dest_buffer:
|
||||||
generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
|
generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
|
||||||
@@ -5198,7 +5211,8 @@ generate_store_var(
|
|||||||
opt_flags);
|
opt_flags);
|
||||||
case dest_global:
|
case dest_global:
|
||||||
// include g: with the name, easier to execute that way
|
// include g: with the name, easier to execute that way
|
||||||
return generate_STORE(cctx, ISN_STOREG, 0, name);
|
return generate_STORE(cctx, vim_strchr(name, AUTOLOAD_CHAR) == NULL
|
||||||
|
? ISN_STOREG : ISN_STOREAUTO, 0, name);
|
||||||
case dest_buffer:
|
case dest_buffer:
|
||||||
// include b: with the name, easier to execute that way
|
// include b: with the name, easier to execute that way
|
||||||
return generate_STORE(cctx, ISN_STOREB, 0, name);
|
return generate_STORE(cctx, ISN_STOREB, 0, name);
|
||||||
@@ -8007,6 +8021,7 @@ delete_instr(isn_T *isn)
|
|||||||
{
|
{
|
||||||
case ISN_DEF:
|
case ISN_DEF:
|
||||||
case ISN_EXEC:
|
case ISN_EXEC:
|
||||||
|
case ISN_LOADAUTO:
|
||||||
case ISN_LOADB:
|
case ISN_LOADB:
|
||||||
case ISN_LOADENV:
|
case ISN_LOADENV:
|
||||||
case ISN_LOADG:
|
case ISN_LOADG:
|
||||||
@@ -8017,6 +8032,7 @@ delete_instr(isn_T *isn)
|
|||||||
case ISN_PUSHFUNC:
|
case ISN_PUSHFUNC:
|
||||||
case ISN_PUSHS:
|
case ISN_PUSHS:
|
||||||
case ISN_RANGE:
|
case ISN_RANGE:
|
||||||
|
case ISN_STOREAUTO:
|
||||||
case ISN_STOREB:
|
case ISN_STOREB:
|
||||||
case ISN_STOREENV:
|
case ISN_STOREENV:
|
||||||
case ISN_STOREG:
|
case ISN_STOREG:
|
||||||
|
@@ -1391,6 +1391,21 @@ call_def_function(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// load autoload variable
|
||||||
|
case ISN_LOADAUTO:
|
||||||
|
{
|
||||||
|
char_u *name = iptr->isn_arg.string;
|
||||||
|
|
||||||
|
if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
|
||||||
|
goto failed;
|
||||||
|
SOURCING_LNUM = iptr->isn_lnum;
|
||||||
|
if (eval_variable(name, STRLEN(name),
|
||||||
|
STACK_TV_BOT(0), NULL, TRUE, FALSE) == FAIL)
|
||||||
|
goto on_error;
|
||||||
|
++ectx.ec_stack.ga_len;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
// load g:/b:/w:/t: namespace
|
// load g:/b:/w:/t: namespace
|
||||||
case ISN_LOADGDICT:
|
case ISN_LOADGDICT:
|
||||||
case ISN_LOADBDICT:
|
case ISN_LOADBDICT:
|
||||||
@@ -1611,6 +1626,14 @@ call_def_function(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// store an autoload variable
|
||||||
|
case ISN_STOREAUTO:
|
||||||
|
SOURCING_LNUM = iptr->isn_lnum;
|
||||||
|
set_var(iptr->isn_arg.string, STACK_TV_BOT(-1), TRUE);
|
||||||
|
clear_tv(STACK_TV_BOT(-1));
|
||||||
|
--ectx.ec_stack.ga_len;
|
||||||
|
break;
|
||||||
|
|
||||||
// store number in local variable
|
// store number in local variable
|
||||||
case ISN_STORENR:
|
case ISN_STORENR:
|
||||||
tv = STACK_TV_VAR(iptr->isn_arg.storenr.stnr_idx);
|
tv = STACK_TV_VAR(iptr->isn_arg.storenr.stnr_idx);
|
||||||
@@ -3286,6 +3309,9 @@ ex_disassemble(exarg_T *eap)
|
|||||||
iptr->isn_arg.loadstore.ls_name, si->sn_name);
|
iptr->isn_arg.loadstore.ls_name, si->sn_name);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ISN_LOADAUTO:
|
||||||
|
smsg("%4d LOADAUTO %s", current, iptr->isn_arg.string);
|
||||||
|
break;
|
||||||
case ISN_LOADG:
|
case ISN_LOADG:
|
||||||
smsg("%4d LOADG g:%s", current, iptr->isn_arg.string);
|
smsg("%4d LOADG g:%s", current, iptr->isn_arg.string);
|
||||||
break;
|
break;
|
||||||
@@ -3337,6 +3363,9 @@ ex_disassemble(exarg_T *eap)
|
|||||||
smsg("%4d STOREV v:%s", current,
|
smsg("%4d STOREV v:%s", current,
|
||||||
get_vim_var_name(iptr->isn_arg.number));
|
get_vim_var_name(iptr->isn_arg.number));
|
||||||
break;
|
break;
|
||||||
|
case ISN_STOREAUTO:
|
||||||
|
smsg("%4d STOREAUTO %s", current, iptr->isn_arg.string);
|
||||||
|
break;
|
||||||
case ISN_STOREG:
|
case ISN_STOREG:
|
||||||
smsg("%4d STOREG %s", current, iptr->isn_arg.string);
|
smsg("%4d STOREG %s", current, iptr->isn_arg.string);
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user