1" Test various aspects of the Vim9 script language.
2
3source check.vim
4source view_util.vim
5
6" Check that "lines" inside ":def" results in an "error" message.
7func CheckDefFailure(lines, error)
8  call writefile(['def Func()'] + a:lines + ['enddef'], 'Xdef')
9  call assert_fails('so Xdef', a:error, a:lines)
10  call delete('Xdef')
11endfunc
12
13func CheckScriptFailure(lines, error)
14  call writefile(a:lines, 'Xdef')
15  call assert_fails('so Xdef', a:error, a:lines)
16  call delete('Xdef')
17endfunc
18
19def Test_syntax()
20  let var = 234
21  let other: list<string> = ['asdf']
22enddef
23
24let s:appendToMe = 'xxx'
25let s:addToMe = 111
26let g:existing = 'yes'
27let g:inc_counter = 1
28let $SOME_ENV_VAR = 'some'
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<bool> = [false, true, false]
37  let list2: list<number> = [1, 2, 3]
38  let list3: list<string> = ['sdf', 'asdf']
39  let list4: list<any> = ['yes', true, 1234]
40  let list5: list<blob> = [0z01, 0z02]
41
42  let listS: list<string> = []
43  let listN: list<number> = []
44
45  let dict1: dict<bool> = #{one: false, two: true}
46  let dict2: dict<number> = #{one: 1, two: 2}
47  let dict3: dict<string> = #{key: 'value'}
48  let dict4: dict<any> = #{one: 1, two: '2'}
49  let dict5: dict<blob> = #{one: 0z01, tw: 0z02}
50
51  let a: number = 6
52  assert_equal(6, a)
53
54  if has('channel')
55    let chan1: channel
56    let job1: job
57    let job2: job = job_start('willfail')
58  endif
59  if has('float')
60    let float1: float = 3.4
61  endif
62  let Funky1: func
63  let Funky2: func = function('len')
64  let Party2: func = funcref('Test_syntax')
65
66  " type becomes list<any>
67  let somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
68  " type becomes dict<any>
69  let somedict = rand() > 0 ? #{a: 1, b: 2} : #{a: 'a', b: 'b'}
70
71  g:newvar = 'new'
72  assert_equal('new', g:newvar)
73
74  assert_equal('yes', g:existing)
75  g:existing = 'no'
76  assert_equal('no', g:existing)
77
78  v:char = 'abc'
79  assert_equal('abc', v:char)
80
81  $ENVVAR = 'foobar'
82  assert_equal('foobar', $ENVVAR)
83  $ENVVAR = ''
84
85  s:appendToMe ..= 'yyy'
86  assert_equal('xxxyyy', s:appendToMe)
87  s:addToMe += 222
88  assert_equal(333, s:addToMe)
89  s:newVar = 'new'
90  assert_equal('new', s:newVar)
91
92  set ts=7
93  &ts += 1
94  assert_equal(8, &ts)
95  &ts -= 3
96  assert_equal(5, &ts)
97  &ts *= 2
98  assert_equal(10, &ts)
99  &ts /= 3
100  assert_equal(3, &ts)
101  set ts=10
102  &ts %= 4
103  assert_equal(2, &ts)
104  call CheckDefFailure(['&notex += 3'], 'E113:')
105  call CheckDefFailure(['&ts ..= "xxx"'], 'E1019:')
106  call CheckDefFailure(['&path += 3'], 'E1013:')
107  " test freeing ISN_STOREOPT
108  call CheckDefFailure(['&ts = 3', 'let asdf'], 'E1022:')
109  &ts = 8
110
111  g:inc_counter += 1
112  assert_equal(2, g:inc_counter)
113
114  $SOME_ENV_VAR ..= 'more'
115  assert_equal('somemore', $SOME_ENV_VAR)
116  call CheckDefFailure(['$SOME_ENV_VAR += "more"'], 'E1013:')
117  call CheckDefFailure(['$SOME_ENV_VAR += 123'], 'E1013:')
118
119  @a = 'areg'
120  @a ..= 'add'
121  assert_equal('aregadd', @a)
122  call CheckDefFailure(['@a += "more"'], 'E1013:')
123  call CheckDefFailure(['@a += 123'], 'E1013:')
124
125  v:errmsg = 'none'
126  v:errmsg ..= 'again'
127  assert_equal('noneagain', v:errmsg)
128  call CheckDefFailure(['v:errmsg += "more"'], 'E1013:')
129  call CheckDefFailure(['v:errmsg += 123'], 'E1013:')
130enddef
131
132def Test_assignment_default()
133
134  " Test default values.
135  let thebool: bool
136  assert_equal(v:false, thebool)
137
138  let thenumber: number
139  assert_equal(0, thenumber)
140
141  if has('float')
142    let thefloat: float
143    assert_equal(0.0, thefloat)
144  endif
145
146  let thestring: string
147  assert_equal('', thestring)
148
149  let theblob: blob
150  assert_equal(0z, theblob)
151
152  let Thefunc: func
153  assert_equal(test_null_function(), Thefunc)
154
155  let thelist: list<any>
156  assert_equal([], thelist)
157
158  let thedict: dict<any>
159  assert_equal({}, thedict)
160
161  if has('channel')
162    let thejob: job
163    assert_equal(test_null_job(), thejob)
164
165    let thechannel: channel
166    assert_equal(test_null_channel(), thechannel)
167  endif
168
169  let nr = 1234 | nr = 5678
170  assert_equal(5678, nr)
171enddef
172
173def Mess(): string
174  v:foldstart = 123
175  return 'xxx'
176enddef
177
178func Test_assignment_failure()
179  call CheckDefFailure(['let var=234'], 'E1004:')
180  call CheckDefFailure(['let var =234'], 'E1004:')
181  call CheckDefFailure(['let var= 234'], 'E1004:')
182
183  call CheckDefFailure(['let true = 1'], 'E1034:')
184  call CheckDefFailure(['let false = 1'], 'E1034:')
185
186  call CheckDefFailure(['let [a; b; c] = g:list'], 'E452:')
187
188  call CheckDefFailure(['let somevar'], "E1022:")
189  call CheckDefFailure(['let &option'], 'E1052:')
190  call CheckDefFailure(['&g:option = 5'], 'E113:')
191
192  call CheckDefFailure(['let $VAR = 5'], 'E1065:')
193
194  call CheckDefFailure(['let @~ = 5'], 'E354:')
195  call CheckDefFailure(['let @a = 5'], 'E1066:')
196
197  call CheckDefFailure(['let g:var = 5'], 'E1016:')
198
199  call CheckDefFailure(['let anr = 4', 'anr ..= "text"'], 'E1019:')
200  call CheckDefFailure(['let xnr += 4'], 'E1020:')
201
202  call CheckScriptFailure(['vim9script', 'def Func()', 'let dummy = s:notfound', 'enddef'], 'E1050:')
203
204  call CheckDefFailure(['let var: list<string> = [123]'], 'expected list<string> but got list<number>')
205  call CheckDefFailure(['let var: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
206
207  call CheckDefFailure(['let var: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>')
208  call CheckDefFailure(['let var: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>')
209
210  call CheckDefFailure(['let var = feedkeys("0")'], 'E1031:')
211  call CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void')
212
213  call CheckDefFailure(['let var: dict <number>'], 'E1068:')
214  call CheckDefFailure(['let var: dict<number'], 'E1009:')
215
216  call assert_fails('s/^/\=Mess()/n', 'E794:')
217  call CheckDefFailure(['let var: dict<number'], 'E1009:')
218endfunc
219
220func Test_wrong_type()
221  call CheckDefFailure(['let var: list<nothing>'], 'E1010:')
222  call CheckDefFailure(['let var: list<list<nothing>>'], 'E1010:')
223  call CheckDefFailure(['let var: dict<nothing>'], 'E1010:')
224  call CheckDefFailure(['let var: dict<dict<nothing>>'], 'E1010:')
225
226  call CheckDefFailure(['let var: dict<number'], 'E1009:')
227  call CheckDefFailure(['let var: dict<list<number>'], 'E1009:')
228
229  call CheckDefFailure(['let var: ally'], 'E1010:')
230  call CheckDefFailure(['let var: bram'], 'E1010:')
231  call CheckDefFailure(['let var: cathy'], 'E1010:')
232  call CheckDefFailure(['let var: dom'], 'E1010:')
233  call CheckDefFailure(['let var: freddy'], 'E1010:')
234  call CheckDefFailure(['let var: john'], 'E1010:')
235  call CheckDefFailure(['let var: larry'], 'E1010:')
236  call CheckDefFailure(['let var: ned'], 'E1010:')
237  call CheckDefFailure(['let var: pam'], 'E1010:')
238  call CheckDefFailure(['let var: sam'], 'E1010:')
239  call CheckDefFailure(['let var: vim'], 'E1010:')
240endfunc
241
242func Test_const()
243  call CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:')
244  call CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:')
245  call CheckDefFailure(['const two'], 'E1021:')
246  call CheckDefFailure(['const &option'], 'E996:')
247endfunc
248
249def Test_block()
250  let outer = 1
251  {
252    let inner = 2
253    assert_equal(1, outer)
254    assert_equal(2, inner)
255  }
256  assert_equal(1, outer)
257enddef
258
259func Test_block_failure()
260  call CheckDefFailure(['{', 'let inner = 1', '}', 'echo inner'], 'E1001:')
261  call CheckDefFailure(['}'], 'E1025:')
262  call CheckDefFailure(['{', 'echo 1'], 'E1026:')
263endfunc
264
265def Test_cmd_modifier()
266  tab echo '0'
267  call CheckDefFailure(['5tab echo 3'], 'E16:')
268enddef
269
270def Test_try_catch()
271  let l = []
272  try
273    add(l, '1')
274    throw 'wrong'
275    add(l, '2')
276  catch
277    add(l, v:exception)
278  finally
279    add(l, '3')
280  endtry
281  assert_equal(['1', 'wrong', '3'], l)
282enddef
283
284def ThrowFromDef()
285  throw 'getout'
286enddef
287
288func CatchInFunc()
289  try
290    call ThrowFromDef()
291  catch
292    let g:thrown_func = v:exception
293  endtry
294endfunc
295
296def CatchInDef()
297  try
298    ThrowFromDef()
299  catch
300    g:thrown_def = v:exception
301  endtry
302enddef
303
304def ReturnFinally(): string
305  try
306    return 'intry'
307  finally
308    g:in_finally = 'finally'
309  endtry
310  return 'end'
311enddef
312
313def Test_try_catch_nested()
314  CatchInFunc()
315  assert_equal('getout', g:thrown_func)
316
317  CatchInDef()
318  assert_equal('getout', g:thrown_def)
319
320  assert_equal('intry', ReturnFinally())
321  assert_equal('finally', g:in_finally)
322enddef
323
324def Test_try_catch_match()
325  let seq = 'a'
326  try
327    throw 'something'
328  catch /nothing/
329    seq ..= 'x'
330  catch /some/
331    seq ..= 'b'
332  catch /asdf/
333    seq ..= 'x'
334  catch ?a\?sdf?
335    seq ..= 'y'
336  finally
337    seq ..= 'c'
338  endtry
339  assert_equal('abc', seq)
340enddef
341
342def Test_try_catch_fails()
343  call CheckDefFailure(['catch'], 'E603:')
344  call CheckDefFailure(['try', 'echo 0', 'catch','catch'], 'E1033:')
345  call CheckDefFailure(['try', 'echo 0', 'catch /pat'], 'E1067:')
346  call CheckDefFailure(['finally'], 'E606:')
347  call CheckDefFailure(['try', 'echo 0', 'finally', 'echo 1', 'finally'], 'E607:')
348  call CheckDefFailure(['endtry'], 'E602:')
349  call CheckDefFailure(['while 1', 'endtry'], 'E170:')
350  call CheckDefFailure(['for i in range(5)', 'endtry'], 'E170:')
351  call CheckDefFailure(['if 2', 'endtry'], 'E171:')
352  call CheckDefFailure(['try', 'echo 1', 'endtry'], 'E1032:')
353
354  call CheckDefFailure(['throw'], 'E471:')
355  call CheckDefFailure(['throw xxx'], 'E1001:')
356enddef
357
358let s:export_script_lines =<< trim END
359  vim9script
360  let name: string = 'bob'
361  def Concat(arg: string): string
362    return name .. arg
363  enddef
364  let g:result = Concat('bie')
365  let g:localname = name
366
367  export const CONST = 1234
368  export let exported = 9876
369  export let exp_name = 'John'
370  export def Exported(): string
371    return 'Exported'
372  enddef
373END
374
375def Test_vim9_import_export()
376  let import_script_lines =<< trim END
377    vim9script
378    import {exported, Exported} from './Xexport.vim'
379    g:imported = exported
380    exported += 3
381    g:imported_added = exported
382    g:imported_func = Exported()
383
384    import {exp_name} from './Xexport.vim'
385    g:imported_name = exp_name
386    exp_name ..= ' Doe'
387    g:imported_name_appended = exp_name
388    g:imported_later = exported
389  END
390
391  writefile(import_script_lines, 'Ximport.vim')
392  writefile(s:export_script_lines, 'Xexport.vim')
393
394  source Ximport.vim
395
396  assert_equal('bobbie', g:result)
397  assert_equal('bob', g:localname)
398  assert_equal(9876, g:imported)
399  assert_equal(9879, g:imported_added)
400  assert_equal(9879, g:imported_later)
401  assert_equal('Exported', g:imported_func)
402  assert_equal('John', g:imported_name)
403  assert_equal('John Doe', g:imported_name_appended)
404  assert_false(exists('g:name'))
405
406  unlet g:result
407  unlet g:localname
408  unlet g:imported
409  unlet g:imported_added
410  unlet g:imported_later
411  unlet g:imported_func
412  unlet g:imported_name g:imported_name_appended
413  delete('Ximport.vim')
414
415  let import_in_def_lines =<< trim END
416    vim9script
417    def ImportInDef()
418      import exported from './Xexport.vim'
419      g:imported = exported
420      exported += 7
421      g:imported_added = exported
422    enddef
423    ImportInDef()
424  END
425  writefile(import_in_def_lines, 'Ximport2.vim')
426  source Ximport2.vim
427  " TODO: this should be 9879
428  assert_equal(9876, g:imported)
429  assert_equal(9883, g:imported_added)
430  unlet g:imported
431  unlet g:imported_added
432  delete('Ximport2.vim')
433
434  let import_star_as_lines =<< trim END
435    vim9script
436    import * as Export from './Xexport.vim'
437    def UseExport()
438      g:imported = Export.exported
439    enddef
440    UseExport()
441  END
442  writefile(import_star_as_lines, 'Ximport.vim')
443  source Ximport.vim
444  assert_equal(9883, g:imported)
445
446  let import_star_as_lines_no_dot =<< trim END
447    vim9script
448    import * as Export from './Xexport.vim'
449    def Func()
450      let dummy = 1
451      let imported = Export + dummy
452    enddef
453  END
454  writefile(import_star_as_lines_no_dot, 'Ximport.vim')
455  assert_fails('source Ximport.vim', 'E1060:')
456
457  let import_star_as_lines_dot_space =<< trim END
458    vim9script
459    import * as Export from './Xexport.vim'
460    def Func()
461      let imported = Export . exported
462    enddef
463  END
464  writefile(import_star_as_lines_dot_space, 'Ximport.vim')
465  assert_fails('source Ximport.vim', 'E1074:')
466
467  let import_star_as_lines_missing_name =<< trim END
468    vim9script
469    import * as Export from './Xexport.vim'
470    def Func()
471      let imported = Export.
472    enddef
473  END
474  writefile(import_star_as_lines_missing_name, 'Ximport.vim')
475  assert_fails('source Ximport.vim', 'E1048:')
476
477  let import_star_lines =<< trim END
478    vim9script
479    import * from './Xexport.vim'
480    g:imported = exported
481  END
482  writefile(import_star_lines, 'Ximport.vim')
483  assert_fails('source Ximport.vim', 'E1045:')
484
485  " try to import something that exists but is not exported
486  let import_not_exported_lines =<< trim END
487    vim9script
488    import name from './Xexport.vim'
489  END
490  writefile(import_not_exported_lines, 'Ximport.vim')
491  assert_fails('source Ximport.vim', 'E1049:')
492
493  " try to import something that is already defined
494  let import_already_defined =<< trim END
495    vim9script
496    let exported = 'something'
497    import exported from './Xexport.vim'
498  END
499  writefile(import_already_defined, 'Ximport.vim')
500  assert_fails('source Ximport.vim', 'E1073:')
501
502  " try to import something that is already defined
503  import_already_defined =<< trim END
504    vim9script
505    let exported = 'something'
506    import * as exported from './Xexport.vim'
507  END
508  writefile(import_already_defined, 'Ximport.vim')
509  assert_fails('source Ximport.vim', 'E1073:')
510
511  " try to import something that is already defined
512  import_already_defined =<< trim END
513    vim9script
514    let exported = 'something'
515    import {exported} from './Xexport.vim'
516  END
517  writefile(import_already_defined, 'Ximport.vim')
518  assert_fails('source Ximport.vim', 'E1073:')
519
520  " import a very long name, requires making a copy
521  let import_long_name_lines =<< trim END
522    vim9script
523    import name012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 from './Xexport.vim'
524  END
525  writefile(import_long_name_lines, 'Ximport.vim')
526  assert_fails('source Ximport.vim', 'E1048:')
527
528  let import_no_from_lines =<< trim END
529    vim9script
530    import name './Xexport.vim'
531  END
532  writefile(import_no_from_lines, 'Ximport.vim')
533  assert_fails('source Ximport.vim', 'E1070:')
534
535  let import_invalid_string_lines =<< trim END
536    vim9script
537    import name from Xexport.vim
538  END
539  writefile(import_invalid_string_lines, 'Ximport.vim')
540  assert_fails('source Ximport.vim', 'E1071:')
541
542  let import_wrong_name_lines =<< trim END
543    vim9script
544    import name from './XnoExport.vim'
545  END
546  writefile(import_wrong_name_lines, 'Ximport.vim')
547  assert_fails('source Ximport.vim', 'E1053:')
548
549  let import_missing_comma_lines =<< trim END
550    vim9script
551    import {exported name} from './Xexport.vim'
552  END
553  writefile(import_missing_comma_lines, 'Ximport3.vim')
554  assert_fails('source Ximport3.vim', 'E1046:')
555
556  delete('Ximport.vim')
557  delete('Ximport3.vim')
558  delete('Xexport.vim')
559
560  " Check that in a Vim9 script 'cpo' is set to the Vim default.
561  set cpo&vi
562  let cpo_before = &cpo
563  let lines =<< trim END
564    vim9script
565    g:cpo_in_vim9script = &cpo
566  END
567  writefile(lines, 'Xvim9_script')
568  source Xvim9_script
569  assert_equal(cpo_before, &cpo)
570  set cpo&vim
571  assert_equal(&cpo, g:cpo_in_vim9script)
572  delete('Xvim9_script')
573enddef
574
575def Test_vim9script_fails()
576  CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:')
577  CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:')
578  CheckScriptFailure(['export let some = 123'], 'E1042:')
579  CheckScriptFailure(['import some from "./Xexport.vim"'], 'E1042:')
580  CheckScriptFailure(['vim9script', 'export let g:some'], 'E1044:')
581  CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:')
582
583  assert_fails('vim9script', 'E1038')
584  assert_fails('export something', 'E1042')
585enddef
586
587def Test_vim9script_reload()
588  let lines =<< trim END
589    vim9script
590    const var = ''
591    let valone = 1234
592    def MyFunc(arg: string)
593       valone = 5678
594    enddef
595  END
596  let morelines =<< trim END
597    let valtwo = 222
598    export def GetValtwo(): number
599      return valtwo
600    enddef
601  END
602  writefile(lines + morelines, 'Xreload.vim')
603  source Xreload.vim
604  source Xreload.vim
605  source Xreload.vim
606
607  let testlines =<< trim END
608    vim9script
609    def TheFunc()
610      import GetValtwo from './Xreload.vim'
611      assert_equal(222, GetValtwo())
612    enddef
613    TheFunc()
614  END
615  writefile(testlines, 'Ximport.vim')
616  source Ximport.vim
617
618  " test that when not using "morelines" valtwo is still defined
619  " need to source Xreload.vim again, import doesn't reload a script
620  writefile(lines, 'Xreload.vim')
621  source Xreload.vim
622  source Ximport.vim
623
624  " cannot declare a var twice
625  lines =<< trim END
626    vim9script
627    let valone = 1234
628    let valone = 5678
629  END
630  writefile(lines, 'Xreload.vim')
631  assert_fails('source Xreload.vim', 'E1041:')
632
633  delete('Xreload.vim')
634  delete('Ximport.vim')
635enddef
636
637def Test_import_absolute()
638  let import_lines = [
639        \ 'vim9script',
640        \ 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"',
641        \ 'def UseExported()',
642        \ '  g:imported_abs = exported',
643        \ '  exported = 8888',
644        \ '  g:imported_after = exported',
645        \ 'enddef',
646        \ 'UseExported()',
647        \ 'g:import_disassembled = execute("disass UseExported")',
648        \ ]
649  writefile(import_lines, 'Ximport_abs.vim')
650  writefile(s:export_script_lines, 'Xexport_abs.vim')
651
652  source Ximport_abs.vim
653
654  assert_equal(9876, g:imported_abs)
655  assert_equal(8888, g:imported_after)
656  assert_match('<SNR>\d\+_UseExported.*'
657        \ .. 'g:imported_abs = exported.*'
658        \ .. '0 LOADSCRIPT exported from .*Xexport_abs.vim.*'
659        \ .. '1 STOREG g:imported_abs.*'
660        \ .. 'exported = 8888.*'
661        \ .. '3 STORESCRIPT exported in .*Xexport_abs.vim.*'
662        \ .. 'g:imported_after = exported.*'
663        \ .. '4 LOADSCRIPT exported from .*Xexport_abs.vim.*'
664        \ .. '5 STOREG g:imported_after.*'
665        \, g:import_disassembled)
666  unlet g:imported_abs
667  unlet g:import_disassembled
668
669  delete('Ximport_abs.vim')
670  delete('Xexport_abs.vim')
671enddef
672
673def Test_import_rtp()
674  let import_lines = [
675        \ 'vim9script',
676        \ 'import exported from "Xexport_rtp.vim"',
677        \ 'g:imported_rtp = exported',
678        \ ]
679  writefile(import_lines, 'Ximport_rtp.vim')
680  mkdir('import')
681  writefile(s:export_script_lines, 'import/Xexport_rtp.vim')
682
683  let save_rtp = &rtp
684  &rtp = getcwd()
685  source Ximport_rtp.vim
686  &rtp = save_rtp
687
688  assert_equal(9876, g:imported_rtp)
689  unlet g:imported_rtp
690
691  delete('Ximport_rtp.vim')
692  delete('import/Xexport_rtp.vim')
693  delete('import', 'd')
694enddef
695
696def Test_fixed_size_list()
697  " will be allocated as one piece of memory, check that changes work
698  let l = [1, 2, 3, 4]
699  l->remove(0)
700  l->add(5)
701  l->insert(99, 1)
702  assert_equal([2, 99, 3, 4, 5], l)
703enddef
704
705def IfElse(what: number): string
706  let res = ''
707  if what == 1
708    res = "one"
709  elseif what == 2
710    res = "two"
711  else
712    res = "three"
713  endif
714  return res
715enddef
716
717def Test_if_elseif_else()
718  assert_equal('one', IfElse(1))
719  assert_equal('two', IfElse(2))
720  assert_equal('three', IfElse(3))
721enddef
722
723def Test_if_elseif_else_fails()
724  call CheckDefFailure(['elseif true'], 'E582:')
725  call CheckDefFailure(['else'], 'E581:')
726  call CheckDefFailure(['endif'], 'E580:')
727  call CheckDefFailure(['if true', 'elseif xxx'], 'E1001:')
728  call CheckDefFailure(['if true', 'echo 1'], 'E171:')
729enddef
730
731let g:bool_true = v:true
732let g:bool_false = v:false
733
734def Test_if_const_expr()
735  let res = false
736  if true ? true : false
737    res = true
738  endif
739  assert_equal(true, res)
740
741  g:glob = 2
742  if false
743    execute('let g:glob = 3')
744  endif
745  assert_equal(2, g:glob)
746  if true
747    execute('let g:glob = 3')
748  endif
749  assert_equal(3, g:glob)
750
751  res = false
752  if g:bool_true ? true : false
753    res = true
754  endif
755  assert_equal(true, res)
756
757  res = false
758  if true ? g:bool_true : false
759    res = true
760  endif
761  assert_equal(true, res)
762
763  res = false
764  if true ? true : g:bool_false
765    res = true
766  endif
767  assert_equal(true, res)
768
769  res = false
770  if true ? false : true
771    res = true
772  endif
773  assert_equal(false, res)
774
775  res = false
776  if false ? false : true
777    res = true
778  endif
779  assert_equal(true, res)
780
781  res = false
782  if false ? true : false
783    res = true
784  endif
785  assert_equal(false, res)
786
787  res = false
788  if has('xyz') ? true : false
789    res = true
790  endif
791  assert_equal(false, res)
792
793  res = false
794  if true && true
795    res = true
796  endif
797  assert_equal(true, res)
798
799  res = false
800  if true && false
801    res = true
802  endif
803  assert_equal(false, res)
804
805  res = false
806  if g:bool_true && false
807    res = true
808  endif
809  assert_equal(false, res)
810
811  res = false
812  if true && g:bool_false
813    res = true
814  endif
815  assert_equal(false, res)
816
817  res = false
818  if false && false
819    res = true
820  endif
821  assert_equal(false, res)
822
823  res = false
824  if true || false
825    res = true
826  endif
827  assert_equal(true, res)
828
829  res = false
830  if g:bool_true || false
831    res = true
832  endif
833  assert_equal(true, res)
834
835  res = false
836  if true || g:bool_false
837    res = true
838  endif
839  assert_equal(true, res)
840
841  res = false
842  if false || false
843    res = true
844  endif
845  assert_equal(false, res)
846enddef
847
848def Test_if_const_expr_fails()
849  call CheckDefFailure(['if "aaa" == "bbb'], 'E114:')
850  call CheckDefFailure(["if 'aaa' == 'bbb"], 'E115:')
851  call CheckDefFailure(["if has('aaa'"], 'E110:')
852  call CheckDefFailure(["if has('aaa') ? true false"], 'E109:')
853enddef
854
855def Test_execute_cmd()
856  new
857  setline(1, 'default')
858  execute 'call setline(1, "execute-string")'
859  assert_equal('execute-string', getline(1))
860  let cmd1 = 'call setline(1,'
861  let cmd2 = '"execute-var")'
862  execute cmd1 cmd2
863  assert_equal('execute-var', getline(1))
864  execute cmd1 cmd2 '|call setline(1, "execute-var-string")'
865  assert_equal('execute-var-string', getline(1))
866  let cmd_first = 'call '
867  let cmd_last = 'setline(1, "execute-var-var")'
868  execute cmd_first .. cmd_last
869  assert_equal('execute-var-var', getline(1))
870  bwipe!
871
872  call CheckDefFailure(['execute xxx'], 'E1001:')
873enddef
874
875def Test_echo_cmd()
876  echo 'some'
877  echon 'thing'
878  assert_match('^something$', Screenline(&lines))
879
880  let str1 = 'some'
881  let str2 = 'more'
882  echo str1 str2
883  assert_match('^some more$', Screenline(&lines))
884enddef
885
886def Test_for_outside_of_function()
887  let lines =<< trim END
888    vim9script
889    new
890    for var in range(0, 3)
891      append(line('$'), var)
892    endfor
893    assert_equal(['', '0', '1', '2', '3'], getline(1, '$'))
894    bwipe!
895  END
896  writefile(lines, 'Xvim9for.vim')
897  source Xvim9for.vim
898  delete('Xvim9for.vim')
899enddef
900
901def Test_for_loop()
902  let result = ''
903  for cnt in range(7)
904    if cnt == 4
905      break
906    endif
907    if cnt == 2
908      continue
909    endif
910    result ..= cnt .. '_'
911  endfor
912  assert_equal('0_1_3_', result)
913enddef
914
915def Test_for_loop_fails()
916  call CheckDefFailure(['for # in range(5)'], 'E690:')
917  call CheckDefFailure(['for i In range(5)'], 'E690:')
918  call CheckDefFailure(['let x = 5', 'for x in range(5)'], 'E1023:')
919  call CheckScriptFailure(['def Func(arg)', 'for arg in range(5)', 'enddef'], 'E1006:')
920  call CheckDefFailure(['for i in "text"'], 'E1024:')
921  call CheckDefFailure(['for i in xxx'], 'E1001:')
922  call CheckDefFailure(['endfor'], 'E588:')
923  call CheckDefFailure(['for i in range(3)', 'echo 3'], 'E170:')
924enddef
925
926def Test_while_loop()
927  let result = ''
928  let cnt = 0
929  while cnt < 555
930    if cnt == 3
931      break
932    endif
933    cnt += 1
934    if cnt == 2
935      continue
936    endif
937    result ..= cnt .. '_'
938  endwhile
939  assert_equal('1_3_', result)
940enddef
941
942def Test_while_loop_fails()
943  call CheckDefFailure(['while xxx'], 'E1001:')
944  call CheckDefFailure(['endwhile'], 'E588:')
945  call CheckDefFailure(['continue'], 'E586:')
946  call CheckDefFailure(['if true', 'continue'], 'E586:')
947  call CheckDefFailure(['break'], 'E587:')
948  call CheckDefFailure(['if true', 'break'], 'E587:')
949  call CheckDefFailure(['while 1', 'echo 3'], 'E170:')
950enddef
951
952def Test_interrupt_loop()
953  let caught = false
954  let x = 0
955  try
956    while 1
957      x += 1
958      if x == 100
959        feedkeys("\<C-C>", 'Lt')
960      endif
961    endwhile
962  catch
963    caught = true
964    assert_equal(100, x)
965  endtry
966  assert_true(caught, 'should have caught an exception')
967enddef
968
969" Keep this last, it messes up highlighting.
970def Test_substitute_cmd()
971  new
972  setline(1, 'something')
973  :substitute(some(other(
974  assert_equal('otherthing', getline(1))
975  bwipe!
976
977  " also when the context is Vim9 script
978  let lines =<< trim END
979    vim9script
980    new
981    setline(1, 'something')
982    :substitute(some(other(
983    assert_equal('otherthing', getline(1))
984    bwipe!
985  END
986  writefile(lines, 'Xvim9lines')
987  source Xvim9lines
988
989  delete('Xvim9lines')
990enddef
991
992" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
993