summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-01-01 21:05:55 +0100
committerBram Moolenaar <Bram@vim.org>2021-01-01 21:05:55 +0100
commit3862ea3f620f02569c2d816ca9ceeeac3a0ad901 (patch)
tree142ce0edacba0966db6d43a86db0af5f7d8eedf9
parentc368957b1904bfaa2b0b52bbcade51b20173f3ed (diff)
downloadvim-git-3862ea3f620f02569c2d816ca9ceeeac3a0ad901.tar.gz
patch 8.2.2268: Vim9: list unpack seen as declarationv8.2.2268
Problem: Vim9: list unpack seen as declaration. Solution: Check for "var". (closes #7594)
-rw-r--r--src/eval.c2
-rw-r--r--src/evalvars.c26
-rw-r--r--src/testdir/test_vim9_assign.vim30
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h1
-rw-r--r--src/vim9compile.c6
-rw-r--r--src/vim9execute.c2
7 files changed, 54 insertions, 15 deletions
diff --git a/src/eval.c b/src/eval.c
index b4b04eb63..ca1c55b4d 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1748,7 +1748,7 @@ next_for_item(void *fi_void, char_u *arg)
{
forinfo_T *fi = (forinfo_T *)fi_void;
int result;
- int flag = in_vim9script() ? ASSIGN_NO_DECL : 0;
+ int flag = in_vim9script() ? ASSIGN_DECL : 0;
listitem_T *item;
if (fi->fi_blob != NULL)
diff --git a/src/evalvars.c b/src/evalvars.c
index 73b9f3d0f..94b857ed9 100644
--- a/src/evalvars.c
+++ b/src/evalvars.c
@@ -912,7 +912,7 @@ ex_let_vars(
int copy, // copy values from "tv", don't move
int semicolon, // from skip_var_list()
int var_count, // from skip_var_list()
- int flags, // ASSIGN_FINAL, ASSIGN_CONST, ASSIGN_NO_DECL
+ int flags, // ASSIGN_FINAL, ASSIGN_CONST, etc.
char_u *op)
{
char_u *arg = arg_start;
@@ -1267,7 +1267,7 @@ ex_let_one(
char_u *arg, // points to variable name
typval_T *tv, // value to assign to variable
int copy, // copy value from "tv"
- int flags, // ASSIGN_CONST, ASSIGN_FINAL, ASSIGN_NO_DECL
+ int flags, // ASSIGN_CONST, ASSIGN_FINAL, etc.
char_u *endchars, // valid chars after variable name or NULL
char_u *op) // "+", "-", "." or NULL
{
@@ -1279,7 +1279,7 @@ ex_let_one(
int opt_flags;
char_u *tofree = NULL;
- if (in_vim9script() && (flags & ASSIGN_NO_DECL) == 0
+ if (in_vim9script() && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0
&& (flags & (ASSIGN_CONST | ASSIGN_FINAL)) == 0
&& vim_strchr((char_u *)"$@&", *arg) != NULL)
{
@@ -1476,7 +1476,8 @@ ex_let_one(
lval_T lv;
p = get_lval(arg, tv, &lv, FALSE, FALSE,
- (flags & ASSIGN_NO_DECL) ? GLV_NO_DECL : 0, FNE_CHECK_START);
+ (flags & (ASSIGN_NO_DECL | ASSIGN_DECL))
+ ? GLV_NO_DECL : 0, FNE_CHECK_START);
if (p != NULL && lv.ll_name != NULL)
{
if (endchars != NULL && vim_strchr(endchars,
@@ -3053,7 +3054,7 @@ set_var(
typval_T *tv,
int copy) // make copy of value in "tv"
{
- set_var_const(name, NULL, tv, copy, ASSIGN_NO_DECL);
+ set_var_const(name, NULL, tv, copy, ASSIGN_DECL);
}
/*
@@ -3067,7 +3068,7 @@ set_var_const(
type_T *type,
typval_T *tv_arg,
int copy, // make copy of value in "tv"
- int flags) // ASSIGN_CONST, ASSIGN_FINAL, ASSIGN_NO_DECL
+ int flags) // ASSIGN_CONST, ASSIGN_FINAL, etc.
{
typval_T *tv = tv_arg;
typval_T bool_tv;
@@ -3087,7 +3088,7 @@ set_var_const(
if (vim9script
&& !is_script_local
- && (flags & ASSIGN_NO_DECL) == 0
+ && (flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0
&& (flags & (ASSIGN_CONST | ASSIGN_FINAL)) == 0
&& name[1] == ':')
{
@@ -3126,7 +3127,7 @@ set_var_const(
if (is_script_local && vim9script)
{
- if ((flags & ASSIGN_NO_DECL) == 0)
+ if ((flags & (ASSIGN_NO_DECL | ASSIGN_DECL)) == 0)
{
semsg(_(e_redefining_script_item_str), name);
goto failed;
@@ -3200,8 +3201,15 @@ set_var_const(
clear_tv(&di->di_tv);
}
- else // add a new variable
+ else
{
+ // add a new variable
+ if (vim9script && is_script_local && (flags & ASSIGN_NO_DECL))
+ {
+ semsg(_(e_unknown_variable_str), name);
+ goto failed;
+ }
+
// Can't add "v:" or "a:" variable.
if (ht == &vimvarht || ht == get_funccal_args_ht())
{
diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim
index d884a4f7a..5f45b57a1 100644
--- a/src/testdir/test_vim9_assign.vim
+++ b/src/testdir/test_vim9_assign.vim
@@ -262,6 +262,12 @@ def Test_assign_unpack()
CheckDefFailure(lines, 'E1031:', 3)
lines =<< trim END
+ [v1, v2] = [1, 2]
+ END
+ CheckDefFailure(lines, 'E1089', 1)
+ CheckScriptFailure(['vim9script'] + lines, 'E1089', 2)
+
+ lines =<< trim END
var v1: number
var v2: number
[v1, v2] = ''
@@ -759,6 +765,8 @@ def Test_assignment_default()
assert_equal(5678, nr)
enddef
+let scriptvar = 'init'
+
def Test_assignment_var_list()
var lines =<< trim END
var v1: string
@@ -794,10 +802,9 @@ def Test_assignment_var_list()
assert_equal('some', $SOME_VAR)
assert_equal('other', $OTHER_VAR)
- [g:globalvar, s:scriptvar, b:bufvar, w:winvar, t:tabvar, v:errmsg] =
- ['global', 'script', 'buf', 'win', 'tab', 'error']
+ [g:globalvar, b:bufvar, w:winvar, t:tabvar, v:errmsg] =
+ ['global', 'buf', 'win', 'tab', 'error']
assert_equal('global', g:globalvar)
- assert_equal('script', s:scriptvar)
assert_equal('buf', b:bufvar)
assert_equal('win', w:winvar)
assert_equal('tab', t:tabvar)
@@ -805,6 +812,21 @@ def Test_assignment_var_list()
unlet g:globalvar
END
CheckDefAndScriptSuccess(lines)
+
+ [g:globalvar, s:scriptvar, b:bufvar] = ['global', 'script', 'buf']
+ assert_equal('global', g:globalvar)
+ assert_equal('script', s:scriptvar)
+ assert_equal('buf', b:bufvar)
+
+ lines =<< trim END
+ vim9script
+ var s:scriptvar = 'init'
+ [g:globalvar, s:scriptvar, w:winvar] = ['global', 'script', 'win']
+ assert_equal('global', g:globalvar)
+ assert_equal('script', s:scriptvar)
+ assert_equal('win', w:winvar)
+ END
+ CheckScriptSuccess(lines)
enddef
def Test_assignment_vim9script()
@@ -1182,7 +1204,7 @@ def Test_var_declaration()
g:other_var = other
# type is inferred
- s:dict = {['a']: 222}
+ var s:dict = {['a']: 222}
def GetDictVal(key: any)
g:dict_val = s:dict[key]
enddef
diff --git a/src/version.c b/src/version.c
index 1c5c6b39f..76a9b4ea9 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2268,
+/**/
2267,
/**/
2266,
diff --git a/src/vim.h b/src/vim.h
index f19a4fe97..a0ee0d6b9 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -2146,6 +2146,7 @@ typedef enum {
#define ASSIGN_FINAL 1 // ":final"
#define ASSIGN_CONST 2 // ":const"
#define ASSIGN_NO_DECL 4 // "name = expr" without ":let"/":const"/":final"
+#define ASSIGN_DECL 8 // may declare variable if it does not exist
#include "ex_cmds.h" // Ex command defines
#include "spell.h" // spell checking stuff
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 19d8473fb..303573f91 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -5634,6 +5634,11 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
semsg(_(e_cannot_use_operator_on_new_variable), name);
goto theend;
}
+ if (!is_decl)
+ {
+ semsg(_(e_unknown_variable_str), name);
+ goto theend;
+ }
// new local variable
if ((type->tt_type == VAR_FUNC || type->tt_type == VAR_PARTIAL)
@@ -6140,6 +6145,7 @@ compile_unletlock(char_u *arg, exarg_T *eap, cctx_T *cctx)
return NULL;
}
+ // TODO: this doesn't work for local variables
ex_unletlock(eap, p, 0, GLV_NO_AUTOLOAD, compile_unlet, cctx);
return eap->nextcmd == NULL ? (char_u *)"" : eap->nextcmd;
}
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 31b127402..b389891df 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -806,7 +806,7 @@ store_var(char_u *name, typval_T *tv)
funccal_entry_T entry;
save_funccal(&entry);
- set_var_const(name, NULL, tv, FALSE, ASSIGN_NO_DECL);
+ set_var_const(name, NULL, tv, FALSE, ASSIGN_DECL);
restore_funccal();
}