]> granicus.if.org Git - vim/commitdiff
patch 8.2.1826: Vim9: cannot use a {} block at script level v8.2.1826
authorBram Moolenaar <Bram@vim.org>
Sat, 10 Oct 2020 19:33:48 +0000 (21:33 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 10 Oct 2020 19:33:48 +0000 (21:33 +0200)
Problem:    Vim9: cannot use a {} block at script level.
Solution:   Recognize a {} block.

src/errors.h
src/ex_cmdidxs.h
src/ex_cmds.h
src/ex_docmd.c
src/ex_eval.c
src/proto/ex_eval.pro
src/structs.h
src/testdir/test_vim9_script.vim
src/version.c

index cddd6910fe3e7f16a05acad22e8a359ff7a3ed19..c2dc633f161d9271a6559fd5268780b41d603660 100644 (file)
@@ -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
index 0f9eb39ff62c18b714be74104c1dc2164eb617f2..2e59d2c502ed00b00e0153cf64a899fb2e31e184 100644 (file)
@@ -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;
index 0c83f521f693805bd06fbd2df74ae30dff3a4efc..0b52c11ee022f21d3028cb49307d5d95336178ac 100644 (file)
@@ -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),
index 310934ed71efe274caf007675d65fe33bca1c39f..4a71989ddbda80221317a64baa2362a96745ffa0 100644 (file)
@@ -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'))
index d205cafc47e6244031672cf658af8b9a26fbfa0c..57c6178727d7f055f5298501733f668b4319632f 100644 (file)
@@ -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"
index 929f47987f35f7104f03c22617611c85443f4e7e..f1861612a589044a063cd47edda13a4194e21ac9 100644 (file)
@@ -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);
index 094b736ad283c2e785847c9a2f06c61c8b39128e..103c70c5e8dbd8acb760ecab4627f4d148d16580 100644 (file)
@@ -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
index 466b2d0788635ea22c08bd5bde5c4a3732df30e7..1edc773cc134c3d29e9ddfe7ac97d7faa3ffffc7 100644 (file)
@@ -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.
index 789e1049385ae7cdab7876cdba2c456347ac9195..6ff2aa08dba344a8fbec3cfbd3790bbc53ca9c49 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1826,
 /**/
     1825,
 /**/