1" Test various aspects of the Vim9 script language.
2
3source check.vim
4source view_util.vim
5source vim9.vim
6source screendump.vim
7
8func Test_def_basic()
9  def SomeFunc(): string
10    return 'yes'
11  enddef
12  call assert_equal('yes', SomeFunc())
13endfunc
14
15def ReturnString(): string
16  return 'string'
17enddef
18
19def ReturnNumber(): number
20  return 123
21enddef
22
23let g:notNumber = 'string'
24
25def ReturnGlobal(): number
26  return g:notNumber
27enddef
28
29def Test_return_something()
30  assert_equal('string', ReturnString())
31  assert_equal(123, ReturnNumber())
32  assert_fails('call ReturnGlobal()', 'E1029: Expected number but got string')
33enddef
34
35def Test_missing_return()
36  CheckDefFailure(['def Missing(): number',
37                   '  if g:cond',
38                   '    echo "no return"',
39                   '  else',
40                   '    return 0',
41                   '  endif'
42                   'enddef'], 'E1027:')
43  CheckDefFailure(['def Missing(): number',
44                   '  if g:cond',
45                   '    return 1',
46                   '  else',
47                   '    echo "no return"',
48                   '  endif'
49                   'enddef'], 'E1027:')
50  CheckDefFailure(['def Missing(): number',
51                   '  if g:cond',
52                   '    return 1',
53                   '  else',
54                   '    return 2',
55                   '  endif'
56                   '  return 3'
57                   'enddef'], 'E1095:')
58enddef
59
60let s:nothing = 0
61def ReturnNothing()
62  s:nothing = 1
63  if true
64    return
65  endif
66  s:nothing = 2
67enddef
68
69def Test_return_nothing()
70  ReturnNothing()
71  assert_equal(1, s:nothing)
72enddef
73
74func Increment()
75  let g:counter += 1
76endfunc
77
78def Test_call_ufunc_count()
79  g:counter = 1
80  Increment()
81  Increment()
82  Increment()
83  " works with and without :call
84  assert_equal(4, g:counter)
85  call assert_equal(4, g:counter)
86  unlet g:counter
87enddef
88
89def MyVarargs(arg: string, ...rest: list<string>): string
90  let res = arg
91  for s in rest
92    res ..= ',' .. s
93  endfor
94  return res
95enddef
96
97def Test_call_varargs()
98  assert_equal('one', MyVarargs('one'))
99  assert_equal('one,two', MyVarargs('one', 'two'))
100  assert_equal('one,two,three', MyVarargs('one', 'two', 'three'))
101enddef
102
103def MyDefaultArgs(name = 'string'): string
104  return name
105enddef
106
107def Test_call_default_args()
108  assert_equal('string', MyDefaultArgs())
109  assert_equal('one', MyDefaultArgs('one'))
110  assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
111
112  CheckScriptFailure(['def Func(arg: number = asdf)', 'enddef', 'defcompile'], 'E1001:')
113  CheckScriptFailure(['def Func(arg: number = "text")', 'enddef', 'defcompile'], 'E1013: argument 1: type mismatch, expected number but got string')
114enddef
115
116def Test_nested_function()
117  def Nested(arg: string): string
118    return 'nested ' .. arg
119  enddef
120  assert_equal('nested function', Nested('function'))
121
122  CheckDefFailure(['def Nested()', 'enddef', 'Nested(66)'], 'E118:')
123  CheckDefFailure(['def Nested(arg: string)', 'enddef', 'Nested()'], 'E119:')
124
125  CheckDefFailure(['func Nested()', 'endfunc'], 'E1086:')
126enddef
127
128func Test_call_default_args_from_func()
129  call assert_equal('string', MyDefaultArgs())
130  call assert_equal('one', MyDefaultArgs('one'))
131  call assert_fails('call MyDefaultArgs("one", "two")', 'E118:')
132endfunc
133
134func TakesOneArg(arg)
135  echo a:arg
136endfunc
137
138def Test_call_wrong_args()
139  call CheckDefFailure(['TakesOneArg()'], 'E119:')
140  call CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:')
141  call CheckDefFailure(['bufnr(xxx)'], 'E1001:')
142  call CheckScriptFailure(['def Func(Ref: func(s: string))'], 'E475:')
143enddef
144
145" Default arg and varargs
146def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string
147  let res = one .. ',' .. two
148  for s in rest
149    res ..= ',' .. s
150  endfor
151  return res
152enddef
153
154def Test_call_def_varargs()
155  call assert_fails('call MyDefVarargs()', 'E119:')
156  assert_equal('one,foo', MyDefVarargs('one'))
157  assert_equal('one,two', MyDefVarargs('one', 'two'))
158  assert_equal('one,two,three', MyDefVarargs('one', 'two', 'three'))
159  call CheckDefFailure(['MyDefVarargs("one", 22)'], 'E1013: argument 2: type mismatch, expected string but got number')
160enddef
161
162let s:value = ''
163
164def FuncOneDefArg(opt = 'text')
165  s:value = opt
166enddef
167
168def FuncTwoDefArg(nr = 123, opt = 'text'): string
169  return nr .. opt
170enddef
171
172def FuncVarargs(...arg: list<string>): string
173  return join(arg, ',')
174enddef
175
176def Test_func_type_varargs()
177  let RefDefArg: func(?string)
178  RefDefArg = FuncOneDefArg
179  RefDefArg()
180  assert_equal('text', s:value)
181  RefDefArg('some')
182  assert_equal('some', s:value)
183
184  let RefDef2Arg: func(?number, ?string): string
185  RefDef2Arg = FuncTwoDefArg
186  assert_equal('123text', RefDef2Arg())
187  assert_equal('99text', RefDef2Arg(99))
188  assert_equal('77some', RefDef2Arg(77, 'some'))
189
190  call CheckDefFailure(['let RefWrong: func(string?)'], 'E1010:')
191  call CheckDefFailure(['let RefWrong: func(?string, string)'], 'E1007:')
192
193  let RefVarargs: func(...list<string>): string
194  RefVarargs = FuncVarargs
195  assert_equal('', RefVarargs())
196  assert_equal('one', RefVarargs('one'))
197  assert_equal('one,two', RefVarargs('one', 'two'))
198
199  call CheckDefFailure(['let RefWrong: func(...list<string>, string)'], 'E110:')
200  call CheckDefFailure(['let RefWrong: func(...list<string>, ?string)'], 'E110:')
201enddef
202
203" Only varargs
204def MyVarargsOnly(...args: list<string>): string
205  return join(args, ',')
206enddef
207
208def Test_call_varargs_only()
209  assert_equal('', MyVarargsOnly())
210  assert_equal('one', MyVarargsOnly('one'))
211  assert_equal('one,two', MyVarargsOnly('one', 'two'))
212  call CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: argument 1: type mismatch, expected string but got number')
213  call CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: argument 2: type mismatch, expected string but got number')
214enddef
215
216def Test_using_var_as_arg()
217  call writefile(['def Func(x: number)',  'let x = 234', 'enddef', 'defcompile'], 'Xdef')
218  call assert_fails('so Xdef', 'E1006:')
219  call delete('Xdef')
220enddef
221
222def DictArg(arg: dict<string>)
223  arg['key'] = 'value'
224enddef
225
226def ListArg(arg: list<string>)
227  arg[0] = 'value'
228enddef
229
230def Test_assign_to_argument()
231  " works for dict and list
232  let d: dict<string> = {}
233  DictArg(d)
234  assert_equal('value', d['key'])
235  let l: list<string> = []
236  ListArg(l)
237  assert_equal('value', l[0])
238
239  call CheckScriptFailure(['def Func(arg: number)', 'arg = 3', 'enddef', 'defcompile'], 'E1090:')
240enddef
241
242def Test_call_func_defined_later()
243  call assert_equal('one', g:DefinedLater('one'))
244  call assert_fails('call NotDefined("one")', 'E117:')
245enddef
246
247func DefinedLater(arg)
248  return a:arg
249endfunc
250
251def Test_call_funcref()
252  assert_equal(3, g:SomeFunc('abc'))
253  assert_fails('NotAFunc()', 'E117:')
254  assert_fails('g:NotAFunc()', 'E117:')
255enddef
256
257let SomeFunc = function('len')
258let NotAFunc = 'text'
259
260def CombineFuncrefTypes()
261  " same arguments, different return type
262  let Ref1: func(bool): string
263  let Ref2: func(bool): number
264  let Ref3: func(bool): any
265  Ref3 = g:cond ? Ref1 : Ref2
266
267  " different number of arguments
268  let Refa1: func(bool): number
269  let Refa2: func(bool, number): number
270  let Refa3: func: number
271  Refa3 = g:cond ? Refa1 : Refa2
272
273  " different argument types
274  let Refb1: func(bool, string): number
275  let Refb2: func(string, number): number
276  let Refb3: func(any, any): number
277  Refb3 = g:cond ? Refb1 : Refb2
278enddef
279
280def FuncWithForwardCall()
281  return g:DefinedEvenLater("yes")
282enddef
283
284def DefinedEvenLater(arg: string): string
285  return arg
286enddef
287
288def Test_error_in_nested_function()
289  " Error in called function requires unwinding the call stack.
290  assert_fails('call FuncWithForwardCall()', 'E1096')
291enddef
292
293def Test_return_type_wrong()
294  CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef', 'defcompile'], 'expected number but got string')
295  CheckScriptFailure(['def Func(): string', 'return 1', 'enddef', 'defcompile'], 'expected string but got number')
296  CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef', 'defcompile'], 'E1096: Returning a value in a function without a return type')
297  CheckScriptFailure(['def Func()', 'return "a"', 'enddef', 'defcompile'], 'E1096: Returning a value in a function without a return type')
298
299  CheckScriptFailure(['def Func(): number', 'return', 'enddef', 'defcompile'], 'E1003:')
300
301  CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:')
302  CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:')
303  CheckScriptFailure(['def Func()', 'return 1'], 'E1057:')
304enddef
305
306def Test_arg_type_wrong()
307  CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>')
308  CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...')
309  CheckScriptFailure(['def Func5(items:string)', 'echo "a"'], 'E1069:')
310  CheckScriptFailure(['def Func5(items)', 'echo "a"'], 'E1077:')
311enddef
312
313def Test_vim9script_call()
314  let lines =<< trim END
315    vim9script
316    let var = ''
317    def MyFunc(arg: string)
318       var = arg
319    enddef
320    MyFunc('foobar')
321    assert_equal('foobar', var)
322
323    let str = 'barfoo'
324    str->MyFunc()
325    assert_equal('barfoo', var)
326
327    g:value = 'value'
328    g:value->MyFunc()
329    assert_equal('value', var)
330
331    let listvar = []
332    def ListFunc(arg: list<number>)
333       listvar = arg
334    enddef
335    [1, 2, 3]->ListFunc()
336    assert_equal([1, 2, 3], listvar)
337
338    let dictvar = {}
339    def DictFunc(arg: dict<number>)
340       dictvar = arg
341    enddef
342    {'a': 1, 'b': 2}->DictFunc()
343    assert_equal(#{a: 1, b: 2}, dictvar)
344    def CompiledDict()
345      {'a': 3, 'b': 4}->DictFunc()
346    enddef
347    CompiledDict()
348    assert_equal(#{a: 3, b: 4}, dictvar)
349
350    #{a: 3, b: 4}->DictFunc()
351    assert_equal(#{a: 3, b: 4}, dictvar)
352
353    ('text')->MyFunc()
354    assert_equal('text', var)
355    ("some")->MyFunc()
356    assert_equal('some', var)
357
358    MyFunc(
359        'continued'
360        )
361    assert_equal('continued',
362            var
363            )
364
365    call MyFunc(
366        'more'
367          ..
368          'lines'
369        )
370    assert_equal(
371        'morelines',
372        var)
373  END
374  writefile(lines, 'Xcall.vim')
375  source Xcall.vim
376  delete('Xcall.vim')
377enddef
378
379def Test_vim9script_call_fail_decl()
380  let lines =<< trim END
381    vim9script
382    let var = ''
383    def MyFunc(arg: string)
384       let var = 123
385    enddef
386    defcompile
387  END
388  writefile(lines, 'Xcall_decl.vim')
389  assert_fails('source Xcall_decl.vim', 'E1054:')
390  delete('Xcall_decl.vim')
391enddef
392
393def Test_vim9script_call_fail_const()
394  let lines =<< trim END
395    vim9script
396    const var = ''
397    def MyFunc(arg: string)
398       var = 'asdf'
399    enddef
400    defcompile
401  END
402  writefile(lines, 'Xcall_const.vim')
403  assert_fails('source Xcall_const.vim', 'E46:')
404  delete('Xcall_const.vim')
405enddef
406
407" Test that inside :function a Python function can be defined, :def is not
408" recognized.
409func Test_function_python()
410  CheckFeature python3
411  let py = 'python3'
412  execute py "<< EOF"
413def do_something():
414  return 1
415EOF
416endfunc
417
418def Test_delfunc()
419  let lines =<< trim END
420    vim9script
421    def g:GoneSoon()
422      echo 'hello'
423    enddef
424
425    def CallGoneSoon()
426      GoneSoon()
427    enddef
428    defcompile
429
430    delfunc g:GoneSoon
431    CallGoneSoon()
432  END
433  writefile(lines, 'XToDelFunc')
434  assert_fails('so XToDelFunc', 'E933')
435  assert_fails('so XToDelFunc', 'E933')
436
437  delete('XToDelFunc')
438enddef
439
440def Test_redef_failure()
441  call writefile(['def Func0(): string',  'return "Func0"', 'enddef'], 'Xdef')
442  so Xdef
443  call writefile(['def Func1(): string',  'return "Func1"', 'enddef'], 'Xdef')
444  so Xdef
445  call writefile(['def! Func0(): string', 'enddef', 'defcompile'], 'Xdef')
446  call assert_fails('so Xdef', 'E1027:')
447  call writefile(['def Func2(): string',  'return "Func2"', 'enddef'], 'Xdef')
448  so Xdef
449  call delete('Xdef')
450
451  call assert_equal(0, g:Func0())
452  call assert_equal('Func1', g:Func1())
453  call assert_equal('Func2', g:Func2())
454
455  delfunc! Func0
456  delfunc! Func1
457  delfunc! Func2
458enddef
459
460def Test_vim9script_func()
461  let lines =<< trim END
462    vim9script
463    func Func(arg)
464      echo a:arg
465    endfunc
466    Func('text')
467  END
468  writefile(lines, 'XVim9Func')
469  so XVim9Func
470
471  delete('XVim9Func')
472enddef
473
474" Test for internal functions returning different types
475func Test_InternalFuncRetType()
476  let lines =<< trim END
477    def RetFloat(): float
478      return ceil(1.456)
479    enddef
480
481    def RetListAny(): list<any>
482      return items({'k' : 'v'})
483    enddef
484
485    def RetListString(): list<string>
486      return split('a:b:c', ':')
487    enddef
488
489    def RetListDictAny(): list<dict<any>>
490      return getbufinfo()
491    enddef
492
493    def RetDictNumber(): dict<number>
494      return wordcount()
495    enddef
496
497    def RetDictString(): dict<string>
498      return environ()
499    enddef
500  END
501  call writefile(lines, 'Xscript')
502  source Xscript
503
504  call assert_equal(2.0, RetFloat())
505  call assert_equal([['k', 'v']], RetListAny())
506  call assert_equal(['a', 'b', 'c'], RetListString())
507  call assert_notequal([], RetListDictAny())
508  call assert_notequal({}, RetDictNumber())
509  call assert_notequal({}, RetDictString())
510  call delete('Xscript')
511endfunc
512
513" Test for passing too many or too few arguments to internal functions
514func Test_internalfunc_arg_error()
515  let l =<< trim END
516    def! FArgErr(): float
517      return ceil(1.1, 2)
518    enddef
519    defcompile
520  END
521  call writefile(l, 'Xinvalidarg')
522  call assert_fails('so Xinvalidarg', 'E118:')
523  let l =<< trim END
524    def! FArgErr(): float
525      return ceil()
526    enddef
527    defcompile
528  END
529  call writefile(l, 'Xinvalidarg')
530  call assert_fails('so Xinvalidarg', 'E119:')
531  call delete('Xinvalidarg')
532endfunc
533
534let s:funcResult = 0
535
536def FuncNoArgNoRet()
537  funcResult = 11
538enddef
539
540def FuncNoArgRetNumber(): number
541  funcResult = 22
542  return 1234
543enddef
544
545def FuncNoArgRetString(): string
546  funcResult = 45
547  return 'text'
548enddef
549
550def FuncOneArgNoRet(arg: number)
551  funcResult = arg
552enddef
553
554def FuncOneArgRetNumber(arg: number): number
555  funcResult = arg
556  return arg
557enddef
558
559def FuncTwoArgNoRet(one: bool, two: number)
560  funcResult = two
561enddef
562
563def FuncOneArgRetString(arg: string): string
564  return arg
565enddef
566
567def FuncOneArgRetAny(arg: any): any
568  return arg
569enddef
570
571def Test_func_type()
572  let Ref1: func()
573  funcResult = 0
574  Ref1 = FuncNoArgNoRet
575  Ref1()
576  assert_equal(11, funcResult)
577
578  let Ref2: func
579  funcResult = 0
580  Ref2 = FuncNoArgNoRet
581  Ref2()
582  assert_equal(11, funcResult)
583
584  funcResult = 0
585  Ref2 = FuncOneArgNoRet
586  Ref2(12)
587  assert_equal(12, funcResult)
588
589  funcResult = 0
590  Ref2 = FuncNoArgRetNumber
591  assert_equal(1234, Ref2())
592  assert_equal(22, funcResult)
593
594  funcResult = 0
595  Ref2 = FuncOneArgRetNumber
596  assert_equal(13, Ref2(13))
597  assert_equal(13, funcResult)
598enddef
599
600def Test_repeat_return_type()
601  let res = 0
602  for n in repeat([1], 3)
603    res += n
604  endfor
605  assert_equal(3, res)
606
607  res = 0
608  for n in add([1, 2], 3)
609    res += n
610  endfor
611  assert_equal(6, res)
612enddef
613
614def Test_argv_return_type()
615  next fileone filetwo
616  let res = ''
617  for name in argv()
618    res ..= name
619  endfor
620  assert_equal('fileonefiletwo', res)
621enddef
622
623def Test_func_type_part()
624  let RefVoid: func: void
625  RefVoid = FuncNoArgNoRet
626  RefVoid = FuncOneArgNoRet
627  CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number')
628  CheckDefFailure(['let RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1013: type mismatch, expected func() but got func(): string')
629
630  let RefAny: func(): any
631  RefAny = FuncNoArgRetNumber
632  RefAny = FuncNoArgRetString
633  CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): any but got func()')
634  CheckDefFailure(['let RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1013: type mismatch, expected func(): any but got func(number)')
635
636  let RefNr: func: number
637  RefNr = FuncNoArgRetNumber
638  RefNr = FuncOneArgRetNumber
639  CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): number but got func()')
640  CheckDefFailure(['let RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1013: type mismatch, expected func(): number but got func(): string')
641
642  let RefStr: func: string
643  RefStr = FuncNoArgRetString
644  RefStr = FuncOneArgRetString
645  CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1013: type mismatch, expected func(): string but got func()')
646  CheckDefFailure(['let RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func(): string but got func(): number')
647enddef
648
649def Test_func_type_fails()
650  CheckDefFailure(['let ref1: func()'], 'E704:')
651
652  CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1013: type mismatch, expected func() but got func(): number')
653  CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1013: type mismatch, expected func() but got func(number)')
654  CheckDefFailure(['let Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1013: type mismatch, expected func() but got func(number): number')
655  CheckDefFailure(['let Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(bool) but got func(bool, number)')
656  CheckDefFailure(['let Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(?bool) but got func(bool, number)')
657  CheckDefFailure(['let Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1013: type mismatch, expected func(...bool) but got func(bool, number)')
658
659  call CheckDefFailure(['let RefWrong: func(string ,number)'], 'E1068:')
660  call CheckDefFailure(['let RefWrong: func(string,number)'], 'E1069:')
661  call CheckDefFailure(['let RefWrong: func(bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool)'], 'E740:')
662  call CheckDefFailure(['let RefWrong: func(bool):string'], 'E1069:')
663enddef
664
665def Test_func_return_type()
666  let nr: number
667  nr = FuncNoArgRetNumber()
668  assert_equal(1234, nr)
669
670  nr = FuncOneArgRetAny(122)
671  assert_equal(122, nr)
672
673  let str: string
674  str = FuncOneArgRetAny('yes')
675  assert_equal('yes', str)
676
677  CheckDefFailure(['let str: string', 'str = FuncNoArgRetNumber()'], 'E1013: type mismatch, expected string but got number')
678enddef
679
680def MultiLine(
681    arg1: string,
682    arg2 = 1234,
683    ...rest: list<string>
684      ): string
685  return arg1 .. arg2 .. join(rest, '-')
686enddef
687
688def MultiLineComment(
689    arg1: string, # comment
690    arg2 = 1234, # comment
691    ...rest: list<string> # comment
692      ): string # comment
693  return arg1 .. arg2 .. join(rest, '-')
694enddef
695
696def Test_multiline()
697  assert_equal('text1234', MultiLine('text'))
698  assert_equal('text777', MultiLine('text', 777))
699  assert_equal('text777one', MultiLine('text', 777, 'one'))
700  assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two'))
701enddef
702
703func Test_multiline_not_vim9()
704  call assert_equal('text1234', MultiLine('text'))
705  call assert_equal('text777', MultiLine('text', 777))
706  call assert_equal('text777one', MultiLine('text', 777, 'one'))
707  call assert_equal('text777one-two', MultiLine('text', 777, 'one', 'two'))
708endfunc
709
710
711" When using CheckScriptFailure() for the below test, E1010 is generated instead
712" of E1056.
713func Test_E1056_1059()
714  let caught_1056 = 0
715  try
716    def F():
717      return 1
718    enddef
719  catch /E1056:/
720    let caught_1056 = 1
721  endtry
722  call assert_equal(1, caught_1056)
723
724  let caught_1059 = 0
725  try
726    def F5(items : list)
727      echo 'a'
728    enddef
729  catch /E1059:/
730    let caught_1059 = 1
731  endtry
732  call assert_equal(1, caught_1059)
733endfunc
734
735func DelMe()
736  echo 'DelMe'
737endfunc
738
739def Test_deleted_function()
740  CheckDefExecFailure([
741      'let RefMe: func = function("g:DelMe")',
742      'delfunc g:DelMe',
743      'echo RefMe()'], 'E117:')
744enddef
745
746def Test_unknown_function()
747  CheckDefExecFailure([
748      'let Ref: func = function("NotExist")',
749      'delfunc g:NotExist'], 'E700:')
750enddef
751
752def RefFunc(Ref: func(string): string): string
753  return Ref('more')
754enddef
755
756def Test_closure_simple()
757  let local = 'some '
758  assert_equal('some more', RefFunc({s -> local .. s}))
759enddef
760
761def MakeRef()
762  let local = 'some '
763  g:Ref = {s -> local .. s}
764enddef
765
766def Test_closure_ref_after_return()
767  MakeRef()
768  assert_equal('some thing', g:Ref('thing'))
769  unlet g:Ref
770enddef
771
772def MakeTwoRefs()
773  let local = ['some']
774  g:Extend = {s -> local->add(s)}
775  g:Read = {-> local}
776enddef
777
778def Test_closure_two_refs()
779  MakeTwoRefs()
780  assert_equal('some', join(g:Read(), ' '))
781  g:Extend('more')
782  assert_equal('some more', join(g:Read(), ' '))
783  g:Extend('even')
784  assert_equal('some more even', join(g:Read(), ' '))
785
786  unlet g:Extend
787  unlet g:Read
788enddef
789
790def ReadRef(Ref: func(): list<string>): string
791  return join(Ref(), ' ')
792enddef
793
794def ExtendRef(Ref: func(string), add: string)
795  Ref(add)
796enddef
797
798def Test_closure_two_indirect_refs()
799  MakeTwoRefs()
800  assert_equal('some', ReadRef(g:Read))
801  ExtendRef(g:Extend, 'more')
802  assert_equal('some more', ReadRef(g:Read))
803  ExtendRef(g:Extend, 'even')
804  assert_equal('some more even', ReadRef(g:Read))
805
806  unlet g:Extend
807  unlet g:Read
808enddef
809
810def MakeArgRefs(theArg: string)
811  let local = 'loc_val'
812  g:UseArg = {s -> theArg .. '/' .. local .. '/' .. s}
813enddef
814
815def MakeArgRefsVarargs(theArg: string, ...rest: list<string>)
816  let local = 'the_loc'
817  g:UseVararg = {s -> theArg .. '/' .. local .. '/' .. s .. '/' .. join(rest)}
818enddef
819
820def Test_closure_using_argument()
821  MakeArgRefs('arg_val')
822  assert_equal('arg_val/loc_val/call_val', g:UseArg('call_val'))
823
824  MakeArgRefsVarargs('arg_val', 'one', 'two')
825  assert_equal('arg_val/the_loc/call_val/one two', g:UseVararg('call_val'))
826
827  unlet g:UseArg
828  unlet g:UseVararg
829enddef
830
831def MakeGetAndAppendRefs()
832  let local = 'a'
833
834  def Append(arg: string)
835    local ..= arg
836  enddef
837  g:Append = Append
838
839  def Get(): string
840    return local
841  enddef
842  g:Get = Get
843enddef
844
845def Test_closure_append_get()
846  MakeGetAndAppendRefs()
847  assert_equal('a', g:Get())
848  g:Append('-b')
849  assert_equal('a-b', g:Get())
850  g:Append('-c')
851  assert_equal('a-b-c', g:Get())
852
853  unlet g:Append
854  unlet g:Get
855enddef
856
857def Test_nested_closure()
858  let local = 'text'
859  def Closure(arg: string): string
860    return local .. arg
861  enddef
862  assert_equal('text!!!', Closure('!!!'))
863enddef
864
865func GetResult(Ref)
866  return a:Ref('some')
867endfunc
868
869def Test_call_closure_not_compiled()
870  let text = 'text'
871  g:Ref = {s ->  s .. text}
872  assert_equal('sometext', GetResult(g:Ref))
873enddef
874
875def Test_sort_return_type()
876  let res: list<number>
877  res = [1, 2, 3]->sort()
878enddef
879
880def Test_getqflist_return_type()
881  let l = getqflist()
882  assert_equal([], l)
883
884  let d = getqflist(#{items: 0})
885  assert_equal(#{items: []}, d)
886enddef
887
888def Test_getloclist_return_type()
889  let l = getloclist(1)
890  assert_equal([], l)
891
892  let d = getloclist(1, #{items: 0})
893  assert_equal(#{items: []}, d)
894enddef
895
896def Test_copy_return_type()
897  let l = copy([1, 2, 3])
898  let res = 0
899  for n in l
900    res += n
901  endfor
902  assert_equal(6, res)
903
904  let dl = deepcopy([1, 2, 3])
905  res = 0
906  for n in dl
907    res += n
908  endfor
909  assert_equal(6, res)
910enddef
911
912def Test_extend_return_type()
913  let l = extend([1, 2], [3])
914  let res = 0
915  for n in l
916    res += n
917  endfor
918  assert_equal(6, res)
919enddef
920
921def Test_insert_return_type()
922  let l = insert([2, 1], 3)
923  let res = 0
924  for n in l
925    res += n
926  endfor
927  assert_equal(6, res)
928enddef
929
930def Test_reverse_return_type()
931  let l = reverse([1, 2, 3])
932  let res = 0
933  for n in l
934    res += n
935  endfor
936  assert_equal(6, res)
937enddef
938
939def Test_remove_return_type()
940  let l = remove(#{one: [1, 2], two: [3, 4]}, 'one')
941  let res = 0
942  for n in l
943    res += n
944  endfor
945  assert_equal(3, res)
946enddef
947
948def Test_filter_return_type()
949  let l = filter([1, 2, 3], {-> 1})
950  let res = 0
951  for n in l
952    res += n
953  endfor
954  assert_equal(6, res)
955enddef
956
957def Wrong_dict_key_type(items: list<number>): list<number>
958  return filter(items, {_, val -> get({val: 1}, 'x')})
959enddef
960
961def Test_wrong_dict_key_type()
962  assert_fails('Wrong_dict_key_type([1, 2, 3])', 'E1029:')
963enddef
964
965def Line_continuation_in_def(dir: string = ''): string
966    let path: string = empty(dir)
967            \ ? 'empty'
968            \ : 'full'
969    return path
970enddef
971
972def Test_line_continuation_in_def()
973  assert_equal('full', Line_continuation_in_def('.'))
974enddef
975
976def Line_continuation_in_lambda(): list<number>
977  let x = range(97, 100)
978      ->map({_, v -> nr2char(v)
979          ->toupper()})
980      ->reverse()
981  return x
982enddef
983
984def Test_line_continuation_in_lambda()
985  assert_equal(['D', 'C', 'B', 'A'], Line_continuation_in_lambda())
986enddef
987
988func Test_silent_echo()
989  CheckScreendump
990
991  let lines =<< trim END
992    vim9script
993    def EchoNothing()
994      silent echo ''
995    enddef
996    defcompile
997  END
998  call writefile(lines, 'XTest_silent_echo')
999
1000  " Check that the balloon shows up after a mouse move
1001  let buf = RunVimInTerminal('-S XTest_silent_echo', {'rows': 6})
1002  call term_sendkeys(buf, ":abc")
1003  call VerifyScreenDump(buf, 'Test_vim9_silent_echo', {})
1004
1005  " clean up
1006  call StopVimInTerminal(buf)
1007  call delete('XTest_silent_echo')
1008endfunc
1009
1010def Fibonacci(n: number): number
1011  if n < 2
1012    return n
1013  else
1014    return Fibonacci(n - 1) + Fibonacci(n - 2)
1015  endif
1016enddef
1017
1018def Test_recursive_call()
1019  assert_equal(6765, Fibonacci(20))
1020enddef
1021
1022def TreeWalk(dir: string): list<any>
1023  return readdir(dir)->map({_, val ->
1024            fnamemodify(dir .. '/' .. val, ':p')->isdirectory()
1025               ? {val : TreeWalk(dir .. '/' .. val)}
1026               : val
1027             })
1028enddef
1029
1030def Test_closure_in_map()
1031  mkdir('XclosureDir/tdir', 'p')
1032  writefile(['111'], 'XclosureDir/file1')
1033  writefile(['222'], 'XclosureDir/file2')
1034  writefile(['333'], 'XclosureDir/tdir/file3')
1035
1036  assert_equal(['file1', 'file2', {'tdir': ['file3']}], TreeWalk('XclosureDir'))
1037
1038  delete('XclosureDir', 'rf')
1039enddef
1040
1041
1042" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
1043