]> granicus.if.org Git - vim/commitdiff
patch 8.2.0733: Vim9: assigning to dict or list argument does not work v8.2.0733
authorBram Moolenaar <Bram@vim.org>
Sun, 10 May 2020 20:53:56 +0000 (22:53 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 10 May 2020 20:53:56 +0000 (22:53 +0200)
Problem:    Vim9: assigning to dict or list argument does not work.
Solution:   Recognize an argument as assignment target.

src/testdir/test_vim9_func.vim
src/version.c
src/vim9compile.c

index ab5f9ecd2d259378a5343970218ba3efb48f0487..c74b4a4510c37317a89ba85e40a2fdf62ec4c64f 100644 (file)
@@ -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:')
index 6a29592c15ad52397e0e02bbeb41842407a88285..9dc3c22e53e10a37f72118a4151ab95ed2c012b4 100644 (file)
@@ -746,6 +746,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    733,
 /**/
     732,
 /**/
index 09e71aca357637028ef90b92cdf8a36f2b897f57..c8c87e737f6abcb78aad31f4a2620f0a4616661a 100644 (file)
@@ -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)