blob: ffeec5dbdfaa5bac6c161d8ffe6c5e798d3b17d9 [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}
45enddef
46
47func Test_assignment_failure()
48 call CheckDefFailure(['let var=234'], 'E1004:')
49 call CheckDefFailure(['let var =234'], 'E1004:')
50 call CheckDefFailure(['let var= 234'], 'E1004:')
51
52 call CheckDefFailure(['let true = 1'], 'E1034:')
53 call CheckDefFailure(['let false = 1'], 'E1034:')
54
55 call CheckDefFailure(['let var: list<string> = [123]'], 'expected list<string> but got list<number>')
56 call CheckDefFailure(['let var: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
57
58 call CheckDefFailure(['let var: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>')
59 call CheckDefFailure(['let var: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>')
60
61 call CheckDefFailure(['let var = feedkeys("0")'], 'E1031:')
62 call CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void')
63endfunc
64
65func Test_const()
66 call CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:')
67 call CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:')
68 call CheckDefFailure(['const two'], 'E1021:')
69endfunc
70
71def Test_block()
72 let outer = 1
73 {
74 let inner = 2
75 assert_equal(1, outer)
76 assert_equal(2, inner)
77 }
78 assert_equal(1, outer)
79enddef
80
81func Test_block_failure()
82 call CheckDefFailure(['{', 'let inner = 1', '}', 'echo inner'], 'E1001:')
83endfunc
84
85def ReturnString(): string
86 return 'string'
87enddef
88
89def ReturnNumber(): number
90 return 123
91enddef
92
93def Test_return_string()
94 assert_equal('string', ReturnString())
95 assert_equal(123, ReturnNumber())
96enddef
97
98func Increment()
99 let g:counter += 1
100endfunc
101
102def Test_call_ufunc_count()
103 g:counter = 1
104 Increment()
105 Increment()
106 Increment()
107 " works with and without :call
108 assert_equal(4, g:counter)
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100109 assert_equal(4, g:counter)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100110 unlet g:counter
111enddef
112
113def MyVarargs(arg: string, ...rest: list<string>): string
114 let res = arg
115 for s in rest
116 res ..= ',' .. s
117 endfor
118 return res
119enddef
120
121def Test_call_varargs()
122 assert_equal('one', MyVarargs('one'))
123 assert_equal('one,two', MyVarargs('one', 'two'))
124 assert_equal('one,two,three', MyVarargs('one', 'two', 'three'))
125enddef
126
127def Test_return_type_wrong()
128 " TODO: why is ! needed for Mac and FreeBSD?
Bram Moolenaar978d1702020-01-26 17:38:12 +0100129 CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef'], 'expected number but got string')
130 CheckScriptFailure(['def Func(): string', 'return 1', 'enddef'], 'expected string but got number')
131 CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef'], 'expected void but got string')
132 CheckScriptFailure(['def Func()', 'return "a"', 'enddef'], 'expected void but got string')
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100133enddef
134
135def Test_try_catch()
136 let l = []
137 try
138 add(l, '1')
139 throw 'wrong'
140 add(l, '2')
141 catch
142 add(l, v:exception)
143 finally
144 add(l, '3')
145 endtry
146 assert_equal(['1', 'wrong', '3'], l)
147enddef
148
149let s:export_script_lines =<< trim END
150 vim9script
151 let name: string = 'bob'
152 def Concat(arg: string): string
153 return name .. arg
154 enddef
155 let g:result = Concat('bie')
156 let g:localname = name
157
158 export const CONST = 1234
159 export let exported = 9876
160 export def Exported(): string
161 return 'Exported'
162 enddef
163END
164
165def Test_vim9script()
166 let import_script_lines =<< trim END
167 vim9script
168 import {exported, Exported} from './Xexport.vim'
169 g:imported = exported
170 g:imported_func = Exported()
171 END
172
173 writefile(import_script_lines, 'Ximport.vim')
174 writefile(s:export_script_lines, 'Xexport.vim')
175
176 source Ximport.vim
177
178 assert_equal('bobbie', g:result)
179 assert_equal('bob', g:localname)
180 assert_equal(9876, g:imported)
181 assert_equal('Exported', g:imported_func)
182 assert_false(exists('g:name'))
183
184 unlet g:result
185 unlet g:localname
186 unlet g:imported
187 unlet g:imported_func
188 delete('Ximport.vim')
189 delete('Xexport.vim')
190
191 CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:')
192 CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:')
193enddef
194
195def Test_vim9script_call()
196 let lines =<< trim END
197 vim9script
198 let var = ''
199 def MyFunc(arg: string)
200 var = arg
201 enddef
202 MyFunc('foobar')
203 assert_equal('foobar', var)
204
205 let str = 'barfoo'
206 str->MyFunc()
207 assert_equal('barfoo', var)
208
209 let g:value = 'value'
210 g:value->MyFunc()
211 assert_equal('value', var)
212
213 let listvar = []
214 def ListFunc(arg: list<number>)
215 listvar = arg
216 enddef
217 [1, 2, 3]->ListFunc()
218 assert_equal([1, 2, 3], listvar)
219
220 let dictvar = {}
221 def DictFunc(arg: dict<number>)
222 dictvar = arg
223 enddef
224 {'a': 1, 'b': 2}->DictFunc()
225 assert_equal(#{a: 1, b: 2}, dictvar)
226 #{a: 3, b: 4}->DictFunc()
227 assert_equal(#{a: 3, b: 4}, dictvar)
228 END
229 writefile(lines, 'Xcall.vim')
230 source Xcall.vim
231 delete('Xcall.vim')
232enddef
233
234def Test_vim9script_call_fail_decl()
235 let lines =<< trim END
236 vim9script
237 let var = ''
238 def MyFunc(arg: string)
239 let var = 123
240 enddef
241 END
242 writefile(lines, 'Xcall_decl.vim')
243 assert_fails('source Xcall_decl.vim', 'E1054:')
244 delete('Xcall_decl.vim')
245enddef
246
247def Test_vim9script_call_fail_const()
248 let lines =<< trim END
249 vim9script
250 const var = ''
251 def MyFunc(arg: string)
252 var = 'asdf'
253 enddef
254 END
255 writefile(lines, 'Xcall_const.vim')
256 assert_fails('source Xcall_const.vim', 'E46:')
257 delete('Xcall_const.vim')
258enddef
259
260def Test_vim9script_reload()
261 let lines =<< trim END
262 vim9script
263 const var = ''
264 let valone = 1234
265 def MyFunc(arg: string)
266 valone = 5678
267 enddef
268 END
269 let morelines =<< trim END
270 let valtwo = 222
271 export def GetValtwo(): number
272 return valtwo
273 enddef
274 END
275 writefile(lines + morelines, 'Xreload.vim')
276 source Xreload.vim
277 source Xreload.vim
278 source Xreload.vim
279
280 let testlines =<< trim END
281 vim9script
282 def TheFunc()
283 import GetValtwo from './Xreload.vim'
284 assert_equal(222, GetValtwo())
285 enddef
286 TheFunc()
287 END
288 writefile(testlines, 'Ximport.vim')
289 source Ximport.vim
290
291 " test that when not using "morelines" valtwo is still defined
292 " need to source Xreload.vim again, import doesn't reload a script
293 writefile(lines, 'Xreload.vim')
294 source Xreload.vim
295 source Ximport.vim
296
297 " cannot declare a var twice
298 lines =<< trim END
299 vim9script
300 let valone = 1234
301 let valone = 5678
302 END
303 writefile(lines, 'Xreload.vim')
304 assert_fails('source Xreload.vim', 'E1041:')
305
306 delete('Xreload.vim')
307 delete('Ximport.vim')
308enddef
309
310def Test_import_absolute()
311 let import_lines = [
312 \ 'vim9script',
313 \ 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"',
314 \ 'g:imported_abs = exported',
315 \ ]
316 writefile(import_lines, 'Ximport_abs.vim')
317 writefile(s:export_script_lines, 'Xexport_abs.vim')
318
319 source Ximport_abs.vim
320
321 assert_equal(9876, g:imported_abs)
322 unlet g:imported_abs
323
324 delete('Ximport_abs.vim')
325 delete('Xexport_abs.vim')
326enddef
327
328def Test_import_rtp()
329 let import_lines = [
330 \ 'vim9script',
331 \ 'import exported from "Xexport_rtp.vim"',
332 \ 'g:imported_rtp = exported',
333 \ ]
334 writefile(import_lines, 'Ximport_rtp.vim')
335 mkdir('import')
336 writefile(s:export_script_lines, 'import/Xexport_rtp.vim')
337
338 let save_rtp = &rtp
339 &rtp = getcwd()
340 source Ximport_rtp.vim
341 &rtp = save_rtp
342
343 assert_equal(9876, g:imported_rtp)
344 unlet g:imported_rtp
345
346 delete('Ximport_rtp.vim')
347 delete('import/Xexport_rtp.vim')
348 delete('import', 'd')
349enddef
350
351def Test_fixed_size_list()
352 " will be allocated as one piece of memory, check that changes work
353 let l = [1, 2, 3, 4]
354 l->remove(0)
355 l->add(5)
356 l->insert(99, 1)
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100357 assert_equal([2, 99, 3, 4, 5], l)
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100358enddef
359
Bram Moolenaar673660a2020-01-26 16:50:05 +0100360" Test that inside :function a Python function can be defined, :def is not
361" recognized.
362func Test_function_python()
363 CheckFeature python3
364 let py = 'python3'
365 execute py "<< EOF"
366def do_something():
367 return 1
368EOF
369endfunc
370
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100371def HasEval()
372 if has('eval')
373 echo 'yes'
374 else
375 echo 'no'
376 endif
377enddef
378
379def HasNothing()
380 if has('nothing')
381 echo 'yes'
382 else
383 echo 'no'
384 endif
385enddef
386
387def Test_compile_const_expr()
388 assert_equal("\nyes", execute('call HasEval()'))
389 let instr = execute('disassemble HasEval')
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100390 assert_match('PUSHS "yes"', instr)
391 assert_notmatch('PUSHS "no"', instr)
392 assert_notmatch('JUMP', instr)
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100393
394 assert_equal("\nno", execute('call HasNothing()'))
395 instr = execute('disassemble HasNothing')
Bram Moolenaar0f18b6d2020-02-02 17:22:27 +0100396 assert_notmatch('PUSHS "yes"', instr)
397 assert_match('PUSHS "no"', instr)
398 assert_notmatch('JUMP', instr)
399enddef
400
401func NotCompiled()
402 echo "not"
403endfunc
404
405let s:scriptvar = 4
406let g:globalvar = 'g'
407
408def s:ScriptFunc(arg: string)
409 let local = 1
410 buffers
411 echo arg
412 echo local
413 echo v:version
414 echo s:scriptvar
415 echo g:globalvar
416 echo &tabstop
417 echo $ENVVAR
418 echo @z
419enddef
420
421def Test_disassemble()
422 assert_fails('disass NoFunc', 'E1061:')
423 assert_fails('disass NotCompiled', 'E1062:')
424
425 let res = execute('disass s:ScriptFunc')
426 assert_match('<SNR>\d*_ScriptFunc.*'
427 \ .. 'buffers.*'
428 \ .. ' EXEC \+buffers.*'
429 \ .. ' LOAD arg\[-1\].*'
430 \ .. ' LOAD $0.*'
431 \ .. ' LOADV v:version.*'
432 \ .. ' LOADS s:scriptvar from .*test_vim9_script.vim.*'
433 \ .. ' LOADG g:globalvar.*'
434 \ .. ' LOADENV $ENVVAR.*'
435 \ .. ' LOADREG @z.*', res)
Bram Moolenaara259d8d2020-01-31 20:10:50 +0100436enddef
437
Bram Moolenaar8a7d6542020-01-26 15:56:19 +0100438
439" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker