mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.2.0981: Vim9: cannot compile "[var, var] = list"
Problem: Vim9: cannot compile "[var, var] = list". Solution: Implement list assignment.
This commit is contained in:
@@ -1431,7 +1431,7 @@ eval_for_line(
|
|||||||
if (fi == NULL)
|
if (fi == NULL)
|
||||||
return 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)
|
if (expr == NULL)
|
||||||
return fi;
|
return fi;
|
||||||
|
|
||||||
|
@@ -164,7 +164,6 @@ static dict_T vimvardict; // Dictionary with v: variables
|
|||||||
// for VIM_VERSION_ defines
|
// for VIM_VERSION_ defines
|
||||||
#include "version.h"
|
#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_glob_vars(int *first);
|
||||||
static void list_buf_vars(int *first);
|
static void list_buf_vars(int *first);
|
||||||
static void list_win_vars(int *first);
|
static void list_win_vars(int *first);
|
||||||
@@ -709,7 +708,7 @@ ex_let(exarg_T *eap)
|
|||||||
if (eap->arg == eap->cmd)
|
if (eap->arg == eap->cmd)
|
||||||
flags |= LET_NO_COMMAND;
|
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)
|
if (argend == NULL)
|
||||||
return;
|
return;
|
||||||
if (argend > arg && argend[-1] == '.') // for var.='str'
|
if (argend > arg && argend[-1] == '.') // for var.='str'
|
||||||
@@ -916,7 +915,8 @@ ex_let_vars(
|
|||||||
* Skip over assignable variable "var" or list of variables "[var, var]".
|
* Skip over assignable variable "var" or list of variables "[var, var]".
|
||||||
* Used for ":let varvar = expr" and ":for varvar in expr".
|
* Used for ":let varvar = expr" and ":for varvar in expr".
|
||||||
* For "[var, var]" increment "*var_count" for each variable.
|
* 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.
|
* Return NULL for an error.
|
||||||
*/
|
*/
|
||||||
char_u *
|
char_u *
|
||||||
@@ -924,7 +924,8 @@ skip_var_list(
|
|||||||
char_u *arg,
|
char_u *arg,
|
||||||
int include_type,
|
int include_type,
|
||||||
int *var_count,
|
int *var_count,
|
||||||
int *semicolon)
|
int *semicolon,
|
||||||
|
int silent)
|
||||||
{
|
{
|
||||||
char_u *p, *s;
|
char_u *p, *s;
|
||||||
|
|
||||||
@@ -935,10 +936,11 @@ skip_var_list(
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
p = skipwhite(p + 1); // skip whites after '[', ';' or ','
|
p = skipwhite(p + 1); // skip whites after '[', ';' or ','
|
||||||
s = skip_var_one(p, TRUE);
|
s = skip_var_one(p, FALSE);
|
||||||
if (s == p)
|
if (s == p)
|
||||||
{
|
{
|
||||||
semsg(_(e_invarg2), p);
|
if (!silent)
|
||||||
|
semsg(_(e_invarg2), p);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
++*var_count;
|
++*var_count;
|
||||||
@@ -957,7 +959,8 @@ skip_var_list(
|
|||||||
}
|
}
|
||||||
else if (*p != ',')
|
else if (*p != ',')
|
||||||
{
|
{
|
||||||
semsg(_(e_invarg2), p);
|
if (!silent)
|
||||||
|
semsg(_(e_invarg2), p);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -972,7 +975,7 @@ skip_var_list(
|
|||||||
* l[idx].
|
* l[idx].
|
||||||
* In Vim9 script also skip over ": type" if "include_type" is TRUE.
|
* 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)
|
skip_var_one(char_u *arg, int include_type)
|
||||||
{
|
{
|
||||||
char_u *end;
|
char_u *end;
|
||||||
@@ -981,10 +984,13 @@ skip_var_one(char_u *arg, int include_type)
|
|||||||
return arg + 2;
|
return arg + 2;
|
||||||
end = find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg,
|
end = find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg,
|
||||||
NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
|
NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
|
||||||
if (include_type && current_sctx.sc_version == SCRIPT_VERSION_VIM9
|
if (include_type && current_sctx.sc_version == SCRIPT_VERSION_VIM9)
|
||||||
&& *end == ':')
|
|
||||||
{
|
{
|
||||||
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;
|
return end;
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
list_T *heredoc_get(exarg_T *eap, char_u *cmd, int script_get);
|
||||||
void ex_let(exarg_T *eap);
|
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);
|
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 list_hashtable_vars(hashtab_T *ht, char *prefix, int empty, int *first);
|
||||||
void ex_unlet(exarg_T *eap);
|
void ex_unlet(exarg_T *eap);
|
||||||
void ex_lockvar(exarg_T *eap);
|
void ex_lockvar(exarg_T *eap);
|
||||||
|
@@ -223,6 +223,14 @@ def Test_assignment_default()
|
|||||||
assert_equal(5678, nr)
|
assert_equal(5678, nr)
|
||||||
enddef
|
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
|
def Mess(): string
|
||||||
v:foldstart = 123
|
v:foldstart = 123
|
||||||
return 'xxx'
|
return 'xxx'
|
||||||
|
@@ -754,6 +754,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 */
|
||||||
|
/**/
|
||||||
|
981,
|
||||||
/**/
|
/**/
|
||||||
980,
|
980,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -112,6 +112,7 @@ typedef enum {
|
|||||||
// expression operations
|
// expression operations
|
||||||
ISN_CONCAT,
|
ISN_CONCAT,
|
||||||
ISN_INDEX, // [expr] list index
|
ISN_INDEX, // [expr] list index
|
||||||
|
ISN_GETITEM, // push list item, isn_arg.number is the index
|
||||||
ISN_MEMBER, // dict[member]
|
ISN_MEMBER, // dict[member]
|
||||||
ISN_STRINGMEMBER, // dict.member using isn_arg.string
|
ISN_STRINGMEMBER, // dict.member using isn_arg.string
|
||||||
ISN_2BOOL, // convert value to bool, invert if isn_arg.number != 0
|
ISN_2BOOL, // convert value to bool, invert if isn_arg.number != 0
|
||||||
|
1286
src/vim9compile.c
1286
src/vim9compile.c
File diff suppressed because it is too large
Load Diff
@@ -2114,6 +2114,31 @@ call_def_function(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ISN_GETITEM:
|
||||||
|
{
|
||||||
|
listitem_T *li;
|
||||||
|
int index = iptr->isn_arg.number;
|
||||||
|
|
||||||
|
// get list item: list is at stack-1, push item
|
||||||
|
tv = STACK_TV_BOT(-1);
|
||||||
|
if (tv->v_type != VAR_LIST)
|
||||||
|
{
|
||||||
|
emsg(_(e_listreq));
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
if ((li = list_find(tv->vval.v_list, index)) == NULL)
|
||||||
|
{
|
||||||
|
semsg(_(e_listidx), index);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
|
||||||
|
goto failed;
|
||||||
|
++ectx.ec_stack.ga_len;
|
||||||
|
copy_tv(&li->li_tv, STACK_TV_BOT(-1));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case ISN_MEMBER:
|
case ISN_MEMBER:
|
||||||
{
|
{
|
||||||
dict_T *dict;
|
dict_T *dict;
|
||||||
@@ -2789,6 +2814,8 @@ ex_disassemble(exarg_T *eap)
|
|||||||
// expression operations
|
// expression operations
|
||||||
case ISN_CONCAT: smsg("%4d CONCAT", current); break;
|
case ISN_CONCAT: smsg("%4d CONCAT", current); break;
|
||||||
case ISN_INDEX: smsg("%4d INDEX", current); break;
|
case ISN_INDEX: smsg("%4d INDEX", current); break;
|
||||||
|
case ISN_GETITEM: smsg("%4d ITEM %lld",
|
||||||
|
current, iptr->isn_arg.number); break;
|
||||||
case ISN_MEMBER: smsg("%4d MEMBER", current); break;
|
case ISN_MEMBER: smsg("%4d MEMBER", current); break;
|
||||||
case ISN_STRINGMEMBER: smsg("%4d MEMBER %s", current,
|
case ISN_STRINGMEMBER: smsg("%4d MEMBER %s", current,
|
||||||
iptr->isn_arg.string); break;
|
iptr->isn_arg.string); break;
|
||||||
|
Reference in New Issue
Block a user