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
24func Test_def_basic()
25  def SomeFunc(): string
26    return 'yes'
27  enddef
28  call assert_equal('yes', SomeFunc())
29endfunc
30
31let s:appendToMe = 'xxx'
32let s:addToMe = 111
33let g:existing = 'yes'
34
35def Test_assignment()
36  let bool1: bool = true
37  assert_equal(v:true, bool1)
38  let bool2: bool = false
39  assert_equal(v:false, bool2)
40
41  let list1: list<bool> = [false, true, false]
42  let list2: list<number> = [1, 2, 3]
43  let list3: list<string> = ['sdf', 'asdf']
44  let list4: list<any> = ['yes', true, 1234]
45  let list5: list<blob> = [0z01, 0z02]
46
47  let listS: list<string> = []
48  let listN: list<number> = []
49
50  let dict1: dict<bool> = #{one: false, two: true}
51  let dict2: dict<number> = #{one: 1, two: 2}
52  let dict3: dict<string> = #{key: 'value'}
53  let dict4: dict<any> = #{one: 1, two: '2'}
54  let dict5: dict<blob> = #{one: 0z01, tw: 0z02}
55
56  if has('channel')
57    let chan1: channel
58    let job1: job
59    let job2: job = job_start('willfail')
60  endif
61  if has('float')
62    let float1: float = 3.4
63  endif
64  let funky1: func
65  let funky2: func = function('len')
66  let party1: partial
67  let party2: partial = funcref('Test_syntax')
68
69  " type becomes list<any>
70  let somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
71  " type becomes dict<any>
72  let somedict = rand() > 0 ? #{a: 1, b: 2} : #{a: 'a', b: 'b'}
73
74  g:newvar = 'new'
75  assert_equal('new', g:newvar)
76
77  assert_equal('yes', g:existing)
78  g:existing = 'no'
79  assert_equal('no', g:existing)
80
81  v:char = 'abc'
82  assert_equal('abc', v:char)
83
84  $ENVVAR = 'foobar'
85  assert_equal('foobar', $ENVVAR)
86  $ENVVAR = ''
87
88  s:appendToMe ..= 'yyy'
89  assert_equal('xxxyyy', s:appendToMe)
90  s:addToMe += 222
91  assert_equal(333, s:addToMe)
92  s:newVar = 'new'
93  assert_equal('new', s:newVar)
94enddef
95
96func Test_assignment_failure()
97  call CheckDefFailure(['let var=234'], 'E1004:')
98  call CheckDefFailure(['let var =234'], 'E1004:')
99  call CheckDefFailure(['let var= 234'], 'E1004:')
100
101  call CheckDefFailure(['let true = 1'], 'E1034:')
102  call CheckDefFailure(['let false = 1'], 'E1034:')
103
104  call CheckDefFailure(['let var: list<string> = [123]'], 'expected list<string> but got list<number>')
105  call CheckDefFailure(['let var: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
106
107  call CheckDefFailure(['let var: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>')
108  call CheckDefFailure(['let var: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>')
109
110  call CheckDefFailure(['let var = feedkeys("0")'], 'E1031:')
111  call CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void')
112
113  call CheckDefFailure(['let var: dict <number>'], 'E1007:')
114  call CheckDefFailure(['let var: dict<number'], 'E1009:')
115
116  call CheckDefFailure(['let var: ally'], 'E1010:')
117  call CheckDefFailure(['let var: bram'], 'E1010:')
118  call CheckDefFailure(['let var: cathy'], 'E1010:')
119  call CheckDefFailure(['let var: dom'], 'E1010:')
120  call CheckDefFailure(['let var: freddy'], 'E1010:')
121  call CheckDefFailure(['let var: john'], 'E1010:')
122  call CheckDefFailure(['let var: larry'], 'E1010:')
123  call CheckDefFailure(['let var: ned'], 'E1010:')
124  call CheckDefFailure(['let var: pam'], 'E1010:')
125  call CheckDefFailure(['let var: sam'], 'E1010:')
126  call CheckDefFailure(['let var: vim'], 'E1010:')
127endfunc
128
129func Test_const()
130  call CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:')
131  call CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:')
132  call CheckDefFailure(['const two'], 'E1021:')
133endfunc
134
135def Test_block()
136  let outer = 1
137  {
138    let inner = 2
139    assert_equal(1, outer)
140    assert_equal(2, inner)
141  }
142  assert_equal(1, outer)
143enddef
144
145func Test_block_failure()
146  call CheckDefFailure(['{', 'let inner = 1', '}', 'echo inner'], 'E1001:')
147endfunc
148
149def ReturnString(): string
150  return 'string'
151enddef
152
153def ReturnNumber(): number
154  return 123
155enddef
156
157let g:notNumber = 'string'
158
159def ReturnGlobal(): number
160  return g:notNumber
161enddef
162
163def Test_return_string()
164  assert_equal('string', ReturnString())
165  assert_equal(123, ReturnNumber())
166  assert_fails('call ReturnGlobal()', 'E1029: Expected number but got string')
167enddef
168
169func Increment()
170  let g:counter += 1
171endfunc
172
173def Test_call_ufunc_count()
174  g:counter = 1
175  Increment()
176  Increment()
177  Increment()
178  " works with and without :call
179  assert_equal(4, g:counter)
180  call assert_equal(4, g:counter)
181  unlet g:counter
182enddef
183
184def MyVarargs(arg: string, ...rest: list<string>): string
185  let res = arg
186  for s in rest
187    res ..= ',' .. s
188  endfor
189  return res
190enddef
191
192def Test_call_varargs()
193  assert_equal('one', MyVarargs('one'))
194  assert_equal('one,two', MyVarargs('one', 'two'))
195  assert_equal('one,two,three', MyVarargs('one', 'two', 'three'))
196enddef
197
198def MyDefaultArgs(name = 'string'): string
199  return name
200enddef
201
202def Test_call_default_args()
203  assert_equal('string', MyDefaultArgs())
204  assert_equal('one', MyDefaultArgs('one'))
205  assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
206enddef
207
208func Test_call_default_args_from_func()
209  call assert_equal('string', MyDefaultArgs())
210  call assert_equal('one', MyDefaultArgs('one'))
211  call assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
212endfunc
213
214func TakesOneArg(arg)
215  echo a:arg
216endfunc
217
218def Test_call_wrong_arg_count()
219  call CheckDefFailure(['TakesOneArg()'], 'E119:')
220  call CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:')
221enddef
222
223" Default arg and varargs
224def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string
225  let res = one .. ',' .. two
226  for s in rest
227    res ..= ',' .. s
228  endfor
229  return res
230enddef
231
232def Test_call_def_varargs()
233  call assert_fails('call MyDefVarargs()', 'E119:')
234  assert_equal('one,foo', MyDefVarargs('one'))
235  assert_equal('one,two', MyDefVarargs('one', 'two'))
236  assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three'))
237enddef
238
239def Test_using_var_as_arg()
240  call writefile(['def Func(x: number)',  'let x = 234', 'enddef'], 'Xdef')
241  call assert_fails('so Xdef', 'E1006:')
242  call delete('Xdef')
243enddef
244
245def Test_call_func_defined_later()
246  call assert_equal('one', DefinedLater('one'))
247  call assert_fails('call NotDefined("one")', 'E117:')
248enddef
249
250func DefinedLater(arg)
251  return a:arg
252endfunc
253
254def FuncWithForwardCall()
255  return DefinedEvenLater("yes")
256enddef
257
258def DefinedEvenLater(arg: string): string
259  return arg
260enddef
261
262def Test_error_in_nested_function()
263  " Error in called function requires unwinding the call stack.
264  assert_fails('call FuncWithForwardCall()', 'E1029')
265enddef
266
267def Test_return_type_wrong()
268  CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef'], 'expected number but got string')
269  CheckScriptFailure(['def Func(): string', 'return 1', 'enddef'], 'expected string but got number')
270  CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef'], 'expected void but got string')
271  CheckScriptFailure(['def Func()', 'return "a"', 'enddef'], 'expected void but got string')
272
273  CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:')
274  CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:')
275enddef
276
277def Test_arg_type_wrong()
278  CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>')
279enddef
280
281def Test_try_catch()
282  let l = []
283  try
284    add(l, '1')
285    throw 'wrong'
286    add(l, '2')
287  catch
288    add(l, v:exception)
289  finally
290    add(l, '3')
291  endtry
292  assert_equal(['1', 'wrong', '3'], l)
293enddef
294
295def ThrowFromDef()
296  throw 'getout'
297enddef
298
299func CatchInFunc()
300  try
301    call ThrowFromDef()
302  catch
303    let g:thrown_func = v:exception
304  endtry
305endfunc
306
307def CatchInDef()
308  try
309    ThrowFromDef()
310  catch
311    g:thrown_def = v:exception
312  endtry
313enddef
314
315def ReturnFinally(): string
316  try
317    return 'intry'
318  finally
319    g:in_finally = 'finally'
320  endtry
321  return 'end'
322enddef
323
324def Test_try_catch_nested()
325  CatchInFunc()
326  assert_equal('getout', g:thrown_func)
327
328  CatchInDef()
329  assert_equal('getout', g:thrown_def)
330
331  assert_equal('intry', ReturnFinally())
332  assert_equal('finally', g:in_finally)
333enddef
334
335def Test_try_catch_match()
336  let seq = 'a'
337  try
338    throw 'something'
339  catch /nothing/
340    seq ..= 'x'
341  catch /some/
342    seq ..= 'b'
343  catch /asdf/
344    seq ..= 'x'
345  finally
346    seq ..= 'c'
347  endtry
348  assert_equal('abc', seq)
349enddef
350
351let s:export_script_lines =<< trim END
352  vim9script
353  let name: string = 'bob'
354  def Concat(arg: string): string
355    return name .. arg
356  enddef
357  let g:result = Concat('bie')
358  let g:localname = name
359
360  export const CONST = 1234
361  export let exported = 9876
362  export let exp_name = 'John'
363  export def Exported(): string
364    return 'Exported'
365  enddef
366END
367
368def Test_vim9_import_export()
369  let import_script_lines =<< trim END
370    vim9script
371    import {exported, Exported} from './Xexport.vim'
372    g:imported = exported
373    exported += 3
374    g:imported_added = exported
375    g:imported_func = Exported()
376
377    import {exp_name} from './Xexport.vim'
378    g:imported_name = exp_name
379    exp_name ..= ' Doe'
380    g:imported_name_appended = exp_name
381    g:imported_later = exported
382  END
383
384  writefile(import_script_lines, 'Ximport.vim')
385  writefile(s:export_script_lines, 'Xexport.vim')
386
387  source Ximport.vim
388
389  assert_equal('bobbie', g:result)
390  assert_equal('bob', g:localname)
391  assert_equal(9876, g:imported)
392  assert_equal(9879, g:imported_added)
393  assert_equal(9879, g:imported_later)
394  assert_equal('Exported', g:imported_func)
395  assert_equal('John', g:imported_name)
396  assert_equal('John Doe', g:imported_name_appended)
397  assert_false(exists('g:name'))
398
399  unlet g:result
400  unlet g:localname
401  unlet g:imported
402  unlet g:imported_added
403  unlet g:imported_later
404  unlet g:imported_func
405  unlet g:imported_name g:imported_name_appended
406  delete('Ximport.vim')
407
408  let import_in_def_lines =<< trim END
409    vim9script
410    def ImportInDef()
411      import exported from './Xexport.vim'
412      g:imported = exported
413      exported += 7
414      g:imported_added = exported
415    enddef
416    ImportInDef()
417  END
418  writefile(import_in_def_lines, 'Ximport2.vim')
419  source Ximport2.vim
420  " TODO: this should be 9879
421  assert_equal(9876, g:imported)
422  assert_equal(9883, g:imported_added)
423  unlet g:imported
424  unlet g:imported_added
425  delete('Ximport2.vim')
426
427  let import_star_as_lines =<< trim END
428    vim9script
429    import * as Export from './Xexport.vim'
430    def UseExport()
431      g:imported = Export.exported
432    enddef
433    UseExport()
434  END
435  writefile(import_star_as_lines, 'Ximport.vim')
436  source Ximport.vim
437  assert_equal(9883, g:imported)
438
439  let import_star_lines =<< trim END
440    vim9script
441    import * from './Xexport.vim'
442    g:imported = exported
443  END
444  writefile(import_star_lines, 'Ximport.vim')
445  assert_fails('source Ximport.vim', 'E1045:')
446
447  " try to import something that exists but is not exported
448  let import_not_exported_lines =<< trim END
449    vim9script
450    import name from './Xexport.vim'
451  END
452  writefile(import_not_exported_lines, 'Ximport.vim')
453  assert_fails('source Ximport.vim', 'E1049:')
454
455  " try to import something that is already defined
456  let import_already_defined =<< trim END
457    vim9script
458    let exported = 'something'
459    import exported from './Xexport.vim'
460  END
461  writefile(import_already_defined, 'Ximport.vim')
462  assert_fails('source Ximport.vim', 'E1073:')
463
464  " try to import something that is already defined
465  import_already_defined =<< trim END
466    vim9script
467    let exported = 'something'
468    import * as exported from './Xexport.vim'
469  END
470  writefile(import_already_defined, 'Ximport.vim')
471  assert_fails('source Ximport.vim', 'E1073:')
472
473  " try to import something that is already defined
474  import_already_defined =<< trim END
475    vim9script
476    let exported = 'something'
477    import {exported} from './Xexport.vim'
478  END
479  writefile(import_already_defined, 'Ximport.vim')
480  assert_fails('source Ximport.vim', 'E1073:')
481
482  " import a very long name, requires making a copy
483  let import_long_name_lines =<< trim END
484    vim9script
485    import name012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 from './Xexport.vim'
486  END
487  writefile(import_long_name_lines, 'Ximport.vim')
488  assert_fails('source Ximport.vim', 'E1048:')
489
490  let import_no_from_lines =<< trim END
491    vim9script
492    import name './Xexport.vim'
493  END
494  writefile(import_no_from_lines, 'Ximport.vim')
495  assert_fails('source Ximport.vim', 'E1070:')
496
497  let import_invalid_string_lines =<< trim END
498    vim9script
499    import name from Xexport.vim
500  END
501  writefile(import_invalid_string_lines, 'Ximport.vim')
502  assert_fails('source Ximport.vim', 'E1071:')
503
504  let import_wrong_name_lines =<< trim END
505    vim9script
506    import name from './XnoExport.vim'
507  END
508  writefile(import_wrong_name_lines, 'Ximport.vim')
509  assert_fails('source Ximport.vim', 'E1053:')
510
511  let import_missing_comma_lines =<< trim END
512    vim9script
513    import {exported name} from './Xexport.vim'
514  END
515  writefile(import_missing_comma_lines, 'Ximport3.vim')
516  assert_fails('source Ximport3.vim', 'E1046:')
517
518  delete('Ximport.vim')
519  delete('Ximport3.vim')
520  delete('Xexport.vim')
521
522  " Check that in a Vim9 script 'cpo' is set to the Vim default.
523  set cpo&vi
524  let cpo_before = &cpo
525  let lines =<< trim END
526    vim9script
527    g:cpo_in_vim9script = &cpo
528  END
529  writefile(lines, 'Xvim9_script')
530  source Xvim9_script
531  assert_equal(cpo_before, &cpo)
532  set cpo&vim
533  assert_equal(&cpo, g:cpo_in_vim9script)
534  delete('Xvim9_script')
535enddef
536
537def Test_vim9script_fails()
538  CheckScriptFailure(['scriptversion 2', 'vim9script'], 'E1039:')
539  CheckScriptFailure(['vim9script', 'scriptversion 2'], 'E1040:')
540  CheckScriptFailure(['export let some = 123'], 'E1042:')
541  CheckScriptFailure(['import some from "./Xexport.vim"'], 'E1042:')
542  CheckScriptFailure(['vim9script', 'export let g:some'], 'E1044:')
543  CheckScriptFailure(['vim9script', 'export echo 134'], 'E1043:')
544
545  assert_fails('vim9script', 'E1038')
546  assert_fails('export something', 'E1042')
547enddef
548
549def Test_vim9script_call()
550  let lines =<< trim END
551    vim9script
552    let var = ''
553    def MyFunc(arg: string)
554       var = arg
555    enddef
556    MyFunc('foobar')
557    assert_equal('foobar', var)
558
559    let str = 'barfoo'
560    str->MyFunc()
561    assert_equal('barfoo', var)
562
563    let g:value = 'value'
564    g:value->MyFunc()
565    assert_equal('value', var)
566
567    let listvar = []
568    def ListFunc(arg: list<number>)
569       listvar = arg
570    enddef
571    [1, 2, 3]->ListFunc()
572    assert_equal([1, 2, 3], listvar)
573
574    let dictvar = {}
575    def DictFunc(arg: dict<number>)
576       dictvar = arg
577    enddef
578    {'a': 1, 'b': 2}->DictFunc()
579    assert_equal(#{a: 1, b: 2}, dictvar)
580    #{a: 3, b: 4}->DictFunc()
581    assert_equal(#{a: 3, b: 4}, dictvar)
582
583    ('text')->MyFunc()
584    assert_equal('text', var)
585    ("some")->MyFunc()
586    assert_equal('some', var)
587  END
588  writefile(lines, 'Xcall.vim')
589  source Xcall.vim
590  delete('Xcall.vim')
591enddef
592
593def Test_vim9script_call_fail_decl()
594  let lines =<< trim END
595    vim9script
596    let var = ''
597    def MyFunc(arg: string)
598       let var = 123
599    enddef
600  END
601  writefile(lines, 'Xcall_decl.vim')
602  assert_fails('source Xcall_decl.vim', 'E1054:')
603  delete('Xcall_decl.vim')
604enddef
605
606def Test_vim9script_call_fail_const()
607  let lines =<< trim END
608    vim9script
609    const var = ''
610    def MyFunc(arg: string)
611       var = 'asdf'
612    enddef
613  END
614  writefile(lines, 'Xcall_const.vim')
615  assert_fails('source Xcall_const.vim', 'E46:')
616  delete('Xcall_const.vim')
617enddef
618
619def Test_vim9script_reload()
620  let lines =<< trim END
621    vim9script
622    const var = ''
623    let valone = 1234
624    def MyFunc(arg: string)
625       valone = 5678
626    enddef
627  END
628  let morelines =<< trim END
629    let valtwo = 222
630    export def GetValtwo(): number
631      return valtwo
632    enddef
633  END
634  writefile(lines + morelines, 'Xreload.vim')
635  source Xreload.vim
636  source Xreload.vim
637  source Xreload.vim
638
639  let testlines =<< trim END
640    vim9script
641    def TheFunc()
642      import GetValtwo from './Xreload.vim'
643      assert_equal(222, GetValtwo())
644    enddef
645    TheFunc()
646  END
647  writefile(testlines, 'Ximport.vim')
648  source Ximport.vim
649
650  " test that when not using "morelines" valtwo is still defined
651  " need to source Xreload.vim again, import doesn't reload a script
652  writefile(lines, 'Xreload.vim')
653  source Xreload.vim
654  source Ximport.vim
655
656  " cannot declare a var twice
657  lines =<< trim END
658    vim9script
659    let valone = 1234
660    let valone = 5678
661  END
662  writefile(lines, 'Xreload.vim')
663  assert_fails('source Xreload.vim', 'E1041:')
664
665  delete('Xreload.vim')
666  delete('Ximport.vim')
667enddef
668
669def Test_import_absolute()
670  let import_lines = [
671        \ 'vim9script',
672        \ 'import exported from "' .. escape(getcwd(), '\') .. '/Xexport_abs.vim"',
673        \ 'def UseExported()',
674        \ '  g:imported_abs = exported',
675        \ '  exported = 8888',
676        \ '  g:imported_after = exported',
677        \ 'enddef',
678        \ 'UseExported()',
679        \ 'g:import_disassembled = execute("disass UseExported")',
680        \ ]
681  writefile(import_lines, 'Ximport_abs.vim')
682  writefile(s:export_script_lines, 'Xexport_abs.vim')
683
684  source Ximport_abs.vim
685
686  assert_equal(9876, g:imported_abs)
687  assert_equal(8888, g:imported_after)
688  assert_match('<SNR>\d\+_UseExported.*'
689        \ .. 'g:imported_abs = exported.*'
690        \ .. '0 LOADSCRIPT exported from .*Xexport_abs.vim.*'
691        \ .. '1 STOREG g:imported_abs.*'
692        \ .. 'exported = 8888.*'
693        \ .. '3 STORESCRIPT exported in .*Xexport_abs.vim.*'
694        \ .. 'g:imported_after = exported.*'
695        \ .. '4 LOADSCRIPT exported from .*Xexport_abs.vim.*'
696        \ .. '5 STOREG g:imported_after.*'
697        \, g:import_disassembled)
698  unlet g:imported_abs
699  unlet g:import_disassembled
700
701  delete('Ximport_abs.vim')
702  delete('Xexport_abs.vim')
703enddef
704
705def Test_import_rtp()
706  let import_lines = [
707        \ 'vim9script',
708        \ 'import exported from "Xexport_rtp.vim"',
709        \ 'g:imported_rtp = exported',
710        \ ]
711  writefile(import_lines, 'Ximport_rtp.vim')
712  mkdir('import')
713  writefile(s:export_script_lines, 'import/Xexport_rtp.vim')
714
715  let save_rtp = &rtp
716  &rtp = getcwd()
717  source Ximport_rtp.vim
718  &rtp = save_rtp
719
720  assert_equal(9876, g:imported_rtp)
721  unlet g:imported_rtp
722
723  delete('Ximport_rtp.vim')
724  delete('import/Xexport_rtp.vim')
725  delete('import', 'd')
726enddef
727
728def Test_fixed_size_list()
729  " will be allocated as one piece of memory, check that changes work
730  let l = [1, 2, 3, 4]
731  l->remove(0)
732  l->add(5)
733  l->insert(99, 1)
734  assert_equal([2, 99, 3, 4, 5], l)
735enddef
736
737" Test that inside :function a Python function can be defined, :def is not
738" recognized.
739func Test_function_python()
740  CheckFeature python3
741  let py = 'python3'
742  execute py "<< EOF"
743def do_something():
744  return 1
745EOF
746endfunc
747
748def IfElse(what: number): string
749  let res = ''
750  if what == 1
751    res = "one"
752  elseif what == 2
753    res = "two"
754  else
755    res = "three"
756  endif
757  return res
758enddef
759
760def Test_if_elseif_else()
761  assert_equal('one', IfElse(1))
762  assert_equal('two', IfElse(2))
763  assert_equal('three', IfElse(3))
764enddef
765
766let g:bool_true = v:true
767let g:bool_false = v:false
768
769def Test_if_const_expr()
770  let res = false
771  if true ? true : false
772    res = true
773  endif
774  assert_equal(true, res)
775
776  res = false
777  if g:bool_true ? true : false
778    res = true
779  endif
780  assert_equal(true, res)
781
782  res = false
783  if true ? g:bool_true : false
784    res = true
785  endif
786  assert_equal(true, res)
787
788  res = false
789  if true ? true : g:bool_false
790    res = true
791  endif
792  assert_equal(true, res)
793
794  res = false
795  if true ? false : true
796    res = true
797  endif
798  assert_equal(false, res)
799
800  res = false
801  if false ? false : true
802    res = true
803  endif
804  assert_equal(true, res)
805
806  res = false
807  if false ? true : false
808    res = true
809  endif
810  assert_equal(false, res)
811
812  res = false
813  if true && true
814    res = true
815  endif
816  assert_equal(true, res)
817
818  res = false
819  if true && false
820    res = true
821  endif
822  assert_equal(false, res)
823
824  res = false
825  if g:bool_true && false
826    res = true
827  endif
828  assert_equal(false, res)
829
830  res = false
831  if true && g:bool_false
832    res = true
833  endif
834  assert_equal(false, res)
835
836  res = false
837  if false && false
838    res = true
839  endif
840  assert_equal(false, res)
841
842  res = false
843  if true || false
844    res = true
845  endif
846  assert_equal(true, res)
847
848  res = false
849  if g:bool_true || false
850    res = true
851  endif
852  assert_equal(true, res)
853
854  res = false
855  if true || g:bool_false
856    res = true
857  endif
858  assert_equal(true, res)
859
860  res = false
861  if false || false
862    res = true
863  endif
864  assert_equal(false, res)
865
866enddef
867
868def Test_delfunc()
869  let lines =<< trim END
870    vim9script
871    def GoneSoon()
872      echo 'hello'
873    enddef
874
875    def CallGoneSoon()
876      GoneSoon()
877    enddef
878
879    delfunc GoneSoon
880    CallGoneSoon()
881  END
882  writefile(lines, 'XToDelFunc')
883  assert_fails('so XToDelFunc', 'E933')
884  assert_fails('so XToDelFunc', 'E933')
885
886  delete('XToDelFunc')
887enddef
888
889def Test_execute_cmd()
890  new
891  setline(1, 'default')
892  execute 'call setline(1, "execute-string")'
893  assert_equal('execute-string', getline(1))
894  let cmd1 = 'call setline(1,'
895  let cmd2 = '"execute-var")'
896  execute cmd1 cmd2
897  assert_equal('execute-var', getline(1))
898  execute cmd1 cmd2 '|call setline(1, "execute-var-string")'
899  assert_equal('execute-var-string', getline(1))
900  let cmd_first = 'call '
901  let cmd_last = 'setline(1, "execute-var-var")'
902  execute cmd_first .. cmd_last
903  assert_equal('execute-var-var', getline(1))
904  bwipe!
905enddef
906
907def Test_echo_cmd()
908  echo 'something'
909  assert_match('^something$', Screenline(&lines))
910
911  let str1 = 'some'
912  let str2 = 'more'
913  echo str1 str2
914  assert_match('^some more$', Screenline(&lines))
915enddef
916
917def Test_for_outside_of_function()
918  let lines =<< trim END
919    vim9script
920    new
921    for var in range(0, 3)
922      append(line('$'), var)
923    endfor
924    assert_equal(['', '0', '1', '2', '3'], getline(1, '$'))
925    bwipe!
926  END
927  writefile(lines, 'Xvim9for.vim')
928  source Xvim9for.vim
929  delete('Xvim9for.vim')
930enddef
931
932def Test_while_loop()
933  let result = ''
934  let cnt = 0
935  while cnt < 555
936    if cnt == 3
937      break
938    endif
939    cnt += 1
940    if cnt == 2
941      continue
942    endif
943    result ..= cnt .. '_'
944  endwhile
945  assert_equal('1_3_', result)
946enddef
947
948def Test_interrupt_loop()
949  let caught = false
950  let x = 0
951  try
952    while 1
953      x += 1
954      if x == 100
955        feedkeys("\<C-C>", 'Lt')
956      endif
957    endwhile
958  catch
959    caught = true
960    assert_equal(100, x)
961  endtry
962  assert_true(caught, 'should have caught an exception')
963enddef
964
965def Test_substitute_cmd()
966  new
967  setline(1, 'something')
968  :substitute(some(other(
969  assert_equal('otherthing', getline(1))
970  bwipe!
971
972  " also when the context is Vim9 script
973  let lines =<< trim END
974    vim9script
975    new
976    setline(1, 'something')
977    :substitute(some(other(
978    assert_equal('otherthing', getline(1))
979    bwipe!
980  END
981  writefile(lines, 'Xvim9lines')
982  source Xvim9lines
983
984  delete('Xvim9lines')
985enddef
986
987def Test_redef_failure()
988  call writefile(['def Func0(): string',  'return "Func0"', 'enddef'], 'Xdef')
989  so Xdef
990  call writefile(['def Func1(): string',  'return "Func1"', 'enddef'], 'Xdef')
991  so Xdef
992  call writefile(['def! Func0(): string', 'enddef'], 'Xdef')
993  call assert_fails('so Xdef', 'E1027:')
994  call writefile(['def Func2(): string',  'return "Func2"', 'enddef'], 'Xdef')
995  so Xdef
996  call delete('Xdef')
997
998  call assert_equal(0, Func0())
999  call assert_equal('Func1', Func1())
1000  call assert_equal('Func2', Func2())
1001
1002  delfunc! Func0
1003  delfunc! Func1
1004  delfunc! Func2
1005enddef
1006
1007" Test for internal functions returning different types
1008func Test_InternalFuncRetType()
1009  let lines =<< trim END
1010    def RetFloat(): float
1011      return ceil(1.456)
1012    enddef
1013
1014    def RetListAny(): list<any>
1015      return items({'k' : 'v'})
1016    enddef
1017
1018    def RetListString(): list<string>
1019      return split('a:b:c', ':')
1020    enddef
1021
1022    def RetListDictAny(): list<dict<any>>
1023      return getbufinfo()
1024    enddef
1025
1026    def RetDictNumber(): dict<number>
1027      return wordcount()
1028    enddef
1029
1030    def RetDictString(): dict<string>
1031      return environ()
1032    enddef
1033  END
1034  call writefile(lines, 'Xscript')
1035  source Xscript
1036
1037  call assert_equal(2.0, RetFloat())
1038  call assert_equal([['k', 'v']], RetListAny())
1039  call assert_equal(['a', 'b', 'c'], RetListString())
1040  call assert_notequal([], RetListDictAny())
1041  call assert_notequal({}, RetDictNumber())
1042  call assert_notequal({}, RetDictString())
1043  call delete('Xscript')
1044endfunc
1045
1046" Test for passing too many or too few arguments to internal functions
1047func Test_internalfunc_arg_error()
1048  let l =<< trim END
1049    def! FArgErr(): float
1050      return ceil(1.1, 2)
1051    enddef
1052  END
1053  call writefile(l, 'Xinvalidarg')
1054  call assert_fails('so Xinvalidarg', 'E118:')
1055  let l =<< trim END
1056    def! FArgErr(): float
1057      return ceil()
1058    enddef
1059  END
1060  call writefile(l, 'Xinvalidarg')
1061  call assert_fails('so Xinvalidarg', 'E119:')
1062  call delete('Xinvalidarg')
1063endfunc
1064
1065" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
1066