]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.2.2194: Vim9: cannot use :const or :final at the script level v8.2.2194
authorBram Moolenaar <Bram@vim.org>
Tue, 22 Dec 2020 20:19:39 +0000 (21:19 +0100)
committerBram Moolenaar <Bram@vim.org>
Tue, 22 Dec 2020 20:19:39 +0000 (21:19 +0100)
Problem:    Vim9: cannot use :const or :final at the script level.
Solution:   Support using :const and :final. (closes #7526)

src/evalvars.c
src/testdir/test_vim9_assign.vim
src/testdir/test_vim9_func.vim
src/version.c
src/vim.h

index ec3f508ed3fcc51843ed9d1da511913770cccf64..7c4cc7a1a815a58d981cc70f678892cc8aefbbd9 100644 (file)
@@ -738,14 +738,14 @@ ex_let(exarg_T *eap)
     int                first = TRUE;
     int                concat;
     int                has_assign;
-    int                flags = eap->cmdidx == CMD_const ? ASSIGN_CONST : 0;
+    int                flags = 0;
     int                vim9script = in_vim9script();
 
     if (eap->cmdidx == CMD_final && !vim9script)
     {
-           // In legacy Vim script ":final" is short for ":finally".
-           ex_finally(eap);
-           return;
+       // In legacy Vim script ":final" is short for ":finally".
+       ex_finally(eap);
+       return;
     }
     if (eap->cmdidx == CMD_let && vim9script)
     {
@@ -756,7 +756,12 @@ ex_let(exarg_T *eap)
        // In legacy Vim script ":const" works like ":final".
        eap->cmdidx = CMD_final;
 
-    // detect Vim9 assignment without ":let" or ":const"
+    if (eap->cmdidx == CMD_const)
+       flags |= ASSIGN_CONST;
+    else if (eap->cmdidx == CMD_final)
+       flags |= ASSIGN_FINAL;
+
+    // Vim9 assignment without ":let", ":const" or ":final"
     if (eap->arg == eap->cmd)
        flags |= ASSIGN_NO_DECL;
 
@@ -909,7 +914,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_CONST, ASSIGN_NO_DECL
+    int                flags,          // ASSIGN_FINAL, ASSIGN_CONST, ASSIGN_NO_DECL
     char_u     *op)
 {
     char_u     *arg = arg_start;
@@ -1264,7 +1269,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_NO_DECL
+    int                flags,          // ASSIGN_CONST, ASSIGN_FINAL, ASSIGN_NO_DECL
     char_u     *endchars,      // valid chars after variable name  or NULL
     char_u     *op)            // "+", "-", "."  or NULL
 {
@@ -1277,6 +1282,7 @@ ex_let_one(
     char_u     *tofree = NULL;
 
     if (in_vim9script() && (flags & ASSIGN_NO_DECL) == 0
+                       && (flags & (ASSIGN_CONST | ASSIGN_FINAL)) == 0
                                  && vim_strchr((char_u *)"$@&", *arg) != NULL)
     {
        vim9_declare_error(arg);
@@ -1286,7 +1292,7 @@ ex_let_one(
     // ":let $VAR = expr": Set environment variable.
     if (*arg == '$')
     {
-       if (flags & ASSIGN_CONST)
+       if (flags & (ASSIGN_CONST | ASSIGN_FINAL))
        {
            emsg(_("E996: Cannot lock an environment variable"));
            return NULL;
@@ -1338,7 +1344,7 @@ ex_let_one(
     // ":let &g:option = expr": Set global option value.
     else if (*arg == '&')
     {
-       if (flags & ASSIGN_CONST)
+       if (flags & (ASSIGN_CONST | ASSIGN_FINAL))
        {
            emsg(_(e_const_option));
            return NULL;
@@ -1422,7 +1428,7 @@ ex_let_one(
     // ":let @r = expr": Set register contents.
     else if (*arg == '@')
     {
-       if (flags & ASSIGN_CONST)
+       if (flags & (ASSIGN_CONST | ASSIGN_FINAL))
        {
            emsg(_("E996: Cannot lock a register"));
            return NULL;
@@ -3056,7 +3062,7 @@ set_var_const(
     type_T     *type,
     typval_T   *tv_arg,
     int                copy,       // make copy of value in "tv"
-    int                flags)      // ASSIGN_CONST, ASSIGN_NO_DECL
+    int                flags)      // ASSIGN_CONST, ASSIGN_FINAL, ASSIGN_NO_DECL
 {
     typval_T   *tv = tv_arg;
     typval_T   bool_tv;
@@ -3077,6 +3083,7 @@ set_var_const(
     if (vim9script
            && !is_script_local
            && (flags & ASSIGN_NO_DECL) == 0
+           && (flags & (ASSIGN_CONST | ASSIGN_FINAL)) == 0
            && name[1] == ':')
     {
        vim9_declare_error(name);
@@ -3106,7 +3113,7 @@ set_var_const(
     {
        if ((di->di_flags & DI_FLAGS_RELOAD) == 0)
        {
-           if (flags & ASSIGN_CONST)
+           if (flags & (ASSIGN_CONST | ASSIGN_FINAL))
            {
                emsg(_(e_cannot_mod));
                goto failed;
@@ -3206,7 +3213,7 @@ set_var_const(
            goto failed;
        }
        di->di_flags = DI_FLAGS_ALLOC;
-       if (flags & ASSIGN_CONST)
+       if (flags & (ASSIGN_CONST | ASSIGN_FINAL))
            di->di_flags |= DI_FLAGS_LOCK;
 
        // A Vim9 script-local variable is also added to sn_all_vars and
index bfc2d20de87d28f146850e6e77904a91d2cfe15d..d5e1b333783b18ca3e4bab668df0e14c60d71d52 100644 (file)
@@ -1127,6 +1127,30 @@ def Test_var_declaration()
 
     const FOO: number = 123
     assert_equal(123, FOO)
+    const FOOS = 'foos'
+    assert_equal('foos', FOOS)
+    final FLIST = [1]
+    assert_equal([1], FLIST)
+    FLIST[0] = 11
+    assert_equal([11], FLIST)
+
+    const g:FOO: number = 321
+    assert_equal(321, g:FOO)
+    const g:FOOS = 'gfoos'
+    assert_equal('gfoos', g:FOOS)
+    final g:FLIST = [2]
+    assert_equal([2], g:FLIST)
+    g:FLIST[0] = 22
+    assert_equal([22], g:FLIST)
+
+    const w:FOO: number = 46
+    assert_equal(46, w:FOO)
+    const w:FOOS = 'wfoos'
+    assert_equal('wfoos', w:FOOS)
+    final w:FLIST = [3]
+    assert_equal([3], w:FLIST)
+    w:FLIST[0] = 33
+    assert_equal([33], w:FLIST)
 
     var s:other: number
     other = 1234
@@ -1150,6 +1174,12 @@ def Test_var_declaration()
   unlet g:var_test
   unlet g:var_prefixed
   unlet g:other_var
+  unlet g:FOO
+  unlet g:FOOS
+  unlet g:FLIST
+  unlet w:FOO
+  unlet w:FOOS
+  unlet w:FLIST
 enddef
 
 def Test_var_declaration_fails()
@@ -1159,6 +1189,22 @@ def Test_var_declaration_fails()
   END
   CheckScriptFailure(lines, 'E1125:')
 
+  lines =<< trim END
+    vim9script
+    const g:constvar = 'string'
+    g:constvar = 'xx'
+  END
+  CheckScriptFailure(lines, 'E741:')
+  unlet g:constvar
+
+  lines =<< trim END
+    vim9script
+    final w:finalvar = [9]
+    w:finalvar = [8]
+  END
+  CheckScriptFailure(lines, 'E1122:')
+  unlet w:finalvar
+
   lines =<< trim END
     vim9script
     const var: string
index bdced0257b60e44b15c00f26ea5f3402d2195d44..749b8e8428b06823eb485cc5f21d45496f8d9924 100644 (file)
@@ -1032,7 +1032,7 @@ def Test_vim9script_call_fail_const()
       call Change()
       unlet g:Aconst
   END
-  CheckScriptFailure(lines, 'E741: Value is locked: Aconst', 2)
+  CheckScriptFailure(lines, 'E1122: Variable is locked: Aconst', 2)
 enddef
 
 " Test that inside :function a Python function can be defined, :def is not
index 73a80aaf96bdb0bd0f003d212d84310e36a458b0..d4ca3c42a0c80ba130510c0e4247ba938216145b 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2194,
 /**/
     2193,
 /**/
index ebd7db441e51b449203c948906f7734147499b90..1dedd814134171f13766cc537f3421f1b87b7d5c 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -2144,7 +2144,7 @@ typedef enum {
 // Flags for assignment functions.
 #define ASSIGN_FINAL   1   // ":final"
 #define ASSIGN_CONST   2   // ":const"
-#define ASSIGN_NO_DECL 4   // "name = expr" without ":let" or ":const"
+#define ASSIGN_NO_DECL 4   // "name = expr" without ":let"/":const"/":final"
 
 #include "ex_cmds.h"       // Ex command defines
 #include "spell.h"         // spell checking stuff