summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-05-10 22:53:56 +0200
committerBram Moolenaar <Bram@vim.org>2020-05-10 22:53:56 +0200
commitcb2bdb1c6d8b6df4a3d9cfb1ad9e602dace5d310 (patch)
tree5b663eb24c488eeeb52eeae812905724dfd1a600
parentf163bd5e41e8ea1d32e7977e671598a9d6f7b23c (diff)
downloadvim-git-cb2bdb1c6d8b6df4a3d9cfb1ad9e602dace5d310.tar.gz
patch 8.2.0733: Vim9: assigning to dict or list argument does not workv8.2.0733
Problem: Vim9: assigning to dict or list argument does not work. Solution: Recognize an argument as assignment target.
-rw-r--r--src/testdir/test_vim9_func.vim20
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c36
3 files changed, 52 insertions, 6 deletions
diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim
index ab5f9ecd2..c74b4a451 100644
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -193,6 +193,26 @@ def Test_using_var_as_arg()
call delete('Xdef')
enddef
+def DictArg(arg: dict<string>)
+ arg['key'] = 'value'
+enddef
+
+def ListArg(arg: list<string>)
+ arg[0] = 'value'
+enddef
+
+def Test_assign_to_argument()
+ " works for dict and list
+ let d: dict<string> = {}
+ DictArg(d)
+ assert_equal('value', d['key'])
+ let l: list<string> = []
+ ListArg(l)
+ assert_equal('value', l[0])
+
+ call CheckScriptFailure(['def Func(arg: number)', 'arg = 3', 'enddef'], 'E1090:')
+enddef
+
def Test_call_func_defined_later()
call assert_equal('one', g:DefinedLater('one'))
call assert_fails('call NotDefined("one")', 'E117:')
diff --git a/src/version.c b/src/version.c
index 6a29592c1..9dc3c22e5 100644
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 733,
+/**/
732,
/**/
731,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 09e71aca3..c8c87e737 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -135,6 +135,7 @@ struct cctx_S {
static char e_var_notfound[] = N_("E1001: variable not found: %s");
static char e_syntax_at[] = N_("E1002: Syntax error at %s");
+static char e_used_as_arg[] = N_("E1006: %s is used as an argument");
static void delete_def_function_contents(dfunc_T *dfunc);
static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
@@ -1652,7 +1653,7 @@ reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
if (lookup_arg(name, len, NULL, NULL, NULL, cctx) == OK)
{
- emsg_namelen(_("E1006: %s is used as an argument"), name, (int)len);
+ emsg_namelen(_(e_used_as_arg), name, (int)len);
return NULL;
}
@@ -4592,6 +4593,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
type_T *type = &t_any;
type_T *member_type = &t_any;
lvar_T *lvar = NULL;
+ lvar_T arg_lvar;
char_u *name;
char_u *sp;
int has_type = FALSE;
@@ -4760,6 +4762,19 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
}
lvar = lookup_local(arg, varlen, cctx);
+ if (lvar == NULL
+ && lookup_arg(arg, varlen,
+ &arg_lvar.lv_idx, &arg_lvar.lv_type,
+ &arg_lvar.lv_from_outer, cctx) == OK)
+ {
+ if (is_decl)
+ {
+ semsg(_(e_used_as_arg), name);
+ goto theend;
+ }
+ arg_lvar.lv_const = 0;
+ lvar = &arg_lvar;
+ }
if (lvar != NULL)
{
if (is_decl)
@@ -4861,13 +4876,13 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
member_type = type;
if (var_end > arg + varlen)
{
+ // Something follows after the variable: "var[idx]".
if (is_decl)
{
emsg(_("E1087: cannot use an index when declaring a variable"));
goto theend;
}
- // Something follows after the variable: "var[idx]".
if (arg[varlen] == '[')
{
has_index = TRUE;
@@ -4884,6 +4899,11 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
goto theend;
}
}
+ else if (lvar == &arg_lvar)
+ {
+ semsg(_("E1090: Cannot assign to argument %s"), name);
+ goto theend;
+ }
if (heredoc)
{
@@ -6515,6 +6535,8 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
oplen = assignment_len(skipwhite(var_end), &heredoc);
if (oplen > 0)
{
+ size_t len = p - ea.cmd;
+
// Recognize an assignment if we recognize the variable
// name:
// "g:var = expr"
@@ -6527,10 +6549,12 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
if (*ea.cmd == '&'
|| *ea.cmd == '$'
|| *ea.cmd == '@'
- || ((p - ea.cmd) > 2 && ea.cmd[1] == ':')
- || lookup_local(ea.cmd, p - ea.cmd, &cctx) != NULL
- || lookup_script(ea.cmd, p - ea.cmd) == OK
- || find_imported(ea.cmd, p - ea.cmd, &cctx) != NULL)
+ || ((len) > 2 && ea.cmd[1] == ':')
+ || lookup_local(ea.cmd, len, &cctx) != NULL
+ || lookup_arg(ea.cmd, len, NULL, NULL,
+ NULL, &cctx) == OK
+ || lookup_script(ea.cmd, len) == OK
+ || find_imported(ea.cmd, len, &cctx) != NULL)
{
line = compile_assignment(ea.cmd, &ea, CMD_SIZE, &cctx);
if (line == NULL)