0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 8.2.0200: Vim9 script commands not sufficiently tested

Problem:    Vim9 script commands not sufficiently tested.
Solution:   Add more tests.  Fix storing global variable.  Make script
            variables work.
This commit is contained in:
Bram Moolenaar 2020-02-02 22:24:04 +01:00
parent 0f18b6d17b
commit b283a8a680
9 changed files with 301 additions and 58 deletions

View File

@ -1206,14 +1206,7 @@ ex_let_one(
} }
if (p != NULL) if (p != NULL)
{ {
vim_setenv(name, p); vim_setenv_ext(name, p);
if (STRICMP(name, "HOME") == 0)
init_homedir();
else if (didset_vim && STRICMP(name, "VIM") == 0)
didset_vim = FALSE;
else if (didset_vimruntime
&& STRICMP(name, "VIMRUNTIME") == 0)
didset_vimruntime = FALSE;
arg_end = arg; arg_end = arg;
} }
name[len] = c1; name[len] = c1;
@ -1966,6 +1959,24 @@ get_vim_var_tv(int idx)
return &vimvars[idx].vv_tv; return &vimvars[idx].vv_tv;
} }
/*
* Set v: variable to "tv". Only accepts the same type.
* Takes over the value of "tv".
*/
int
set_vim_var_tv(int idx, typval_T *tv)
{
if (vimvars[idx].vv_type != tv->v_type)
{
emsg(_("E1063: type mismatch for v: variable"));
clear_tv(tv);
return FAIL;
}
clear_tv(&vimvars[idx].vv_di.di_tv);
vimvars[idx].vv_di.di_tv = *tv;
return OK;
}
/* /*
* Get number v: variable value. * Get number v: variable value.
*/ */

View File

@ -1853,6 +1853,22 @@ vim_unsetenv(char_u *var)
#endif #endif
/*
* Set environment variable "name" and take care of side effects.
*/
void
vim_setenv_ext(char_u *name, char_u *val)
{
vim_setenv(name, val);
if (STRICMP(name, "HOME") == 0)
init_homedir();
else if (didset_vim && STRICMP(name, "VIM") == 0)
didset_vim = FALSE;
else if (didset_vimruntime
&& STRICMP(name, "VIMRUNTIME") == 0)
didset_vimruntime = FALSE;
}
/* /*
* Our portable version of setenv. * Our portable version of setenv.
*/ */

View File

@ -33,6 +33,7 @@ void set_vim_var_type(int idx, vartype_T type);
void set_vim_var_nr(int idx, varnumber_T val); void set_vim_var_nr(int idx, varnumber_T val);
char *get_vim_var_name(int idx); char *get_vim_var_name(int idx);
typval_T *get_vim_var_tv(int idx); typval_T *get_vim_var_tv(int idx);
int set_vim_var_tv(int idx, typval_T *tv);
varnumber_T get_vim_var_nr(int idx); varnumber_T get_vim_var_nr(int idx);
char_u *get_vim_var_str(int idx); char_u *get_vim_var_str(int idx);
list_T *get_vim_var_list(int idx); list_T *get_vim_var_list(int idx);

View File

@ -31,6 +31,7 @@ void expand_env(char_u *src, char_u *dst, int dstlen);
void expand_env_esc(char_u *srcp, char_u *dst, int dstlen, int esc, int one, char_u *startstr); void expand_env_esc(char_u *srcp, char_u *dst, int dstlen, int esc, int one, char_u *startstr);
char_u *vim_getenv(char_u *name, int *mustfree); char_u *vim_getenv(char_u *name, int *mustfree);
void vim_unsetenv(char_u *var); void vim_unsetenv(char_u *var);
void vim_setenv_ext(char_u *name, char_u *val);
void vim_setenv(char_u *name, char_u *val); void vim_setenv(char_u *name, char_u *val);
char_u *get_env_name(expand_T *xp, int idx); char_u *get_env_name(expand_T *xp, int idx);
char_u *get_users(expand_T *xp, int idx); char_u *get_users(expand_T *xp, int idx);

View File

@ -42,6 +42,13 @@ def Test_assignment()
let dict1: dict<string> = #{key: 'value'} let dict1: dict<string> = #{key: 'value'}
let dict2: dict<number> = #{one: 1, two: 2} let dict2: dict<number> = #{one: 1, two: 2}
v:char = 'abc'
call assert_equal('abc', v:char)
$ENVVAR = 'foobar'
call assert_equal('foobar', $ENVVAR)
$ENVVAR = ''
enddef enddef
func Test_assignment_failure() func Test_assignment_failure()
@ -106,7 +113,7 @@ def Test_call_ufunc_count()
Increment() Increment()
" works with and without :call " works with and without :call
assert_equal(4, g:counter) assert_equal(4, g:counter)
assert_equal(4, g:counter) call assert_equal(4, g:counter)
unlet g:counter unlet g:counter
enddef enddef
@ -311,7 +318,11 @@ def Test_import_absolute()
let import_lines = [ let import_lines = [
\ 'vim9script', \ 'vim9script',
\ 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"', \ 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"',
\ 'g:imported_abs = exported', \ 'def UseExported()',
\ ' g:imported_abs = exported',
\ 'enddef',
\ 'UseExported()',
\ 'g:import_disassabled = execute("disass UseExported")',
\ ] \ ]
writefile(import_lines, 'Ximport_abs.vim') writefile(import_lines, 'Ximport_abs.vim')
writefile(s:export_script_lines, 'Xexport_abs.vim') writefile(s:export_script_lines, 'Xexport_abs.vim')
@ -319,7 +330,12 @@ def Test_import_absolute()
source Ximport_abs.vim source Ximport_abs.vim
assert_equal(9876, g:imported_abs) assert_equal(9876, g:imported_abs)
assert_match('<SNR>\d\+_UseExported.*'
\ .. 'g:imported_abs = exported.*'
\ .. '0 LOADSCRIPT exported from .*Xexport_abs.vim.*'
\ .. '1 STOREG g:imported_abs', g:import_disassabled)
unlet g:imported_abs unlet g:imported_abs
unlet g:import_disassabled
delete('Ximport_abs.vim') delete('Ximport_abs.vim')
delete('Xexport_abs.vim') delete('Xexport_abs.vim')
@ -405,7 +421,7 @@ endfunc
let s:scriptvar = 4 let s:scriptvar = 4
let g:globalvar = 'g' let g:globalvar = 'g'
def s:ScriptFunc(arg: string) def s:ScriptFuncLoad(arg: string)
let local = 1 let local = 1
buffers buffers
echo arg echo arg
@ -418,12 +434,25 @@ def s:ScriptFunc(arg: string)
echo @z echo @z
enddef enddef
def s:ScriptFuncStore()
let localnr = 1
localnr = 2
let localstr = 'abc'
localstr = 'xyz'
v:char = 'abc'
s:scriptvar = 'sv'
g:globalvar = 'gv'
&tabstop = 8
$ENVVAR = 'ev'
@z = 'rv'
enddef
def Test_disassemble() def Test_disassemble()
assert_fails('disass NoFunc', 'E1061:') assert_fails('disass NoFunc', 'E1061:')
assert_fails('disass NotCompiled', 'E1062:') assert_fails('disass NotCompiled', 'E1062:')
let res = execute('disass s:ScriptFunc') let res = execute('disass s:ScriptFuncLoad')
assert_match('<SNR>\d*_ScriptFunc.*' assert_match('<SNR>\d*_ScriptFuncLoad.*'
\ .. 'buffers.*' \ .. 'buffers.*'
\ .. ' EXEC \+buffers.*' \ .. ' EXEC \+buffers.*'
\ .. ' LOAD arg\[-1\].*' \ .. ' LOAD arg\[-1\].*'
@ -432,7 +461,31 @@ def Test_disassemble()
\ .. ' LOADS s:scriptvar from .*test_vim9_script.vim.*' \ .. ' LOADS s:scriptvar from .*test_vim9_script.vim.*'
\ .. ' LOADG g:globalvar.*' \ .. ' LOADG g:globalvar.*'
\ .. ' LOADENV $ENVVAR.*' \ .. ' LOADENV $ENVVAR.*'
\ .. ' LOADREG @z.*', res) \ .. ' LOADREG @z.*'
\, res)
" TODO:
" v:char =
" s:scriptvar =
res = execute('disass s:ScriptFuncStore')
assert_match('<SNR>\d*_ScriptFuncStore.*'
\ .. 'localnr = 2.*'
\ .. ' STORE 2 in $0.*'
\ .. 'localstr = ''xyz''.*'
\ .. ' STORE $1.*'
\ .. 'v:char = ''abc''.*'
\ .. 'STOREV v:char.*'
\ .. 's:scriptvar = ''sv''.*'
\ .. ' STORES s:scriptvar in .*test_vim9_script.vim.*'
\ .. 'g:globalvar = ''gv''.*'
\ .. ' STOREG g:globalvar.*'
\ .. '&tabstop = 8.*'
\ .. ' STOREOPT &tabstop.*'
\ .. '$ENVVAR = ''ev''.*'
\ .. ' STOREENV $ENVVAR.*'
\ .. '@z = ''rv''.*'
\ .. ' STOREREG @z.*'
\, res)
enddef enddef

View File

@ -742,6 +742,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 */
/**/
200,
/**/ /**/
199, 199,
/**/ /**/

View File

@ -18,17 +18,21 @@ typedef enum {
// get and set variables // get and set variables
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_LOADSCRIPT, // push script-local variable isn_arg.script.
ISN_LOADS, // push s: variable isn_arg.string
ISN_LOADG, // push g: variable isn_arg.string ISN_LOADG, // push g: variable isn_arg.string
ISN_LOADS, // push s: variable isn_arg.loadstore
ISN_LOADSCRIPT, // push script-local variable isn_arg.script.
ISN_LOADOPT, // push option isn_arg.string ISN_LOADOPT, // push option isn_arg.string
ISN_LOADENV, // push environment variable isn_arg.string ISN_LOADENV, // push environment variable isn_arg.string
ISN_LOADREG, // push register isn_arg.number ISN_LOADREG, // push register isn_arg.number
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_STOREG, // pop into global variable isn_arg.string ISN_STOREG, // pop into global variable isn_arg.string
ISN_STORES, // pop into scirpt variable isn_arg.loadstore
ISN_STORESCRIPT, // pop into scirpt variable isn_arg.script ISN_STORESCRIPT, // pop into scirpt variable isn_arg.script
ISN_STOREOPT, // pop into option isn_arg.string ISN_STOREOPT, // pop into option isn_arg.string
ISN_STOREENV, // pop into environment variable isn_arg.string
ISN_STOREREG, // pop into register isn_arg.number
// ISN_STOREOTHER, // pop into other script variable isn_arg.other. // ISN_STOREOTHER, // pop into other script variable isn_arg.other.
ISN_STORENR, // store number into local variable isn_arg.storenr.str_idx ISN_STORENR, // store number into local variable isn_arg.storenr.str_idx
@ -180,13 +184,13 @@ typedef struct {
int so_flags; int so_flags;
} storeopt_T; } storeopt_T;
// arguments to ISN_LOADS // arguments to ISN_LOADS and ISN_STORES
typedef struct { typedef struct {
char_u *ls_name; // variable name char_u *ls_name; // variable name
int ls_sid; // script ID int ls_sid; // script ID
} loads_T; } loadstore_T;
// arguments to ISN_LOADSCRIPT // arguments to ISN_LOADSCRIPT and ISN_STORESCRIPT
typedef struct { typedef struct {
int script_sid; // script ID int script_sid; // script ID
int script_idx; // index in sn_var_vals int script_idx; // index in sn_var_vals
@ -217,7 +221,7 @@ typedef struct {
checktype_T type; checktype_T type;
storenr_T storenr; storenr_T storenr;
storeopt_T storeopt; storeopt_T storeopt;
loads_T loads; loadstore_T loadstore;
script_T script; script_T script;
} isn_arg; } isn_arg;
} isn_T; } isn_T;

View File

@ -335,7 +335,7 @@ check_number_or_float(vartype_T type1, vartype_T type2, char_u *op)
|| type2 == VAR_UNKNOWN))) || type2 == VAR_UNKNOWN)))
{ {
if (*op == '+') if (*op == '+')
semsg(_("E1035: wrong argument type for +")); emsg(_("E1035: wrong argument type for +"));
else else
semsg(_("E1036: %c requires number or float arguments"), *op); semsg(_("E1036: %c requires number or float arguments"), *op);
return FAIL; return FAIL;
@ -720,21 +720,50 @@ generate_LOAD(
return OK; return OK;
} }
/*
* Generate an ISN_LOADV instruction.
*/
static int
generate_LOADV(
cctx_T *cctx,
char_u *name,
int error)
{
// load v:var
int vidx = find_vim_var(name);
if (vidx < 0)
{
if (error)
semsg(_(e_var_notfound), name);
return FAIL;
}
// TODO: get actual type
return generate_LOAD(cctx, ISN_LOADV, vidx, NULL, &t_any);
}
/* /*
* Generate an ISN_LOADS instruction. * Generate an ISN_LOADS instruction.
*/ */
static int static int
generate_LOADS( generate_OLDSCRIPT(
cctx_T *cctx, cctx_T *cctx,
isntype_T isn_type,
char_u *name, char_u *name,
int sid) int sid,
type_T *type)
{ {
isn_T *isn; isn_T *isn;
if ((isn = generate_instr_type(cctx, ISN_LOADS, &t_any)) == NULL) if (isn_type == ISN_LOADS)
isn = generate_instr_type(cctx, isn_type, type);
else
isn = generate_instr_drop(cctx, isn_type, 1);
if (isn == NULL)
return FAIL; return FAIL;
isn->isn_arg.loads.ls_name = vim_strsave(name); isn->isn_arg.loadstore.ls_name = vim_strsave(name);
isn->isn_arg.loads.ls_sid = sid; isn->isn_arg.loadstore.ls_sid = sid;
return OK; return OK;
} }
@ -743,7 +772,7 @@ generate_LOADS(
* Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction. * Generate an ISN_LOADSCRIPT or ISN_STORESCRIPT instruction.
*/ */
static int static int
generate_SCRIPT( generate_VIM9SCRIPT(
cctx_T *cctx, cctx_T *cctx,
isntype_T isn_type, isntype_T isn_type,
int sid, int sid,
@ -1476,13 +1505,14 @@ compile_load_scriptvar(cctx_T *cctx, char_u *name)
if (idx == -1) if (idx == -1)
{ {
// variable exists but is not in sn_var_vals: old style script. // variable exists but is not in sn_var_vals: old style script.
return generate_LOADS(cctx, name, current_sctx.sc_sid); return generate_OLDSCRIPT(cctx, ISN_LOADS, name, current_sctx.sc_sid,
&t_any);
} }
if (idx >= 0) if (idx >= 0)
{ {
svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx; svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx;
generate_SCRIPT(cctx, ISN_LOADSCRIPT, generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
current_sctx.sc_sid, idx, sv->sv_type); current_sctx.sc_sid, idx, sv->sv_type);
return OK; return OK;
} }
@ -1491,7 +1521,7 @@ compile_load_scriptvar(cctx_T *cctx, char_u *name)
if (import != NULL) if (import != NULL)
{ {
// TODO: check this is a variable, not a function // TODO: check this is a variable, not a function
generate_SCRIPT(cctx, ISN_LOADSCRIPT, generate_VIM9SCRIPT(cctx, ISN_LOADSCRIPT,
import->imp_sid, import->imp_sid,
import->imp_var_vals_idx, import->imp_var_vals_idx,
import->imp_type); import->imp_type);
@ -1523,18 +1553,7 @@ compile_load(char_u **arg, char_u *end, cctx_T *cctx, int error)
if (**arg == 'v') if (**arg == 'v')
{ {
// load v:var res = generate_LOADV(cctx, name, error);
int vidx = find_vim_var(name);
if (vidx < 0)
{
if (error)
semsg(_(e_var_notfound), name);
goto theend;
}
// TODO: get actual type
res = generate_LOAD(cctx, ISN_LOADV, vidx, NULL, &t_any);
} }
else if (**arg == 'g') else if (**arg == 'g')
{ {
@ -3071,6 +3090,9 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
int opt_type; int opt_type;
int opt_flags = 0; int opt_flags = 0;
int global = FALSE; int global = FALSE;
int env = FALSE;
int reg = FALSE;
int vimvaridx = -1;
int script = FALSE; int script = FALSE;
int oplen = 0; int oplen = 0;
int heredoc = FALSE; int heredoc = FALSE;
@ -3135,6 +3157,29 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
else else
type = &t_number; // both number and boolean option type = &t_number; // both number and boolean option
} }
else if (*arg == '$')
{
env = TRUE;
if (is_decl)
{
semsg(_("E1065: Cannot declare an environment variable: %s"), name);
goto theend;
}
}
else if (*arg == '@')
{
if (!valid_yank_reg(arg[1], TRUE))
{
emsg_invreg(arg[1]);
return FAIL;
}
reg = TRUE;
if (is_decl)
{
semsg(_("E1066: Cannot declare a register: %s"), name);
goto theend;
}
}
else if (STRNCMP(arg, "g:", 2) == 0) else if (STRNCMP(arg, "g:", 2) == 0)
{ {
global = TRUE; global = TRUE;
@ -3144,6 +3189,20 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
goto theend; goto theend;
} }
} }
else if (STRNCMP(arg, "v:", 2) == 0)
{
vimvaridx = find_vim_var(name + 2);
if (vimvaridx < 0)
{
semsg(_(e_var_notfound), arg);
goto theend;
}
if (is_decl)
{
semsg(_("E1064: Cannot declare a v: variable: %s"), name);
goto theend;
}
}
else else
{ {
for (idx = 0; reserved[idx] != NULL; ++idx) for (idx = 0; reserved[idx] != NULL; ++idx)
@ -3171,7 +3230,9 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
} }
} }
} }
else if (lookup_script(arg, varlen) == OK) else if ((STRNCMP(arg, "s:", 2) == 0
? lookup_script(arg + 2, varlen - 2)
: lookup_script(arg, varlen)) == OK)
{ {
script = TRUE; script = TRUE;
if (is_decl) if (is_decl)
@ -3226,7 +3287,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
} }
// +=, /=, etc. require an existing variable // +=, /=, etc. require an existing variable
if (idx < 0 && !global && !option) if (idx < 0 && !global && !env && !reg && !option)
{ {
if (oplen > 1 && !heredoc) if (oplen > 1 && !heredoc)
{ {
@ -3272,6 +3333,13 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
generate_LOAD(cctx, ISN_LOADOPT, 0, name + 1, type); generate_LOAD(cctx, ISN_LOADOPT, 0, name + 1, type);
else if (global) else if (global)
generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type); generate_LOAD(cctx, ISN_LOADG, 0, name + 2, type);
else if (env)
// Include $ in the name here
generate_LOAD(cctx, ISN_LOADENV, 0, name, type);
else if (reg)
generate_LOAD(cctx, ISN_LOADREG, arg[1], NULL, &t_string);
else if (vimvaridx >= 0)
generate_LOADV(cctx, name + 2, TRUE);
else else
generate_LOAD(cctx, ISN_LOAD, idx, NULL, type); generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
} }
@ -3362,12 +3430,25 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
if (option) if (option)
generate_STOREOPT(cctx, name + 1, opt_flags); generate_STOREOPT(cctx, name + 1, opt_flags);
else if (global) else if (global)
generate_STORE(cctx, ISN_STOREG, 0, name + 2); // include g: with the name, easier to execute that way
generate_STORE(cctx, ISN_STOREG, 0, name);
else if (env)
generate_STORE(cctx, ISN_STOREENV, 0, name + 1);
else if (reg)
generate_STORE(cctx, ISN_STOREREG, name[1], NULL);
else if (vimvaridx >= 0)
generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL);
else if (script) else if (script)
{ {
idx = get_script_item_idx(current_sctx.sc_sid, name, TRUE); char_u *rawname = name + (name[1] == ':' ? 2 : 0);
idx = get_script_item_idx(current_sctx.sc_sid, rawname, TRUE);
// TODO: specific type // TODO: specific type
generate_SCRIPT(cctx, ISN_STORESCRIPT, if (idx < 0)
generate_OLDSCRIPT(cctx, ISN_STORES, rawname,
current_sctx.sc_sid, &t_any);
else
generate_VIM9SCRIPT(cctx, ISN_STORESCRIPT,
current_sctx.sc_sid, idx, &t_any); current_sctx.sc_sid, idx, &t_any);
} }
else else
@ -4527,8 +4608,9 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
ea.cmd = skipwhite(ea.cmd); ea.cmd = skipwhite(ea.cmd);
// Assuming the command starts with a variable or function name, find // Assuming the command starts with a variable or function name, find
// what follows. Also "&opt = value". // what follows. Also "&opt = val", "$ENV = val" and "@r = val".
p = (*ea.cmd == '&') ? ea.cmd + 1 : ea.cmd; p = (*ea.cmd == '&' || *ea.cmd == '$' || *ea.cmd == '@')
? ea.cmd + 1 : ea.cmd;
p = to_name_end(p); p = to_name_end(p);
if (p > ea.cmd && *p != NUL) if (p > ea.cmd && *p != NUL)
{ {
@ -4554,7 +4636,11 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
// "g:var = expr" // "g:var = expr"
// "var = expr" where "var" is a local var name. // "var = expr" where "var" is a local var name.
// "&opt = expr" // "&opt = expr"
// "$ENV = expr"
// "@r = expr"
if (*ea.cmd == '&' if (*ea.cmd == '&'
|| *ea.cmd == '$'
|| *ea.cmd == '@'
|| ((p - ea.cmd) > 2 && ea.cmd[1] == ':') || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
|| lookup_local(ea.cmd, p - ea.cmd, &cctx) >= 0 || lookup_local(ea.cmd, p - ea.cmd, &cctx) >= 0
|| lookup_script(ea.cmd, p - ea.cmd) == OK) || lookup_script(ea.cmd, p - ea.cmd) == OK)
@ -4776,12 +4862,14 @@ delete_instr(isn_T *isn)
case ISN_MEMBER: case ISN_MEMBER:
case ISN_PUSHEXC: case ISN_PUSHEXC:
case ISN_PUSHS: case ISN_PUSHS:
case ISN_STOREENV:
case ISN_STOREG: case ISN_STOREG:
vim_free(isn->isn_arg.string); vim_free(isn->isn_arg.string);
break; break;
case ISN_LOADS: case ISN_LOADS:
vim_free(isn->isn_arg.loads.ls_name); case ISN_STORES:
vim_free(isn->isn_arg.loadstore.ls_name);
break; break;
case ISN_STOREOPT: case ISN_STOREOPT:
@ -4841,7 +4929,9 @@ delete_instr(isn_T *isn)
case ISN_PUSHSPEC: case ISN_PUSHSPEC:
case ISN_RETURN: case ISN_RETURN:
case ISN_STORE: case ISN_STORE:
case ISN_STOREV:
case ISN_STORENR: case ISN_STORENR:
case ISN_STOREREG:
case ISN_STORESCRIPT: case ISN_STORESCRIPT:
case ISN_THROW: case ISN_THROW:
case ISN_TRY: case ISN_TRY:

View File

@ -488,7 +488,7 @@ call_def_function(
++ectx.ec_stack.ga_len; ++ectx.ec_stack.ga_len;
break; break;
// load s: variable in vim9script // load s: variable in Vim9 script
case ISN_LOADSCRIPT: case ISN_LOADSCRIPT:
{ {
scriptitem_T *si = scriptitem_T *si =
@ -507,12 +507,13 @@ call_def_function(
// load s: variable in old script // load s: variable in old script
case ISN_LOADS: case ISN_LOADS:
{ {
hashtab_T *ht = &SCRIPT_VARS(iptr->isn_arg.loads.ls_sid); hashtab_T *ht = &SCRIPT_VARS(
char_u *name = iptr->isn_arg.loads.ls_name; iptr->isn_arg.loadstore.ls_sid);
char_u *name = iptr->isn_arg.loadstore.ls_name;
dictitem_T *di = find_var_in_ht(ht, 0, name, TRUE); dictitem_T *di = find_var_in_ht(ht, 0, name, TRUE);
if (di == NULL) if (di == NULL)
{ {
semsg(_("E121: Undefined variable: s:%s"), name); semsg(_(e_undefvar), name);
goto failed; goto failed;
} }
else else
@ -601,7 +602,26 @@ call_def_function(
*tv = *STACK_TV_BOT(0); *tv = *STACK_TV_BOT(0);
break; break;
// store script-local variable // store s: variable in old script
case ISN_STORES:
{
hashtab_T *ht = &SCRIPT_VARS(
iptr->isn_arg.loadstore.ls_sid);
char_u *name = iptr->isn_arg.loadstore.ls_name;
dictitem_T *di = find_var_in_ht(ht, 0, name, TRUE);
if (di == NULL)
{
semsg(_(e_undefvar), name);
goto failed;
}
--ectx.ec_stack.ga_len;
clear_tv(&di->di_tv);
di->di_tv = *STACK_TV_BOT(0);
}
break;
// store script-local variable in Vim9 script
case ISN_STORESCRIPT: case ISN_STORESCRIPT:
{ {
scriptitem_T *si = SCRIPT_ITEM( scriptitem_T *si = SCRIPT_ITEM(
@ -648,6 +668,32 @@ call_def_function(
} }
break; break;
// store $ENV
case ISN_STOREENV:
--ectx.ec_stack.ga_len;
vim_setenv_ext(iptr->isn_arg.string,
tv_get_string(STACK_TV_BOT(0)));
break;
// store @r
case ISN_STOREREG:
{
int reg = iptr->isn_arg.number;
--ectx.ec_stack.ga_len;
write_reg_contents(reg == '@' ? '"' : reg,
tv_get_string(STACK_TV_BOT(0)), -1, FALSE);
}
break;
// store v: variable
case ISN_STOREV:
--ectx.ec_stack.ga_len;
if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0))
== FAIL)
goto failed;
break;
// store g: variable // store g: variable
case ISN_STOREG: case ISN_STOREG:
{ {
@ -1583,7 +1629,8 @@ ex_disassemble(exarg_T *eap)
break; break;
case ISN_LOADS: case ISN_LOADS:
{ {
scriptitem_T *si = SCRIPT_ITEM(iptr->isn_arg.loads.ls_sid); scriptitem_T *si = SCRIPT_ITEM(
iptr->isn_arg.loadstore.ls_sid);
smsg("%4d LOADS s:%s from %s", current, smsg("%4d LOADS s:%s from %s", current,
iptr->isn_arg.string, si->sn_name); iptr->isn_arg.string, si->sn_name);
@ -1605,8 +1652,21 @@ ex_disassemble(exarg_T *eap)
case ISN_STORE: case ISN_STORE:
smsg("%4d STORE $%lld", current, iptr->isn_arg.number); smsg("%4d STORE $%lld", current, iptr->isn_arg.number);
break; break;
case ISN_STOREV:
smsg("%4d STOREV v:%s", current,
get_vim_var_name(iptr->isn_arg.number));
break;
case ISN_STOREG: case ISN_STOREG:
smsg("%4d STOREG g:%s", current, iptr->isn_arg.string); smsg("%4d STOREG %s", current, iptr->isn_arg.string);
break;
case ISN_STORES:
{
scriptitem_T *si = SCRIPT_ITEM(
iptr->isn_arg.loadstore.ls_sid);
smsg("%4d STORES s:%s in %s", current,
iptr->isn_arg.string, si->sn_name);
}
break; break;
case ISN_STORESCRIPT: case ISN_STORESCRIPT:
{ {
@ -1623,7 +1683,12 @@ ex_disassemble(exarg_T *eap)
smsg("%4d STOREOPT &%s", current, smsg("%4d STOREOPT &%s", current,
iptr->isn_arg.storeopt.so_name); iptr->isn_arg.storeopt.so_name);
break; break;
case ISN_STOREENV:
smsg("%4d STOREENV $%s", current, iptr->isn_arg.string);
break;
case ISN_STOREREG:
smsg("%4d STOREREG @%c", current, iptr->isn_arg.number);
break;
case ISN_STORENR: case ISN_STORENR:
smsg("%4d STORE %lld in $%d", current, smsg("%4d STORE %lld in $%d", current,
iptr->isn_arg.storenr.str_val, iptr->isn_arg.storenr.str_val,