Skip to content

Commit 03290b8

Browse files
committed
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)
1 parent 1f33e0a commit 03290b8

10 files changed

Lines changed: 106 additions & 15 deletions

File tree

src/dict.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1073,7 +1073,7 @@ dict_extend(dict_T *d1, dict_T *d2, char_u *action)
10731073
&& HI2DI(hi2)->di_tv.v_type == VAR_FUNC
10741074
&& var_wrong_func_name(hi2->hi_key, di1 == NULL))
10751075
break;
1076-
if (!valid_varname(hi2->hi_key))
1076+
if (!valid_varname(hi2->hi_key, TRUE))
10771077
break;
10781078
}
10791079
if (di1 == NULL)

src/eval.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1049,7 +1049,7 @@ get_lval(
10491049
wrong = (lp->ll_dict->dv_scope == VAR_DEF_SCOPE
10501050
&& rettv->v_type == VAR_FUNC
10511051
&& var_wrong_func_name(key, lp->ll_di == NULL))
1052-
|| !valid_varname(key);
1052+
|| !valid_varname(key, TRUE);
10531053
if (len != -1)
10541054
key[len] = prevval;
10551055
if (wrong)

src/evalvars.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3195,8 +3195,10 @@ set_var_const(
31953195
goto failed;
31963196
}
31973197

3198-
// Make sure the variable name is valid.
3199-
if (!valid_varname(varname))
3198+
// Make sure the variable name is valid. In Vim9 script an autoload
3199+
// variable must be prefixed with "g:".
3200+
if (!valid_varname(varname, !vim9script
3201+
|| STRNCMP(name, "g:", 2) == 0))
32003202
goto failed;
32013203

32023204
di = alloc(sizeof(dictitem_T) + STRLEN(varname));
@@ -3349,17 +3351,17 @@ value_check_lock(int lock, char_u *name, int use_gettext)
33493351
}
33503352

33513353
/*
3352-
* Check if a variable name is valid.
3354+
* Check if a variable name is valid. When "autoload" is true "#" is allowed.
33533355
* Return FALSE and give an error if not.
33543356
*/
33553357
int
3356-
valid_varname(char_u *varname)
3358+
valid_varname(char_u *varname, int autoload)
33573359
{
33583360
char_u *p;
33593361

33603362
for (p = varname; *p != NUL; ++p)
33613363
if (!eval_isnamec1(*p) && (p == varname || !VIM_ISDIGIT(*p))
3362-
&& *p != AUTOLOAD_CHAR)
3364+
&& !(autoload && *p == AUTOLOAD_CHAR))
33633365
{
33643366
semsg(_(e_illvar), varname);
33653367
return FALSE;

src/proto/evalvars.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ int var_check_lock(int flags, char_u *name, int use_gettext);
7575
int var_check_fixed(int flags, char_u *name, int use_gettext);
7676
int var_wrong_func_name(char_u *name, int new_var);
7777
int value_check_lock(int lock, char_u *name, int use_gettext);
78-
int valid_varname(char_u *varname);
78+
int valid_varname(char_u *varname, int autoload);
7979
void reset_v_option_vars(void);
8080
void assert_error(garray_T *gap);
8181
int var_exists(char_u *var);

src/testdir/test_vim9_disassemble.vim

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ def s:ScriptFuncLoad(arg: string)
2323
echo s:scriptvar
2424
echo g:globalvar
2525
echo get(g:, "global")
26+
echo g:auto#var
2627
echo b:buffervar
2728
echo get(b:, "buffer")
2829
echo w:windowvar
@@ -68,8 +69,14 @@ def Test_disassemble_load()
6869
'echo get(g:, "global")\_s*' ..
6970
'\d\+ LOAD g:\_s*' ..
7071
'\d\+ PUSHS "global"\_s*' ..
71-
'\d\+ BCALL get(argc 2).*' ..
72-
' LOADB b:buffervar.*' ..
72+
'\d\+ BCALL get(argc 2)\_s*' ..
73+
'\d\+ ECHO 1\_s*' ..
74+
'echo g:auto#var\_s*' ..
75+
'\d\+ LOADAUTO g:auto#var\_s*' ..
76+
'\d\+ ECHO 1\_s*' ..
77+
'echo b:buffervar\_s*' ..
78+
'\d\+ LOADB b:buffervar\_s*' ..
79+
'\d\+ ECHO 1\_s*' ..
7380
'echo get(b:, "buffer")\_s*' ..
7481
'\d\+ LOAD b:\_s*' ..
7582
'\d\+ PUSHS "buffer"\_s*' ..
@@ -197,6 +204,7 @@ def s:ScriptFuncStore()
197204
v:char = 'abc'
198205
s:scriptvar = 'sv'
199206
g:globalvar = 'gv'
207+
g:auto#var = 'av'
200208
b:buffervar = 'bv'
201209
w:windowvar = 'wv'
202210
t:tabpagevar = 'tv'
@@ -220,6 +228,8 @@ def Test_disassemble_store()
220228
' STORES s:scriptvar in .*test_vim9_disassemble.vim.*' ..
221229
'g:globalvar = ''gv''.*' ..
222230
' STOREG g:globalvar.*' ..
231+
'g:auto#var = ''av''.*' ..
232+
' STOREAUTO g:auto#var.*' ..
223233
'b:buffervar = ''bv''.*' ..
224234
' STOREB b:buffervar.*' ..
225235
'w:windowvar = ''wv''.*' ..

src/testdir/test_vim9_script.vim

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2779,8 +2779,32 @@ def Test_vim9_copen()
27792779
quit
27802780
enddef
27812781

2782-
" test using a vim9script that is auto-loaded from an autocmd
2782+
" test using an auto-loaded function and variable
27832783
def Test_vim9_autoload()
2784+
var lines =<< trim END
2785+
vim9script
2786+
def some#gettest(): string
2787+
return 'test'
2788+
enddef
2789+
g:some#name = 'name'
2790+
END
2791+
2792+
mkdir('Xdir/autoload', 'p')
2793+
writefile(lines, 'Xdir/autoload/some.vim')
2794+
var save_rtp = &rtp
2795+
exe 'set rtp^=' .. getcwd() .. '/Xdir'
2796+
2797+
assert_equal('test', g:some#gettest())
2798+
assert_equal('name', g:some#name)
2799+
g:some#other = 'other'
2800+
assert_equal('other', g:some#other)
2801+
2802+
delete('Xdir', 'rf')
2803+
&rtp = save_rtp
2804+
enddef
2805+
2806+
" test using a vim9script that is auto-loaded from an autocmd
2807+
def Test_vim9_aucmd_autoload()
27842808
var lines =<< trim END
27852809
vim9script
27862810
def foo#test()
@@ -2842,6 +2866,12 @@ def Test_vim9_autoload_error()
28422866
delete('Xdidit')
28432867
delete('Xscript')
28442868
delete('Xruntime', 'rf')
2869+
2870+
lines =<< trim END
2871+
vim9script
2872+
var foo#bar = 'asdf'
2873+
END
2874+
CheckScriptFailure(lines, 'E461: Illegal variable name: foo#bar', 2)
28452875
enddef
28462876

28472877
def Test_script_var_in_autocmd()

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,8 @@ static char *(features[]) =
750750

751751
static int included_patches[] =
752752
{ /* Add new patch number below this line */
753+
/**/
754+
2162,
753755
/**/
754756
2161,
755757
/**/

src/vim9.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ typedef enum {
2424
ISN_LOAD, // push local variable isn_arg.number
2525
ISN_LOADV, // push v: variable isn_arg.number
2626
ISN_LOADG, // push g: variable isn_arg.string
27+
ISN_LOADAUTO, // push g: autoload variable isn_arg.string
2728
ISN_LOADB, // push b: variable isn_arg.string
2829
ISN_LOADW, // push w: variable isn_arg.string
2930
ISN_LOADT, // push t: variable isn_arg.string
@@ -41,6 +42,7 @@ typedef enum {
4142
ISN_STORE, // pop into local variable isn_arg.number
4243
ISN_STOREV, // pop into v: variable isn_arg.number
4344
ISN_STOREG, // pop into global variable isn_arg.string
45+
ISN_STOREAUTO, // pop into global autoload variable isn_arg.string
4446
ISN_STOREB, // pop into buffer-local variable isn_arg.string
4547
ISN_STOREW, // pop into window-local variable isn_arg.string
4648
ISN_STORET, // pop into tab-local variable isn_arg.string

src/vim9compile.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2535,7 +2535,17 @@ compile_load(
25352535
case 's': res = compile_load_scriptvar(cctx, name,
25362536
NULL, NULL, error);
25372537
break;
2538-
case 'g': isn_type = ISN_LOADG; break;
2538+
case 'g': if (vim_strchr(name, AUTOLOAD_CHAR) == NULL)
2539+
isn_type = ISN_LOADG;
2540+
else
2541+
{
2542+
isn_type = ISN_LOADAUTO;
2543+
vim_free(name);
2544+
name = vim_strnsave(*arg, end - *arg);
2545+
if (name == NULL)
2546+
return FAIL;
2547+
}
2548+
break;
25392549
case 'w': isn_type = ISN_LOADW; break;
25402550
case 't': isn_type = ISN_LOADT; break;
25412551
case 'b': isn_type = ISN_LOADB; break;
@@ -2738,7 +2748,7 @@ compile_call(
27382748
if (compile_arguments(arg, cctx, &argcount) == FAIL)
27392749
goto theend;
27402750

2741-
is_autoload = vim_strchr(name, '#') != NULL;
2751+
is_autoload = vim_strchr(name, AUTOLOAD_CHAR) != NULL;
27422752
if (ASCII_ISLOWER(*name) && name[1] != ':' && !is_autoload)
27432753
{
27442754
int idx;
@@ -4986,7 +4996,10 @@ generate_loadvar(
49864996
generate_LOAD(cctx, ISN_LOADOPT, 0, name, type);
49874997
break;
49884998
case dest_global:
4989-
generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
4999+
if (vim_strchr(name, AUTOLOAD_CHAR) == NULL)
5000+
generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
5001+
else
5002+
generate_LOAD(cctx, ISN_LOADAUTO, 0, name, type);
49905003
break;
49915004
case dest_buffer:
49925005
generate_LOAD(cctx, ISN_LOADB, 0, name + 2, type);
@@ -5198,7 +5211,8 @@ generate_store_var(
51985211
opt_flags);
51995212
case dest_global:
52005213
// include g: with the name, easier to execute that way
5201-
return generate_STORE(cctx, ISN_STOREG, 0, name);
5214+
return generate_STORE(cctx, vim_strchr(name, AUTOLOAD_CHAR) == NULL
5215+
? ISN_STOREG : ISN_STOREAUTO, 0, name);
52025216
case dest_buffer:
52035217
// include b: with the name, easier to execute that way
52045218
return generate_STORE(cctx, ISN_STOREB, 0, name);
@@ -8007,6 +8021,7 @@ delete_instr(isn_T *isn)
80078021
{
80088022
case ISN_DEF:
80098023
case ISN_EXEC:
8024+
case ISN_LOADAUTO:
80108025
case ISN_LOADB:
80118026
case ISN_LOADENV:
80128027
case ISN_LOADG:
@@ -8017,6 +8032,7 @@ delete_instr(isn_T *isn)
80178032
case ISN_PUSHFUNC:
80188033
case ISN_PUSHS:
80198034
case ISN_RANGE:
8035+
case ISN_STOREAUTO:
80208036
case ISN_STOREB:
80218037
case ISN_STOREENV:
80228038
case ISN_STOREG:

src/vim9execute.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,6 +1391,21 @@ call_def_function(
13911391
}
13921392
break;
13931393

1394+
// load autoload variable
1395+
case ISN_LOADAUTO:
1396+
{
1397+
char_u *name = iptr->isn_arg.string;
1398+
1399+
if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
1400+
goto failed;
1401+
SOURCING_LNUM = iptr->isn_lnum;
1402+
if (eval_variable(name, STRLEN(name),
1403+
STACK_TV_BOT(0), NULL, TRUE, FALSE) == FAIL)
1404+
goto on_error;
1405+
++ectx.ec_stack.ga_len;
1406+
}
1407+
break;
1408+
13941409
// load g:/b:/w:/t: namespace
13951410
case ISN_LOADGDICT:
13961411
case ISN_LOADBDICT:
@@ -1611,6 +1626,14 @@ call_def_function(
16111626
}
16121627
break;
16131628

1629+
// store an autoload variable
1630+
case ISN_STOREAUTO:
1631+
SOURCING_LNUM = iptr->isn_lnum;
1632+
set_var(iptr->isn_arg.string, STACK_TV_BOT(-1), TRUE);
1633+
clear_tv(STACK_TV_BOT(-1));
1634+
--ectx.ec_stack.ga_len;
1635+
break;
1636+
16141637
// store number in local variable
16151638
case ISN_STORENR:
16161639
tv = STACK_TV_VAR(iptr->isn_arg.storenr.stnr_idx);
@@ -3286,6 +3309,9 @@ ex_disassemble(exarg_T *eap)
32863309
iptr->isn_arg.loadstore.ls_name, si->sn_name);
32873310
}
32883311
break;
3312+
case ISN_LOADAUTO:
3313+
smsg("%4d LOADAUTO %s", current, iptr->isn_arg.string);
3314+
break;
32893315
case ISN_LOADG:
32903316
smsg("%4d LOADG g:%s", current, iptr->isn_arg.string);
32913317
break;
@@ -3337,6 +3363,9 @@ ex_disassemble(exarg_T *eap)
33373363
smsg("%4d STOREV v:%s", current,
33383364
get_vim_var_name(iptr->isn_arg.number));
33393365
break;
3366+
case ISN_STOREAUTO:
3367+
smsg("%4d STOREAUTO %s", current, iptr->isn_arg.string);
3368+
break;
33403369
case ISN_STOREG:
33413370
smsg("%4d STOREG %s", current, iptr->isn_arg.string);
33423371
break;

0 commit comments

Comments
 (0)