Mercurial > vim
view src/testdir/test_vim9_script.vim @ 19319:c5f04bfc7bf6
Added tag v8.2.0217 for changeset 673a95ef80afd8df2303b924957c7f84df19dd15
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 05 Feb 2020 22:30:05 +0100 |
parents | 17dc6282f370 |
children | 6e199d1d11d0 |
line wrap: on
line source
" Test various aspects of the Vim9 script language. source check.vim " Check that "lines" inside ":def" results in an "error" message. func CheckDefFailure(lines, error) call writefile(['def Func()'] + a:lines + ['enddef'], 'Xdef') call assert_fails('so Xdef', a:error, a:lines) call delete('Xdef') endfunc func CheckScriptFailure(lines, error) call writefile(a:lines, 'Xdef') call assert_fails('so Xdef', a:error, a:lines) call delete('Xdef') endfunc def Test_syntax() let var = 234 let other: list<string> = ['asdf'] enddef func Test_def_basic() def SomeFunc(): string return 'yes' enddef call assert_equal('yes', SomeFunc()) endfunc def Test_assignment() let bool1: bool = true assert_equal(v:true, bool1) let bool2: bool = false assert_equal(v:false, bool2) let list1: list<string> = ['sdf', 'asdf'] let list2: list<number> = [1, 2, 3] " TODO: does not work yet " let listS: list<string> = [] " let listN: list<number> = [] let dict1: dict<string> = #{key: 'value'} let dict2: dict<number> = #{one: 1, two: 2} v:char = 'abc' call assert_equal('abc', v:char) $ENVVAR = 'foobar' call assert_equal('foobar', $ENVVAR) $ENVVAR = '' enddef func Test_assignment_failure() call CheckDefFailure(['let var=234'], 'E1004:') call CheckDefFailure(['let var =234'], 'E1004:') call CheckDefFailure(['let var= 234'], 'E1004:') call CheckDefFailure(['let true = 1'], 'E1034:') call CheckDefFailure(['let false = 1'], 'E1034:') call CheckDefFailure(['let var: list<string> = [123]'], 'expected list<string> but got list<number>') call CheckDefFailure(['let var: list<number> = ["xx"]'], 'expected list<number> but got list<string>') call CheckDefFailure(['let var: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>') call CheckDefFailure(['let var: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>') call CheckDefFailure(['let var = feedkeys("0")'], 'E1031:') call CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void') endfunc func Test_const() call CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:') call CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:') call CheckDefFailure(['const two'], 'E1021:') endfunc def Test_block() let outer = 1 { let inner = 2 assert_equal(1, outer) assert_equal(2, inner) } assert_equal(1, outer) enddef func Test_block_failure() call CheckDefFailure(['{', 'let inner = 1', '}', 'echo inner'], 'E1001:') endfunc def ReturnString(): string return 'string' enddef def ReturnNumber(): number return 123 enddef def Test_return_string() assert_equal('string', ReturnString()) assert_equal(123, ReturnNumber()) enddef func Increment() let g:counter += 1 endfunc def Test_call_ufunc_count() g:counter = 1 Increment() Increment() Increment() " works with and without :call assert_equal(4, g:counter) call assert_equal(4, g:counter) unlet g:counter enddef def MyVarargs(arg: string, ...rest: list<string>): string let res = arg for s in rest res ..= ',' .. s endfor return res enddef def Test_call_varargs() assert_equal('one', MyVarargs('one')) assert_equal('one,two', MyVarargs('one', 'two')) assert_equal('one,two,three', MyVarargs('one', 'two', 'three')) enddef "def Test_call_func_defined_later() " call assert_equal('one', DefineLater('one')) " call assert_fails('call NotDefined("one")', 'E99:') "enddef func DefineLater(arg) return a:arg endfunc def MyDefaultArgs(name = 'string'): string return name enddef func Test_call_default_args_from_func() " TODO: implement using default value for optional argument "call assert_equal('string', MyDefaultArgs()) call assert_fails('call MyDefaultArgs()', 'optional arguments not implemented yet') call assert_equal('one', MyDefaultArgs('one')) call assert_fails('call MyDefaultArgs("one", "two")', 'E118:') endfunc def Test_call_default_args() " TODO: implement using default value for optional argument "assert_equal('string', MyDefaultArgs()) assert_equal('one', MyDefaultArgs('one')) assert_fails('call MyDefaultArgs("one", "two")', 'E118:') enddef def Test_return_type_wrong() CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef'], 'expected number but got string') CheckScriptFailure(['def Func(): string', 'return 1', 'enddef'], 'expected string but got number') CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef'], 'expected void but got string') CheckScriptFailure(['def Func()', 'return "a"', 'enddef'], 'expected void but got string') enddef def Test_arg_type_wrong() CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>') enddef def Test_try_catch() let l = [] try add(l, '1') throw 'wrong' add(l, '2') catch add(l, v:exception) finally add(l, '3') endtry assert_equal(['1', 'wrong', '3'], l) enddef let s:export_script_lines =<< trim END vim9script let name: string = 'bob' def Concat(arg: string): string return name .. arg enddef let g:result = Concat('bie') let g:localname = name export const CONST = 1234 export let exported = 9876 export def Exported(): string return 'Exported' enddef END def Test_vim9script() let import_script_lines =<< trim END vim9script import {exported, Exported} from './Xexport.vim' g:imported = exported g:imported_func = Exported() END writefile(import_script_lines, 'Ximport.vim') writefile(s:export_script_lines, 'Xexport.vim') source Ximport.vim assert_equal('bobbie', g:result) assert_equal('bob', g:localname) assert_equal(9876, g:imported) assert_equal('Exported', g:imported_func) assert_false(exists('g:name')) unlet g:result unlet g:localname unlet g:imported unlet g:imported_func delete('Ximport.vim') delete('Xexport.vim') CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:') CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:') enddef def Test_vim9script_call() let lines =<< trim END vim9script let var = '' def MyFunc(arg: string) var = arg enddef MyFunc('foobar') assert_equal('foobar', var) let str = 'barfoo' str->MyFunc() assert_equal('barfoo', var) let g:value = 'value' g:value->MyFunc() assert_equal('value', var) let listvar = [] def ListFunc(arg: list<number>) listvar = arg enddef [1, 2, 3]->ListFunc() assert_equal([1, 2, 3], listvar) let dictvar = {} def DictFunc(arg: dict<number>) dictvar = arg enddef {'a': 1, 'b': 2}->DictFunc() assert_equal(#{a: 1, b: 2}, dictvar) #{a: 3, b: 4}->DictFunc() assert_equal(#{a: 3, b: 4}, dictvar) END writefile(lines, 'Xcall.vim') source Xcall.vim delete('Xcall.vim') enddef def Test_vim9script_call_fail_decl() let lines =<< trim END vim9script let var = '' def MyFunc(arg: string) let var = 123 enddef END writefile(lines, 'Xcall_decl.vim') assert_fails('source Xcall_decl.vim', 'E1054:') delete('Xcall_decl.vim') enddef def Test_vim9script_call_fail_const() let lines =<< trim END vim9script const var = '' def MyFunc(arg: string) var = 'asdf' enddef END writefile(lines, 'Xcall_const.vim') assert_fails('source Xcall_const.vim', 'E46:') delete('Xcall_const.vim') enddef def Test_vim9script_reload() let lines =<< trim END vim9script const var = '' let valone = 1234 def MyFunc(arg: string) valone = 5678 enddef END let morelines =<< trim END let valtwo = 222 export def GetValtwo(): number return valtwo enddef END writefile(lines + morelines, 'Xreload.vim') source Xreload.vim source Xreload.vim source Xreload.vim let testlines =<< trim END vim9script def TheFunc() import GetValtwo from './Xreload.vim' assert_equal(222, GetValtwo()) enddef TheFunc() END writefile(testlines, 'Ximport.vim') source Ximport.vim " test that when not using "morelines" valtwo is still defined " need to source Xreload.vim again, import doesn't reload a script writefile(lines, 'Xreload.vim') source Xreload.vim source Ximport.vim " cannot declare a var twice lines =<< trim END vim9script let valone = 1234 let valone = 5678 END writefile(lines, 'Xreload.vim') assert_fails('source Xreload.vim', 'E1041:') delete('Xreload.vim') delete('Ximport.vim') enddef def Test_import_absolute() let import_lines = [ \ 'vim9script', \ 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"', \ 'def UseExported()', \ ' g:imported_abs = exported', \ ' exported = 8888', \ ' g:imported_after = exported', \ 'enddef', \ 'UseExported()', \ 'g:import_disassembled = execute("disass UseExported")', \ ] writefile(import_lines, 'Ximport_abs.vim') writefile(s:export_script_lines, 'Xexport_abs.vim') source Ximport_abs.vim assert_equal(9876, g:imported_abs) assert_equal(8888, g:imported_after) assert_match('<SNR>\d\+_UseExported.*' \ .. 'g:imported_abs = exported.*' \ .. '0 LOADSCRIPT exported from .*Xexport_abs.vim.*' \ .. '1 STOREG g:imported_abs.*' \ .. 'exported = 8888.*' \ .. '3 STORESCRIPT exported in .*Xexport_abs.vim.*' \ .. 'g:imported_after = exported.*' \ .. '4 LOADSCRIPT exported from .*Xexport_abs.vim.*' \ .. '5 STOREG g:imported_after.*' \, g:import_disassembled) unlet g:imported_abs unlet g:import_disassembled delete('Ximport_abs.vim') delete('Xexport_abs.vim') enddef def Test_import_rtp() let import_lines = [ \ 'vim9script', \ 'import exported from "Xexport_rtp.vim"', \ 'g:imported_rtp = exported', \ ] writefile(import_lines, 'Ximport_rtp.vim') mkdir('import') writefile(s:export_script_lines, 'import/Xexport_rtp.vim') let save_rtp = &rtp &rtp = getcwd() source Ximport_rtp.vim &rtp = save_rtp assert_equal(9876, g:imported_rtp) unlet g:imported_rtp delete('Ximport_rtp.vim') delete('import/Xexport_rtp.vim') delete('import', 'd') enddef def Test_fixed_size_list() " will be allocated as one piece of memory, check that changes work let l = [1, 2, 3, 4] l->remove(0) l->add(5) l->insert(99, 1) assert_equal([2, 99, 3, 4, 5], l) enddef " Test that inside :function a Python function can be defined, :def is not " recognized. func Test_function_python() CheckFeature python3 let py = 'python3' execute py "<< EOF" def do_something(): return 1 EOF endfunc def HasEval() if has('eval') echo 'yes' else echo 'no' endif enddef def HasNothing() if has('nothing') echo 'yes' else echo 'no' endif enddef def Test_compile_const_expr() assert_equal("\nyes", execute('call HasEval()')) let instr = execute('disassemble HasEval') assert_match('PUSHS "yes"', instr) assert_notmatch('PUSHS "no"', instr) assert_notmatch('JUMP', instr) assert_equal("\nno", execute('call HasNothing()')) instr = execute('disassemble HasNothing') assert_notmatch('PUSHS "yes"', instr) assert_match('PUSHS "no"', instr) assert_notmatch('JUMP', instr) enddef func NotCompiled() echo "not" endfunc let s:scriptvar = 4 let g:globalvar = 'g' def s:ScriptFuncLoad(arg: string) let local = 1 buffers echo arg echo local echo v:version echo s:scriptvar echo g:globalvar echo &tabstop echo $ENVVAR echo @z enddef def s:ScriptFuncPush() let localbool = true let localspec = v:none let localblob = 0z1234 if has('float') let localfloat = 1.234 endif enddef def s:ScriptFuncStore() let localnr = 1 localnr = 2 let localstr = 'abc' localstr = 'xyz' v:char = 'abc' s:scriptvar = 'sv' g:globalvar = 'gv' &tabstop = 8 $ENVVAR = 'ev' @z = 'rv' enddef def s:ScriptFuncTry() try echo 'yes' catch /fail/ echo 'no' finally echo 'end' endtry enddef def Test_disassemble() assert_fails('disass NoFunc', 'E1061:') assert_fails('disass NotCompiled', 'E1062:') let res = execute('disass s:ScriptFuncLoad') assert_match('<SNR>\d*_ScriptFuncLoad.*' \ .. 'buffers.*' \ .. ' EXEC \+buffers.*' \ .. ' LOAD arg\[-1\].*' \ .. ' LOAD $0.*' \ .. ' LOADV v:version.*' \ .. ' LOADS s:scriptvar from .*test_vim9_script.vim.*' \ .. ' LOADG g:globalvar.*' \ .. ' LOADENV $ENVVAR.*' \ .. ' LOADREG @z.*' \, res) res = execute('disass s:ScriptFuncPush') assert_match('<SNR>\d*_ScriptFuncPush.*' \ .. 'localbool = true.*' \ .. ' PUSH v:true.*' \ .. 'localspec = v:none.*' \ .. ' PUSH v:none.*' \ .. 'localblob = 0z1234.*' \ .. ' PUSHBLOB 0z1234.*' \, res) if has('float') assert_match('<SNR>\d*_ScriptFuncPush.*' \ .. 'localfloat = 1.234.*' \ .. ' PUSHF 1.234.*' \, res) endif res = execute('disass s:ScriptFuncStore') assert_match('<SNR>\d*_ScriptFuncStore.*' \ .. 'localnr = 2.*' \ .. ' STORE 2 in $0.*' \ .. 'localstr = ''xyz''.*' \ .. ' STORE $1.*' \ .. 'v:char = ''abc''.*' \ .. 'STOREV v:char.*' \ .. 's:scriptvar = ''sv''.*' \ .. ' STORES s:scriptvar in .*test_vim9_script.vim.*' \ .. 'g:globalvar = ''gv''.*' \ .. ' STOREG g:globalvar.*' \ .. '&tabstop = 8.*' \ .. ' STOREOPT &tabstop.*' \ .. '$ENVVAR = ''ev''.*' \ .. ' STOREENV $ENVVAR.*' \ .. '@z = ''rv''.*' \ .. ' STOREREG @z.*' \, res) res = execute('disass s:ScriptFuncTry') assert_match('<SNR>\d*_ScriptFuncTry.*' \ .. 'try.*' \ .. 'TRY catch -> \d\+, finally -> \d\+.*' \ .. 'catch /fail/.*' \ .. ' JUMP -> \d\+.*' \ .. ' PUSH v:exception.*' \ .. ' PUSHS "fail".*' \ .. ' COMPARESTRING =\~.*' \ .. ' JUMP_IF_FALSE -> \d\+.*' \ .. ' CATCH.*' \ .. 'finally.*' \ .. ' PUSHS "end".*' \ .. 'endtry.*' \ .. ' ENDTRY.*' \, res) enddef " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker