blob: 4b57bde0bd2b6d6debdf9723bf14db43b4ddbca4 [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
Bram Moolenaar6e587dc2020-02-06 13:15:52 +010030let s:appendToMe = 'xxx'
31let s:addToMe = 111
32
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010033def Test_assignment()
34 let bool1: bool = true
35 assert_equal(v:true, bool1)
36 let bool2: bool = false
37 assert_equal(v:false, bool2)
38
39 let list1: list<string> = ['sdf', 'asdf']
40 let list2: list<number> = [1, 2, 3]
41
42 " TODO: does not work yet
43 " let listS: list<string> = []
44 " let listN: list<number> = []
45
46 let dict1: dict<string> = #{key: 'value'}
47 let dict2: dict<number> = #{one: 1, two: 2}
Bram Moolenaarb283a8a2020-02-02 22:24:04 +010048
49 v:char = 'abc'
Bram Moolenaar6e587dc2020-02-06 13:15:52 +010050 assert_equal('abc', v:char)
Bram Moolenaarb283a8a2020-02-02 22:24:04 +010051
52 $ENVVAR = 'foobar'
Bram Moolenaar6e587dc2020-02-06 13:15:52 +010053 assert_equal('foobar', $ENVVAR)
Bram Moolenaarb283a8a2020-02-02 22:24:04 +010054 $ENVVAR = ''
Bram Moolenaar6e587dc2020-02-06 13:15:52 +010055
56 appendToMe ..= 'yyy'
57 assert_equal('xxxyyy', appendToMe)
58 addToMe += 222
59 assert_equal(333, addToMe)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +010060enddef
61
62func Test_assignment_failure()
63 call CheckDefFailure(['let var=234'], 'E1004:')
64 call CheckDefFailure(['let var =234'], 'E1004:')
65 call CheckDefFailure(['let var= 234'], 'E1004:')
66
67 call CheckDefFailure(['let true = 1'], 'E1034:')
68 call CheckDefFailure(['let false = 1'], 'E1034:')
69
70 call CheckDefFailure(['let var: list<string> = [123]'], 'expected list<string> but got list<number>')
71 call CheckDefFailure(['let var: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
72
73 call CheckDefFailure(['let var: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>')
74 call CheckDefFailure(['let var: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>')
75
76 call CheckDefFailure(['let var = feedkeys("0")'], 'E1031:')
77 call CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void')
78endfunc
79
80func Test_const()
81 call CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:')
82 call CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:')
83 call CheckDefFailure(['const two'], 'E1021:')
84endfunc
85
86def Test_block()
87 let outer = 1
88 {
89 let inner = 2
90 assert_equal(1, outer)
91 assert_equal(2, inner)
92 }
93 assert_equal(1, outer)
94enddef
95
96func Test_block_failure()
97 call CheckDefFailure(['{', 'let inner = 1', '}', 'echo inner'], 'E1001:')
98endfunc
99
100def ReturnString(): string
101 return 'string'
102enddef
103
104def ReturnNumber(): number
105 return 123
106enddef
107
108def Test_return_string()
109 assert_equal('string', ReturnString())
110 assert_equal(123, ReturnNumber())
111enddef
112
113func Increment()
114 let g:counter += 1
115endfunc
116
117def Test_call_ufunc_count()
118 g:counter = 1
119 Increment()
120 Increment()
121 Increment()
122 " works with and without :call
123 assert_equal(4, g:counter)
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100124 call assert_equal(4, g:counter)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100125 unlet g:counter
126enddef
127
128def MyVarargs(arg: string, ...rest: list<string>): string
129 let res = arg
130 for s in rest
131 res ..= ',' .. s
132 endfor
133 return res
134enddef
135
136def Test_call_varargs()
137 assert_equal('one', MyVarargs('one'))
138 assert_equal('one,two', MyVarargs('one', 'two'))
139 assert_equal('one,two,three', MyVarargs('one', 'two', 'three'))
140enddef
141
Bram Moolenaar170fcfc2020-02-06 17:51:35 +0100142def MyDefaultArgs(name = 'string'): string
143 return name
144enddef
145
146def Test_call_default_args()
147 assert_equal('string', MyDefaultArgs())
148 assert_equal('one', MyDefaultArgs('one'))
149 assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
150enddef
151
152func Test_call_default_args_from_func()
153 call assert_equal('string', MyDefaultArgs())
154 call assert_equal('one', MyDefaultArgs('one'))
155 call assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
156endfunc
157
158" Default arg and varargs
159def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string
160 let res = one .. ',' .. two
161 for s in rest
162 res ..= ',' .. s
163 endfor
164 return res
165enddef
166
167def Test_call_def_varargs()
168 call assert_fails('call MyDefVarargs()', 'E119:')
169 assert_equal('one,foo', MyDefVarargs('one'))
170 assert_equal('one,two', MyDefVarargs('one', 'two'))
171 assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three'))
172enddef
173
174
Bram Moolenaar26e117e2020-02-04 21:24:15 +0100175"def Test_call_func_defined_later()
176" call assert_equal('one', DefineLater('one'))
177" call assert_fails('call NotDefined("one")', 'E99:')
178"enddef
179
180func DefineLater(arg)
181 return a:arg
182endfunc
183
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100184def Test_return_type_wrong()
Bram Moolenaar978d1702020-01-26 17:38:12 +0100185 CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef'], 'expected number but got string')
186 CheckScriptFailure(['def Func(): string', 'return 1', 'enddef'], 'expected string but got number')
187 CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef'], 'expected void but got string')
188 CheckScriptFailure(['def Func()', 'return "a"', 'enddef'], 'expected void but got string')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100189enddef
190
Bram Moolenaarbfe12042020-02-04 21:54:07 +0100191def Test_arg_type_wrong()
192 CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>')
193enddef
194
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100195def Test_try_catch()
196 let l = []
197 try
198 add(l, '1')
199 throw 'wrong'
200 add(l, '2')
201 catch
202 add(l, v:exception)
203 finally
204 add(l, '3')
205 endtry
206 assert_equal(['1', 'wrong', '3'], l)
207enddef
208
209let s:export_script_lines =<< trim END
210 vim9script
211 let name: string = 'bob'
212 def Concat(arg: string): string
213 return name .. arg
214 enddef
215 let g:result = Concat('bie')
216 let g:localname = name
217
218 export const CONST = 1234
219 export let exported = 9876
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100220 export let exp_name = 'John'
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100221 export def Exported(): string
222 return 'Exported'
223 enddef
224END
225
226def Test_vim9script()
227 let import_script_lines =<< trim END
228 vim9script
229 import {exported, Exported} from './Xexport.vim'
230 g:imported = exported
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100231 exported += 3
232 g:imported_added = exported
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100233 g:imported_func = Exported()
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100234
235 import {exp_name} from './Xexport.vim'
236 g:imported_name = exp_name
237 exp_name ..= ' Doe'
238 g:imported_name_appended = exp_name
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100239 END
240
241 writefile(import_script_lines, 'Ximport.vim')
242 writefile(s:export_script_lines, 'Xexport.vim')
243
244 source Ximport.vim
245
246 assert_equal('bobbie', g:result)
247 assert_equal('bob', g:localname)
248 assert_equal(9876, g:imported)
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100249 assert_equal(9879, g:imported_added)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100250 assert_equal('Exported', g:imported_func)
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100251 assert_equal('John', g:imported_name)
252 assert_equal('John Doe', g:imported_name_appended)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100253 assert_false(exists('g:name'))
254
255 unlet g:result
256 unlet g:localname
257 unlet g:imported
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100258 unlet g:imported_added
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100259 unlet g:imported_func
Bram Moolenaar6e587dc2020-02-06 13:15:52 +0100260 unlet g:imported_name g:imported_name_appended
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100261 delete('Ximport.vim')
262 delete('Xexport.vim')
263
264 CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:')
265 CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:')
266enddef
267
268def Test_vim9script_call()
269 let lines =<< trim END
270 vim9script
271 let var = ''
272 def MyFunc(arg: string)
273 var = arg
274 enddef
275 MyFunc('foobar')
276 assert_equal('foobar', var)
277
278 let str = 'barfoo'
279 str->MyFunc()
280 assert_equal('barfoo', var)
281
282 let g:value = 'value'
283 g:value->MyFunc()
284 assert_equal('value', var)
285
286 let listvar = []
287 def ListFunc(arg: list<number>)
288 listvar = arg
289 enddef
290 [1, 2, 3]->ListFunc()
291 assert_equal([1, 2, 3], listvar)
292
293 let dictvar = {}
294 def DictFunc(arg: dict<number>)
295 dictvar = arg
296 enddef
297 {'a': 1, 'b': 2}->DictFunc()
298 assert_equal(#{a: 1, b: 2}, dictvar)
299 #{a: 3, b: 4}->DictFunc()
300 assert_equal(#{a: 3, b: 4}, dictvar)
301 END
302 writefile(lines, 'Xcall.vim')
303 source Xcall.vim
304 delete('Xcall.vim')
305enddef
306
307def Test_vim9script_call_fail_decl()
308 let lines =<< trim END
309 vim9script
310 let var = ''
311 def MyFunc(arg: string)
312 let var = 123
313 enddef
314 END
315 writefile(lines, 'Xcall_decl.vim')
316 assert_fails('source Xcall_decl.vim', 'E1054:')
317 delete('Xcall_decl.vim')
318enddef
319
320def Test_vim9script_call_fail_const()
321 let lines =<< trim END
322 vim9script
323 const var = ''
324 def MyFunc(arg: string)
325 var = 'asdf'
326 enddef
327 END
328 writefile(lines, 'Xcall_const.vim')
329 assert_fails('source Xcall_const.vim', 'E46:')
330 delete('Xcall_const.vim')
331enddef
332
333def Test_vim9script_reload()
334 let lines =<< trim END
335 vim9script
336 const var = ''
337 let valone = 1234
338 def MyFunc(arg: string)
339 valone = 5678
340 enddef
341 END
342 let morelines =<< trim END
343 let valtwo = 222
344 export def GetValtwo(): number
345 return valtwo
346 enddef
347 END
348 writefile(lines + morelines, 'Xreload.vim')
349 source Xreload.vim
350 source Xreload.vim
351 source Xreload.vim
352
353 let testlines =<< trim END
354 vim9script
355 def TheFunc()
356 import GetValtwo from './Xreload.vim'
357 assert_equal(222, GetValtwo())
358 enddef
359 TheFunc()
360 END
361 writefile(testlines, 'Ximport.vim')
362 source Ximport.vim
363
364 " test that when not using "morelines" valtwo is still defined
365 " need to source Xreload.vim again, import doesn't reload a script
366 writefile(lines, 'Xreload.vim')
367 source Xreload.vim
368 source Ximport.vim
369
370 " cannot declare a var twice
371 lines =<< trim END
372 vim9script
373 let valone = 1234
374 let valone = 5678
375 END
376 writefile(lines, 'Xreload.vim')
377 assert_fails('source Xreload.vim', 'E1041:')
378
379 delete('Xreload.vim')
380 delete('Ximport.vim')
381enddef
382
383def Test_import_absolute()
384 let import_lines = [
385 \ 'vim9script',
386 \ 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"',
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100387 \ 'def UseExported()',
388 \ ' g:imported_abs = exported',
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100389 \ ' exported = 8888',
390 \ ' g:imported_after = exported',
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100391 \ 'enddef',
392 \ 'UseExported()',
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100393 \ 'g:import_disassembled = execute("disass UseExported")',
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100394 \ ]
395 writefile(import_lines, 'Ximport_abs.vim')
396 writefile(s:export_script_lines, 'Xexport_abs.vim')
397
398 source Ximport_abs.vim
399
400 assert_equal(9876, g:imported_abs)
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100401 assert_equal(8888, g:imported_after)
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100402 assert_match('<SNR>\d\+_UseExported.*'
403 \ .. 'g:imported_abs = exported.*'
404 \ .. '0 LOADSCRIPT exported from .*Xexport_abs.vim.*'
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100405 \ .. '1 STOREG g:imported_abs.*'
406 \ .. 'exported = 8888.*'
407 \ .. '3 STORESCRIPT exported in .*Xexport_abs.vim.*'
408 \ .. 'g:imported_after = exported.*'
409 \ .. '4 LOADSCRIPT exported from .*Xexport_abs.vim.*'
410 \ .. '5 STOREG g:imported_after.*'
411 \, g:import_disassembled)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100412 unlet g:imported_abs
Bram Moolenaar4e12a5d2020-02-03 20:50:59 +0100413 unlet g:import_disassembled
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100414
415 delete('Ximport_abs.vim')
416 delete('Xexport_abs.vim')
417enddef
418
419def Test_import_rtp()
420 let import_lines = [
421 \ 'vim9script',
422 \ 'import exported from "Xexport_rtp.vim"',
423 \ 'g:imported_rtp = exported',
424 \ ]
425 writefile(import_lines, 'Ximport_rtp.vim')
426 mkdir('import')
427 writefile(s:export_script_lines, 'import/Xexport_rtp.vim')
428
429 let save_rtp = &rtp
430 &rtp = getcwd()
431 source Ximport_rtp.vim
432 &rtp = save_rtp
433
434 assert_equal(9876, g:imported_rtp)
435 unlet g:imported_rtp
436
437 delete('Ximport_rtp.vim')
438 delete('import/Xexport_rtp.vim')
439 delete('import', 'd')
440enddef
441
442def Test_fixed_size_list()
443 " will be allocated as one piece of memory, check that changes work
444 let l = [1, 2, 3, 4]
445 l->remove(0)
446 l->add(5)
447 l->insert(99, 1)
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100448 assert_equal([2, 99, 3, 4, 5], l)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100449enddef
450
Bram Moolenaar673660a2020-01-26 16:50:05 +0100451" Test that inside :function a Python function can be defined, :def is not
452" recognized.
453func Test_function_python()
454 CheckFeature python3
455 let py = 'python3'
456 execute py "<< EOF"
457def do_something():
458 return 1
459EOF
460endfunc
461
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100462def HasEval()
463 if has('eval')
464 echo 'yes'
465 else
466 echo 'no'
467 endif
468enddef
469
470def HasNothing()
471 if has('nothing')
472 echo 'yes'
473 else
474 echo 'no'
475 endif
476enddef
477
478def Test_compile_const_expr()
479 assert_equal("\nyes", execute('call HasEval()'))
480 let instr = execute('disassemble HasEval')
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100481 assert_match('PUSHS "yes"', instr)
482 assert_notmatch('PUSHS "no"', instr)
483 assert_notmatch('JUMP', instr)
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100484
485 assert_equal("\nno", execute('call HasNothing()'))
486 instr = execute('disassemble HasNothing')
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100487 assert_notmatch('PUSHS "yes"', instr)
488 assert_match('PUSHS "no"', instr)
489 assert_notmatch('JUMP', instr)
490enddef
491
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100492
493" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker