blob: 023fc0f751d64ebc918d6cf0fa88a9de690819a3 [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
134def Test_return_type_wrong()
135 " TODO: why is ! needed for Mac and FreeBSD?
Bram Moolenaar978d1702020-01-26 17:38:12 +0100136 CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef'], 'expected number but got string')
137 CheckScriptFailure(['def Func(): string', 'return 1', 'enddef'], 'expected string but got number')
138 CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef'], 'expected void but got string')
139 CheckScriptFailure(['def Func()', 'return "a"', 'enddef'], 'expected void but got string')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100140enddef
141
142def Test_try_catch()
143 let l = []
144 try
145 add(l, '1')
146 throw 'wrong'
147 add(l, '2')
148 catch
149 add(l, v:exception)
150 finally
151 add(l, '3')
152 endtry
153 assert_equal(['1', 'wrong', '3'], l)
154enddef
155
156let s:export_script_lines =<< trim END
157 vim9script
158 let name: string = 'bob'
159 def Concat(arg: string): string
160 return name .. arg
161 enddef
162 let g:result = Concat('bie')
163 let g:localname = name
164
165 export const CONST = 1234
166 export let exported = 9876
167 export def Exported(): string
168 return 'Exported'
169 enddef
170END
171
172def Test_vim9script()
173 let import_script_lines =<< trim END
174 vim9script
175 import {exported, Exported} from './Xexport.vim'
176 g:imported = exported
177 g:imported_func = Exported()
178 END
179
180 writefile(import_script_lines, 'Ximport.vim')
181 writefile(s:export_script_lines, 'Xexport.vim')
182
183 source Ximport.vim
184
185 assert_equal('bobbie', g:result)
186 assert_equal('bob', g:localname)
187 assert_equal(9876, g:imported)
188 assert_equal('Exported', g:imported_func)
189 assert_false(exists('g:name'))
190
191 unlet g:result
192 unlet g:localname
193 unlet g:imported
194 unlet g:imported_func
195 delete('Ximport.vim')
196 delete('Xexport.vim')
197
198 CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:')
199 CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:')
200enddef
201
202def Test_vim9script_call()
203 let lines =<< trim END
204 vim9script
205 let var = ''
206 def MyFunc(arg: string)
207 var = arg
208 enddef
209 MyFunc('foobar')
210 assert_equal('foobar', var)
211
212 let str = 'barfoo'
213 str->MyFunc()
214 assert_equal('barfoo', var)
215
216 let g:value = 'value'
217 g:value->MyFunc()
218 assert_equal('value', var)
219
220 let listvar = []
221 def ListFunc(arg: list<number>)
222 listvar = arg
223 enddef
224 [1, 2, 3]->ListFunc()
225 assert_equal([1, 2, 3], listvar)
226
227 let dictvar = {}
228 def DictFunc(arg: dict<number>)
229 dictvar = arg
230 enddef
231 {'a': 1, 'b': 2}->DictFunc()
232 assert_equal(#{a: 1, b: 2}, dictvar)
233 #{a: 3, b: 4}->DictFunc()
234 assert_equal(#{a: 3, b: 4}, dictvar)
235 END
236 writefile(lines, 'Xcall.vim')
237 source Xcall.vim
238 delete('Xcall.vim')
239enddef
240
241def Test_vim9script_call_fail_decl()
242 let lines =<< trim END
243 vim9script
244 let var = ''
245 def MyFunc(arg: string)
246 let var = 123
247 enddef
248 END
249 writefile(lines, 'Xcall_decl.vim')
250 assert_fails('source Xcall_decl.vim', 'E1054:')
251 delete('Xcall_decl.vim')
252enddef
253
254def Test_vim9script_call_fail_const()
255 let lines =<< trim END
256 vim9script
257 const var = ''
258 def MyFunc(arg: string)
259 var = 'asdf'
260 enddef
261 END
262 writefile(lines, 'Xcall_const.vim')
263 assert_fails('source Xcall_const.vim', 'E46:')
264 delete('Xcall_const.vim')
265enddef
266
267def Test_vim9script_reload()
268 let lines =<< trim END
269 vim9script
270 const var = ''
271 let valone = 1234
272 def MyFunc(arg: string)
273 valone = 5678
274 enddef
275 END
276 let morelines =<< trim END
277 let valtwo = 222
278 export def GetValtwo(): number
279 return valtwo
280 enddef
281 END
282 writefile(lines + morelines, 'Xreload.vim')
283 source Xreload.vim
284 source Xreload.vim
285 source Xreload.vim
286
287 let testlines =<< trim END
288 vim9script
289 def TheFunc()
290 import GetValtwo from './Xreload.vim'
291 assert_equal(222, GetValtwo())
292 enddef
293 TheFunc()
294 END
295 writefile(testlines, 'Ximport.vim')
296 source Ximport.vim
297
298 " test that when not using "morelines" valtwo is still defined
299 " need to source Xreload.vim again, import doesn't reload a script
300 writefile(lines, 'Xreload.vim')
301 source Xreload.vim
302 source Ximport.vim
303
304 " cannot declare a var twice
305 lines =<< trim END
306 vim9script
307 let valone = 1234
308 let valone = 5678
309 END
310 writefile(lines, 'Xreload.vim')
311 assert_fails('source Xreload.vim', 'E1041:')
312
313 delete('Xreload.vim')
314 delete('Ximport.vim')
315enddef
316
317def Test_import_absolute()
318 let import_lines = [
319 \ 'vim9script',
320 \ 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"',
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100321 \ 'def UseExported()',
322 \ ' g:imported_abs = exported',
323 \ 'enddef',
324 \ 'UseExported()',
325 \ 'g:import_disassabled = execute("disass UseExported")',
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100326 \ ]
327 writefile(import_lines, 'Ximport_abs.vim')
328 writefile(s:export_script_lines, 'Xexport_abs.vim')
329
330 source Ximport_abs.vim
331
332 assert_equal(9876, g:imported_abs)
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100333 assert_match('<SNR>\d\+_UseExported.*'
334 \ .. 'g:imported_abs = exported.*'
335 \ .. '0 LOADSCRIPT exported from .*Xexport_abs.vim.*'
336 \ .. '1 STOREG g:imported_abs', g:import_disassabled)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100337 unlet g:imported_abs
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100338 unlet g:import_disassabled
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100339
340 delete('Ximport_abs.vim')
341 delete('Xexport_abs.vim')
342enddef
343
344def Test_import_rtp()
345 let import_lines = [
346 \ 'vim9script',
347 \ 'import exported from "Xexport_rtp.vim"',
348 \ 'g:imported_rtp = exported',
349 \ ]
350 writefile(import_lines, 'Ximport_rtp.vim')
351 mkdir('import')
352 writefile(s:export_script_lines, 'import/Xexport_rtp.vim')
353
354 let save_rtp = &rtp
355 &rtp = getcwd()
356 source Ximport_rtp.vim
357 &rtp = save_rtp
358
359 assert_equal(9876, g:imported_rtp)
360 unlet g:imported_rtp
361
362 delete('Ximport_rtp.vim')
363 delete('import/Xexport_rtp.vim')
364 delete('import', 'd')
365enddef
366
367def Test_fixed_size_list()
368 " will be allocated as one piece of memory, check that changes work
369 let l = [1, 2, 3, 4]
370 l->remove(0)
371 l->add(5)
372 l->insert(99, 1)
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100373 assert_equal([2, 99, 3, 4, 5], l)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100374enddef
375
Bram Moolenaar673660a2020-01-26 16:50:05 +0100376" Test that inside :function a Python function can be defined, :def is not
377" recognized.
378func Test_function_python()
379 CheckFeature python3
380 let py = 'python3'
381 execute py "<< EOF"
382def do_something():
383 return 1
384EOF
385endfunc
386
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100387def HasEval()
388 if has('eval')
389 echo 'yes'
390 else
391 echo 'no'
392 endif
393enddef
394
395def HasNothing()
396 if has('nothing')
397 echo 'yes'
398 else
399 echo 'no'
400 endif
401enddef
402
403def Test_compile_const_expr()
404 assert_equal("\nyes", execute('call HasEval()'))
405 let instr = execute('disassemble HasEval')
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100406 assert_match('PUSHS "yes"', instr)
407 assert_notmatch('PUSHS "no"', instr)
408 assert_notmatch('JUMP', instr)
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100409
410 assert_equal("\nno", execute('call HasNothing()'))
411 instr = execute('disassemble HasNothing')
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100412 assert_notmatch('PUSHS "yes"', instr)
413 assert_match('PUSHS "no"', instr)
414 assert_notmatch('JUMP', instr)
415enddef
416
417func NotCompiled()
418 echo "not"
419endfunc
420
421let s:scriptvar = 4
422let g:globalvar = 'g'
423
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100424def s:ScriptFuncLoad(arg: string)
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100425 let local = 1
426 buffers
427 echo arg
428 echo local
429 echo v:version
430 echo s:scriptvar
431 echo g:globalvar
432 echo &tabstop
433 echo $ENVVAR
434 echo @z
435enddef
436
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100437def s:ScriptFuncStore()
438 let localnr = 1
439 localnr = 2
440 let localstr = 'abc'
441 localstr = 'xyz'
442 v:char = 'abc'
443 s:scriptvar = 'sv'
444 g:globalvar = 'gv'
445 &tabstop = 8
446 $ENVVAR = 'ev'
447 @z = 'rv'
448enddef
449
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100450def Test_disassemble()
451 assert_fails('disass NoFunc', 'E1061:')
452 assert_fails('disass NotCompiled', 'E1062:')
453
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100454 let res = execute('disass s:ScriptFuncLoad')
455 assert_match('<SNR>\d*_ScriptFuncLoad.*'
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100456 \ .. 'buffers.*'
457 \ .. ' EXEC \+buffers.*'
458 \ .. ' LOAD arg\[-1\].*'
459 \ .. ' LOAD $0.*'
460 \ .. ' LOADV v:version.*'
461 \ .. ' LOADS s:scriptvar from .*test_vim9_script.vim.*'
462 \ .. ' LOADG g:globalvar.*'
463 \ .. ' LOADENV $ENVVAR.*'
Bram Moolenaarb283a8a2020-02-02 22:24:04 +0100464 \ .. ' LOADREG @z.*'
465 \, res)
466
467 " TODO:
468 " v:char =
469 " s:scriptvar =
470 res = execute('disass s:ScriptFuncStore')
471 assert_match('<SNR>\d*_ScriptFuncStore.*'
472 \ .. 'localnr = 2.*'
473 \ .. ' STORE 2 in $0.*'
474 \ .. 'localstr = ''xyz''.*'
475 \ .. ' STORE $1.*'
476 \ .. 'v:char = ''abc''.*'
477 \ .. 'STOREV v:char.*'
478 \ .. 's:scriptvar = ''sv''.*'
479 \ .. ' STORES s:scriptvar in .*test_vim9_script.vim.*'
480 \ .. 'g:globalvar = ''gv''.*'
481 \ .. ' STOREG g:globalvar.*'
482 \ .. '&tabstop = 8.*'
483 \ .. ' STOREOPT &tabstop.*'
484 \ .. '$ENVVAR = ''ev''.*'
485 \ .. ' STOREENV $ENVVAR.*'
486 \ .. '@z = ''rv''.*'
487 \ .. ' STOREREG @z.*'
488 \, res)
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100489enddef
490
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100491
492" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker