summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-10-10 21:33:48 +0200
committerBram Moolenaar <Bram@vim.org>2020-10-10 21:33:48 +0200
commit9becdf2b98e56d5eb193f3413d706ea433269216 (patch)
tree5733bdcc5289fed0156acb11d6e9e32bef266a06 /src
parentd747548c664815bb6e8520afa90b6108e1997591 (diff)
patch 8.2.1826: Vim9: cannot use a {} block at script levelv8.2.1826
Problem: Vim9: cannot use a {} block at script level. Solution: Recognize a {} block.
Diffstat (limited to 'src')
-rw-r--r--src/errors.h2
-rw-r--r--src/ex_cmdidxs.h2
-rw-r--r--src/ex_cmds.h6
-rw-r--r--src/ex_docmd.c10
-rw-r--r--src/ex_eval.c35
-rw-r--r--src/proto/ex_eval.pro2
-rw-r--r--src/structs.h1
-rw-r--r--src/testdir/test_vim9_script.vim21
-rw-r--r--src/version.c2
9 files changed, 76 insertions, 5 deletions
diff --git a/src/errors.h b/src/errors.h
index cddd6910fe..c2dc633f16 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -278,4 +278,6 @@ EXTERN char e_cannot_use_let_in_vim9_script[]
INIT(= N_("E1126: Cannot use :let in Vim9 script"));
EXTERN char e_missing_name_after_dot[]
INIT(= N_("E1127: Missing name after dot"));
+EXTERN char e_endblock_without_block[]
+ INIT(= N_("E1128: } without {"));
#endif
diff --git a/src/ex_cmdidxs.h b/src/ex_cmdidxs.h
index 0f9eb39ff6..2e59d2c502 100644
--- a/src/ex_cmdidxs.h
+++ b/src/ex_cmdidxs.h
@@ -69,4 +69,4 @@ static const unsigned char cmdidxs2[26][26] =
/* z */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
-static const int command_count = 571;
+static const int command_count = 573;
diff --git a/src/ex_cmds.h b/src/ex_cmds.h
index 0c83f521f6..0b52c11ee0 100644
--- a/src/ex_cmds.h
+++ b/src/ex_cmds.h
@@ -1812,6 +1812,12 @@ EXCMD(CMD_rshift, ">", ex_operators,
EXCMD(CMD_at, "@", ex_at,
EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
ADDR_LINES),
+EXCMD(CMD_block, "{{{{{{{{", ex_block, // not found normally
+ 0,
+ ADDR_NONE),
+EXCMD(CMD_endblock, "}", ex_endblock,
+ EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
+ ADDR_NONE),
EXCMD(CMD_tilde, "~", ex_substitute,
EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY,
ADDR_LINES),
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 310934ed71..4a71989ddb 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -3222,7 +3222,7 @@ find_ex_command(
*p == '('
|| (p == eap->cmd
? (
- // "{..." is an dict expression.
+ // "{..." is a dict expression or block start.
*eap->cmd == '{'
// "'string'->func()" is an expression.
|| *eap->cmd == '\''
@@ -3234,6 +3234,12 @@ find_ex_command(
// "varname->func()" is an expression.
: (*p == '-' && p[1] == '>')))
{
+ if (*eap->cmd == '{' && ends_excmd(*skipwhite(eap->cmd + 1)))
+ {
+ // "{" by itself is the start of a block.
+ eap->cmdidx = CMD_block;
+ return eap->cmd + 1;
+ }
eap->cmdidx = CMD_eval;
return eap->cmd;
}
@@ -3355,7 +3361,7 @@ find_ex_command(
}
// check for non-alpha command
- if (p == eap->cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL)
+ if (p == eap->cmd && vim_strchr((char_u *)"@*!=><&~#}", *p) != NULL)
++p;
len = (int)(p - eap->cmd);
if (*eap->cmd == 'd' && (p[-1] == 'l' || p[-1] == 'p'))
diff --git a/src/ex_eval.c b/src/ex_eval.c
index d205cafc47..57c6178727 100644
--- a/src/ex_eval.c
+++ b/src/ex_eval.c
@@ -1002,7 +1002,7 @@ ex_endif(exarg_T *eap)
did_endif = TRUE;
if (cstack->cs_idx < 0
|| (cstack->cs_flags[cstack->cs_idx]
- & (CSF_WHILE | CSF_FOR | CSF_TRY)))
+ & (CSF_WHILE | CSF_FOR | CSF_TRY | CSF_BLOCK)))
eap->errmsg = _(e_endif_without_if);
else
{
@@ -1043,7 +1043,7 @@ ex_else(exarg_T *eap)
if (cstack->cs_idx < 0
|| (cstack->cs_flags[cstack->cs_idx]
- & (CSF_WHILE | CSF_FOR | CSF_TRY)))
+ & (CSF_WHILE | CSF_FOR | CSF_TRY | CSF_BLOCK)))
{
if (eap->cmdidx == CMD_else)
{
@@ -1375,6 +1375,37 @@ ex_endwhile(exarg_T *eap)
}
}
+/*
+ * "{" start of a block in Vim9 script
+ */
+ void
+ex_block(exarg_T *eap)
+{
+ cstack_T *cstack = eap->cstack;
+
+ if (cstack->cs_idx == CSTACK_LEN - 1)
+ eap->errmsg = _("E579: block nesting too deep");
+ else
+ {
+ enter_block(cstack);
+ cstack->cs_flags[cstack->cs_idx] = CSF_BLOCK | CSF_ACTIVE | CSF_TRUE;
+ }
+}
+
+/*
+ * "}" end of a block in Vim9 script
+ */
+ void
+ex_endblock(exarg_T *eap)
+{
+ cstack_T *cstack = eap->cstack;
+
+ if (cstack->cs_idx < 0
+ || (cstack->cs_flags[cstack->cs_idx] & CSF_BLOCK) == 0)
+ eap->errmsg = _(e_endblock_without_block);
+ else
+ leave_block(cstack);
+}
/*
* ":throw expr"
diff --git a/src/proto/ex_eval.pro b/src/proto/ex_eval.pro
index 929f47987f..f1861612a5 100644
--- a/src/proto/ex_eval.pro
+++ b/src/proto/ex_eval.pro
@@ -20,6 +20,8 @@ void ex_while(exarg_T *eap);
void ex_continue(exarg_T *eap);
void ex_break(exarg_T *eap);
void ex_endwhile(exarg_T *eap);
+void ex_block(exarg_T *eap);
+void ex_endblock(exarg_T *eap);
void ex_throw(exarg_T *eap);
void do_throw(cstack_T *cstack);
void ex_try(exarg_T *eap);
diff --git a/src/structs.h b/src/structs.h
index 094b736ad2..103c70c5e8 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -907,6 +907,7 @@ typedef struct {
# define CSF_ELSE 0x0004 // ":else" has been passed
# define CSF_WHILE 0x0008 // is a ":while"
# define CSF_FOR 0x0010 // is a ":for"
+# define CSF_BLOCK 0x0020 // is a "{" block
# define CSF_TRY 0x0100 // is a ":try"
# define CSF_FINALLY 0x0200 // ":finally" has been passed
diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim
index 466b2d0788..1edc773cc1 100644
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -2733,6 +2733,27 @@ def Test_script_var_scope()
echo one
END
CheckScriptFailure(lines, 'E121:', 6)
+
+ lines =<< trim END
+ vim9script
+ {
+ var one = 'one'
+ assert_equal('one', one)
+ }
+ assert_false(exists('one'))
+ assert_false(exists('s:one'))
+ END
+ CheckScriptSuccess(lines)
+
+ lines =<< trim END
+ vim9script
+ {
+ var one = 'one'
+ echo one
+ }
+ echo one
+ END
+ CheckScriptFailure(lines, 'E121:', 6)
enddef
" Keep this last, it messes up highlighting.
diff --git a/src/version.c b/src/version.c
index 789e104938..6ff2aa08db 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 */
/**/
+ 1826,
+/**/
1825,
/**/
1824,