blob: fee07083e614b339caf79f3adfe09ee6d660bb84 [file] [log] [blame]
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01001" Test various aspects of the Vim9 script language.
2
Bram Moolenaar673660a2020-01-26 16:50:05 +01003source check.vim
4
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01005" Check that "lines" inside ":def" results in an "error" message.
6func CheckDefFailure(lines, error)
Bram Moolenaar978d1702020-01-26 17:38:12 +01007 call writefile(['def Func()'] + a:lines + ['enddef'], 'Xdef')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +01008 call assert_fails('so Xdef', a:error, a:lines)
9 call delete('Xdef')
10endfunc
11
12func CheckScriptFailure(lines, error)
13 call writefile(a:lines, 'Xdef')
14 call assert_fails('so Xdef', a:error, a:lines)
15 call delete('Xdef')
16endfunc
17
18def Test_syntax()
19 let var = 234
20 let other: list<string> = ['asdf']
21enddef
22
23func Test_def_basic()
24 def SomeFunc(): string
25 return 'yes'
26 enddef
27 call assert_equal('yes', SomeFunc())
28endfunc
29
30def Test_assignment()
31 let bool1: bool = true
32 assert_equal(v:true, bool1)
33 let bool2: bool = false
34 assert_equal(v:false, bool2)
35
36 let list1: list<string> = ['sdf', 'asdf']
37 let list2: list<number> = [1, 2, 3]
38
39 " TODO: does not work yet
40 " let listS: list<string> = []
41 " let listN: list<number> = []
42
43 let dict1: dict<string> = #{key: 'value'}
44 let dict2: dict<number> = #{one: 1, two: 2}
Bram Moolenaarb283a8a2020-02-02 22:24:04 +010045
46 v:char = 'abc'
47 call assert_equal('abc', v:char)
48
49 $ENVVAR = 'foobar'
50 call assert_equal('foobar', $ENVVAR)
51 $ENVVAR = ''
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010052enddef
53
54func Test_assignment_failure()
55 call CheckDefFailure(['let var=234'], 'E1004:')
56 call CheckDefFailure(['let var =234'], 'E1004:')
57 call CheckDefFailure(['let var= 234'], 'E1004:')
58
59 call CheckDefFailure(['let true = 1'], 'E1034:')
60 call CheckDefFailure(['let false = 1'], 'E1034:')
61
62 call CheckDefFailure(['let var: list<string> = [123]'], 'expected list<string> but got list<number>')
63 call CheckDefFailure(['let var: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
64
65 call CheckDefFailure(['let var: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>')
66 call CheckDefFailure(['let var: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>')
67
68 call CheckDefFailure(['let var = feedkeys("0")'], 'E1031:')
69 call CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void')
70endfunc
71
72func Test_const()
73 call CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:')
74 call CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:')
75 call CheckDefFailure(['const two'], 'E1021:')
76endfunc
77
78def Test_block()
79 let outer = 1
80 {
81 let inner = 2
82 assert_equal(1, outer)
83 assert_equal(2, inner)
84 }
85 assert_equal(1, outer)
86enddef
87
88func Test_block_failure()
89 call CheckDefFailure(['{', 'let inner = 1', '}', 'echo inner'], 'E1001:')
90endfunc
91
92def ReturnString(): string
93 return 'string'
94enddef
95
96def ReturnNumber(): number
97 return 123
98enddef
99
100def Test_return_string()
101 assert_equal('string', ReturnString())
102 assert_equal(123, ReturnNumber())
103enddef
104
105func Increment()
106 let g:counter += 1
107endfunc
108
109def Test_call_ufunc_count()
110 g:counter = 1
111 Increment()
112 Increment()
113 Increment()
114 " works with and without :call
115 assert_equal(4, g:counter)
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100116 call assert_equal(4, g:counter)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100117 unlet g:counter
118enddef
119
120def MyVarargs(arg: string, ...rest: list<string>): string
121 let res = arg
122 for s in rest
123 res ..= ',' .. s
124 endfor
125 return res
126enddef
127
128def Test_call_varargs()
129 assert_equal('one', MyVarargs('one'))
130 assert_equal('one,two', MyVarargs('one', 'two'))
131 assert_equal('one,two,three', MyVarargs('one', 'two', 'three'))
132enddef
133
Bram Moolenaar26e117e2020-02-04 21:24:15 +0100134"def Test_call_func_defined_later()
135" call assert_equal('one', DefineLater('one'))
136" call assert_fails('call NotDefined("one")', 'E99:')
137"enddef
138
139func DefineLater(arg)
140 return a:arg
141endfunc
142
143def MyDefaultArgs(name = 'string'): string
144 return name
145enddef
146
147func Test_call_default_args_from_func()
148 " TODO: implement using default value for optional argument
149 "call assert_equal('string', MyDefaultArgs())
150 call assert_fails('call MyDefaultArgs()', 'optional arguments not implemented yet')
151 call assert_equal('one', MyDefaultArgs('one'))
152 call assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
153endfunc
154
155def Test_call_default_args()
156 " TODO: implement using default value for optional argument
157 "assert_equal('string', MyDefaultArgs())
158 assert_equal('one', MyDefaultArgs('one'))
159 assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
160enddef
161
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100162def Test_return_type_wrong()
163 " TODO: why is ! needed for Mac and FreeBSD?
Bram Moolenaar978d1702020-01-26 17:38:12 +0100164 CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef'], 'expected number but got string')
165 CheckScriptFailure(['def Func(): string', 'return 1', 'enddef'], 'expected string but got number')
166 CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef'], 'expected void but got string')
167 CheckScriptFailure(['def Func()', 'return "a"', 'enddef'], 'expected void but got string')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100168enddef
169
170def Test_try_catch()
171 let l = []
172 try
173 add(l, '1')
174 throw 'wrong'
175 add(l, '2')
176 catch
177 add(l, v:exception)
178 finally
179 add(l, '3')
180 endtry
181 assert_equal(['1', 'wrong', '3'], l)
182enddef
183
184let s:export_script_lines =<< trim END
185 vim9script
186 let name: string = 'bob'
187 def Concat(arg: string): string
188 return name .. arg
189 enddef
190 let g:result = Concat('bie')
191 let g:localname = name
192
193 export const CONST = 1234
194 export let exported = 9876
195 export def Exported(): string
196 return 'Exported'
197 enddef
198END
199
200def Test_vim9script()
201 let import_script_lines =<< trim END
202 vim9script
203 import {exported, Exported} from './Xexport.vim'
204 g:imported = exported
205 g:imported_func = Exported()
206 END
207
208 writefile(import_script_lines, 'Ximport.vim')
209 writefile(s:export_script_lines, 'Xexport.vim')
210
211 source Ximport.vim
212
213 assert_equal('bobbie', g:result)
214 assert_equal('bob', g:localname)
215 assert_equal(9876, g:imported)
216 assert_equal('Exported', g:imported_func)
217 assert_false(exists('g:name'))
218
219 unlet g:result
220 unlet g:localname
221 unlet g:imported
222 unlet g:imported_func
223 delete('Ximport.vim')
224 delete('Xexport.vim')
225
226 CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:')
227 CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:')
228enddef
229
230def Test_vim9script_call()
231 let lines =<< trim END
232 vim9script
233 let var = ''
234 def MyFunc(arg: string)
235 var = arg
236 enddef
237 MyFunc('foobar')
238 assert_equal('foobar', var)
239
240 let str = 'barfoo'
241 str->MyFunc()
242 assert_equal('barfoo', var)
243
244 let g:value = 'value'
245 g:value->MyFunc()
246 assert_equal('value', var)
247
248 let listvar = []
249 def ListFunc(arg: list<number>)
250 listvar = arg
251 enddef
252 [1, 2, 3]->ListFunc()
253 assert_equal([1, 2, 3], listvar)
254
255 let dictvar = {}
256 def DictFunc(arg: dict<number>)
257 dictvar = arg
258 enddef
259 {'a': 1, 'b': 2}->DictFunc()
260 assert_equal(#{a: 1, b: 2}, dictvar)
261 #{a: 3, b: 4}->DictFunc()
262 assert_equal(#{a: 3, b: 4}, dictvar)
263 END
264 writefile(lines, 'Xcall.vim')
265 source Xcall.vim
266 delete('Xcall.vim')
267enddef
268
269def Test_vim9script_call_fail_decl()
270 let lines =<< trim END
271 vim9script
272 let var = ''
273 def MyFunc(arg: string)
274 let var = 123
275 enddef
276 END
277 writefile(lines, 'Xcall_decl.vim')
278 assert_fails('source Xcall_decl.vim', 'E1054:')
279 delete('Xcall_decl.vim')
280enddef
281
282def Test_vim9script_call_fail_const()
283 let lines =<< trim END
284 vim9script
285 const var = ''
286 def MyFunc(arg: string)
287 var = 'asdf'
288 enddef
289 END
290 writefile(lines, 'Xcall_const.vim')
291 assert_fails('source Xcall_const.vim', 'E46:')
292 delete('Xcall_const.vim')
293enddef
294
295def Test_vim9script_reload()
296 let lines =<< trim END
297 vim9script
298 const var = ''
299 let valone = 1234
300 def MyFunc(arg: string)
301 valone = 5678
302 enddef
303 END
304 let morelines =<< trim END
305 let valtwo = 222
306 export def GetValtwo(): number
307 return valtwo
308 enddef
309 END
310 writefile(lines + morelines, 'Xreload.vim')
311 source Xreload.vim
312 source Xreload.vim
313 source Xreload.vim
314
315 let testlines =<< trim END
316 vim9script
317 def TheFunc()
318 import GetValtwo from './Xreload.vim'
319 assert_equal(222, GetValtwo())
320 enddef
321 TheFunc()
322 END
323 writefile(testlines, 'Ximport.vim')
324 source Ximport.vim
325
326 " test that when not using "morelines" valtwo is still defined
327 " need to source Xreload.vim again, import doesn't reload a script
328 writefile(lines, 'Xreload.vim')
329 source Xreload.vim
330 source Ximport.vim
331
332 " cannot declare a var twice
333 lines =<< trim END
334 vim9script
335 let valone = 1234
336 let valone = 5678
337 END
338 writefile(lines, 'Xreload.vim')
339 assert_fails('source Xreload.vim', 'E1041:')
340
341 delete('Xreload.vim')
342 delete('Ximport.vim')
343enddef
344
345def Test_import_absolute()
346 let import_lines = [
347 \ 'vim9script',
348 \ 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"',
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100349 \ 'def UseExported()',
350 \ ' g:imported_abs = exported',
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100351 \ ' exported = 8888',
352 \ ' g:imported_after = exported',
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100353 \ 'enddef',
354 \ 'UseExported()',
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100355 \ 'g:import_disassembled = execute("disass UseExported")',
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100356 \ ]
357 writefile(import_lines, 'Ximport_abs.vim')
358 writefile(s:export_script_lines, 'Xexport_abs.vim')
359
360 source Ximport_abs.vim
361
362 assert_equal(9876, g:imported_abs)
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100363 assert_equal(8888, g:imported_after)
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100364 assert_match('<SNR>\d\+_UseExported.*'
365 \ .. 'g:imported_abs = exported.*'
366 \ .. '0 LOADSCRIPT exported from .*Xexport_abs.vim.*'
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100367 \ .. '1 STOREG g:imported_abs.*'
368 \ .. 'exported = 8888.*'
369 \ .. '3 STORESCRIPT exported in .*Xexport_abs.vim.*'
370 \ .. 'g:imported_after = exported.*'
371 \ .. '4 LOADSCRIPT exported from .*Xexport_abs.vim.*'
372 \ .. '5 STOREG g:imported_after.*'
373 \, g:import_disassembled)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100374 unlet g:imported_abs
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100375 unlet g:import_disassembled
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100376
377 delete('Ximport_abs.vim')
378 delete('Xexport_abs.vim')
379enddef
380
381def Test_import_rtp()
382 let import_lines = [
383 \ 'vim9script',
384 \ 'import exported from "Xexport_rtp.vim"',
385 \ 'g:imported_rtp = exported',
386 \ ]
387 writefile(import_lines, 'Ximport_rtp.vim')
388 mkdir('import')
389 writefile(s:export_script_lines, 'import/Xexport_rtp.vim')
390
391 let save_rtp = &rtp
392 &rtp = getcwd()
393 source Ximport_rtp.vim
394 &rtp = save_rtp
395
396 assert_equal(9876, g:imported_rtp)
397 unlet g:imported_rtp
398
399 delete('Ximport_rtp.vim')
400 delete('import/Xexport_rtp.vim')
401 delete('import', 'd')
402enddef
403
404def Test_fixed_size_list()
405 " will be allocated as one piece of memory, check that changes work
406 let l = [1, 2, 3, 4]
407 l->remove(0)
408 l->add(5)
409 l->insert(99, 1)
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100410 assert_equal([2, 99, 3, 4, 5], l)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100411enddef
412
Bram Moolenaar673660a2020-01-26 16:50:05 +0100413" Test that inside :function a Python function can be defined, :def is not
414" recognized.
415func Test_function_python()
416 CheckFeature python3
417 let py = 'python3'
418 execute py "<< EOF"
419def do_something():
420 return 1
421EOF
422endfunc
423
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100424def HasEval()
425 if has('eval')
426 echo 'yes'
427 else
428 echo 'no'
429 endif
430enddef
431
432def HasNothing()
433 if has('nothing')
434 echo 'yes'
435 else
436 echo 'no'
437 endif
438enddef
439
440def Test_compile_const_expr()
441 assert_equal("\nyes", execute('call HasEval()'))
442 let instr = execute('disassemble HasEval')
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100443 assert_match('PUSHS "yes"', instr)
444 assert_notmatch('PUSHS "no"', instr)
445 assert_notmatch('JUMP', instr)
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100446
447 assert_equal("\nno", execute('call HasNothing()'))
448 instr = execute('disassemble HasNothing')
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100449 assert_notmatch('PUSHS "yes"', instr)
450 assert_match('PUSHS "no"', instr)
451 assert_notmatch('JUMP', instr)
452enddef
453
454func NotCompiled()
455 echo "not"
456endfunc
457
458let s:scriptvar = 4
459let g:globalvar = 'g'
460
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100461def s:ScriptFuncLoad(arg: string)
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100462 let local = 1
463 buffers
464 echo arg
465 echo local
466 echo v:version
467 echo s:scriptvar
468 echo g:globalvar
469 echo &tabstop
470 echo $ENVVAR
471 echo @z
472enddef
473
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100474def s:ScriptFuncStore()
475 let localnr = 1
476 localnr = 2
477 let localstr = 'abc'
478 localstr = 'xyz'
479 v:char = 'abc'
480 s:scriptvar = 'sv'
481 g:globalvar = 'gv'
482 &tabstop = 8
483 $ENVVAR = 'ev'
484 @z = 'rv'
485enddef
486
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100487def Test_disassemble()
488 assert_fails('disass NoFunc', 'E1061:')
489 assert_fails('disass NotCompiled', 'E1062:')
490
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100491 let res = execute('disass s:ScriptFuncLoad')
492 assert_match('<SNR>\d*_ScriptFuncLoad.*'
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100493 \ .. 'buffers.*'
494 \ .. ' EXEC \+buffers.*'
495 \ .. ' LOAD arg\[-1\].*'
496 \ .. ' LOAD $0.*'
497 \ .. ' LOADV v:version.*'
498 \ .. ' LOADS s:scriptvar from .*test_vim9_script.vim.*'
499 \ .. ' LOADG g:globalvar.*'
500 \ .. ' LOADENV $ENVVAR.*'
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100501 \ .. ' LOADREG @z.*'
502 \, res)
503
504 " TODO:
505 " v:char =
506 " s:scriptvar =
507 res = execute('disass s:ScriptFuncStore')
508 assert_match('<SNR>\d*_ScriptFuncStore.*'
509 \ .. 'localnr = 2.*'
510 \ .. ' STORE 2 in $0.*'
511 \ .. 'localstr = ''xyz''.*'
512 \ .. ' STORE $1.*'
513 \ .. 'v:char = ''abc''.*'
514 \ .. 'STOREV v:char.*'
515 \ .. 's:scriptvar = ''sv''.*'
516 \ .. ' STORES s:scriptvar in .*test_vim9_script.vim.*'
517 \ .. 'g:globalvar = ''gv''.*'
518 \ .. ' STOREG g:globalvar.*'
519 \ .. '&tabstop = 8.*'
520 \ .. ' STOREOPT &tabstop.*'
521 \ .. '$ENVVAR = ''ev''.*'
522 \ .. ' STOREENV $ENVVAR.*'
523 \ .. '@z = ''rv''.*'
524 \ .. ' STOREREG @z.*'
525 \, res)
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100526enddef
527
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100528
529" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker