1" Test various aspects of the Vim9 script language.
2
3source check.vim
4source term_util.vim
5source view_util.vim
6source vim9.vim
7source screendump.vim
8
9func Test_def_basic()
10  def SomeFunc(): string
11    return 'yes'
12  enddef
13  call SomeFunc()->assert_equal('yes')
14endfunc
15
16func Test_compiling_error()
17  " use a terminal to see the whole error message
18  CheckRunVimInTerminal
19
20  call TestCompilingError()
21  call TestCompilingErrorInTry()
22endfunc
23
24def TestCompilingError()
25  var lines =<< trim END
26    vim9script
27    def Fails()
28      echo nothing
29    enddef
30    defcompile
31  END
32  writefile(lines, 'XTest_compile_error')
33  var buf = RunVimInTerminal('-S XTest_compile_error',
34              {rows: 10, wait_for_ruler: 0})
35  WaitForAssert(() => assert_match('Error detected while compiling command line.*Fails.*Variable not found: nothing',
36                     Term_getlines(buf, range(1, 9))))
37
38  # clean up
39  StopVimInTerminal(buf)
40  delete('XTest_compile_error')
41enddef
42
43def TestCompilingErrorInTry()
44  var dir = 'Xdir/autoload'
45  mkdir(dir, 'p')
46
47  var lines =<< trim END
48      vim9script
49      def script#OnlyCompiled()
50        g:runtime = 'yes'
51        invalid
52      enddef
53  END
54  writefile(lines, dir .. '/script.vim')
55
56  lines =<< trim END
57      vim9script
58      todo
59      try
60        script#OnlyCompiled()
61      catch /nothing/
62      endtry
63  END
64  lines[1] = 'set rtp=' .. getcwd() .. '/Xdir'
65  writefile(lines, 'XTest_compile_error')
66
67  var buf = RunVimInTerminal('-S XTest_compile_error', {rows: 10, wait_for_ruler: 0})
68  WaitForAssert(() => assert_match('Error detected while compiling command line.*function script#OnlyCompiled.*Invalid command: invalid',
69                     Term_getlines(buf, range(1, 9))))
70
71  # clean up
72  StopVimInTerminal(buf)
73  delete('XTest_compile_error')
74  delete('Xdir', 'rf')
75enddef
76
77def Test_compile_error_in_called_function()
78  var lines =<< trim END
79      vim9script
80      var n: number
81      def Foo()
82        &hls = n
83      enddef
84      def Bar()
85        Foo()
86      enddef
87      silent! Foo()
88      Bar()
89  END
90  CheckScriptFailureList(lines, ['E1012:', 'E1191:'])
91enddef
92
93def Test_wrong_function_name()
94  var lines =<< trim END
95      vim9script
96      func _Foo()
97        echo 'foo'
98      endfunc
99  END
100  CheckScriptFailure(lines, 'E128:')
101
102  lines =<< trim END
103      vim9script
104      def _Foo()
105        echo 'foo'
106      enddef
107  END
108  CheckScriptFailure(lines, 'E128:')
109enddef
110
111def Test_autoload_name_mismatch()
112  var dir = 'Xdir/autoload'
113  mkdir(dir, 'p')
114
115  var lines =<< trim END
116      vim9script
117      def scriptX#Function()
118        # comment
119        g:runtime = 'yes'
120      enddef
121  END
122  writefile(lines, dir .. '/script.vim')
123
124  var save_rtp = &rtp
125  exe 'set rtp=' .. getcwd() .. '/Xdir'
126  lines =<< trim END
127      call script#Function()
128  END
129  CheckScriptFailure(lines, 'E746:', 2)
130
131  &rtp = save_rtp
132  delete(dir, 'rf')
133enddef
134
135def Test_autoload_names()
136  var dir = 'Xdir/autoload'
137  mkdir(dir, 'p')
138
139  var lines =<< trim END
140      func foobar#function()
141        return 'yes'
142      endfunc
143      let foobar#var = 'no'
144  END
145  writefile(lines, dir .. '/foobar.vim')
146
147  var save_rtp = &rtp
148  exe 'set rtp=' .. getcwd() .. '/Xdir'
149
150  lines =<< trim END
151      assert_equal('yes', foobar#function())
152      var Function = foobar#function
153      assert_equal('yes', Function())
154
155      assert_equal('no', foobar#var)
156  END
157  CheckDefAndScriptSuccess(lines)
158
159  &rtp = save_rtp
160  delete(dir, 'rf')
161enddef
162
163def Test_autoload_error_in_script()
164  var dir = 'Xdir/autoload'
165  mkdir(dir, 'p')
166
167  var lines =<< trim END
168      func scripterror#function()
169        let g:called_function = 'yes'
170      endfunc
171      let 0 = 1
172  END
173  writefile(lines, dir .. '/scripterror.vim')
174
175  var save_rtp = &rtp
176  exe 'set rtp=' .. getcwd() .. '/Xdir'
177
178  g:called_function = 'no'
179  # The error in the autoload script cannot be checked with assert_fails(), use
180  # CheckDefSuccess() instead of CheckDefFailure()
181  try
182    CheckDefSuccess(['scripterror#function()'])
183  catch
184    assert_match('E121: Undefined variable: 0', v:exception)
185  endtry
186  assert_equal('no', g:called_function)
187
188  lines =<< trim END
189      func scriptcaught#function()
190        let g:called_function = 'yes'
191      endfunc
192      try
193        let 0 = 1
194      catch
195        let g:caught = v:exception
196      endtry
197  END
198  writefile(lines, dir .. '/scriptcaught.vim')
199
200  g:called_function = 'no'
201  CheckDefSuccess(['scriptcaught#function()'])
202  assert_match('E121: Undefined variable: 0', g:caught)
203  assert_equal('yes', g:called_function)
204
205  &rtp = save_rtp
206  delete(dir, 'rf')
207enddef
208
209def CallRecursive(n: number): number
210  return CallRecursive(n + 1)
211enddef
212
213def CallMapRecursive(l: list<number>): number
214  return map(l, (_, v) => CallMapRecursive([v]))[0]
215enddef
216
217def Test_funcdepth_error()
218  set maxfuncdepth=10
219
220  var caught = false
221  try
222    CallRecursive(1)
223  catch /E132:/
224    caught = true
225  endtry
226  assert_true(caught)
227
228  caught = false
229  try
230    CallMapRecursive([1])
231  catch /E132:/
232    caught = true
233  endtry
234  assert_true(caught)
235
236  set maxfuncdepth&
237enddef
238
239def Test_endfunc_enddef()
240  var lines =<< trim END
241    def Test()
242      echo 'test'
243      endfunc
244    enddef
245  END
246  CheckScriptFailure(lines, 'E1151:', 3)
247
248  lines =<< trim END
249    def Test()
250      func Nested()
251        echo 'test'
252      enddef
253    enddef
254  END
255  CheckScriptFailure(lines, 'E1152:', 4)
256
257  lines =<< trim END
258    def Ok()
259      echo 'hello'
260    enddef | echo 'there'
261    def Bad()
262      echo 'hello'
263    enddef there
264  END
265  CheckScriptFailure(lines, 'E1173: Text found after enddef: there', 6)
266enddef
267
268def Test_missing_endfunc_enddef()
269  var lines =<< trim END
270    vim9script
271    def Test()
272      echo 'test'
273    endef
274  END
275  CheckScriptFailure(lines, 'E1057:', 2)
276
277  lines =<< trim END
278    vim9script
279    func Some()
280      echo 'test'
281    enfffunc
282  END
283  CheckScriptFailure(lines, 'E126:', 2)
284enddef
285
286def Test_white_space_before_paren()
287  var lines =<< trim END
288    vim9script
289    def Test ()
290      echo 'test'
291    enddef
292  END
293  CheckScriptFailure(lines, 'E1068:', 2)
294
295  lines =<< trim END
296    vim9script
297    func Test ()
298      echo 'test'
299    endfunc
300  END
301  CheckScriptFailure(lines, 'E1068:', 2)
302
303  lines =<< trim END
304    def Test ()
305      echo 'test'
306    enddef
307  END
308  CheckScriptFailure(lines, 'E1068:', 1)
309
310  lines =<< trim END
311    func Test ()
312      echo 'test'
313    endfunc
314  END
315  CheckScriptSuccess(lines)
316enddef
317
318def Test_enddef_dict_key()
319  var d = {
320    enddef: 'x',
321    endfunc: 'y',
322  }
323  assert_equal({enddef: 'x', endfunc: 'y'}, d)
324enddef
325
326def ReturnString(): string
327  return 'string'
328enddef
329
330def ReturnNumber(): number
331  return 123
332enddef
333
334let g:notNumber = 'string'
335
336def ReturnGlobal(): number
337  return g:notNumber
338enddef
339
340def Test_return_something()
341  ReturnString()->assert_equal('string')
342  ReturnNumber()->assert_equal(123)
343  assert_fails('ReturnGlobal()', 'E1012: Type mismatch; expected number but got string', '', 1, 'ReturnGlobal')
344enddef
345
346def Test_check_argument_type()
347  var lines =<< trim END
348      vim9script
349      def Val(a: number, b: number): number
350        return 0
351      enddef
352      def Func()
353        var x: any = true
354        Val(0, x)
355      enddef
356      disass Func
357      Func()
358  END
359  CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got bool', 2)
360enddef
361
362def Test_missing_return()
363  CheckDefFailure(['def Missing(): number',
364                   '  if g:cond',
365                   '    echo "no return"',
366                   '  else',
367                   '    return 0',
368                   '  endif'
369                   'enddef'], 'E1027:')
370  CheckDefFailure(['def Missing(): number',
371                   '  if g:cond',
372                   '    return 1',
373                   '  else',
374                   '    echo "no return"',
375                   '  endif'
376                   'enddef'], 'E1027:')
377  CheckDefFailure(['def Missing(): number',
378                   '  if g:cond',
379                   '    return 1',
380                   '  else',
381                   '    return 2',
382                   '  endif'
383                   '  return 3'
384                   'enddef'], 'E1095:')
385enddef
386
387def Test_return_bool()
388  var lines =<< trim END
389      vim9script
390      def MenuFilter(id: number, key: string): bool
391        return popup_filter_menu(id, key)
392      enddef
393      def YesnoFilter(id: number, key: string): bool
394        return popup_filter_yesno(id, key)
395      enddef
396      defcompile
397  END
398  CheckScriptSuccess(lines)
399enddef
400
401let s:nothing = 0
402def ReturnNothing()
403  s:nothing = 1
404  if true
405    return
406  endif
407  s:nothing = 2
408enddef
409
410def Test_return_nothing()
411  ReturnNothing()
412  s:nothing->assert_equal(1)
413enddef
414
415def Test_return_invalid()
416  var lines =<< trim END
417    vim9script
418    def Func(): invalid
419      return xxx
420    enddef
421    defcompile
422  END
423  CheckScriptFailure(lines, 'E1010:', 2)
424
425  lines =<< trim END
426      vim9script
427      def Test(Fun: func(number): number): list<number>
428          return map([1, 2, 3], (_, i) => Fun(i))
429      enddef
430      defcompile
431      def Inc(nr: number): nr
432        return nr + 2
433      enddef
434      echo Test(Inc)
435  END
436  # doing this twice was leaking memory
437  CheckScriptFailure(lines, 'E1010:')
438  CheckScriptFailure(lines, 'E1010:')
439enddef
440
441def Test_return_list_any()
442  var lines =<< trim END
443      vim9script
444      def Func(): list<string>
445        var l: list<any>
446        l->add('string')
447        return l
448      enddef
449      echo Func()
450  END
451  CheckScriptFailure(lines, 'E1012:')
452  lines =<< trim END
453      vim9script
454      def Func(): list<string>
455        var l: list<any>
456        l += ['string']
457        return l
458      enddef
459      echo Func()
460  END
461  CheckScriptFailure(lines, 'E1012:')
462enddef
463
464func Increment()
465  let g:counter += 1
466endfunc
467
468def Test_call_ufunc_count()
469  g:counter = 1
470  Increment()
471  Increment()
472  Increment()
473  # works with and without :call
474  g:counter->assert_equal(4)
475  eval g:counter->assert_equal(4)
476  unlet g:counter
477enddef
478
479def MyVarargs(arg: string, ...rest: list<string>): string
480  var res = arg
481  for s in rest
482    res ..= ',' .. s
483  endfor
484  return res
485enddef
486
487def Test_call_varargs()
488  MyVarargs('one')->assert_equal('one')
489  MyVarargs('one', 'two')->assert_equal('one,two')
490  MyVarargs('one', 'two', 'three')->assert_equal('one,two,three')
491enddef
492
493def Test_call_white_space()
494  CheckDefAndScriptFailure2(["call Test ('text')"], 'E476:', 'E1068:')
495enddef
496
497def MyDefaultArgs(name = 'string'): string
498  return name
499enddef
500
501def MyDefaultSecond(name: string, second: bool  = true): string
502  return second ? name : 'none'
503enddef
504
505
506def Test_call_default_args()
507  MyDefaultArgs()->assert_equal('string')
508  MyDefaultArgs(v:none)->assert_equal('string')
509  MyDefaultArgs('one')->assert_equal('one')
510  assert_fails('MyDefaultArgs("one", "two")', 'E118:', '', 4, 'Test_call_default_args')
511
512  MyDefaultSecond('test')->assert_equal('test')
513  MyDefaultSecond('test', true)->assert_equal('test')
514  MyDefaultSecond('test', false)->assert_equal('none')
515
516  var lines =<< trim END
517      def MyDefaultThird(name: string, aa = 'aa', bb = 'bb'): string
518        return name .. aa .. bb
519      enddef
520
521      MyDefaultThird('->')->assert_equal('->aabb')
522      MyDefaultThird('->', v:none)->assert_equal('->aabb')
523      MyDefaultThird('->', 'xx')->assert_equal('->xxbb')
524      MyDefaultThird('->', v:none, v:none)->assert_equal('->aabb')
525      MyDefaultThird('->', 'xx', v:none)->assert_equal('->xxbb')
526      MyDefaultThird('->', v:none, 'yy')->assert_equal('->aayy')
527      MyDefaultThird('->', 'xx', 'yy')->assert_equal('->xxyy')
528
529      def DefArg(mandatory: any, optional = mandatory): string
530        return mandatory .. optional
531      enddef
532      DefArg(1234)->assert_equal('12341234')
533      DefArg("ok")->assert_equal('okok')
534  END
535  CheckDefAndScriptSuccess(lines)
536
537  CheckScriptFailure(['def Func(arg: number = asdf)', 'enddef', 'defcompile'], 'E1001:')
538  delfunc g:Func
539  CheckScriptFailure(['def Func(arg: number = "text")', 'enddef', 'defcompile'], 'E1013: Argument 1: type mismatch, expected number but got string')
540  delfunc g:Func
541  CheckDefFailure(['def Func(x: number = )', 'enddef'], 'E15:')
542
543  lines =<< trim END
544      vim9script
545      def Func(a = b == 0 ? 1 : 2, b = 0)
546      enddef
547      defcompile
548  END
549  CheckScriptFailure(lines, 'E1001: Variable not found: b')
550enddef
551
552def FuncWithComment(  # comment
553  a: number, #comment
554  b: bool, # comment
555  c: string) #comment
556  assert_equal(4, a)
557  assert_equal(true, b)
558  assert_equal('yes', c)
559enddef
560
561def Test_func_with_comments()
562  FuncWithComment(4, true, 'yes')
563
564  var lines =<< trim END
565      def Func(# comment
566        arg: string)
567      enddef
568  END
569  CheckScriptFailure(lines, 'E125:', 1)
570
571  lines =<< trim END
572      def Func(
573        arg: string# comment
574        )
575      enddef
576  END
577  CheckScriptFailure(lines, 'E475:', 2)
578
579  lines =<< trim END
580      def Func(
581        arg: string
582        )# comment
583      enddef
584  END
585  CheckScriptFailure(lines, 'E488:', 3)
586enddef
587
588def Test_nested_function()
589  def NestedDef(arg: string): string
590    return 'nested ' .. arg
591  enddef
592  NestedDef(':def')->assert_equal('nested :def')
593
594  func NestedFunc(arg)
595    return 'nested ' .. a:arg
596  endfunc
597  NestedFunc(':func')->assert_equal('nested :func')
598
599  CheckDefFailure(['def Nested()', 'enddef', 'Nested(66)'], 'E118:')
600  CheckDefFailure(['def Nested(arg: string)', 'enddef', 'Nested()'], 'E119:')
601
602  CheckDefFailure(['def s:Nested()', 'enddef'], 'E1075:')
603  CheckDefFailure(['def b:Nested()', 'enddef'], 'E1075:')
604
605  var lines =<< trim END
606      def Outer()
607        def Inner()
608          # comment
609        enddef
610        def Inner()
611        enddef
612      enddef
613  END
614  CheckDefFailure(lines, 'E1073:')
615
616  lines =<< trim END
617      def Outer()
618        def Inner()
619          # comment
620        enddef
621        def! Inner()
622        enddef
623      enddef
624  END
625  CheckDefFailure(lines, 'E1117:')
626
627  # nested function inside conditional
628  lines =<< trim END
629      vim9script
630      var thecount = 0
631      if true
632        def Test(): number
633          def TheFunc(): number
634            thecount += 1
635            return thecount
636          enddef
637          return TheFunc()
638        enddef
639      endif
640      defcompile
641      assert_equal(1, Test())
642      assert_equal(2, Test())
643  END
644  CheckScriptSuccess(lines)
645
646  # also works when "thecount" is inside the "if" block
647  lines =<< trim END
648      vim9script
649      if true
650        var thecount = 0
651        def Test(): number
652          def TheFunc(): number
653            thecount += 1
654            return thecount
655          enddef
656          return TheFunc()
657        enddef
658      endif
659      defcompile
660      assert_equal(1, Test())
661      assert_equal(2, Test())
662  END
663  CheckScriptSuccess(lines)
664
665  lines =<< trim END
666      vim9script
667      def Outer()
668        def Inner()
669          echo 'hello'
670        enddef burp
671      enddef
672      defcompile
673  END
674  CheckScriptFailure(lines, 'E1173: Text found after enddef: burp', 3)
675enddef
676
677def Test_not_nested_function()
678  echo printf('%d',
679      function('len')('xxx'))
680enddef
681
682func Test_call_default_args_from_func()
683  call MyDefaultArgs()->assert_equal('string')
684  call MyDefaultArgs('one')->assert_equal('one')
685  call assert_fails('call MyDefaultArgs("one", "two")', 'E118:', '', 3, 'Test_call_default_args_from_func')
686endfunc
687
688def Test_nested_global_function()
689  var lines =<< trim END
690      vim9script
691      def Outer()
692          def g:Inner(): string
693              return 'inner'
694          enddef
695      enddef
696      defcompile
697      Outer()
698      g:Inner()->assert_equal('inner')
699      delfunc g:Inner
700      Outer()
701      g:Inner()->assert_equal('inner')
702      delfunc g:Inner
703      Outer()
704      g:Inner()->assert_equal('inner')
705      delfunc g:Inner
706  END
707  CheckScriptSuccess(lines)
708
709  lines =<< trim END
710      vim9script
711      def Outer()
712          func g:Inner()
713            return 'inner'
714          endfunc
715      enddef
716      defcompile
717      Outer()
718      g:Inner()->assert_equal('inner')
719      delfunc g:Inner
720      Outer()
721      g:Inner()->assert_equal('inner')
722      delfunc g:Inner
723      Outer()
724      g:Inner()->assert_equal('inner')
725      delfunc g:Inner
726  END
727  CheckScriptSuccess(lines)
728
729  lines =<< trim END
730      vim9script
731      def Outer()
732          def g:Inner(): string
733              return 'inner'
734          enddef
735      enddef
736      defcompile
737      Outer()
738      Outer()
739  END
740  CheckScriptFailure(lines, "E122:")
741  delfunc g:Inner
742
743  lines =<< trim END
744      vim9script
745      def Outer()
746        def g:Inner()
747          echo map([1, 2, 3], (_, v) => v + 1)
748        enddef
749        g:Inner()
750      enddef
751      Outer()
752  END
753  CheckScriptSuccess(lines)
754  delfunc g:Inner
755
756  lines =<< trim END
757      vim9script
758      def Func()
759        echo 'script'
760      enddef
761      def Outer()
762        def Func()
763          echo 'inner'
764        enddef
765      enddef
766      defcompile
767  END
768  CheckScriptFailure(lines, "E1073:", 1)
769
770  lines =<< trim END
771      vim9script
772      def Func()
773        echo 'script'
774      enddef
775      def Func()
776        echo 'script'
777      enddef
778  END
779  CheckScriptFailure(lines, "E1073:", 5)
780enddef
781
782def DefListAll()
783  def
784enddef
785
786def DefListOne()
787  def DefListOne
788enddef
789
790def DefListMatches()
791  def /DefList
792enddef
793
794def Test_nested_def_list()
795  var funcs = split(execute('call DefListAll()'), "\n")
796  assert_true(len(funcs) > 10)
797  assert_true(funcs->index('def DefListAll()') >= 0)
798
799  funcs = split(execute('call DefListOne()'), "\n")
800  assert_equal(['   def DefListOne()', '1    def DefListOne', '   enddef'], funcs)
801
802  funcs = split(execute('call DefListMatches()'), "\n")
803  assert_true(len(funcs) >= 3)
804  assert_true(funcs->index('def DefListAll()') >= 0)
805  assert_true(funcs->index('def DefListOne()') >= 0)
806  assert_true(funcs->index('def DefListMatches()') >= 0)
807
808  var lines =<< trim END
809    vim9script
810    def Func()
811      def +Func+
812    enddef
813    defcompile
814  END
815  CheckScriptFailure(lines, 'E476:', 1)
816enddef
817
818def Test_global_local_function()
819  var lines =<< trim END
820      vim9script
821      def g:Func(): string
822          return 'global'
823      enddef
824      def Func(): string
825          return 'local'
826      enddef
827      g:Func()->assert_equal('global')
828      Func()->assert_equal('local')
829      delfunc g:Func
830  END
831  CheckScriptSuccess(lines)
832
833  lines =<< trim END
834      vim9script
835      def g:Funcy()
836        echo 'funcy'
837      enddef
838      s:Funcy()
839  END
840  CheckScriptFailure(lines, 'E117:')
841enddef
842
843def Test_local_function_shadows_global()
844  var lines =<< trim END
845      vim9script
846      def g:Gfunc(): string
847        return 'global'
848      enddef
849      def AnotherFunc(): number
850        var Gfunc = function('len')
851        return Gfunc('testing')
852      enddef
853      g:Gfunc()->assert_equal('global')
854      AnotherFunc()->assert_equal(7)
855      delfunc g:Gfunc
856  END
857  CheckScriptSuccess(lines)
858
859  lines =<< trim END
860      vim9script
861      def g:Func(): string
862        return 'global'
863      enddef
864      def AnotherFunc()
865        g:Func = function('len')
866      enddef
867      AnotherFunc()
868  END
869  CheckScriptFailure(lines, 'E705:')
870  delfunc g:Func
871
872  # global function is found without g: prefix
873  lines =<< trim END
874      vim9script
875      def g:Func(): string
876        return 'global'
877      enddef
878      def AnotherFunc(): string
879        return Func()
880      enddef
881      assert_equal('global', AnotherFunc())
882    delfunc g:Func
883  END
884  CheckScriptSuccess(lines)
885
886  lines =<< trim END
887      vim9script
888      def g:Func(): string
889        return 'global'
890      enddef
891      assert_equal('global', Func())
892      delfunc g:Func
893  END
894  CheckScriptSuccess(lines)
895enddef
896
897func TakesOneArg(arg)
898  echo a:arg
899endfunc
900
901def Test_call_wrong_args()
902  CheckDefFailure(['TakesOneArg()'], 'E119:')
903  CheckDefFailure(['TakesOneArg(11, 22)'], 'E118:')
904  CheckDefFailure(['bufnr(xxx)'], 'E1001:')
905  CheckScriptFailure(['def Func(Ref: func(s: string))'], 'E475:')
906
907  var lines =<< trim END
908    vim9script
909    def Func(s: string)
910      echo s
911    enddef
912    Func([])
913  END
914  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got list<unknown>', 5)
915
916  lines =<< trim END
917    vim9script
918    var name = 'piet'
919    def FuncOne(name: string)
920      echo nr
921    enddef
922  END
923  CheckScriptFailure(lines, 'E1168:')
924
925  lines =<< trim END
926    vim9script
927    def FuncOne(nr: number)
928      echo nr
929    enddef
930    def FuncTwo()
931      FuncOne()
932    enddef
933    defcompile
934  END
935  writefile(lines, 'Xscript')
936  var didCatch = false
937  try
938    source Xscript
939  catch
940    assert_match('E119: Not enough arguments for function: <SNR>\d\+_FuncOne', v:exception)
941    assert_match('Xscript\[8\]..function <SNR>\d\+_FuncTwo, line 1', v:throwpoint)
942    didCatch = true
943  endtry
944  assert_true(didCatch)
945
946  lines =<< trim END
947    vim9script
948    def FuncOne(nr: number)
949      echo nr
950    enddef
951    def FuncTwo()
952      FuncOne(1, 2)
953    enddef
954    defcompile
955  END
956  writefile(lines, 'Xscript')
957  didCatch = false
958  try
959    source Xscript
960  catch
961    assert_match('E118: Too many arguments for function: <SNR>\d\+_FuncOne', v:exception)
962    assert_match('Xscript\[8\]..function <SNR>\d\+_FuncTwo, line 1', v:throwpoint)
963    didCatch = true
964  endtry
965  assert_true(didCatch)
966
967  delete('Xscript')
968enddef
969
970def Test_call_funcref_wrong_args()
971  var head =<< trim END
972      vim9script
973      def Func3(a1: string, a2: number, a3: list<number>)
974        echo a1 .. a2 .. a3[0]
975      enddef
976      def Testme()
977        var funcMap: dict<func> = {func: Func3}
978  END
979  var tail =<< trim END
980      enddef
981      Testme()
982  END
983  CheckScriptSuccess(head + ["funcMap['func']('str', 123, [1, 2, 3])"] + tail)
984
985  CheckScriptFailure(head + ["funcMap['func']('str', 123)"] + tail, 'E119:')
986  CheckScriptFailure(head + ["funcMap['func']('str', 123, [1], 4)"] + tail, 'E118:')
987
988  var lines =<< trim END
989      vim9script
990      var Ref: func(number): any
991      Ref = (j) => !j
992      echo Ref(false)
993  END
994  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected number but got bool', 4)
995
996  lines =<< trim END
997      vim9script
998      var Ref: func(number): any
999      Ref = (j) => !j
1000      call Ref(false)
1001  END
1002  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected number but got bool', 4)
1003enddef
1004
1005def Test_call_lambda_args()
1006  var lines =<< trim END
1007    var Callback = (..._) => 'anything'
1008    assert_equal('anything', Callback())
1009    assert_equal('anything', Callback(1))
1010    assert_equal('anything', Callback('a', 2))
1011
1012    assert_equal('xyz', ((a: string): string => a)('xyz'))
1013  END
1014  CheckDefAndScriptSuccess(lines)
1015
1016  CheckDefFailure(['echo ((i) => 0)()'],
1017                  'E119: Not enough arguments for function: ((i) => 0)()')
1018
1019  lines =<< trim END
1020      var Ref = (x: number, y: number) => x + y
1021      echo Ref(1, 'x')
1022  END
1023  CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected number but got string')
1024
1025  lines =<< trim END
1026    var Ref: func(job, string, number)
1027    Ref = (x, y) => 0
1028  END
1029  CheckDefAndScriptFailure(lines, 'E1012:')
1030
1031  lines =<< trim END
1032    var Ref: func(job, string)
1033    Ref = (x, y, z) => 0
1034  END
1035  CheckDefAndScriptFailure(lines, 'E1012:')
1036
1037  lines =<< trim END
1038      var one = 1
1039      var l = [1, 2, 3]
1040      echo map(l, (one) => one)
1041  END
1042  CheckDefFailure(lines, 'E1167:')
1043  CheckScriptFailure(['vim9script'] + lines, 'E1168:')
1044
1045  lines =<< trim END
1046    var Ref: func(any, ?any): bool
1047    Ref = (_, y = 1) => false
1048  END
1049  CheckDefAndScriptFailure(lines, 'E1172:')
1050
1051  lines =<< trim END
1052      var a = 0
1053      var b = (a == 0 ? 1 : 2)
1054      assert_equal(1, b)
1055      var txt = 'a'
1056      b = (txt =~ 'x' ? 1 : 2)
1057      assert_equal(2, b)
1058  END
1059  CheckDefAndScriptSuccess(lines)
1060
1061  lines =<< trim END
1062      def ShadowLocal()
1063        var one = 1
1064        var l = [1, 2, 3]
1065        echo map(l, (one) => one)
1066      enddef
1067  END
1068  CheckDefFailure(lines, 'E1167:')
1069
1070  lines =<< trim END
1071      def Shadowarg(one: number)
1072        var l = [1, 2, 3]
1073        echo map(l, (one) => one)
1074      enddef
1075  END
1076  CheckDefFailure(lines, 'E1167:')
1077
1078  lines =<< trim END
1079    echo ((a) => a)('aa', 'bb')
1080  END
1081  CheckDefAndScriptFailure(lines, 'E118:', 1)
1082
1083  lines =<< trim END
1084    echo 'aa'->((a) => a)('bb')
1085  END
1086  CheckDefFailure(lines, 'E118: Too many arguments for function: ->((a) => a)(''bb'')', 1)
1087  CheckScriptFailure(['vim9script'] + lines, 'E118: Too many arguments for function: <lambda>', 2)
1088enddef
1089
1090def Test_lambda_line_nr()
1091  var lines =<< trim END
1092      vim9script
1093      # comment
1094      # comment
1095      var id = timer_start(1'000, (_) => 0)
1096      var out = execute('verbose ' .. timer_info(id)[0].callback
1097          ->string()
1098          ->substitute("('\\|')", ' ', 'g'))
1099      assert_match('Last set from .* line 4', out)
1100  END
1101  CheckScriptSuccess(lines)
1102enddef
1103
1104def FilterWithCond(x: string, Cond: func(string): bool): bool
1105  return Cond(x)
1106enddef
1107
1108def Test_lambda_return_type()
1109  var lines =<< trim END
1110    var Ref = (): => 123
1111  END
1112  CheckDefAndScriptFailure(lines, 'E1157:', 1)
1113
1114  # no space before the return type
1115  lines =<< trim END
1116    var Ref = (x):number => x + 1
1117  END
1118  CheckDefAndScriptFailure(lines, 'E1069:', 1)
1119
1120  # this works
1121  for x in ['foo', 'boo']
1122    echo FilterWithCond(x, (v) => v =~ '^b')
1123  endfor
1124
1125  # this fails
1126  lines =<< trim END
1127      echo FilterWithCond('foo', (v) => v .. '^b')
1128  END
1129  CheckDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected func(string): bool but got func(any): string', 1)
1130
1131  lines =<< trim END
1132      var Lambda1 = (x) => {
1133              return x
1134              }
1135      assert_equal('asdf', Lambda1('asdf'))
1136      var Lambda2 = (x): string => {
1137              return x
1138              }
1139      assert_equal('foo', Lambda2('foo'))
1140  END
1141  CheckDefAndScriptSuccess(lines)
1142
1143  lines =<< trim END
1144      var Lambda = (x): string => {
1145              return x
1146              }
1147      echo Lambda(['foo'])
1148  END
1149  CheckDefExecAndScriptFailure(lines, 'E1012:')
1150enddef
1151
1152def Test_lambda_uses_assigned_var()
1153  CheckDefSuccess([
1154        'var x: any = "aaa"'
1155        'x = filter(["bbb"], (_, v) => v =~ x)'])
1156enddef
1157
1158def Test_pass_legacy_lambda_to_def_func()
1159  var lines =<< trim END
1160      vim9script
1161      func Foo()
1162        eval s:Bar({x -> 0})
1163      endfunc
1164      def Bar(y: any)
1165      enddef
1166      Foo()
1167  END
1168  CheckScriptSuccess(lines)
1169
1170  lines =<< trim END
1171      vim9script
1172      def g:TestFunc(f: func)
1173      enddef
1174      legacy call g:TestFunc({-> 0})
1175      delfunc g:TestFunc
1176
1177      def g:TestFunc(f: func(number))
1178      enddef
1179      legacy call g:TestFunc({nr -> 0})
1180      delfunc g:TestFunc
1181  END
1182  CheckScriptSuccess(lines)
1183enddef
1184
1185def Test_lambda_in_reduce_line_break()
1186  # this was using freed memory
1187  var lines =<< trim END
1188      vim9script
1189      const result: dict<number> =
1190          ['Bob', 'Sam', 'Cat', 'Bob', 'Cat', 'Cat']
1191          ->reduce((acc, val) => {
1192              if has_key(acc, val)
1193                  acc[val] += 1
1194                  return acc
1195              else
1196                  acc[val] = 1
1197                  return acc
1198              endif
1199          }, {})
1200      assert_equal({Bob: 2, Sam: 1, Cat: 3}, result)
1201  END
1202  CheckScriptSuccess(lines)
1203enddef
1204
1205" Default arg and varargs
1206def MyDefVarargs(one: string, two = 'foo', ...rest: list<string>): string
1207  var res = one .. ',' .. two
1208  for s in rest
1209    res ..= ',' .. s
1210  endfor
1211  return res
1212enddef
1213
1214def Test_call_def_varargs()
1215  assert_fails('MyDefVarargs()', 'E119:', '', 1, 'Test_call_def_varargs')
1216  MyDefVarargs('one')->assert_equal('one,foo')
1217  MyDefVarargs('one', 'two')->assert_equal('one,two')
1218  MyDefVarargs('one', 'two', 'three')->assert_equal('one,two,three')
1219  CheckDefFailure(['MyDefVarargs("one", 22)'],
1220      'E1013: Argument 2: type mismatch, expected string but got number')
1221  CheckDefFailure(['MyDefVarargs("one", "two", 123)'],
1222      'E1013: Argument 3: type mismatch, expected string but got number')
1223
1224  var lines =<< trim END
1225      vim9script
1226      def Func(...l: list<string>)
1227        echo l
1228      enddef
1229      Func('a', 'b', 'c')
1230  END
1231  CheckScriptSuccess(lines)
1232
1233  lines =<< trim END
1234      vim9script
1235      def Func(...l: list<string>)
1236        echo l
1237      enddef
1238      Func()
1239  END
1240  CheckScriptSuccess(lines)
1241
1242  lines =<< trim END
1243      vim9script
1244      def Func(...l: list<any>)
1245        echo l
1246      enddef
1247      Func(0)
1248  END
1249  CheckScriptSuccess(lines)
1250
1251  lines =<< trim END
1252      vim9script
1253      def Func(...l: any)
1254        echo l
1255      enddef
1256      Func(0)
1257  END
1258  CheckScriptFailure(lines, 'E1180:', 2)
1259
1260  lines =<< trim END
1261      vim9script
1262      def Func(..._l: list<string>)
1263        echo _l
1264      enddef
1265      Func('a', 'b', 'c')
1266  END
1267  CheckScriptSuccess(lines)
1268
1269  lines =<< trim END
1270      vim9script
1271      def Func(...l: list<string>)
1272        echo l
1273      enddef
1274      Func(1, 2, 3)
1275  END
1276  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch')
1277
1278  lines =<< trim END
1279      vim9script
1280      def Func(...l: list<string>)
1281        echo l
1282      enddef
1283      Func('a', 9)
1284  END
1285  CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch')
1286
1287  lines =<< trim END
1288      vim9script
1289      def Func(...l: list<string>)
1290        echo l
1291      enddef
1292      Func(1, 'a')
1293  END
1294  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch')
1295
1296  lines =<< trim END
1297      vim9script
1298      def Func(  # some comment
1299                ...l = []
1300                )
1301        echo l
1302      enddef
1303  END
1304  CheckScriptFailure(lines, 'E1160:')
1305
1306  lines =<< trim END
1307      vim9script
1308      def DoIt()
1309        g:Later('')
1310      enddef
1311      defcompile
1312      def g:Later(...l:  list<number>)
1313      enddef
1314      DoIt()
1315  END
1316  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected number but got string')
1317enddef
1318
1319let s:value = ''
1320
1321def FuncOneDefArg(opt = 'text')
1322  s:value = opt
1323enddef
1324
1325def FuncTwoDefArg(nr = 123, opt = 'text'): string
1326  return nr .. opt
1327enddef
1328
1329def FuncVarargs(...arg: list<string>): string
1330  return join(arg, ',')
1331enddef
1332
1333def Test_func_type_varargs()
1334  var RefDefArg: func(?string)
1335  RefDefArg = FuncOneDefArg
1336  RefDefArg()
1337  s:value->assert_equal('text')
1338  RefDefArg('some')
1339  s:value->assert_equal('some')
1340
1341  var RefDef2Arg: func(?number, ?string): string
1342  RefDef2Arg = FuncTwoDefArg
1343  RefDef2Arg()->assert_equal('123text')
1344  RefDef2Arg(99)->assert_equal('99text')
1345  RefDef2Arg(77, 'some')->assert_equal('77some')
1346
1347  CheckDefFailure(['var RefWrong: func(string?)'], 'E1010:')
1348  CheckDefFailure(['var RefWrong: func(?string, string)'], 'E1007:')
1349
1350  var RefVarargs: func(...list<string>): string
1351  RefVarargs = FuncVarargs
1352  RefVarargs()->assert_equal('')
1353  RefVarargs('one')->assert_equal('one')
1354  RefVarargs('one', 'two')->assert_equal('one,two')
1355
1356  CheckDefFailure(['var RefWrong: func(...list<string>, string)'], 'E110:')
1357  CheckDefFailure(['var RefWrong: func(...list<string>, ?string)'], 'E110:')
1358enddef
1359
1360" Only varargs
1361def MyVarargsOnly(...args: list<string>): string
1362  return join(args, ',')
1363enddef
1364
1365def Test_call_varargs_only()
1366  MyVarargsOnly()->assert_equal('')
1367  MyVarargsOnly('one')->assert_equal('one')
1368  MyVarargsOnly('one', 'two')->assert_equal('one,two')
1369  CheckDefFailure(['MyVarargsOnly(1)'], 'E1013: Argument 1: type mismatch, expected string but got number')
1370  CheckDefFailure(['MyVarargsOnly("one", 2)'], 'E1013: Argument 2: type mismatch, expected string but got number')
1371enddef
1372
1373def Test_using_var_as_arg()
1374  writefile(['def Func(x: number)',  'var x = 234', 'enddef', 'defcompile'], 'Xdef')
1375  assert_fails('so Xdef', 'E1006:', '', 1, 'Func')
1376  delete('Xdef')
1377enddef
1378
1379def DictArg(arg: dict<string>)
1380  arg['key'] = 'value'
1381enddef
1382
1383def ListArg(arg: list<string>)
1384  arg[0] = 'value'
1385enddef
1386
1387def Test_assign_to_argument()
1388  # works for dict and list
1389  var d: dict<string> = {}
1390  DictArg(d)
1391  d['key']->assert_equal('value')
1392  var l: list<string> = []
1393  ListArg(l)
1394  l[0]->assert_equal('value')
1395
1396  CheckScriptFailure(['def Func(arg: number)', 'arg = 3', 'enddef', 'defcompile'], 'E1090:')
1397  delfunc! g:Func
1398enddef
1399
1400" These argument names are reserved in legacy functions.
1401def WithReservedNames(firstline: string, lastline: string): string
1402  return firstline .. lastline
1403enddef
1404
1405def Test_argument_names()
1406  assert_equal('OK', WithReservedNames('O', 'K'))
1407enddef
1408
1409def Test_call_func_defined_later()
1410  g:DefinedLater('one')->assert_equal('one')
1411  assert_fails('NotDefined("one")', 'E117:', '', 2, 'Test_call_func_defined_later')
1412enddef
1413
1414func DefinedLater(arg)
1415  return a:arg
1416endfunc
1417
1418def Test_call_funcref()
1419  g:SomeFunc('abc')->assert_equal(3)
1420  assert_fails('NotAFunc()', 'E117:', '', 2, 'Test_call_funcref') # comment after call
1421  assert_fails('g:NotAFunc()', 'E117:', '', 3, 'Test_call_funcref')
1422
1423  var lines =<< trim END
1424    vim9script
1425    def RetNumber(): number
1426      return 123
1427    enddef
1428    var Funcref: func: number = function('RetNumber')
1429    Funcref()->assert_equal(123)
1430  END
1431  CheckScriptSuccess(lines)
1432
1433  lines =<< trim END
1434    vim9script
1435    def RetNumber(): number
1436      return 123
1437    enddef
1438    def Bar(F: func: number): number
1439      return F()
1440    enddef
1441    var Funcref = function('RetNumber')
1442    Bar(Funcref)->assert_equal(123)
1443  END
1444  CheckScriptSuccess(lines)
1445
1446  lines =<< trim END
1447    vim9script
1448    def UseNumber(nr: number)
1449      echo nr
1450    enddef
1451    var Funcref: func(number) = function('UseNumber')
1452    Funcref(123)
1453  END
1454  CheckScriptSuccess(lines)
1455
1456  lines =<< trim END
1457    vim9script
1458    def UseNumber(nr: number)
1459      echo nr
1460    enddef
1461    var Funcref: func(string) = function('UseNumber')
1462  END
1463  CheckScriptFailure(lines, 'E1012: Type mismatch; expected func(string) but got func(number)')
1464
1465  lines =<< trim END
1466    vim9script
1467    def EchoNr(nr = 34)
1468      g:echo = nr
1469    enddef
1470    var Funcref: func(?number) = function('EchoNr')
1471    Funcref()
1472    g:echo->assert_equal(34)
1473    Funcref(123)
1474    g:echo->assert_equal(123)
1475  END
1476  CheckScriptSuccess(lines)
1477
1478  lines =<< trim END
1479    vim9script
1480    def EchoList(...l: list<number>)
1481      g:echo = l
1482    enddef
1483    var Funcref: func(...list<number>) = function('EchoList')
1484    Funcref()
1485    g:echo->assert_equal([])
1486    Funcref(1, 2, 3)
1487    g:echo->assert_equal([1, 2, 3])
1488  END
1489  CheckScriptSuccess(lines)
1490
1491  lines =<< trim END
1492    vim9script
1493    def OptAndVar(nr: number, opt = 12, ...l: list<number>): number
1494      g:optarg = opt
1495      g:listarg = l
1496      return nr
1497    enddef
1498    var Funcref: func(number, ?number, ...list<number>): number = function('OptAndVar')
1499    Funcref(10)->assert_equal(10)
1500    g:optarg->assert_equal(12)
1501    g:listarg->assert_equal([])
1502
1503    Funcref(11, 22)->assert_equal(11)
1504    g:optarg->assert_equal(22)
1505    g:listarg->assert_equal([])
1506
1507    Funcref(17, 18, 1, 2, 3)->assert_equal(17)
1508    g:optarg->assert_equal(18)
1509    g:listarg->assert_equal([1, 2, 3])
1510  END
1511  CheckScriptSuccess(lines)
1512enddef
1513
1514let SomeFunc = function('len')
1515let NotAFunc = 'text'
1516
1517def CombineFuncrefTypes()
1518  # same arguments, different return type
1519  var Ref1: func(bool): string
1520  var Ref2: func(bool): number
1521  var Ref3: func(bool): any
1522  Ref3 = g:cond ? Ref1 : Ref2
1523
1524  # different number of arguments
1525  var Refa1: func(bool): number
1526  var Refa2: func(bool, number): number
1527  var Refa3: func: number
1528  Refa3 = g:cond ? Refa1 : Refa2
1529
1530  # different argument types
1531  var Refb1: func(bool, string): number
1532  var Refb2: func(string, number): number
1533  var Refb3: func(any, any): number
1534  Refb3 = g:cond ? Refb1 : Refb2
1535enddef
1536
1537def FuncWithForwardCall()
1538  return g:DefinedEvenLater("yes")
1539enddef
1540
1541def DefinedEvenLater(arg: string): string
1542  return arg
1543enddef
1544
1545def Test_error_in_nested_function()
1546  # Error in called function requires unwinding the call stack.
1547  assert_fails('FuncWithForwardCall()', 'E1096:', '', 1, 'FuncWithForwardCall')
1548enddef
1549
1550def Test_return_type_wrong()
1551  CheckScriptFailure([
1552        'def Func(): number',
1553        'return "a"',
1554        'enddef',
1555        'defcompile'], 'expected number but got string')
1556  delfunc! g:Func
1557  CheckScriptFailure([
1558        'def Func(): string',
1559        'return 1',
1560        'enddef',
1561        'defcompile'], 'expected string but got number')
1562  delfunc! g:Func
1563  CheckScriptFailure([
1564        'def Func(): void',
1565        'return "a"',
1566        'enddef',
1567        'defcompile'],
1568        'E1096: Returning a value in a function without a return type')
1569  delfunc! g:Func
1570  CheckScriptFailure([
1571        'def Func()',
1572        'return "a"',
1573        'enddef',
1574        'defcompile'],
1575        'E1096: Returning a value in a function without a return type')
1576  delfunc! g:Func
1577
1578  CheckScriptFailure([
1579        'def Func(): number',
1580        'return',
1581        'enddef',
1582        'defcompile'], 'E1003:')
1583  delfunc! g:Func
1584
1585  CheckScriptFailure([
1586        'def Func():number',
1587        'return 123',
1588        'enddef',
1589        'defcompile'], 'E1069:')
1590  delfunc! g:Func
1591
1592  CheckScriptFailure([
1593        'def Func() :number',
1594        'return 123',
1595        'enddef',
1596        'defcompile'], 'E1059:')
1597  delfunc! g:Func
1598
1599  CheckScriptFailure([
1600        'def Func() : number',
1601        'return 123',
1602        'enddef',
1603        'defcompile'], 'E1059:')
1604  delfunc! g:Func
1605
1606  CheckScriptFailure(['def Func(): list', 'return []', 'enddef'], 'E1008:')
1607  delfunc! g:Func
1608  CheckScriptFailure(['def Func(): dict', 'return {}', 'enddef'], 'E1008:')
1609  delfunc! g:Func
1610  CheckScriptFailure(['def Func()', 'return 1'], 'E1057:')
1611  delfunc! g:Func
1612
1613  CheckScriptFailure([
1614        'vim9script',
1615        'def FuncB()',
1616        '  return 123',
1617        'enddef',
1618        'def FuncA()',
1619        '   FuncB()',
1620        'enddef',
1621        'defcompile'], 'E1096:')
1622enddef
1623
1624def Test_arg_type_wrong()
1625  CheckScriptFailure(['def Func3(items: list)', 'echo "a"', 'enddef'], 'E1008: Missing <type>')
1626  CheckScriptFailure(['def Func4(...)', 'echo "a"', 'enddef'], 'E1055: Missing name after ...')
1627  CheckScriptFailure(['def Func5(items:string)', 'echo "a"'], 'E1069:')
1628  CheckScriptFailure(['def Func5(items)', 'echo "a"'], 'E1077:')
1629  CheckScriptFailure(['def Func6(...x:list<number>)', 'echo "a"', 'enddef'], 'E1069:')
1630  CheckScriptFailure(['def Func7(...x: int)', 'echo "a"', 'enddef'], 'E1010:')
1631enddef
1632
1633def Test_white_space_before_comma()
1634  var lines =<< trim END
1635    vim9script
1636    def Func(a: number , b: number)
1637    enddef
1638  END
1639  CheckScriptFailure(lines, 'E1068:')
1640  call assert_fails('vim9cmd echo stridx("a" .. "b" , "a")', 'E1068:')
1641enddef
1642
1643def Test_white_space_after_comma()
1644  var lines =<< trim END
1645    vim9script
1646    def Func(a: number,b: number)
1647    enddef
1648  END
1649  CheckScriptFailure(lines, 'E1069:')
1650
1651  # OK in legacy function
1652  lines =<< trim END
1653    vim9script
1654    func Func(a,b)
1655    endfunc
1656  END
1657  CheckScriptSuccess(lines)
1658enddef
1659
1660def Test_vim9script_call()
1661  var lines =<< trim END
1662    vim9script
1663    var name = ''
1664    def MyFunc(arg: string)
1665       name = arg
1666    enddef
1667    MyFunc('foobar')
1668    name->assert_equal('foobar')
1669
1670    var str = 'barfoo'
1671    str->MyFunc()
1672    name->assert_equal('barfoo')
1673
1674    g:value = 'value'
1675    g:value->MyFunc()
1676    name->assert_equal('value')
1677
1678    var listvar = []
1679    def ListFunc(arg: list<number>)
1680       listvar = arg
1681    enddef
1682    [1, 2, 3]->ListFunc()
1683    listvar->assert_equal([1, 2, 3])
1684
1685    var dictvar = {}
1686    def DictFunc(arg: dict<number>)
1687       dictvar = arg
1688    enddef
1689    {a: 1, b: 2}->DictFunc()
1690    dictvar->assert_equal({a: 1, b: 2})
1691    def CompiledDict()
1692      {a: 3, b: 4}->DictFunc()
1693    enddef
1694    CompiledDict()
1695    dictvar->assert_equal({a: 3, b: 4})
1696
1697    {a: 3, b: 4}->DictFunc()
1698    dictvar->assert_equal({a: 3, b: 4})
1699
1700    ('text')->MyFunc()
1701    name->assert_equal('text')
1702    ("some")->MyFunc()
1703    name->assert_equal('some')
1704
1705    # line starting with single quote is not a mark
1706    # line starting with double quote can be a method call
1707    'asdfasdf'->MyFunc()
1708    name->assert_equal('asdfasdf')
1709    "xyz"->MyFunc()
1710    name->assert_equal('xyz')
1711
1712    def UseString()
1713      'xyork'->MyFunc()
1714    enddef
1715    UseString()
1716    name->assert_equal('xyork')
1717
1718    def UseString2()
1719      "knife"->MyFunc()
1720    enddef
1721    UseString2()
1722    name->assert_equal('knife')
1723
1724    # prepending a colon makes it a mark
1725    new
1726    setline(1, ['aaa', 'bbb', 'ccc'])
1727    normal! 3Gmt1G
1728    :'t
1729    getcurpos()[1]->assert_equal(3)
1730    bwipe!
1731
1732    MyFunc(
1733        'continued'
1734        )
1735    assert_equal('continued',
1736            name
1737            )
1738
1739    call MyFunc(
1740        'more'
1741          ..
1742          'lines'
1743        )
1744    assert_equal(
1745        'morelines',
1746        name)
1747  END
1748  writefile(lines, 'Xcall.vim')
1749  source Xcall.vim
1750  delete('Xcall.vim')
1751enddef
1752
1753def Test_vim9script_call_fail_decl()
1754  var lines =<< trim END
1755    vim9script
1756    var name = ''
1757    def MyFunc(arg: string)
1758       var name = 123
1759    enddef
1760    defcompile
1761  END
1762  CheckScriptFailure(lines, 'E1054:')
1763enddef
1764
1765def Test_vim9script_call_fail_type()
1766  var lines =<< trim END
1767    vim9script
1768    def MyFunc(arg: string)
1769      echo arg
1770    enddef
1771    MyFunc(1234)
1772  END
1773  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected string but got number')
1774enddef
1775
1776def Test_vim9script_call_fail_const()
1777  var lines =<< trim END
1778    vim9script
1779    const var = ''
1780    def MyFunc(arg: string)
1781       var = 'asdf'
1782    enddef
1783    defcompile
1784  END
1785  writefile(lines, 'Xcall_const.vim')
1786  assert_fails('source Xcall_const.vim', 'E46:', '', 1, 'MyFunc')
1787  delete('Xcall_const.vim')
1788
1789  lines =<< trim END
1790      const g:Aconst = 77
1791      def Change()
1792        # comment
1793        g:Aconst = 99
1794      enddef
1795      call Change()
1796      unlet g:Aconst
1797  END
1798  CheckScriptFailure(lines, 'E741: Value is locked: Aconst', 2)
1799enddef
1800
1801" Test that inside :function a Python function can be defined, :def is not
1802" recognized.
1803func Test_function_python()
1804  CheckFeature python3
1805  let py = 'python3'
1806  execute py "<< EOF"
1807def do_something():
1808  return 1
1809EOF
1810endfunc
1811
1812def Test_delfunc()
1813  var lines =<< trim END
1814    vim9script
1815    def g:GoneSoon()
1816      echo 'hello'
1817    enddef
1818
1819    def CallGoneSoon()
1820      GoneSoon()
1821    enddef
1822    defcompile
1823
1824    delfunc g:GoneSoon
1825    CallGoneSoon()
1826  END
1827  writefile(lines, 'XToDelFunc')
1828  assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon')
1829  assert_fails('so XToDelFunc', 'E933:', '', 1, 'CallGoneSoon')
1830
1831  delete('XToDelFunc')
1832enddef
1833
1834def Test_redef_failure()
1835  writefile(['def Func0(): string',  'return "Func0"', 'enddef'], 'Xdef')
1836  so Xdef
1837  writefile(['def Func1(): string',  'return "Func1"', 'enddef'], 'Xdef')
1838  so Xdef
1839  writefile(['def! Func0(): string', 'enddef', 'defcompile'], 'Xdef')
1840  assert_fails('so Xdef', 'E1027:', '', 1, 'Func0')
1841  writefile(['def Func2(): string',  'return "Func2"', 'enddef'], 'Xdef')
1842  so Xdef
1843  delete('Xdef')
1844
1845  assert_fails('g:Func0()', 'E1091:')
1846  g:Func1()->assert_equal('Func1')
1847  g:Func2()->assert_equal('Func2')
1848
1849  delfunc! Func0
1850  delfunc! Func1
1851  delfunc! Func2
1852enddef
1853
1854def Test_vim9script_func()
1855  var lines =<< trim END
1856    vim9script
1857    func Func(arg)
1858      echo a:arg
1859    endfunc
1860    Func('text')
1861  END
1862  writefile(lines, 'XVim9Func')
1863  so XVim9Func
1864
1865  delete('XVim9Func')
1866enddef
1867
1868let s:funcResult = 0
1869
1870def FuncNoArgNoRet()
1871  s:funcResult = 11
1872enddef
1873
1874def FuncNoArgRetNumber(): number
1875  s:funcResult = 22
1876  return 1234
1877enddef
1878
1879def FuncNoArgRetString(): string
1880  s:funcResult = 45
1881  return 'text'
1882enddef
1883
1884def FuncOneArgNoRet(arg: number)
1885  s:funcResult = arg
1886enddef
1887
1888def FuncOneArgRetNumber(arg: number): number
1889  s:funcResult = arg
1890  return arg
1891enddef
1892
1893def FuncTwoArgNoRet(one: bool, two: number)
1894  s:funcResult = two
1895enddef
1896
1897def FuncOneArgRetString(arg: string): string
1898  return arg
1899enddef
1900
1901def FuncOneArgRetAny(arg: any): any
1902  return arg
1903enddef
1904
1905def Test_func_type()
1906  var Ref1: func()
1907  s:funcResult = 0
1908  Ref1 = FuncNoArgNoRet
1909  Ref1()
1910  s:funcResult->assert_equal(11)
1911
1912  var Ref2: func
1913  s:funcResult = 0
1914  Ref2 = FuncNoArgNoRet
1915  Ref2()
1916  s:funcResult->assert_equal(11)
1917
1918  s:funcResult = 0
1919  Ref2 = FuncOneArgNoRet
1920  Ref2(12)
1921  s:funcResult->assert_equal(12)
1922
1923  s:funcResult = 0
1924  Ref2 = FuncNoArgRetNumber
1925  Ref2()->assert_equal(1234)
1926  s:funcResult->assert_equal(22)
1927
1928  s:funcResult = 0
1929  Ref2 = FuncOneArgRetNumber
1930  Ref2(13)->assert_equal(13)
1931  s:funcResult->assert_equal(13)
1932enddef
1933
1934def Test_repeat_return_type()
1935  var res = 0
1936  for n in repeat([1], 3)
1937    res += n
1938  endfor
1939  res->assert_equal(3)
1940
1941  res = 0
1942  for n in add([1, 2], 3)
1943    res += n
1944  endfor
1945  res->assert_equal(6)
1946enddef
1947
1948def Test_argv_return_type()
1949  next fileone filetwo
1950  var res = ''
1951  for name in argv()
1952    res ..= name
1953  endfor
1954  res->assert_equal('fileonefiletwo')
1955enddef
1956
1957def Test_func_type_part()
1958  var RefVoid: func: void
1959  RefVoid = FuncNoArgNoRet
1960  RefVoid = FuncOneArgNoRet
1961  CheckDefFailure(['var RefVoid: func: void', 'RefVoid = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...) but got func(): number')
1962  CheckDefFailure(['var RefVoid: func: void', 'RefVoid = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...) but got func(): string')
1963
1964  var RefAny: func(): any
1965  RefAny = FuncNoArgRetNumber
1966  RefAny = FuncNoArgRetString
1967  CheckDefFailure(['var RefAny: func(): any', 'RefAny = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func()')
1968  CheckDefFailure(['var RefAny: func(): any', 'RefAny = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func(): any but got func(number)')
1969
1970  var RefAnyNoArgs: func: any = RefAny
1971
1972  var RefNr: func: number
1973  RefNr = FuncNoArgRetNumber
1974  RefNr = FuncOneArgRetNumber
1975  CheckDefFailure(['var RefNr: func: number', 'RefNr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): number but got func()')
1976  CheckDefFailure(['var RefNr: func: number', 'RefNr = FuncNoArgRetString'], 'E1012: Type mismatch; expected func(...): number but got func(): string')
1977
1978  var RefStr: func: string
1979  RefStr = FuncNoArgRetString
1980  RefStr = FuncOneArgRetString
1981  CheckDefFailure(['var RefStr: func: string', 'RefStr = FuncNoArgNoRet'], 'E1012: Type mismatch; expected func(...): string but got func()')
1982  CheckDefFailure(['var RefStr: func: string', 'RefStr = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func(...): string but got func(): number')
1983enddef
1984
1985def Test_func_type_fails()
1986  CheckDefFailure(['var ref1: func()'], 'E704:')
1987
1988  CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncNoArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(): number')
1989  CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncOneArgNoRet'], 'E1012: Type mismatch; expected func() but got func(number)')
1990  CheckDefFailure(['var Ref1: func()', 'Ref1 = FuncOneArgRetNumber'], 'E1012: Type mismatch; expected func() but got func(number): number')
1991  CheckDefFailure(['var Ref1: func(bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(bool) but got func(bool, number)')
1992  CheckDefFailure(['var Ref1: func(?bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(?bool) but got func(bool, number)')
1993  CheckDefFailure(['var Ref1: func(...bool)', 'Ref1 = FuncTwoArgNoRet'], 'E1012: Type mismatch; expected func(...bool) but got func(bool, number)')
1994
1995  CheckDefFailure(['var RefWrong: func(string ,number)'], 'E1068:')
1996  CheckDefFailure(['var RefWrong: func(string,number)'], 'E1069:')
1997  CheckDefFailure(['var RefWrong: func(bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool)'], 'E1005:')
1998  CheckDefFailure(['var RefWrong: func(bool):string'], 'E1069:')
1999enddef
2000
2001def Test_func_return_type()
2002  var nr: number
2003  nr = FuncNoArgRetNumber()
2004  nr->assert_equal(1234)
2005
2006  nr = FuncOneArgRetAny(122)
2007  nr->assert_equal(122)
2008
2009  var str: string
2010  str = FuncOneArgRetAny('yes')
2011  str->assert_equal('yes')
2012
2013  CheckDefFailure(['var str: string', 'str = FuncNoArgRetNumber()'], 'E1012: Type mismatch; expected string but got number')
2014enddef
2015
2016def Test_func_common_type()
2017  def FuncOne(n: number): number
2018    return n
2019  enddef
2020  def FuncTwo(s: string): number
2021    return len(s)
2022  enddef
2023  def FuncThree(n: number, s: string): number
2024    return n + len(s)
2025  enddef
2026  var list = [FuncOne, FuncTwo, FuncThree]
2027  assert_equal(8, list[0](8))
2028  assert_equal(4, list[1]('word'))
2029  assert_equal(7, list[2](3, 'word'))
2030enddef
2031
2032def MultiLine(
2033    arg1: string,
2034    arg2 = 1234,
2035    ...rest: list<string>
2036      ): string
2037  return arg1 .. arg2 .. join(rest, '-')
2038enddef
2039
2040def MultiLineComment(
2041    arg1: string, # comment
2042    arg2 = 1234, # comment
2043    ...rest: list<string> # comment
2044      ): string # comment
2045  return arg1 .. arg2 .. join(rest, '-')
2046enddef
2047
2048def Test_multiline()
2049  MultiLine('text')->assert_equal('text1234')
2050  MultiLine('text', 777)->assert_equal('text777')
2051  MultiLine('text', 777, 'one')->assert_equal('text777one')
2052  MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two')
2053enddef
2054
2055func Test_multiline_not_vim9()
2056  call MultiLine('text')->assert_equal('text1234')
2057  call MultiLine('text', 777)->assert_equal('text777')
2058  call MultiLine('text', 777, 'one')->assert_equal('text777one')
2059  call MultiLine('text', 777, 'one', 'two')->assert_equal('text777one-two')
2060endfunc
2061
2062
2063" When using CheckScriptFailure() for the below test, E1010 is generated instead
2064" of E1056.
2065func Test_E1056_1059()
2066  let caught_1056 = 0
2067  try
2068    def F():
2069      return 1
2070    enddef
2071  catch /E1056:/
2072    let caught_1056 = 1
2073  endtry
2074  eval caught_1056->assert_equal(1)
2075
2076  let caught_1059 = 0
2077  try
2078    def F5(items : list)
2079      echo 'a'
2080    enddef
2081  catch /E1059:/
2082    let caught_1059 = 1
2083  endtry
2084  eval caught_1059->assert_equal(1)
2085endfunc
2086
2087func DelMe()
2088  echo 'DelMe'
2089endfunc
2090
2091def Test_error_reporting()
2092  # comment lines at the start of the function
2093  var lines =<< trim END
2094    " comment
2095    def Func()
2096      # comment
2097      # comment
2098      invalid
2099    enddef
2100    defcompile
2101  END
2102  writefile(lines, 'Xdef')
2103  try
2104    source Xdef
2105    assert_report('should have failed')
2106  catch /E476:/
2107    v:exception->assert_match('Invalid command: invalid')
2108    v:throwpoint->assert_match(', line 3$')
2109  endtry
2110  delfunc! g:Func
2111
2112  # comment lines after the start of the function
2113  lines =<< trim END
2114    " comment
2115    def Func()
2116      var x = 1234
2117      # comment
2118      # comment
2119      invalid
2120    enddef
2121    defcompile
2122  END
2123  writefile(lines, 'Xdef')
2124  try
2125    source Xdef
2126    assert_report('should have failed')
2127  catch /E476:/
2128    v:exception->assert_match('Invalid command: invalid')
2129    v:throwpoint->assert_match(', line 4$')
2130  endtry
2131  delfunc! g:Func
2132
2133  lines =<< trim END
2134    vim9script
2135    def Func()
2136      var db = {foo: 1, bar: 2}
2137      # comment
2138      var x = db.asdf
2139    enddef
2140    defcompile
2141    Func()
2142  END
2143  writefile(lines, 'Xdef')
2144  try
2145    source Xdef
2146    assert_report('should have failed')
2147  catch /E716:/
2148    v:throwpoint->assert_match('_Func, line 3$')
2149  endtry
2150  delfunc! g:Func
2151
2152  delete('Xdef')
2153enddef
2154
2155def Test_deleted_function()
2156  CheckDefExecFailure([
2157      'var RefMe: func = function("g:DelMe")',
2158      'delfunc g:DelMe',
2159      'echo RefMe()'], 'E117:')
2160enddef
2161
2162def Test_unknown_function()
2163  CheckDefExecFailure([
2164      'var Ref: func = function("NotExist")',
2165      'delfunc g:NotExist'], 'E700:')
2166enddef
2167
2168def RefFunc(Ref: func(any): any): string
2169  return Ref('more')
2170enddef
2171
2172def Test_closure_simple()
2173  var local = 'some '
2174  RefFunc((s) => local .. s)->assert_equal('some more')
2175enddef
2176
2177def MakeRef()
2178  var local = 'some '
2179  g:Ref = (s) => local .. s
2180enddef
2181
2182def Test_closure_ref_after_return()
2183  MakeRef()
2184  g:Ref('thing')->assert_equal('some thing')
2185  unlet g:Ref
2186enddef
2187
2188def MakeTwoRefs()
2189  var local = ['some']
2190  g:Extend = (s) => local->add(s)
2191  g:Read = () => local
2192enddef
2193
2194def Test_closure_two_refs()
2195  MakeTwoRefs()
2196  join(g:Read(), ' ')->assert_equal('some')
2197  g:Extend('more')
2198  join(g:Read(), ' ')->assert_equal('some more')
2199  g:Extend('even')
2200  join(g:Read(), ' ')->assert_equal('some more even')
2201
2202  unlet g:Extend
2203  unlet g:Read
2204enddef
2205
2206def ReadRef(Ref: func(): list<string>): string
2207  return join(Ref(), ' ')
2208enddef
2209
2210def ExtendRef(Ref: func(string): list<string>, add: string)
2211  Ref(add)
2212enddef
2213
2214def Test_closure_two_indirect_refs()
2215  MakeTwoRefs()
2216  ReadRef(g:Read)->assert_equal('some')
2217  ExtendRef(g:Extend, 'more')
2218  ReadRef(g:Read)->assert_equal('some more')
2219  ExtendRef(g:Extend, 'even')
2220  ReadRef(g:Read)->assert_equal('some more even')
2221
2222  unlet g:Extend
2223  unlet g:Read
2224enddef
2225
2226def MakeArgRefs(theArg: string)
2227  var local = 'loc_val'
2228  g:UseArg = (s) => theArg .. '/' .. local .. '/' .. s
2229enddef
2230
2231def MakeArgRefsVarargs(theArg: string, ...rest: list<string>)
2232  var local = 'the_loc'
2233  g:UseVararg = (s) => theArg .. '/' .. local .. '/' .. s .. '/' .. join(rest)
2234enddef
2235
2236def Test_closure_using_argument()
2237  MakeArgRefs('arg_val')
2238  g:UseArg('call_val')->assert_equal('arg_val/loc_val/call_val')
2239
2240  MakeArgRefsVarargs('arg_val', 'one', 'two')
2241  g:UseVararg('call_val')->assert_equal('arg_val/the_loc/call_val/one two')
2242
2243  unlet g:UseArg
2244  unlet g:UseVararg
2245
2246  var lines =<< trim END
2247      vim9script
2248      def Test(Fun: func(number): number): list<number>
2249        return map([1, 2, 3], (_, i) => Fun(i))
2250      enddef
2251      def Inc(nr: number): number
2252        return nr + 2
2253      enddef
2254      assert_equal([3, 4, 5], Test(Inc))
2255  END
2256  CheckScriptSuccess(lines)
2257enddef
2258
2259def MakeGetAndAppendRefs()
2260  var local = 'a'
2261
2262  def Append(arg: string)
2263    local ..= arg
2264  enddef
2265  g:Append = Append
2266
2267  def Get(): string
2268    return local
2269  enddef
2270  g:Get = Get
2271enddef
2272
2273def Test_closure_append_get()
2274  MakeGetAndAppendRefs()
2275  g:Get()->assert_equal('a')
2276  g:Append('-b')
2277  g:Get()->assert_equal('a-b')
2278  g:Append('-c')
2279  g:Get()->assert_equal('a-b-c')
2280
2281  unlet g:Append
2282  unlet g:Get
2283enddef
2284
2285def Test_nested_closure()
2286  var local = 'text'
2287  def Closure(arg: string): string
2288    return local .. arg
2289  enddef
2290  Closure('!!!')->assert_equal('text!!!')
2291enddef
2292
2293func GetResult(Ref)
2294  return a:Ref('some')
2295endfunc
2296
2297def Test_call_closure_not_compiled()
2298  var text = 'text'
2299  g:Ref = (s) =>  s .. text
2300  GetResult(g:Ref)->assert_equal('sometext')
2301enddef
2302
2303def Test_double_closure_fails()
2304  var lines =<< trim END
2305    vim9script
2306    def Func()
2307      var name = 0
2308      for i in range(2)
2309          timer_start(0, () => name)
2310      endfor
2311    enddef
2312    Func()
2313  END
2314  CheckScriptSuccess(lines)
2315enddef
2316
2317def Test_nested_closure_used()
2318  var lines =<< trim END
2319      vim9script
2320      def Func()
2321        var x = 'hello'
2322        var Closure = () => x
2323        g:Myclosure = () => Closure()
2324      enddef
2325      Func()
2326      assert_equal('hello', g:Myclosure())
2327  END
2328  CheckScriptSuccess(lines)
2329enddef
2330
2331def Test_nested_closure_fails()
2332  var lines =<< trim END
2333    vim9script
2334    def FuncA()
2335      FuncB(0)
2336    enddef
2337    def FuncB(n: number): list<string>
2338      return map([0], (_, v) => n)
2339    enddef
2340    FuncA()
2341  END
2342  CheckScriptFailure(lines, 'E1012:')
2343enddef
2344
2345def Test_global_closure()
2346  var lines =<< trim END
2347      vim9script
2348      def ReverseEveryNLines(n: number, line1: number, line2: number)
2349        var mods = 'sil keepj keepp lockm '
2350        var range = ':' .. line1 .. ',' .. line2
2351        def g:Offset(): number
2352            var offset = (line('.') - line1 + 1) % n
2353            return offset != 0 ? offset : n
2354        enddef
2355        exe mods .. range .. 'g/^/exe "m .-" .. g:Offset()'
2356      enddef
2357
2358      new
2359      repeat(['aaa', 'bbb', 'ccc'], 3)->setline(1)
2360      ReverseEveryNLines(3, 1, 9)
2361  END
2362  CheckScriptSuccess(lines)
2363  var expected = repeat(['ccc', 'bbb', 'aaa'], 3)
2364  assert_equal(expected, getline(1, 9))
2365  bwipe!
2366enddef
2367
2368def Test_global_closure_called_directly()
2369  var lines =<< trim END
2370      vim9script
2371      def Outer()
2372        var x = 1
2373        def g:Inner()
2374          var y = x
2375          x += 1
2376          assert_equal(1, y)
2377        enddef
2378        g:Inner()
2379        assert_equal(2, x)
2380      enddef
2381      Outer()
2382  END
2383  CheckScriptSuccess(lines)
2384  delfunc g:Inner
2385enddef
2386
2387def Test_closure_called_from_legacy()
2388  var lines =<< trim END
2389      vim9script
2390      def Func()
2391        var outer = 'foo'
2392        var F = () => {
2393              outer = 'bar'
2394            }
2395        execute printf('call %s()', string(F))
2396      enddef
2397      Func()
2398  END
2399  CheckScriptFailure(lines, 'E1248')
2400enddef
2401
2402def Test_failure_in_called_function()
2403  # this was using the frame index as the return value
2404  var lines =<< trim END
2405      vim9script
2406      au TerminalWinOpen * eval [][0]
2407      def PopupTerm(a: any)
2408        # make sure typvals on stack are string
2409        ['a', 'b', 'c', 'd', 'e', 'f', 'g']->join()
2410        FireEvent()
2411      enddef
2412      def FireEvent()
2413          do TerminalWinOpen
2414      enddef
2415      # use try/catch to make eval fail
2416      try
2417          call PopupTerm(0)
2418      catch
2419      endtry
2420      au! TerminalWinOpen
2421  END
2422  CheckScriptSuccess(lines)
2423enddef
2424
2425def Test_nested_lambda()
2426  var lines =<< trim END
2427    vim9script
2428    def Func()
2429      var x = 4
2430      var Lambda1 = () => 7
2431      var Lambda2 = () => [Lambda1(), x]
2432      var res = Lambda2()
2433      assert_equal([7, 4], res)
2434    enddef
2435    Func()
2436  END
2437  CheckScriptSuccess(lines)
2438enddef
2439
2440def Test_double_nested_lambda()
2441  var lines =<< trim END
2442      vim9script
2443      def F(head: string): func(string): func(string): string
2444        return (sep: string): func(string): string => ((tail: string): string => {
2445            return head .. sep .. tail
2446          })
2447      enddef
2448      assert_equal('hello-there', F('hello')('-')('there'))
2449  END
2450  CheckScriptSuccess(lines)
2451enddef
2452
2453def Test_nested_inline_lambda()
2454  var lines =<< trim END
2455      vim9script
2456      def F(text: string): func(string): func(string): string
2457        return (arg: string): func(string): string => ((sep: string): string => {
2458            return sep .. arg .. text
2459          })
2460      enddef
2461      assert_equal('--there++', F('++')('there')('--'))
2462  END
2463  CheckScriptSuccess(lines)
2464
2465  lines =<< trim END
2466      vim9script
2467      echo range(4)->mapnew((_, v) => {
2468        return range(v) ->mapnew((_, s) => {
2469          return string(s)
2470          })
2471        })
2472  END
2473  CheckScriptSuccess(lines)
2474
2475  lines =<< trim END
2476      vim9script
2477
2478      def s:func()
2479        range(10)
2480          ->mapnew((_, _) => ({
2481            key: range(10)->mapnew((_, _) => {
2482              return ' '
2483            }),
2484          }))
2485      enddef
2486
2487      defcomp
2488  END
2489  CheckScriptSuccess(lines)
2490enddef
2491
2492def Shadowed(): list<number>
2493  var FuncList: list<func: number> = [() => 42]
2494  return FuncList->mapnew((_, Shadowed) => Shadowed())
2495enddef
2496
2497def Test_lambda_arg_shadows_func()
2498  assert_equal([42], Shadowed())
2499enddef
2500
2501def Line_continuation_in_def(dir: string = ''): string
2502  var path: string = empty(dir)
2503          \ ? 'empty'
2504          \ : 'full'
2505  return path
2506enddef
2507
2508def Test_line_continuation_in_def()
2509  Line_continuation_in_def('.')->assert_equal('full')
2510enddef
2511
2512def Test_script_var_in_lambda()
2513  var lines =<< trim END
2514      vim9script
2515      var script = 'test'
2516      assert_equal(['test'], map(['one'], (_, _) => script))
2517  END
2518  CheckScriptSuccess(lines)
2519enddef
2520
2521def Line_continuation_in_lambda(): list<string>
2522  var x = range(97, 100)
2523      ->mapnew((_, v) => nr2char(v)
2524          ->toupper())
2525      ->reverse()
2526  return x
2527enddef
2528
2529def Test_line_continuation_in_lambda()
2530  Line_continuation_in_lambda()->assert_equal(['D', 'C', 'B', 'A'])
2531
2532  var lines =<< trim END
2533      vim9script
2534      var res = [{n: 1, m: 2, s: 'xxx'}]
2535                ->mapnew((_, v: dict<any>): string => printf('%d:%d:%s',
2536                    v.n,
2537                    v.m,
2538                    substitute(v.s, '.*', 'yyy', '')
2539                    ))
2540      assert_equal(['1:2:yyy'], res)
2541  END
2542  CheckScriptSuccess(lines)
2543enddef
2544
2545def Test_list_lambda()
2546  timer_start(1000, (_) => 0)
2547  var body = execute(timer_info()[0].callback
2548         ->string()
2549         ->substitute("('", ' ', '')
2550         ->substitute("')", '', '')
2551         ->substitute('function\zs', ' ', ''))
2552  assert_match('def <lambda>\d\+(_: any): number\n1  return 0\n   enddef', body)
2553enddef
2554
2555def Test_lambda_block_variable()
2556  var lines =<< trim END
2557      vim9script
2558      var flist: list<func>
2559      for i in range(10)
2560          var inloop = i
2561          flist[i] = () => inloop
2562      endfor
2563  END
2564  CheckScriptSuccess(lines)
2565
2566  lines =<< trim END
2567      vim9script
2568      if true
2569        var outloop = 5
2570        var flist: list<func>
2571        for i in range(10)
2572          flist[i] = () => outloop
2573        endfor
2574      endif
2575  END
2576  CheckScriptSuccess(lines)
2577
2578  lines =<< trim END
2579      vim9script
2580      if true
2581        var outloop = 5
2582      endif
2583      var flist: list<func>
2584      for i in range(10)
2585        flist[i] = () => outloop
2586      endfor
2587  END
2588  CheckScriptFailure(lines, 'E1001: Variable not found: outloop', 1)
2589
2590  lines =<< trim END
2591      vim9script
2592      for i in range(10)
2593        var Ref = () => 0
2594      endfor
2595      assert_equal(0, ((i) => 0)(0))
2596  END
2597  CheckScriptSuccess(lines)
2598enddef
2599
2600def Test_legacy_lambda()
2601  legacy echo {x -> 'hello ' .. x}('foo')
2602
2603  var lines =<< trim END
2604      echo {x -> 'hello ' .. x}('foo')
2605  END
2606  CheckDefAndScriptFailure(lines, 'E720:')
2607
2608  lines =<< trim END
2609      vim9script
2610      def Func()
2611        echo (() => 'no error')()
2612      enddef
2613      legacy call s:Func()
2614  END
2615  CheckScriptSuccess(lines)
2616enddef
2617
2618def Test_legacy()
2619  var lines =<< trim END
2620      vim9script
2621      func g:LegacyFunction()
2622        let g:legacyvar = 1
2623      endfunc
2624      def Testit()
2625        legacy call g:LegacyFunction()
2626      enddef
2627      Testit()
2628      assert_equal(1, g:legacyvar)
2629      unlet g:legacyvar
2630      delfunc g:LegacyFunction
2631  END
2632  CheckScriptSuccess(lines)
2633enddef
2634
2635def Test_legacy_errors()
2636  for cmd in ['if', 'elseif', 'else', 'endif',
2637              'for', 'endfor', 'continue', 'break',
2638              'while', 'endwhile',
2639              'try', 'catch', 'finally', 'endtry']
2640    CheckDefFailure(['legacy ' .. cmd .. ' expr'], 'E1189:')
2641  endfor
2642enddef
2643
2644def Test_call_legacy_with_dict()
2645  var lines =<< trim END
2646      vim9script
2647      func Legacy() dict
2648        let g:result = self.value
2649      endfunc
2650      def TestDirect()
2651        var d = {value: 'yes', func: Legacy}
2652        d.func()
2653      enddef
2654      TestDirect()
2655      assert_equal('yes', g:result)
2656      unlet g:result
2657
2658      def TestIndirect()
2659        var d = {value: 'foo', func: Legacy}
2660        var Fi = d.func
2661        Fi()
2662      enddef
2663      TestIndirect()
2664      assert_equal('foo', g:result)
2665      unlet g:result
2666
2667      var d = {value: 'bar', func: Legacy}
2668      d.func()
2669      assert_equal('bar', g:result)
2670      unlet g:result
2671  END
2672  CheckScriptSuccess(lines)
2673enddef
2674
2675def DoFilterThis(a: string): list<string>
2676  # closure nested inside another closure using argument
2677  var Filter = (l) => filter(l, (_, v) => stridx(v, a) == 0)
2678  return ['x', 'y', 'a', 'x2', 'c']->Filter()
2679enddef
2680
2681def Test_nested_closure_using_argument()
2682  assert_equal(['x', 'x2'], DoFilterThis('x'))
2683enddef
2684
2685def Test_triple_nested_closure()
2686  var what = 'x'
2687  var Match = (val: string, cmp: string): bool => stridx(val, cmp) == 0
2688  var Filter = (l) => filter(l, (_, v) => Match(v, what))
2689  assert_equal(['x', 'x2'], ['x', 'y', 'a', 'x2', 'c']->Filter())
2690enddef
2691
2692func Test_silent_echo()
2693  CheckScreendump
2694
2695  let lines =<< trim END
2696    vim9script
2697    def EchoNothing()
2698      silent echo ''
2699    enddef
2700    defcompile
2701  END
2702  call writefile(lines, 'XTest_silent_echo')
2703
2704  " Check that the balloon shows up after a mouse move
2705  let buf = RunVimInTerminal('-S XTest_silent_echo', {'rows': 6})
2706  call term_sendkeys(buf, ":abc")
2707  call VerifyScreenDump(buf, 'Test_vim9_silent_echo', {})
2708
2709  " clean up
2710  call StopVimInTerminal(buf)
2711  call delete('XTest_silent_echo')
2712endfunc
2713
2714def SilentlyError()
2715  execute('silent! invalid')
2716  g:did_it = 'yes'
2717enddef
2718
2719func UserError()
2720  silent! invalid
2721endfunc
2722
2723def SilentlyUserError()
2724  UserError()
2725  g:did_it = 'yes'
2726enddef
2727
2728" This can't be a :def function, because the assert would not be reached.
2729func Test_ignore_silent_error()
2730  let g:did_it = 'no'
2731  call SilentlyError()
2732  call assert_equal('yes', g:did_it)
2733
2734  let g:did_it = 'no'
2735  call SilentlyUserError()
2736  call assert_equal('yes', g:did_it)
2737
2738  unlet g:did_it
2739endfunc
2740
2741def Test_ignore_silent_error_in_filter()
2742  var lines =<< trim END
2743      vim9script
2744      def Filter(winid: number, key: string): bool
2745          if key == 'o'
2746              silent! eval [][0]
2747              return true
2748          endif
2749          return popup_filter_menu(winid, key)
2750      enddef
2751
2752      popup_create('popup', {filter: Filter})
2753      feedkeys("o\r", 'xnt')
2754  END
2755  CheckScriptSuccess(lines)
2756enddef
2757
2758def Fibonacci(n: number): number
2759  if n < 2
2760    return n
2761  else
2762    return Fibonacci(n - 1) + Fibonacci(n - 2)
2763  endif
2764enddef
2765
2766def Test_recursive_call()
2767  Fibonacci(20)->assert_equal(6765)
2768enddef
2769
2770def TreeWalk(dir: string): list<any>
2771  return readdir(dir)->mapnew((_, val) =>
2772            fnamemodify(dir .. '/' .. val, ':p')->isdirectory()
2773               ? {[val]: TreeWalk(dir .. '/' .. val)}
2774               : val
2775             )
2776enddef
2777
2778def Test_closure_in_map()
2779  mkdir('XclosureDir/tdir', 'p')
2780  writefile(['111'], 'XclosureDir/file1')
2781  writefile(['222'], 'XclosureDir/file2')
2782  writefile(['333'], 'XclosureDir/tdir/file3')
2783
2784  TreeWalk('XclosureDir')->assert_equal(['file1', 'file2', {tdir: ['file3']}])
2785
2786  delete('XclosureDir', 'rf')
2787enddef
2788
2789def Test_invalid_function_name()
2790  var lines =<< trim END
2791      vim9script
2792      def s: list<string>
2793  END
2794  CheckScriptFailure(lines, 'E129:')
2795
2796  lines =<< trim END
2797      vim9script
2798      def g: list<string>
2799  END
2800  CheckScriptFailure(lines, 'E129:')
2801
2802  lines =<< trim END
2803      vim9script
2804      def <SID>: list<string>
2805  END
2806  CheckScriptFailure(lines, 'E884:')
2807
2808  lines =<< trim END
2809      vim9script
2810      def F list<string>
2811  END
2812  CheckScriptFailure(lines, 'E488:')
2813enddef
2814
2815def Test_partial_call()
2816  var lines =<< trim END
2817      var Xsetlist: func
2818      Xsetlist = function('setloclist', [0])
2819      Xsetlist([], ' ', {title: 'test'})
2820      getloclist(0, {title: 1})->assert_equal({title: 'test'})
2821
2822      Xsetlist = function('setloclist', [0, [], ' '])
2823      Xsetlist({title: 'test'})
2824      getloclist(0, {title: 1})->assert_equal({title: 'test'})
2825
2826      Xsetlist = function('setqflist')
2827      Xsetlist([], ' ', {title: 'test'})
2828      getqflist({title: 1})->assert_equal({title: 'test'})
2829
2830      Xsetlist = function('setqflist', [[], ' '])
2831      Xsetlist({title: 'test'})
2832      getqflist({title: 1})->assert_equal({title: 'test'})
2833
2834      var Len: func: number = function('len', ['word'])
2835      assert_equal(4, Len())
2836
2837      var RepeatFunc = function('repeat', ['o'])
2838      assert_equal('ooooo', RepeatFunc(5))
2839  END
2840  CheckDefAndScriptSuccess(lines)
2841
2842  lines =<< trim END
2843      vim9script
2844      def Foo(Parser: any)
2845      enddef
2846      var Expr: func(dict<any>): dict<any>
2847      const Call = Foo(Expr)
2848  END
2849  CheckScriptFailure(lines, 'E1235:')
2850enddef
2851
2852def Test_cmd_modifier()
2853  tab echo '0'
2854  CheckDefFailure(['5tab echo 3'], 'E16:')
2855enddef
2856
2857def Test_restore_modifiers()
2858  # check that when compiling a :def function command modifiers are not messed
2859  # up.
2860  var lines =<< trim END
2861      vim9script
2862      set eventignore=
2863      autocmd QuickFixCmdPost * copen
2864      def AutocmdsDisabled()
2865        eval 1 + 2
2866      enddef
2867      func Func()
2868        noautocmd call s:AutocmdsDisabled()
2869        let g:ei_after = &eventignore
2870      endfunc
2871      Func()
2872  END
2873  CheckScriptSuccess(lines)
2874  g:ei_after->assert_equal('')
2875enddef
2876
2877def StackTop()
2878  eval 1 + 2
2879  eval 2 + 3
2880  # call not on fourth line
2881  StackBot()
2882enddef
2883
2884def StackBot()
2885  # throw an error
2886  eval [][0]
2887enddef
2888
2889def Test_callstack_def()
2890  try
2891    StackTop()
2892  catch
2893    v:throwpoint->assert_match('Test_callstack_def\[2\]..StackTop\[4\]..StackBot, line 2')
2894  endtry
2895enddef
2896
2897" Re-using spot for variable used in block
2898def Test_block_scoped_var()
2899  var lines =<< trim END
2900      vim9script
2901      def Func()
2902        var x = ['a', 'b', 'c']
2903        if 1
2904          var y = 'x'
2905          map(x, (_, _) => y)
2906        endif
2907        var z = x
2908        assert_equal(['x', 'x', 'x'], z)
2909      enddef
2910      Func()
2911  END
2912  CheckScriptSuccess(lines)
2913enddef
2914
2915def Test_reset_did_emsg()
2916  var lines =<< trim END
2917      @s = 'blah'
2918      au BufWinLeave * #
2919      def Func()
2920        var winid = popup_create('popup', {})
2921        exe '*s'
2922        popup_close(winid)
2923      enddef
2924      Func()
2925  END
2926  CheckScriptFailure(lines, 'E492:', 8)
2927  delfunc! g:Func
2928enddef
2929
2930def Test_did_emsg_reset()
2931  # executing an autocommand resets did_emsg, this should not result in a
2932  # builtin function considered failing
2933  var lines =<< trim END
2934      vim9script
2935      au BufWinLeave * #
2936      def Func()
2937          popup_menu('', {callback: (a, b) => popup_create('', {})->popup_close()})
2938          eval [][0]
2939      enddef
2940      nno <F3> <cmd>call <sid>Func()<cr>
2941      feedkeys("\<F3>\e", 'xt')
2942  END
2943  writefile(lines, 'XemsgReset')
2944  assert_fails('so XemsgReset', ['E684:', 'E684:'], lines, 2)
2945  delete('XemsgReset')
2946  nunmap <F3>
2947  au! BufWinLeave
2948enddef
2949
2950def Test_abort_with_silent_call()
2951  var lines =<< trim END
2952      vim9script
2953      g:result = 'none'
2954      def Func()
2955        g:result += 3
2956        g:result = 'yes'
2957      enddef
2958      # error is silenced, but function aborts on error
2959      silent! Func()
2960      assert_equal('none', g:result)
2961      unlet g:result
2962  END
2963  CheckScriptSuccess(lines)
2964enddef
2965
2966def Test_continues_with_silent_error()
2967  var lines =<< trim END
2968      vim9script
2969      g:result = 'none'
2970      def Func()
2971        silent!  g:result += 3
2972        g:result = 'yes'
2973      enddef
2974      # error is silenced, function does not abort
2975      Func()
2976      assert_equal('yes', g:result)
2977      unlet g:result
2978  END
2979  CheckScriptSuccess(lines)
2980enddef
2981
2982def Test_abort_even_with_silent()
2983  var lines =<< trim END
2984      vim9script
2985      g:result = 'none'
2986      def Func()
2987        eval {-> ''}() .. '' .. {}['X']
2988        g:result = 'yes'
2989      enddef
2990      silent! Func()
2991      assert_equal('none', g:result)
2992      unlet g:result
2993  END
2994  CheckScriptSuccess(lines)
2995enddef
2996
2997def Test_cmdmod_silent_restored()
2998  var lines =<< trim END
2999      vim9script
3000      def Func()
3001        g:result = 'none'
3002        silent! g:result += 3
3003        g:result = 'none'
3004        g:result += 3
3005      enddef
3006      Func()
3007  END
3008  # can't use CheckScriptFailure, it ignores the :silent!
3009  var fname = 'Xdefsilent'
3010  writefile(lines, fname)
3011  var caught = 'no'
3012  try
3013    exe 'source ' .. fname
3014  catch /E1030:/
3015    caught = 'yes'
3016    assert_match('Func, line 4', v:throwpoint)
3017  endtry
3018  assert_equal('yes', caught)
3019  delete(fname)
3020enddef
3021
3022def Test_cmdmod_silent_nested()
3023  var lines =<< trim END
3024      vim9script
3025      var result = ''
3026
3027      def Error()
3028          result ..= 'Eb'
3029          eval [][0]
3030          result ..= 'Ea'
3031      enddef
3032
3033      def Crash()
3034          result ..= 'Cb'
3035          sil! Error()
3036          result ..= 'Ca'
3037      enddef
3038
3039      Crash()
3040      assert_equal('CbEbEaCa', result)
3041  END
3042  CheckScriptSuccess(lines)
3043enddef
3044
3045def Test_dict_member_with_silent()
3046  var lines =<< trim END
3047      vim9script
3048      g:result = 'none'
3049      var d: dict<any>
3050      def Func()
3051        try
3052          g:result = map([], (_, v) => ({}[v]))->join() .. d['']
3053        catch
3054        endtry
3055      enddef
3056      silent! Func()
3057      assert_equal('0', g:result)
3058      unlet g:result
3059  END
3060  CheckScriptSuccess(lines)
3061enddef
3062
3063def Test_skip_cmds_with_silent()
3064  var lines =<< trim END
3065      vim9script
3066
3067      def Func(b: bool)
3068        Crash()
3069      enddef
3070
3071      def Crash()
3072        sil! :/not found/d _
3073        sil! :/not found/put _
3074      enddef
3075
3076      Func(true)
3077  END
3078  CheckScriptSuccess(lines)
3079enddef
3080
3081def Test_opfunc()
3082  nnoremap <F3> <cmd>set opfunc=Opfunc<cr>g@
3083  def g:Opfunc(_: any): string
3084    setline(1, 'ASDF')
3085    return ''
3086  enddef
3087  new
3088  setline(1, 'asdf')
3089  feedkeys("\<F3>$", 'x')
3090  assert_equal('ASDF', getline(1))
3091
3092  bwipe!
3093  nunmap <F3>
3094enddef
3095
3096" this was crashing on exit
3097def Test_nested_lambda_in_closure()
3098  var lines =<< trim END
3099      vim9script
3100      command WriteDone writefile(['Done'], 'XnestedDone')
3101      def Outer()
3102          def g:Inner()
3103              echo map([1, 2, 3], {_, v -> v + 1})
3104          enddef
3105          g:Inner()
3106      enddef
3107      defcompile
3108      # not reached
3109  END
3110  if !RunVim([], lines, '--clean -c WriteDone -c quit')
3111    return
3112  endif
3113  assert_equal(['Done'], readfile('XnestedDone'))
3114  delete('XnestedDone')
3115enddef
3116
3117def Test_check_func_arg_types()
3118  var lines =<< trim END
3119      vim9script
3120      def F1(x: string): string
3121        return x
3122      enddef
3123
3124      def F2(x: number): number
3125        return x + 1
3126      enddef
3127
3128      def G(g: func): dict<func>
3129        return {f: g}
3130      enddef
3131
3132      def H(d: dict<func>): string
3133        return d.f('a')
3134      enddef
3135  END
3136
3137  CheckScriptSuccess(lines + ['echo H(G(F1))'])
3138  CheckScriptFailure(lines + ['echo H(G(F2))'], 'E1013:')
3139enddef
3140
3141def Test_list_any_type_checked()
3142  var lines =<< trim END
3143      vim9script
3144      def Foo()
3145        --decl--
3146        Bar(l)
3147      enddef
3148      def Bar(ll: list<dict<any>>)
3149      enddef
3150      Foo()
3151  END
3152  lines[2] = 'var l: list<any>'
3153  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected list<dict<any>> but got list<any>', 2)
3154
3155  lines[2] = 'var l: list<any> = []'
3156  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected list<dict<any>> but got list<any>', 2)
3157
3158  lines[2] = 'var l: list<any> = [11]'
3159  CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected list<dict<any>> but got list<number>', 2)
3160enddef
3161
3162def Test_compile_error()
3163  var lines =<< trim END
3164    def g:Broken()
3165      echo 'a' + {}
3166    enddef
3167    call g:Broken()
3168  END
3169  # First call: compilation error
3170  CheckScriptFailure(lines, 'E1051: Wrong argument type for +')
3171
3172  # Second call won't try compiling again
3173  assert_fails('call g:Broken()', 'E1091: Function is not compiled: Broken')
3174  delfunc g:Broken
3175
3176  # No error when compiling with :silent!
3177  lines =<< trim END
3178    def g:Broken()
3179      echo 'a' + []
3180    enddef
3181    silent! defcompile
3182  END
3183  CheckScriptSuccess(lines)
3184
3185  # Calling the function won't try compiling again
3186  assert_fails('call g:Broken()', 'E1091: Function is not compiled: Broken')
3187  delfunc g:Broken
3188enddef
3189
3190def Test_ignored_argument()
3191  var lines =<< trim END
3192      vim9script
3193      def Ignore(_, _): string
3194        return 'yes'
3195      enddef
3196      assert_equal('yes', Ignore(1, 2))
3197
3198      func Ok(_)
3199        return a:_
3200      endfunc
3201      assert_equal('ok', Ok('ok'))
3202
3203      func Oktoo()
3204        let _ = 'too'
3205        return _
3206      endfunc
3207      assert_equal('too', Oktoo())
3208
3209      assert_equal([[1], [2], [3]], range(3)->mapnew((_, v) => [v]->map((_, w) => w + 1)))
3210  END
3211  CheckScriptSuccess(lines)
3212
3213  lines =<< trim END
3214      def Ignore(_: string): string
3215        return _
3216      enddef
3217      defcompile
3218  END
3219  CheckScriptFailure(lines, 'E1181:', 1)
3220
3221  lines =<< trim END
3222      var _ = 1
3223  END
3224  CheckDefAndScriptFailure(lines, 'E1181:', 1)
3225
3226  lines =<< trim END
3227      var x = _
3228  END
3229  CheckDefAndScriptFailure(lines, 'E1181:', 1)
3230enddef
3231
3232def Test_too_many_arguments()
3233  var lines =<< trim END
3234    echo [0, 1, 2]->map(() => 123)
3235  END
3236  CheckDefExecAndScriptFailure(lines, 'E1106: 2 arguments too many', 1)
3237
3238  lines =<< trim END
3239    echo [0, 1, 2]->map((_) => 123)
3240  END
3241  CheckDefExecAndScriptFailure(lines, 'E1106: One argument too many', 1)
3242enddef
3243
3244def Test_closing_brace_at_start_of_line()
3245  var lines =<< trim END
3246      def Func()
3247      enddef
3248      Func(
3249      )
3250  END
3251  call CheckDefAndScriptSuccess(lines)
3252enddef
3253
3254func CreateMydict()
3255  let g:mydict = {}
3256  func g:mydict.afunc()
3257    let g:result = self.key
3258  endfunc
3259endfunc
3260
3261def Test_numbered_function_reference()
3262  CreateMydict()
3263  var output = execute('legacy func g:mydict.afunc')
3264  var funcName = 'g:' .. substitute(output, '.*function \(\d\+\).*', '\1', '')
3265  execute 'function(' .. funcName .. ', [], {key: 42})()'
3266  # check that the function still exists
3267  assert_equal(output, execute('legacy func g:mydict.afunc'))
3268  unlet g:mydict
3269enddef
3270
3271if has('python3')
3272  def Test_python3_heredoc()
3273    py3 << trim EOF
3274      import vim
3275      vim.vars['didit'] = 'yes'
3276    EOF
3277    assert_equal('yes', g:didit)
3278
3279    python3 << trim EOF
3280      import vim
3281      vim.vars['didit'] = 'again'
3282    EOF
3283    assert_equal('again', g:didit)
3284  enddef
3285endif
3286
3287" This messes up syntax highlight, keep near the end.
3288if has('lua')
3289  def Test_lua_heredoc()
3290    g:d = {}
3291    lua << trim EOF
3292        x = vim.eval('g:d')
3293        x['key'] = 'val'
3294    EOF
3295    assert_equal('val', g:d.key)
3296  enddef
3297endif
3298
3299
3300" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
3301