# HG changeset patch # User Bram Moolenaar # Date 1601213404 -7200 # Node ID 1cefe1c013ac0786551bd76ea2e1e93a0572c694 # Parent f22c7b159f37f4b59459fbea7f3286a6571fb471 patch 8.2.1756: Vim9: :let will soon be disallowed Commit: https://github.com/vim/vim/commit/cfcd011fcd8021da52fba62dabf7a2497f1879b7 Author: Bram Moolenaar Date: Sun Sep 27 15:19:27 2020 +0200 patch 8.2.1756: Vim9: :let will soon be disallowed Problem: Vim9: :let will soon be disallowed. Solution: Add v:disallow_let temporarily. Fix tests. diff --git a/src/errors.h b/src/errors.h --- a/src/errors.h +++ b/src/errors.h @@ -274,4 +274,6 @@ EXTERN char e_str_cannot_be_used_in_lega INIT(= N_("E1124: \"%s\" cannot be used in legacy Vim script")); EXTERN char e_final_requires_a_value[] INIT(= N_("E1125: Final requires a value")); +EXTERN char e_cannot_use_let_in_vim9_script[] + INIT(= N_("E1126: Cannot use :let in Vim9 script")); #endif diff --git a/src/evalvars.c b/src/evalvars.c --- a/src/evalvars.c +++ b/src/evalvars.c @@ -146,6 +146,7 @@ static struct vimvar {VV_NAME("echospace", VAR_NUMBER), VV_RO}, {VV_NAME("argv", VAR_LIST), VV_RO}, {VV_NAME("collate", VAR_STRING), VV_RO}, + {VV_NAME("disallow_let", VAR_NUMBER), 0}, // TODO: remove }; // shorthand @@ -734,6 +735,12 @@ ex_let(exarg_T *eap) ex_finally(eap); return; } + if (get_vim_var_nr(VV_DISALLOW_LET) + && eap->cmdidx == CMD_let && vim9script) + { + emsg(_(e_cannot_use_let_in_vim9_script)); + return; + } if (eap->cmdidx == CMD_const && !vim9script && !eap->forceit) // In legacy Vim script ":const" works like ":final". eap->cmdidx = CMD_final; 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 @@ -6,6 +6,9 @@ source view_util.vim source vim9.vim source shared.vim +" TODO: remove later +let v:disallow_let = 1 + def Test_range_only() new setline(1, ['blah', 'Blah']) @@ -45,17 +48,17 @@ def Test_unlet() CheckScriptFailure([ 'vim9script', - 'let svar = 123', + 'var svar = 123', 'unlet svar', ], 'E1081:') CheckScriptFailure([ 'vim9script', - 'let svar = 123', + 'var svar = 123', 'unlet s:svar', ], 'E1081:') CheckScriptFailure([ 'vim9script', - 'let svar = 123', + 'var svar = 123', 'def Func()', ' unlet svar', 'enddef', @@ -63,7 +66,7 @@ def Test_unlet() ], 'E1081:') CheckScriptFailure([ 'vim9script', - 'let svar = 123', + 'var svar = 123', 'def Func()', ' unlet s:svar', 'enddef', @@ -119,7 +122,7 @@ def Test_delfunction() ], 'E1084:') # Check that global :def function can be replaced and deleted - let lines =<< trim END + var lines =<< trim END vim9script def g:Global(): string return "yes" @@ -168,59 +171,59 @@ def Test_delfunction() enddef def Test_wrong_type() - CheckDefFailure(['let var: list'], 'E1010:') - CheckDefFailure(['let var: list>'], 'E1010:') - CheckDefFailure(['let var: dict'], 'E1010:') - CheckDefFailure(['let var: dict>'], 'E1010:') + CheckDefFailure(['var name: list'], 'E1010:') + CheckDefFailure(['var name: list>'], 'E1010:') + CheckDefFailure(['var name: dict'], 'E1010:') + CheckDefFailure(['var name: dict>'], 'E1010:') - CheckDefFailure(['let var: dict'], 'E1009:') + CheckDefFailure(['var name: dict'], 'E1009:') - CheckDefFailure(['let var: ally'], 'E1010:') - CheckDefFailure(['let var: bram'], 'E1010:') - CheckDefFailure(['let var: cathy'], 'E1010:') - CheckDefFailure(['let var: dom'], 'E1010:') - CheckDefFailure(['let var: freddy'], 'E1010:') - CheckDefFailure(['let var: john'], 'E1010:') - CheckDefFailure(['let var: larry'], 'E1010:') - CheckDefFailure(['let var: ned'], 'E1010:') - CheckDefFailure(['let var: pam'], 'E1010:') - CheckDefFailure(['let var: sam'], 'E1010:') - CheckDefFailure(['let var: vim'], 'E1010:') + CheckDefFailure(['var name: ally'], 'E1010:') + CheckDefFailure(['var name: bram'], 'E1010:') + CheckDefFailure(['var name: cathy'], 'E1010:') + CheckDefFailure(['var name: dom'], 'E1010:') + CheckDefFailure(['var name: freddy'], 'E1010:') + CheckDefFailure(['var name: john'], 'E1010:') + CheckDefFailure(['var name: larry'], 'E1010:') + CheckDefFailure(['var name: ned'], 'E1010:') + CheckDefFailure(['var name: pam'], 'E1010:') + CheckDefFailure(['var name: sam'], 'E1010:') + CheckDefFailure(['var name: vim'], 'E1010:') - CheckDefFailure(['let Ref: number', 'Ref()'], 'E1085:') - CheckDefFailure(['let Ref: string', 'let res = Ref()'], 'E1085:') + CheckDefFailure(['var Ref: number', 'Ref()'], 'E1085:') + CheckDefFailure(['var Ref: string', 'var res = Ref()'], 'E1085:') enddef def Test_const() - CheckDefFailure(['final var = 234', 'var = 99'], 'E1018:') - CheckDefFailure(['final one = 234', 'let one = 99'], 'E1017:') - CheckDefFailure(['final list = [1, 2]', 'let list = [3, 4]'], 'E1017:') + CheckDefFailure(['final name = 234', 'name = 99'], 'E1018:') + CheckDefFailure(['final one = 234', 'var one = 99'], 'E1017:') + CheckDefFailure(['final list = [1, 2]', 'var list = [3, 4]'], 'E1017:') CheckDefFailure(['final two'], 'E1125:') CheckDefFailure(['final &option'], 'E996:') - let lines =<< trim END + var lines =<< trim END final list = [1, 2, 3] list[0] = 4 list->assert_equal([4, 2, 3]) const other = [5, 6, 7] other->assert_equal([5, 6, 7]) - let varlist = [7, 8] + var varlist = [7, 8] const constlist = [1, varlist, 3] varlist[0] = 77 # TODO: does not work yet # constlist[1][1] = 88 - let cl = constlist[1] + var cl = constlist[1] cl[1] = 88 constlist->assert_equal([1, [77, 88], 3]) - let vardict = #{five: 5, six: 6} + var vardict = #{five: 5, six: 6} const constdict = #{one: 1, two: vardict, three: 3} vardict['five'] = 55 # TODO: does not work yet # constdict['two']['six'] = 66 - let cd = constdict['two'] + var cd = constdict['two'] cd['six'] = 66 constdict->assert_equal(#{one: 1, two: #{five: 55, six: 66}, three: 3}) END @@ -228,7 +231,7 @@ def Test_const() enddef def Test_const_bang() - let lines =<< trim END + var lines =<< trim END const var = 234 var = 99 END @@ -273,9 +276,9 @@ enddef def Test_block() - let outer = 1 + var outer = 1 { - let inner = 2 + var inner = 2 assert_equal(1, outer) assert_equal(2, inner) } @@ -283,7 +286,7 @@ def Test_block() enddef def Test_block_failure() - CheckDefFailure(['{', 'let inner = 1', '}', 'echo inner'], 'E1001:') + CheckDefFailure(['{', 'var inner = 1', '}', 'echo inner'], 'E1001:') CheckDefFailure(['}'], 'E1025:') CheckDefFailure(['{', 'echo 1'], 'E1026:') enddef @@ -293,7 +296,7 @@ func g:NoSuchFunc() endfunc def Test_try_catch() - let l = [] + var l = [] try # comment add(l, '1') throw 'wrong' @@ -321,7 +324,7 @@ def Test_try_catch() endtry assert_equal(['1', 'caught', 'finally'], l) - let n: number + var n: number try n = l[3] catch /E684:/ @@ -358,7 +361,7 @@ def Test_try_catch() endtry assert_equal(121, n) - let d = #{one: 1} + var d = #{one: 1} try n = d[g:astring] catch /E716:/ @@ -387,7 +390,7 @@ def Test_try_catch() endtry assert_equal(255, n) - let nd: dict + var nd: dict try nd = {g:anumber: 1} catch /E1012:/ @@ -452,7 +455,7 @@ def Test_try_catch() endtry assert_equal(355, n) - let P = function('g:NoSuchFunc') + var P = function('g:NoSuchFunc') delfunc g:NoSuchFunc try echo P() @@ -553,7 +556,7 @@ enddef def TryTwo(n: number): string try - let x = {} + var x = {} catch endtry return 'text' @@ -564,7 +567,7 @@ def Test_try_catch_twice() enddef def Test_try_catch_match() - let seq = 'a' + var seq = 'a' try throw 'something' catch /nothing/ @@ -599,7 +602,7 @@ enddef def Test_throw_vimscript() # only checks line continuation - let lines =<< trim END + var lines =<< trim END vim9script try throw 'one' @@ -613,7 +616,7 @@ enddef def Test_error_in_nested_function() # an error in a nested :function aborts executin in the calling :def function - let lines =<< trim END + var lines =<< trim END vim9script def Func() Error() @@ -632,7 +635,7 @@ enddef def Test_cexpr_vimscript() # only checks line continuation set errorformat=File\ %f\ line\ %l - let lines =<< trim END + var lines =<< trim END vim9script cexpr 'File' .. ' someFile' .. @@ -645,7 +648,7 @@ enddef def Test_statusline_syntax() # legacy syntax is used for 'statusline' - let lines =<< trim END + var lines =<< trim END vim9script func g:Status() return '%{"x" is# "x"}' @@ -659,9 +662,9 @@ enddef def Test_list_vimscript() # checks line continuation and comments - let lines =<< trim END + var lines =<< trim END vim9script - let mylist = [ + var mylist = [ 'one', # comment 'two', # empty line follows @@ -702,7 +705,7 @@ endif let s:export_script_lines =<< trim END vim9script - let name: string = 'bob' + var name: string = 'bob' def Concat(arg: string): string return name .. arg enddef @@ -710,8 +713,8 @@ let s:export_script_lines =<< trim END g:localname = name export const CONST = 1234 - export let exported = 9876 - export let exp_name = 'John' + export var exported = 9876 + export var exp_name = 'John' export def Exported(): string return 'Exported' enddef @@ -723,7 +726,7 @@ def Undo_export_script_lines() enddef def Test_vim9_import_export() - let import_script_lines =<< trim END + var import_script_lines =<< trim END vim9script import {exported, Exported} from './Xexport.vim' g:imported = exported @@ -732,7 +735,7 @@ def Test_vim9_import_export() g:imported_func = Exported() def GetExported(): string - let local_dict = #{ref: Exported} + var local_dict = #{ref: Exported} return local_dict.ref() enddef g:funcref_result = GetExported() @@ -769,7 +772,7 @@ def Test_vim9_import_export() delete('Ximport.vim') # similar, with line breaks - let import_line_break_script_lines =<< trim END + var import_line_break_script_lines =<< trim END vim9script import { exported, @@ -797,7 +800,7 @@ def Test_vim9_import_export() delete('Ximport_lbr.vim') # import inside :def function - let import_in_def_lines =<< trim END + var import_in_def_lines =<< trim END vim9script def ImportInDef() import exported from './Xexport.vim' @@ -816,7 +819,7 @@ def Test_vim9_import_export() unlet g:imported_added delete('Ximport2.vim') - let import_star_as_lines =<< trim END + var import_star_as_lines =<< trim END vim9script import * as Export from './Xexport.vim' def UseExport() @@ -828,41 +831,41 @@ def Test_vim9_import_export() source Ximport.vim assert_equal(9883, g:imported) - let import_star_as_lines_no_dot =<< trim END + var import_star_as_lines_no_dot =<< trim END vim9script import * as Export from './Xexport.vim' def Func() - let dummy = 1 - let imported = Export + dummy + var dummy = 1 + var imported = Export + dummy enddef defcompile END writefile(import_star_as_lines_no_dot, 'Ximport.vim') assert_fails('source Ximport.vim', 'E1060:', '', 2, 'Func') - let import_star_as_lines_dot_space =<< trim END + var import_star_as_lines_dot_space =<< trim END vim9script import * as Export from './Xexport.vim' def Func() - let imported = Export . exported + var imported = Export . exported enddef defcompile END writefile(import_star_as_lines_dot_space, 'Ximport.vim') assert_fails('source Ximport.vim', 'E1074:', '', 1, 'Func') - let import_star_as_lines_missing_name =<< trim END + var import_star_as_lines_missing_name =<< trim END vim9script import * as Export from './Xexport.vim' def Func() - let imported = Export. + var imported = Export. enddef defcompile END writefile(import_star_as_lines_missing_name, 'Ximport.vim') assert_fails('source Ximport.vim', 'E1048:', '', 1, 'Func') - let import_star_as_lbr_lines =<< trim END + var import_star_as_lbr_lines =<< trim END vim9script import * as Export @@ -877,7 +880,7 @@ def Test_vim9_import_export() source Ximport.vim assert_equal(9883, g:imported) - let import_star_lines =<< trim END + var import_star_lines =<< trim END vim9script import * from './Xexport.vim' END @@ -885,7 +888,7 @@ def Test_vim9_import_export() assert_fails('source Ximport.vim', 'E1045:', '', 2, 'Ximport.vim') # try to import something that exists but is not exported - let import_not_exported_lines =<< trim END + var import_not_exported_lines =<< trim END vim9script import name from './Xexport.vim' END @@ -893,9 +896,9 @@ def Test_vim9_import_export() assert_fails('source Ximport.vim', 'E1049:', '', 2, 'Ximport.vim') # try to import something that is already defined - let import_already_defined =<< trim END + var import_already_defined =<< trim END vim9script - let exported = 'something' + var exported = 'something' import exported from './Xexport.vim' END writefile(import_already_defined, 'Ximport.vim') @@ -904,7 +907,7 @@ def Test_vim9_import_export() # try to import something that is already defined import_already_defined =<< trim END vim9script - let exported = 'something' + var exported = 'something' import * as exported from './Xexport.vim' END writefile(import_already_defined, 'Ximport.vim') @@ -913,42 +916,42 @@ def Test_vim9_import_export() # try to import something that is already defined import_already_defined =<< trim END vim9script - let exported = 'something' + var exported = 'something' import {exported} from './Xexport.vim' END writefile(import_already_defined, 'Ximport.vim') assert_fails('source Ximport.vim', 'E1073:', '', 3, 'Ximport.vim') # import a very long name, requires making a copy - let import_long_name_lines =<< trim END + var import_long_name_lines =<< trim END vim9script import name012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 from './Xexport.vim' END writefile(import_long_name_lines, 'Ximport.vim') assert_fails('source Ximport.vim', 'E1048:', '', 2, 'Ximport.vim') - let import_no_from_lines =<< trim END + var import_no_from_lines =<< trim END vim9script import name './Xexport.vim' END writefile(import_no_from_lines, 'Ximport.vim') assert_fails('source Ximport.vim', 'E1070:', '', 2, 'Ximport.vim') - let import_invalid_string_lines =<< trim END + var import_invalid_string_lines =<< trim END vim9script import name from Xexport.vim END writefile(import_invalid_string_lines, 'Ximport.vim') assert_fails('source Ximport.vim', 'E1071:', '', 2, 'Ximport.vim') - let import_wrong_name_lines =<< trim END + var import_wrong_name_lines =<< trim END vim9script import name from './XnoExport.vim' END writefile(import_wrong_name_lines, 'Ximport.vim') assert_fails('source Ximport.vim', 'E1053:', '', 2, 'Ximport.vim') - let import_missing_comma_lines =<< trim END + var import_missing_comma_lines =<< trim END vim9script import {exported name} from './Xexport.vim' END @@ -961,8 +964,8 @@ def Test_vim9_import_export() # Check that in a Vim9 script 'cpo' is set to the Vim default. set cpo&vi - let cpo_before = &cpo - let lines =<< trim END + var cpo_before = &cpo + var lines =<< trim END vim9script g:cpo_in_vim9script = &cpo END @@ -981,7 +984,7 @@ endfunc def Test_import_export_expr_map() # check that :import and :export work when buffer is locked - let export_lines =<< trim END + var export_lines =<< trim END vim9script export def That(): string return 'yes' @@ -989,7 +992,7 @@ def Test_import_export_expr_map() END writefile(export_lines, 'Xexport_that.vim') - let import_lines =<< trim END + var import_lines =<< trim END vim9script import That from './Xexport_that.vim' assert_equal('yes', That()) @@ -1007,13 +1010,13 @@ enddef def Test_import_in_filetype() # check that :import works when the buffer is locked mkdir('ftplugin', 'p') - let export_lines =<< trim END + var export_lines =<< trim END vim9script - export let That = 'yes' + export var That = 'yes' END writefile(export_lines, 'ftplugin/Xexport_ft.vim') - let import_lines =<< trim END + var import_lines =<< trim END vim9script import That from './Xexport_ft.vim' assert_equal('yes', That) @@ -1021,7 +1024,7 @@ def Test_import_in_filetype() END writefile(import_lines, 'ftplugin/qf.vim') - let save_rtp = &rtp + var save_rtp = &rtp &rtp = getcwd() .. ',' .. &rtp filetype plugin on @@ -1035,7 +1038,7 @@ def Test_import_in_filetype() enddef def Test_use_import_in_mapping() - let lines =<< trim END + var lines =<< trim END vim9script export def Funcx() g:result = 42 @@ -1062,12 +1065,12 @@ enddef def Test_vim9script_fails() CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:') CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:') - CheckScriptFailure(['export let some = 123'], 'E1042:') + CheckScriptFailure(['export var some = 123'], 'E1042:') CheckScriptFailure(['import some from "./Xexport.vim"'], 'E1048:') - CheckScriptFailure(['vim9script', 'export let g:some'], 'E1022:') + CheckScriptFailure(['vim9script', 'export var g:some'], 'E1022:') CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:') - CheckScriptFailure(['vim9script', 'let str: string', 'str = 1234'], 'E1012:') + CheckScriptFailure(['vim9script', 'var str: string', 'str = 1234'], 'E1012:') CheckScriptFailure(['vim9script', 'const str = "asdf"', 'str = "xxx"'], 'E46:') assert_fails('vim9script', 'E1038:') @@ -1082,7 +1085,7 @@ func Test_import_fails_without_script() endfunc def Run_Test_import_fails_on_command_line() - let export =<< trim END + var export =<< trim END vim9script export def Foo(): number return 0 @@ -1090,7 +1093,7 @@ def Run_Test_import_fails_on_command_lin END writefile(export, 'XexportCmd.vim') - let buf = RunVimInTerminal('-c "import Foo from ''./XexportCmd.vim''"', #{ + var buf = RunVimInTerminal('-c "import Foo from ''./XexportCmd.vim''"', #{ rows: 6, wait_for_ruler: 0}) WaitForAssert({-> assert_match('^E1094:', term_getline(buf, 5))}) @@ -1099,16 +1102,16 @@ def Run_Test_import_fails_on_command_lin enddef def Test_vim9script_reload_import() - let lines =<< trim END + var lines =<< trim END vim9script const var = '' - let valone = 1234 + var valone = 1234 def MyFunc(arg: string) valone = 5678 enddef END - let morelines =<< trim END - let valtwo = 222 + var morelines =<< trim END + var valtwo = 222 export def GetValtwo(): number return valtwo enddef @@ -1118,7 +1121,7 @@ def Test_vim9script_reload_import() source Xreload.vim source Xreload.vim - let testlines =<< trim END + var testlines =<< trim END vim9script def TheFunc() import GetValtwo from './Xreload.vim' @@ -1137,8 +1140,8 @@ def Test_vim9script_reload_import() # cannot declare a var twice lines =<< trim END vim9script - let valone = 1234 - let valone = 5678 + var valone = 1234 + var valone = 5678 END writefile(lines, 'Xreload.vim') assert_fails('source Xreload.vim', 'E1041:', '', 3, 'Xreload.vim') @@ -1154,7 +1157,7 @@ enddef " Not exported function that is referenced needs to be accessed by the " script-local name. def Test_vim9script_funcref() - let sortlines =<< trim END + var sortlines =<< trim END vim9script def Compare(i1: number, i2: number): number return i2 - i1 @@ -1166,7 +1169,7 @@ def Test_vim9script_funcref() END writefile(sortlines, 'Xsort.vim') - let lines =<< trim END + var lines =<< trim END vim9script import FastSort from './Xsort.vim' def Test() @@ -1183,7 +1186,7 @@ def Test_vim9script_funcref() delete('Xsort.vim') delete('Xscript.vim') - let Funcref = function('s:RetSome') + var Funcref = function('s:RetSome') assert_equal('some', Funcref()) enddef @@ -1191,7 +1194,7 @@ enddef " script where FastFilter() is called from, both as a string and as a direct " function reference. def Test_vim9script_funcref_other_script() - let filterLines =<< trim END + var filterLines =<< trim END vim9script export def FilterFunc(idx: number, val: number): bool return idx % 2 == 1 @@ -1205,15 +1208,15 @@ def Test_vim9script_funcref_other_script END writefile(filterLines, 'Xfilter.vim') - let lines =<< trim END + var lines =<< trim END vim9script import {FilterFunc, FastFilter, FastFilterDirect} from './Xfilter.vim' def Test() - let x: list = FastFilter() + var x: list = FastFilter() enddef Test() def TestDirect() - let x: list = FastFilterDirect() + var x: list = FastFilterDirect() enddef TestDirect() END @@ -1222,13 +1225,13 @@ def Test_vim9script_funcref_other_script enddef def Test_vim9script_reload_delfunc() - let first_lines =<< trim END + var first_lines =<< trim END vim9script def FuncYes(): string return 'yes' enddef END - let withno_lines =<< trim END + var withno_lines =<< trim END def FuncNo(): string return 'no' enddef @@ -1237,7 +1240,7 @@ def Test_vim9script_reload_delfunc() assert_equal('no', FuncNo()) enddef END - let nono_lines =<< trim END + var nono_lines =<< trim END def g:DoCheck(no_exists: bool) assert_equal('yes', FuncYes()) assert_fails('FuncNo()', 'E117:', '', 2, 'DoCheck') @@ -1264,9 +1267,9 @@ enddef def Test_vim9script_reload_delvar() # write the script with a script-local variable - let lines =<< trim END + var lines =<< trim END vim9script - let var = 'string' + var name = 'string' END writefile(lines, 'XreloadVar.vim') source XreloadVar.vim @@ -1275,7 +1278,7 @@ def Test_vim9script_reload_delvar() lines =<< trim END vim9script def Func() - let var = 'string' + var name = 'string' enddef END writefile(lines, 'XreloadVar.vim') @@ -1285,7 +1288,7 @@ def Test_vim9script_reload_delvar() enddef def Test_import_absolute() - let import_lines = [ + var import_lines = [ 'vim9script', 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"', 'def UseExported()', @@ -1323,7 +1326,7 @@ def Test_import_absolute() enddef def Test_import_rtp() - let import_lines = [ + var import_lines = [ 'vim9script', 'import exported from "Xexport_rtp.vim"', 'g:imported_rtp = exported', @@ -1332,7 +1335,7 @@ def Test_import_rtp() mkdir('import') writefile(s:export_script_lines, 'import/Xexport_rtp.vim') - let save_rtp = &rtp + var save_rtp = &rtp &rtp = getcwd() source Ximport_rtp.vim &rtp = save_rtp @@ -1346,7 +1349,7 @@ def Test_import_rtp() enddef def Test_import_compile_error() - let export_lines = [ + var export_lines = [ 'vim9script', 'export def ExpFunc(): string', ' return notDefined', @@ -1354,7 +1357,7 @@ def Test_import_compile_error() ] writefile(export_lines, 'Xexported.vim') - let import_lines = [ + var import_lines = [ 'vim9script', 'import ExpFunc from "./Xexported.vim"', 'def ImpFunc()', @@ -1377,7 +1380,7 @@ def Test_import_compile_error() enddef def Test_func_redefine_error() - let lines = [ + var lines = [ 'vim9script', 'def Func()', ' eval [][0]', @@ -1400,7 +1403,7 @@ def Test_func_redefine_error() enddef def Test_func_overrules_import_fails() - let export_lines =<< trim END + var export_lines =<< trim END vim9script export def Func() echo 'imported' @@ -1408,7 +1411,7 @@ def Test_func_overrules_import_fails() END writefile(export_lines, 'XexportedFunc.vim') - let lines =<< trim END + var lines =<< trim END vim9script import Func from './XexportedFunc.vim' def Func() @@ -1433,7 +1436,7 @@ def Test_func_overrules_import_fails() enddef def Test_func_redefine_fails() - let lines =<< trim END + var lines =<< trim END vim9script def Func() echo 'one' @@ -1450,7 +1453,7 @@ def Test_func_redefine_fails() return 'foo' enddef def Func() - let Foo = {-> 'lambda'} + var Foo = {-> 'lambda'} enddef defcompile END @@ -1459,7 +1462,7 @@ enddef def Test_fixed_size_list() # will be allocated as one piece of memory, check that changes work - let l = [1, 2, 3, 4] + var l = [1, 2, 3, 4] l->remove(0) l->add(5) l->insert(99, 1) @@ -1485,7 +1488,7 @@ def Test_no_insert_xit() enddef def IfElse(what: number): string - let res = '' + var res = '' if what == 1 res = "one" elseif what == 2 @@ -1514,7 +1517,7 @@ let g:bool_true = v:true let g:bool_false = v:false def Test_if_const_expr() - let res = false + var res = false if true ? true : false res = true endif @@ -1643,7 +1646,7 @@ def Test_if_const_expr_fails() enddef def RunNested(i: number): number - let x: number = 0 + var x: number = 0 if i % 2 if 1 # comment @@ -1671,21 +1674,21 @@ def Test_execute_cmd() execute "setline(1, 'execute-string')" assert_equal('execute-string', getline(1)) - let cmd1 = 'setline(1,' - let cmd2 = '"execute-var")' + var cmd1 = 'setline(1,' + var cmd2 = '"execute-var")' execute cmd1 cmd2 # comment assert_equal('execute-var', getline(1)) execute cmd1 cmd2 '|setline(1, "execute-var-string")' assert_equal('execute-var-string', getline(1)) - let cmd_first = 'call ' - let cmd_last = 'setline(1, "execute-var-var")' + var cmd_first = 'call ' + var cmd_last = 'setline(1, "execute-var-var")' execute cmd_first .. cmd_last assert_equal('execute-var-var', getline(1)) bwipe! - let n = true + var n = true execute 'echomsg' (n ? '"true"' : '"no"') assert_match('^true$', Screenline(&lines)) @@ -1699,7 +1702,7 @@ enddef def Test_execute_cmd_vimscript() # only checks line continuation - let lines =<< trim END + var lines =<< trim END vim9script execute 'g:someVar' .. ' = ' .. @@ -1719,8 +1722,8 @@ def Test_echo_cmd() echon "thing" assert_match('^something$', Screenline(&lines)) - let str1 = 'some' - let str2 = 'more' + var str1 = 'some' + var str2 = 'more' echo str1 str2 assert_match('^some more$', Screenline(&lines)) @@ -1739,7 +1742,7 @@ enddef def Test_echomsg_cmd_vimscript() # only checks line continuation - let lines =<< trim END + var lines =<< trim END vim9script echomsg 'here' .. ' is ' .. @@ -1759,7 +1762,7 @@ enddef def Test_echoerr_cmd_vimscript() # only checks line continuation - let lines =<< trim END + var lines =<< trim END vim9script try echoerr 'this' @@ -1773,7 +1776,7 @@ def Test_echoerr_cmd_vimscript() enddef def Test_for_outside_of_function() - let lines =<< trim END + var lines =<< trim END vim9script new for var in range(0, 3) @@ -1788,7 +1791,7 @@ def Test_for_outside_of_function() enddef def Test_for_loop() - let result = '' + var result = '' for cnt in range(7) if cnt == 4 break @@ -1800,7 +1803,7 @@ def Test_for_loop() endfor assert_equal('0_1_3_', result) - let concat = '' + var concat = '' for str in eval('["one", "two"]') concat ..= str endfor @@ -1810,7 +1813,7 @@ enddef def Test_for_loop_fails() CheckDefFailure(['for # in range(5)'], 'E690:') CheckDefFailure(['for i In range(5)'], 'E690:') - CheckDefFailure(['let x = 5', 'for x in range(5)'], 'E1017:') + CheckDefFailure(['var x = 5', 'for x in range(5)'], 'E1017:') CheckScriptFailure(['def Func(arg: any)', 'for arg in range(5)', 'enddef', 'defcompile'], 'E1006:') CheckDefFailure(['for i in "text"'], 'E1012:') CheckDefFailure(['for i in xxx'], 'E1001:') @@ -1819,8 +1822,8 @@ def Test_for_loop_fails() enddef def Test_while_loop() - let result = '' - let cnt = 0 + var result = '' + var cnt = 0 while cnt < 555 if cnt == 3 break @@ -1845,8 +1848,8 @@ def Test_while_loop_fails() enddef def Test_interrupt_loop() - let caught = false - let x = 0 + var caught = false + var x = 0 try while 1 x += 1 @@ -1864,14 +1867,14 @@ def Test_interrupt_loop() enddef def Test_automatic_line_continuation() - let mylist = [ + var mylist = [ 'one', 'two', 'three', ] # comment assert_equal(['one', 'two', 'three'], mylist) - let mydict = { + var mydict = { 'one': 1, 'two': 2, 'three': @@ -2340,32 +2343,37 @@ def Test_vim9_comment_not_compiled() CheckScriptFailure([ 'vim9script', - 'let g:var = 123', + 'let var = 123', + ], 'E1126: Cannot use :let in Vim9 script') + + CheckScriptFailure([ + 'vim9script', + 'var g:var = 123', ], 'E1016: Cannot declare a global variable:') CheckScriptFailure([ 'vim9script', - 'let b:var = 123', + 'var b:var = 123', ], 'E1016: Cannot declare a buffer variable:') CheckScriptFailure([ 'vim9script', - 'let w:var = 123', + 'var w:var = 123', ], 'E1016: Cannot declare a window variable:') CheckScriptFailure([ 'vim9script', - 'let t:var = 123', + 'var t:var = 123', ], 'E1016: Cannot declare a tab variable:') CheckScriptFailure([ 'vim9script', - 'let v:version = 123', + 'var v:version = 123', ], 'E1016: Cannot declare a v: variable:') CheckScriptFailure([ 'vim9script', - 'let $VARIABLE = "text"', + 'var $VARIABLE = "text"', ], 'E1016: Cannot declare an environment variable:') CheckScriptFailure([ @@ -2406,12 +2414,12 @@ def Test_vim9_comment_not_compiled() CheckScriptSuccess([ 'vim9script', - 'let v = 1 # comment5', + 'var v = 1 # comment5', ]) CheckScriptFailure([ 'vim9script', - 'let v = 1# comment6', + 'var v = 1# comment6', ], 'E15:') CheckScriptSuccess([ @@ -2439,7 +2447,7 @@ def Test_vim9_comment_not_compiled() enddef def Test_finish() - let lines =<< trim END + var lines =<< trim END vim9script g:res = 'one' if v:false | finish | endif @@ -2456,7 +2464,7 @@ def Test_finish() enddef def Test_let_func_call() - let lines =<< trim END + var lines =<< trim END vim9script func GetValue() if exists('g:count') @@ -2466,9 +2474,9 @@ def Test_let_func_call() endif return 'this' endfunc - let val: string = GetValue() + var val: string = GetValue() # env var is always a string - let env = $TERM + var env = $TERM END writefile(lines, 'Xfinished') source Xfinished @@ -2480,32 +2488,32 @@ def Test_let_func_call() enddef def Test_let_missing_type() - let lines =<< trim END + var lines =<< trim END vim9script - let var = g:unknown + var name = g:unknown END CheckScriptFailure(lines, 'E121:') lines =<< trim END vim9script - let nr: number = 123 - let var = nr + var nr: number = 123 + var name = nr END CheckScriptSuccess(lines) enddef def Test_let_declaration() - let lines =<< trim END + var lines =<< trim END vim9script - let var: string - g:var_uninit = var - var = 'text' - g:var_test = var + var name: string + g:var_uninit = name + name = 'text' + g:var_test = name # prefixing s: is optional - s:var = 'prefixed' - g:var_prefixed = s:var + s:name = 'prefixed' + g:var_prefixed = s:name - let s:other: number + var s:other: number other = 1234 g:other_var = other @@ -2530,7 +2538,7 @@ def Test_let_declaration() enddef def Test_let_declaration_fails() - let lines =<< trim END + var lines =<< trim END vim9script final var: string END @@ -2544,41 +2552,41 @@ def Test_let_declaration_fails() lines =<< trim END vim9script - let 9var: string + var 9var: string END CheckScriptFailure(lines, 'E475:') enddef def Test_let_type_check() - let lines =<< trim END + var lines =<< trim END vim9script - let var: string - var = 1234 + var name: string + name = 1234 END CheckScriptFailure(lines, 'E1012:') lines =<< trim END vim9script - let var:string + var name:string END CheckScriptFailure(lines, 'E1069:') lines =<< trim END vim9script - let var: asdf + var name: asdf END CheckScriptFailure(lines, 'E1010:') lines =<< trim END vim9script - let s:l: list + var s:l: list s:l = [] END CheckScriptSuccess(lines) lines =<< trim END vim9script - let s:d: dict + var s:d: dict s:d = {} END CheckScriptSuccess(lines) @@ -2587,28 +2595,28 @@ enddef let g:dict_number = #{one: 1, two: 2} def Test_let_list_dict_type() - let ll: list + var ll: list ll = [1, 2, 2, 3, 3, 3]->uniq() ll->assert_equal([1, 2, 3]) - let dd: dict + var dd: dict dd = g:dict_number dd->assert_equal(g:dict_number) - let lines =<< trim END - let ll: list + var lines =<< trim END + var ll: list ll = [1, 2, 3]->map('"one"') END CheckDefExecFailure(lines, 'E1012: Type mismatch; expected list but got list') enddef def Test_forward_declaration() - let lines =<< trim END + var lines =<< trim END vim9script def GetValue(): string return theVal enddef - let theVal = 'something' + var theVal = 'something' g:initVal = GetValue() theVal = 'else' g:laterVal = GetValue() @@ -2624,7 +2632,7 @@ def Test_forward_declaration() enddef def Test_source_vim9_from_legacy() - let legacy_lines =<< trim END + var legacy_lines =<< trim END source Xvim9_script.vim call assert_false(exists('local')) @@ -2645,11 +2653,11 @@ def Test_source_vim9_from_legacy() END writefile(legacy_lines, 'Xlegacy_script.vim') - let vim9_lines =<< trim END + var vim9_lines =<< trim END vim9script - let local = 'local' + var local = 'local' g:global = 'global' - export let exported = 'exported' + export var exported = 'exported' export def GetText(): string return 'text' enddef @@ -2669,7 +2677,7 @@ func Test_vim9script_not_global() " check that items defined in Vim9 script are script-local, not global let vim9lines =<< trim END vim9script - let var = 'local' + var name = 'local' func TheFunc() echo 'local' endfunc @@ -2709,7 +2717,7 @@ enddef " test using a vim9script that is auto-loaded from an autocmd def Test_vim9_autoload() - let lines =<< trim END + var lines =<< trim END vim9script def foo#test() echomsg getreg('"') @@ -2718,7 +2726,7 @@ def Test_vim9_autoload() mkdir('Xdir/autoload', 'p') writefile(lines, 'Xdir/autoload/foo.vim') - let save_rtp = &rtp + var save_rtp = &rtp exe 'set rtp^=' .. getcwd() .. '/Xdir' augroup test autocmd TextYankPost * call foo#test() @@ -2735,7 +2743,7 @@ enddef " This was causing a crash because suppress_errthrow wasn't reset. def Test_vim9_autoload_error() - let lines =<< trim END + var lines =<< trim END vim9script def crash#func() try @@ -2775,7 +2783,7 @@ enddef def Test_script_var_in_autocmd() # using a script variable from an autocommand, defined in a :def function in a # legacy Vim script, cannot check the variable type. - let lines =<< trim END + var lines =<< trim END let s:counter = 1 def s:Func() au! CursorHold @@ -2793,17 +2801,17 @@ def Test_cmdline_win() # if the Vim syntax highlighting uses Vim9 constructs they can be used from # the command line window. mkdir('rtp/syntax', 'p') - let export_lines =<< trim END + var export_lines =<< trim END vim9script - export let That = 'yes' + export var That = 'yes' END writefile(export_lines, 'rtp/syntax/Xexport.vim') - let import_lines =<< trim END + var import_lines =<< trim END vim9script import That from './Xexport.vim' END writefile(import_lines, 'rtp/syntax/vim.vim') - let save_rtp = &rtp + var save_rtp = &rtp &rtp = getcwd() .. '/rtp' .. ',' .. &rtp syntax on augroup CmdWin @@ -2830,9 +2838,9 @@ def Test_invalid_sid() enddef def Test_unset_any_variable() - let lines =<< trim END - let var: any - assert_equal(0, var) + var lines =<< trim END + var name: any + assert_equal(0, name) END CheckDefAndScriptSuccess(lines) enddef @@ -2846,7 +2854,7 @@ endfunc def Run_Test_define_func_at_command_line() # run in a separate Vim instance to avoid the script context - let lines =<< trim END + var lines =<< trim END func CheckAndQuit() call assert_fails('call Afunc()', 'E117: Unknown function: Bfunc') call writefile(['errors: ' .. string(v:errors)], 'Xdidcmd') @@ -2854,7 +2862,7 @@ def Run_Test_define_func_at_command_line END writefile([''], 'Xdidcmd') writefile(lines, 'XcallFunc') - let buf = RunVimInTerminal('-S XcallFunc', #{rows: 6}) + var buf = RunVimInTerminal('-S XcallFunc', #{rows: 6}) # define Afunc() on the command line term_sendkeys(buf, ":def Afunc()\Bfunc()\enddef\") term_sendkeys(buf, ":call CheckAndQuit()\") @@ -2874,7 +2882,7 @@ def Test_substitute_cmd() bwipe! # also when the context is Vim9 script - let lines =<< trim END + var lines =<< trim END vim9script new setline(1, 'something') diff --git a/src/userfunc.c b/src/userfunc.c --- a/src/userfunc.c +++ b/src/userfunc.c @@ -3214,19 +3214,20 @@ def_function(exarg_T *eap, char_u *name_ is_heredoc = TRUE; } - // Check for ":let v =<< [trim] EOF" - // and ":let [a, b] =<< [trim] EOF" + // Check for ":cmd v =<< [trim] EOF" + // and ":cmd [a, b] =<< [trim] EOF" + // Where "cmd" can be "let", "var", "final" or "const". arg = skipwhite(skiptowhite(p)); if (*arg == '[') arg = vim_strchr(arg, ']'); if (arg != NULL) { arg = skipwhite(skiptowhite(arg)); - if ( arg[0] == '=' && arg[1] == '<' && arg[2] =='<' - && ((p[0] == 'l' - && p[1] == 'e' - && (!ASCII_ISALNUM(p[2]) - || (p[2] == 't' && !ASCII_ISALNUM(p[3])))))) + if (arg[0] == '=' && arg[1] == '<' && arg[2] =='<' + && (checkforcmd(&p, "let", 2) + || checkforcmd(&p, "var", 3) + || checkforcmd(&p, "final", 5) + || checkforcmd(&p, "const", 5))) { p = skipwhite(arg + 3); if (STRNCMP(p, "trim", 4) == 0) 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 */ /**/ + 1756, +/**/ 1755, /**/ 1754, diff --git a/src/vim.h b/src/vim.h --- a/src/vim.h +++ b/src/vim.h @@ -1992,7 +1992,8 @@ typedef int sock_T; #define VV_ECHOSPACE 93 #define VV_ARGV 94 #define VV_COLLATE 95 -#define VV_LEN 96 // number of v: vars +#define VV_DISALLOW_LET 96 // TODO: remove again +#define VV_LEN 97 // number of v: vars // used for v_number in VAR_BOOL and VAR_SPECIAL #define VVAL_FALSE 0L // VAR_BOOL diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -6979,6 +6979,12 @@ compile_def_function(ufunc_T *ufunc, int break; case CMD_let: + if (get_vim_var_nr(VV_DISALLOW_LET)) + { + emsg(_(e_cannot_use_let_in_vim9_script)); + break; + } + // FALLTHROUGH case CMD_var: case CMD_final: case CMD_const: