# HG changeset patch # User Bram Moolenaar # Date 1602359106 -7200 # Node ID 7d25264c246c2d2f62073724821a231f78726a31 # Parent 0ecf643db43531787215446d54140225f99c87ef patch 8.2.1826: Vim9: cannot use a {} block at script level Commit: https://github.com/vim/vim/commit/9becdf2b98e56d5eb193f3413d706ea433269216 Author: Bram Moolenaar Date: Sat Oct 10 21:33:48 2020 +0200 patch 8.2.1826: Vim9: cannot use a {} block at script level Problem: Vim9: cannot use a {} block at script level. Solution: Recognize a {} block. diff --git a/src/errors.h b/src/errors.h --- a/src/errors.h +++ b/src/errors.h @@ -278,4 +278,6 @@ EXTERN char e_cannot_use_let_in_vim9_scr 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 --- a/src/ex_cmdidxs.h +++ b/src/ex_cmdidxs.h @@ -69,4 +69,4 @@ static const unsigned char cmdidxs2[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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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 --- 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,