changeset 20401:918b9a05cf35 v8.2.0755

patch 8.2.0755: Vim9: No error when variable initializer is not a constant Commit: https://github.com/vim/vim/commit/227a69de1e0f9457a9fc9e098d999304faff55f8 Author: Bram Moolenaar <Bram@vim.org> Date: Fri May 15 18:17:28 2020 +0200 patch 8.2.0755: Vim9: No error when variable initializer is not a constant Problem: Vim9: No error when variable initializer is not a constant. Solution: Return FAIL when trying to get a variable value. Do not execute a script when an error is deteted in the first or second phase.
author Bram Moolenaar <Bram@vim.org>
date Fri, 15 May 2020 18:30:04 +0200
parents 9a53e38d4abb
children ad9971ac44ca
files src/eval.c src/testdir/test_vim9_script.vim src/version.c src/vim9script.c
diffstat 4 files changed, 47 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -2695,6 +2695,8 @@ eval7(
 	{
 	    if (**arg == '(')		// recursive!
 		ret = eval_func(arg, s, len, rettv, flags, NULL);
+	    else if (flags & EVAL_CONSTANT)
+		ret = FAIL;
 	    else if (evaluate)
 		ret = get_var_tv(s, len, rettv, NULL, TRUE, FALSE);
 	    else
--- a/src/testdir/test_vim9_script.vim
+++ b/src/testdir/test_vim9_script.vim
@@ -494,8 +494,8 @@ let s:export_script_lines =<< trim END
   def Concat(arg: string): string
     return name .. arg
   enddef
-  let g:result: string = Concat('bie')
-  let g:localname = name
+  g:result = Concat('bie')
+  g:localname = name
 
   export const CONST = 1234
   export let exported = 9876
@@ -1747,10 +1747,34 @@ def Test_let_missing_type()
     endfunc
     let val = GetValue() 
   END
-  writefile(lines, 'Xfinished')
-  assert_fails('source Xfinished', 'E1091:')
+  CheckScriptFailure(lines, 'E1091:')
+
+  lines =<< trim END
+    vim9script
+    let var = g:unkown
+  END
+  CheckScriptFailure(lines, 'E1091:')
 
-  delete('Xfinished')
+  " TODO: eventually this would work
+  lines =<< trim END
+    vim9script
+    let var = has('eval')
+  END
+  CheckScriptFailure(lines, 'E1091:')
+
+  " TODO: eventually this would work
+  lines =<< trim END
+    vim9script
+    let var = len('string')
+  END
+  CheckScriptFailure(lines, 'E1091:')
+
+  lines =<< trim END
+    vim9script
+    let nr: number = 123
+    let var = nr
+  END
+  CheckScriptFailure(lines, 'E1091:')
 enddef
 
 def Test_forward_declaration()
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    755,
+/**/
     754,
 /**/
     753,
--- a/src/vim9script.c
+++ b/src/vim9script.c
@@ -37,6 +37,7 @@ ex_vim9script(exarg_T *eap)
     garray_T	    func_ga;
     int		    idx;
     ufunc_T	    *ufunc;
+    int		    start_called_emsg = called_emsg;
 
     if (!getline_equal(eap->getline, eap->cookie, getsourceline))
     {
@@ -66,7 +67,7 @@ ex_vim9script(exarg_T *eap)
     // The types are recognized, so that they can be used when compiling a
     // function.
     gap = source_get_line_ga(eap->cookie);
-    for (;;)
+    while (called_emsg == start_called_emsg)
     {
 	char_u	    *line;
 	char_u	    *p;
@@ -132,22 +133,29 @@ ex_vim9script(exarg_T *eap)
 	}
 	else if (checkforcmd(&p, "finish", 4))
 	{
-	    // TODO: this should not happen below "if false".
-	    // Use "if cond | finish | endif as a workaround.
 	    break;
 	}
     }
 
     // Compile the :def functions.
-    for (idx = 0; idx < func_ga.ga_len; ++idx)
+    for (idx = 0; idx < func_ga.ga_len && called_emsg == start_called_emsg; ++idx)
     {
 	ufunc = ((ufunc_T **)(func_ga.ga_data))[idx];
 	compile_def_function(ufunc, FALSE, NULL);
     }
     ga_clear(&func_ga);
 
-    // Return to process the commands at the script level.
-    source_use_line_ga(eap->cookie);
+    if (called_emsg == start_called_emsg)
+    {
+	// Return to process the commands at the script level.
+	source_use_line_ga(eap->cookie);
+    }
+    else
+    {
+	// If there was an error in the first or second phase then don't
+	// execute the script lines.
+	do_finish(eap, FALSE);
+    }
 }
 
 /*