Skip to content

Commit

Permalink
patch 8.2.0981: Vim9: cannot compile "[var, var] = list"
Browse files Browse the repository at this point in the history
Problem:    Vim9: cannot compile "[var, var] = list".
Solution:   Implement list assignment.
  • Loading branch information
brammool committed Jun 14, 2020
1 parent a65d8b5 commit 47a519a
Show file tree
Hide file tree
Showing 8 changed files with 741 additions and 558 deletions.
2 changes: 1 addition & 1 deletion src/eval.c
Expand Up @@ -1431,7 +1431,7 @@ eval_for_line(
if (fi == NULL)
return NULL;

expr = skip_var_list(arg, TRUE, &fi->fi_varcount, &fi->fi_semicolon);
expr = skip_var_list(arg, TRUE, &fi->fi_varcount, &fi->fi_semicolon, FALSE);
if (expr == NULL)
return fi;

Expand Down
28 changes: 17 additions & 11 deletions src/evalvars.c
Expand Up @@ -164,7 +164,6 @@ static dict_T vimvardict; // Dictionary with v: variables
// for VIM_VERSION_ defines
#include "version.h"

static char_u *skip_var_one(char_u *arg, int include_type);
static void list_glob_vars(int *first);
static void list_buf_vars(int *first);
static void list_win_vars(int *first);
Expand Down Expand Up @@ -709,7 +708,7 @@ ex_let(exarg_T *eap)
if (eap->arg == eap->cmd)
flags |= LET_NO_COMMAND;

argend = skip_var_list(arg, TRUE, &var_count, &semicolon);
argend = skip_var_list(arg, TRUE, &var_count, &semicolon, FALSE);
if (argend == NULL)
return;
if (argend > arg && argend[-1] == '.') // for var.='str'
Expand Down Expand Up @@ -916,15 +915,17 @@ ex_let_vars(
* Skip over assignable variable "var" or list of variables "[var, var]".
* Used for ":let varvar = expr" and ":for varvar in expr".
* For "[var, var]" increment "*var_count" for each variable.
* for "[var, var; var]" set "semicolon".
* for "[var, var; var]" set "semicolon" to 1.
* If "silent" is TRUE do not give an "invalid argument" error message.
* Return NULL for an error.
*/
char_u *
skip_var_list(
char_u *arg,
int include_type,
int *var_count,
int *semicolon)
int *semicolon,
int silent)
{
char_u *p, *s;

Expand All @@ -935,10 +936,11 @@ skip_var_list(
for (;;)
{
p = skipwhite(p + 1); // skip whites after '[', ';' or ','
s = skip_var_one(p, TRUE);
s = skip_var_one(p, FALSE);
if (s == p)
{
semsg(_(e_invarg2), p);
if (!silent)
semsg(_(e_invarg2), p);
return NULL;
}
++*var_count;
Expand All @@ -957,7 +959,8 @@ skip_var_list(
}
else if (*p != ',')
{
semsg(_(e_invarg2), p);
if (!silent)
semsg(_(e_invarg2), p);
return NULL;
}
}
Expand All @@ -972,7 +975,7 @@ skip_var_list(
* l[idx].
* In Vim9 script also skip over ": type" if "include_type" is TRUE.
*/
static char_u *
char_u *
skip_var_one(char_u *arg, int include_type)
{
char_u *end;
Expand All @@ -981,10 +984,13 @@ skip_var_one(char_u *arg, int include_type)
return arg + 2;
end = find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg,
NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
if (include_type && current_sctx.sc_version == SCRIPT_VERSION_VIM9
&& *end == ':')
if (include_type && current_sctx.sc_version == SCRIPT_VERSION_VIM9)
{
end = skip_type(skipwhite(end + 1));
// "a: type" is declaring variable "a" with a type, not "a:".
if (end == arg + 2 && end[-1] == ':')
--end;
if (*end == ':')
end = skip_type(skipwhite(end + 1));
}
return end;
}
Expand Down
3 changes: 2 additions & 1 deletion src/proto/evalvars.pro
Expand Up @@ -16,7 +16,8 @@ void restore_vimvar(int idx, typval_T *save_tv);
list_T *heredoc_get(exarg_T *eap, char_u *cmd, int script_get);
void ex_let(exarg_T *eap);
int ex_let_vars(char_u *arg_start, typval_T *tv, int copy, int semicolon, int var_count, int flags, char_u *op);
char_u *skip_var_list(char_u *arg, int include_type, int *var_count, int *semicolon);
char_u *skip_var_list(char_u *arg, int include_type, int *var_count, int *semicolon, int silent);
char_u *skip_var_one(char_u *arg, int include_type);
void list_hashtable_vars(hashtab_T *ht, char *prefix, int empty, int *first);
void ex_unlet(exarg_T *eap);
void ex_lockvar(exarg_T *eap);
Expand Down
8 changes: 8 additions & 0 deletions src/testdir/test_vim9_script.vim
Expand Up @@ -223,6 +223,14 @@ def Test_assignment_default()
assert_equal(5678, nr)
enddef

def Test_assignment_var_list()
let v1: string
let v2: string
[v1, v2] = ['one', 'two']
assert_equal('one', v1)
assert_equal('two', v2)
enddef

def Mess(): string
v:foldstart = 123
return 'xxx'
Expand Down
2 changes: 2 additions & 0 deletions src/version.c
Expand Up @@ -754,6 +754,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
/**/
981,
/**/
980,
/**/
Expand Down
1 change: 1 addition & 0 deletions src/vim9.h
Expand Up @@ -112,6 +112,7 @@ typedef enum {
// expression operations
ISN_CONCAT,
ISN_INDEX, // [expr] list index
ISN_GETITEM, // push list item, isn_arg.number is the index
ISN_MEMBER, // dict[member]
ISN_STRINGMEMBER, // dict.member using isn_arg.string
ISN_2BOOL, // convert value to bool, invert if isn_arg.number != 0
Expand Down

0 comments on commit 47a519a

Please sign in to comment.