1" Test various aspects of the Vim script language.
2" Most of this was formerly in test49.vim (developed by Servatius Brandt
3" <[email protected]>)
4
5source check.vim
6source shared.vim
7source script_util.vim
8
9"-------------------------------------------------------------------------------
10" Test environment							    {{{1
11"-------------------------------------------------------------------------------
12
13" Append a message to the "messages" file
14func Xout(text)
15    split messages
16    $put =a:text
17    wq
18endfunc
19
20com! -nargs=1	     Xout     call Xout(<args>)
21
22" Create a new instance of Vim and run the commands in 'test' and then 'verify'
23" The commands in 'test' are expected to store the test results in the Xtest.out
24" file. If the test passes successfully, then Xtest.out should be empty.
25func RunInNewVim(test, verify)
26  let init =<< trim END
27    set cpo-=C            " support line-continuation in sourced script
28    source script_util.vim
29    XpathINIT
30    XloopINIT
31  END
32  let cleanup =<< trim END
33    call writefile(v:errors, 'Xtest.out')
34    qall
35  END
36  call writefile(init, 'Xtest.vim')
37  call writefile(a:test, 'Xtest.vim', 'a')
38  call writefile(a:verify, 'Xverify.vim')
39  call writefile(cleanup, 'Xverify.vim', 'a')
40  call RunVim([], [], "-S Xtest.vim -S Xverify.vim")
41  call assert_equal([], readfile('Xtest.out'))
42  call delete('Xtest.out')
43  call delete('Xtest.vim')
44  call delete('Xverify.vim')
45endfunc
46
47"-------------------------------------------------------------------------------
48" Test 1:   :endwhile in function					    {{{1
49"
50"	    Detect if a broken loop is (incorrectly) reactivated by the
51"	    :endwhile.  Use a :return to prevent an endless loop, and make
52"	    this test first to get a meaningful result on an error before other
53"	    tests will hang.
54"-------------------------------------------------------------------------------
55
56func T1_F()
57    Xpath 'a'
58    let first = 1
59    while 1
60	Xpath 'b'
61	if first
62	    Xpath 'c'
63	    let first = 0
64	    break
65	else
66	    Xpath 'd'
67	    return
68	endif
69    endwhile
70endfunc
71
72func T1_G()
73    Xpath 'h'
74    let first = 1
75    while 1
76	Xpath 'i'
77	if first
78	    Xpath 'j'
79	    let first = 0
80	    break
81	else
82	    Xpath 'k'
83	    return
84	endif
85	if 1	" unmatched :if
86    endwhile
87endfunc
88
89func Test_endwhile_function()
90  XpathINIT
91  call T1_F()
92  Xpath 'F'
93
94  try
95    call T1_G()
96  catch
97    " Catch missing :endif
98    call assert_true(v:exception =~ 'E171:')
99    Xpath 'x'
100  endtry
101  Xpath 'G'
102
103  call assert_equal('abcFhijxG', g:Xpath)
104endfunc
105
106"-------------------------------------------------------------------------------
107" Test 2:   :endwhile in script						    {{{1
108"
109"	    Detect if a broken loop is (incorrectly) reactivated by the
110"	    :endwhile.  Use a :finish to prevent an endless loop, and place
111"	    this test before others that might hang to get a meaningful result
112"	    on an error.
113"
114"	    This test executes the bodies of the functions T1_F and T1_G from
115"	    the previous test as script files (:return replaced by :finish).
116"-------------------------------------------------------------------------------
117
118func Test_endwhile_script()
119  XpathINIT
120  ExecAsScript T1_F
121  Xpath 'F'
122  call DeleteTheScript()
123
124  try
125    ExecAsScript T1_G
126  catch
127    " Catch missing :endif
128    call assert_true(v:exception =~ 'E171:')
129    Xpath 'x'
130  endtry
131  Xpath 'G'
132  call DeleteTheScript()
133
134  call assert_equal('abcFhijxG', g:Xpath)
135endfunc
136
137"-------------------------------------------------------------------------------
138" Test 3:   :if, :elseif, :while, :continue, :break			    {{{1
139"-------------------------------------------------------------------------------
140
141func Test_if_while()
142    XpathINIT
143    if 1
144	Xpath 'a'
145	let loops = 3
146	while loops > -1	    " main loop: loops == 3, 2, 1 (which breaks)
147	    if loops <= 0
148		let break_err = 1
149		let loops = -1
150	    else
151		Xpath 'b' . loops
152	    endif
153	    if (loops == 2)
154		while loops == 2 " dummy loop
155		    Xpath 'c' . loops
156		    let loops = loops - 1
157		    continue    " stop dummy loop
158		    Xpath 'd' . loops
159		endwhile
160		continue	    " continue main loop
161		Xpath 'e' . loops
162	    elseif (loops == 1)
163		let p = 1
164		while p	    " dummy loop
165		    Xpath 'f' . loops
166		    let p = 0
167		    break	    " break dummy loop
168		    Xpath 'g' . loops
169		endwhile
170		Xpath 'h' . loops
171		unlet p
172		break	    " break main loop
173		Xpath 'i' . loops
174	    endif
175	    if (loops > 0)
176		Xpath 'j' . loops
177	    endif
178	    while loops == 3    " dummy loop
179		let loops = loops - 1
180	    endwhile	    " end dummy loop
181	endwhile		    " end main loop
182	Xpath 'k'
183    else
184	Xpath 'l'
185    endif
186    Xpath 'm'
187    if exists("break_err")
188	Xpath 'm'
189	unlet break_err
190    endif
191
192    unlet loops
193
194    call assert_equal('ab3j3b2c2b1f1h1km', g:Xpath)
195endfunc
196
197"-------------------------------------------------------------------------------
198" Test 4:   :return							    {{{1
199"-------------------------------------------------------------------------------
200
201func T4_F()
202    if 1
203	Xpath 'a'
204	let loops = 3
205	while loops > 0				"    3:  2:     1:
206	    Xpath 'b' . loops
207	    if (loops == 2)
208		Xpath 'c' . loops
209		return
210		Xpath 'd' . loops
211	    endif
212	    Xpath 'e' . loops
213	    let loops = loops - 1
214	endwhile
215	Xpath 'f'
216    else
217	Xpath 'g'
218    endif
219endfunc
220
221func Test_return()
222    XpathINIT
223    call T4_F()
224    Xpath '4'
225
226    call assert_equal('ab3e3b2c24', g:Xpath)
227endfunc
228
229
230"-------------------------------------------------------------------------------
231" Test 5:   :finish							    {{{1
232"
233"	    This test executes the body of the function T4_F from the previous
234"	    test as a script file (:return replaced by :finish).
235"-------------------------------------------------------------------------------
236
237func Test_finish()
238    XpathINIT
239    ExecAsScript T4_F
240    Xpath '5'
241    call DeleteTheScript()
242
243    call assert_equal('ab3e3b2c25', g:Xpath)
244endfunc
245
246
247
248"-------------------------------------------------------------------------------
249" Test 6:   Defining functions in :while loops				    {{{1
250"
251"	     Functions can be defined inside other functions.  An inner function
252"	     gets defined when the outer function is executed.  Functions may
253"	     also be defined inside while loops.  Expressions in braces for
254"	     defining the function name are allowed.
255"
256"	     The functions are defined when sourcing the script, only the
257"	     resulting path is checked in the test function.
258"-------------------------------------------------------------------------------
259
260XpathINIT
261
262" The command CALL collects the argument of all its invocations in "calls"
263" when used from a function (that is, when the global variable "calls" needs
264" the "g:" prefix).  This is to check that the function code is skipped when
265" the function is defined.  For inner functions, do so only if the outer
266" function is not being executed.
267"
268let calls = ""
269com! -nargs=1 CALL
270	    \ if !exists("calls") && !exists("outer") |
271	    \ let g:calls = g:calls . <args> |
272	    \ endif
273
274let i = 0
275while i < 3
276    let i = i + 1
277    if i == 1
278	Xpath 'a'
279	function! F1(arg)
280	    CALL a:arg
281	    let outer = 1
282
283	    let j = 0
284	    while j < 1
285		Xpath 'b'
286		let j = j + 1
287		function! G1(arg)
288		    CALL a:arg
289		endfunction
290		Xpath 'c'
291	    endwhile
292	endfunction
293	Xpath 'd'
294
295	continue
296    endif
297
298    Xpath 'e' . i
299    function! F{i}(i, arg)
300	CALL a:arg
301	let outer = 1
302
303	if a:i == 3
304	    Xpath 'f'
305	endif
306	let k = 0
307	while k < 3
308	    Xpath 'g' . k
309	    let k = k + 1
310	    function! G{a:i}{k}(arg)
311		CALL a:arg
312	    endfunction
313	    Xpath 'h' . k
314	endwhile
315    endfunction
316    Xpath 'i'
317
318endwhile
319
320if exists("*G1")
321    Xpath 'j'
322endif
323if exists("*F1")
324    call F1("F1")
325    if exists("*G1")
326       call G1("G1")
327    endif
328endif
329
330if exists("G21") || exists("G22") || exists("G23")
331    Xpath 'k'
332endif
333if exists("*F2")
334    call F2(2, "F2")
335    if exists("*G21")
336       call G21("G21")
337    endif
338    if exists("*G22")
339       call G22("G22")
340    endif
341    if exists("*G23")
342       call G23("G23")
343    endif
344endif
345
346if exists("G31") || exists("G32") || exists("G33")
347    Xpath 'l'
348endif
349if exists("*F3")
350    call F3(3, "F3")
351    if exists("*G31")
352       call G31("G31")
353    endif
354    if exists("*G32")
355       call G32("G32")
356    endif
357    if exists("*G33")
358       call G33("G33")
359    endif
360endif
361
362Xpath 'm'
363
364let g:test6_result = g:Xpath
365let g:test6_calls = calls
366
367unlet calls
368delfunction F1
369delfunction G1
370delfunction F2
371delfunction G21
372delfunction G22
373delfunction G23
374delfunction G31
375delfunction G32
376delfunction G33
377
378func Test_defining_functions()
379    call assert_equal('ade2ie3ibcg0h1g1h2g2h3fg0h1g1h2g2h3m', g:test6_result)
380    call assert_equal('F1G1F2G21G22G23F3G31G32G33', g:test6_calls)
381endfunc
382
383"-------------------------------------------------------------------------------
384" Test 7:   Continuing on errors outside functions			    {{{1
385"
386"	    On an error outside a function, the script processing continues
387"	    at the line following the outermost :endif or :endwhile.  When not
388"	    inside an :if or :while, the script processing continues at the next
389"	    line.
390"-------------------------------------------------------------------------------
391
392XpathINIT
393
394if 1
395    Xpath 'a'
396    while 1
397	Xpath 'b'
398	asdf
399	Xpath 'c'
400	break
401    endwhile | Xpath 'd'
402    Xpath 'e'
403endif | Xpath 'f'
404Xpath 'g'
405
406while 1
407    Xpath 'h'
408    if 1
409	Xpath 'i'
410	asdf
411	Xpath 'j'
412    endif | Xpath 'k'
413    Xpath 'l'
414    break
415endwhile | Xpath 'm'
416Xpath 'n'
417
418asdf
419Xpath 'o'
420
421asdf | Xpath 'p'
422Xpath 'q'
423
424let g:test7_result = g:Xpath
425
426func Test_error_in_script()
427    call assert_equal('abghinoq', g:test7_result)
428endfunc
429
430"-------------------------------------------------------------------------------
431" Test 8:   Aborting and continuing on errors inside functions		    {{{1
432"
433"	    On an error inside a function without the "abort" attribute, the
434"	    script processing continues at the next line (unless the error was
435"	    in a :return command).  On an error inside a function with the
436"	    "abort" attribute, the function is aborted and the script processing
437"	    continues after the function call; the value -1 is returned then.
438"-------------------------------------------------------------------------------
439
440XpathINIT
441
442func T8_F()
443    if 1
444	Xpath 'a'
445	while 1
446	    Xpath 'b'
447	    asdf
448	    Xpath 'c'
449	    asdf | Xpath 'd'
450	    Xpath 'e'
451	    break
452	endwhile
453	Xpath 'f'
454    endif | Xpath 'g'
455    Xpath 'h'
456
457    while 1
458	Xpath 'i'
459	if 1
460	    Xpath 'j'
461	    asdf
462	    Xpath 'k'
463	    asdf | Xpath 'l'
464	    Xpath 'm'
465	endif
466	Xpath 'n'
467	break
468    endwhile | Xpath 'o'
469    Xpath 'p'
470
471    return novar		" returns (default return value 0)
472    Xpath 'q'
473    return 1			" not reached
474endfunc
475
476func T8_G() abort
477    if 1
478	Xpath 'r'
479	while 1
480	    Xpath 's'
481	    asdf		" returns -1
482	    Xpath 't'
483	    break
484	endwhile
485	Xpath 'v'
486    endif | Xpath 'w'
487    Xpath 'x'
488
489    return -4			" not reached
490endfunc
491
492func T8_H() abort
493    while 1
494	Xpath 'A'
495	if 1
496	    Xpath 'B'
497	    asdf		" returns -1
498	    Xpath 'C'
499	endif
500	Xpath 'D'
501	break
502    endwhile | Xpath 'E'
503    Xpath 'F'
504
505    return -4			" not reached
506endfunc
507
508" Aborted functions (T8_G and T8_H) return -1.
509let g:test8_sum = (T8_F() + 1) - 4 * T8_G() - 8 * T8_H()
510Xpath 'X'
511let g:test8_result = g:Xpath
512
513func Test_error_in_function()
514    call assert_equal(13, g:test8_sum)
515    call assert_equal('abcefghijkmnoprsABX', g:test8_result)
516
517    delfunction T8_F
518    delfunction T8_G
519    delfunction T8_H
520endfunc
521
522
523"-------------------------------------------------------------------------------
524" Test 9:   Continuing after aborted functions				    {{{1
525"
526"	    When a function with the "abort" attribute is aborted due to an
527"	    error, the next function back in the call hierarchy without an
528"	    "abort" attribute continues; the value -1 is returned then.
529"-------------------------------------------------------------------------------
530
531XpathINIT
532
533func F() abort
534    Xpath 'a'
535    let result = G()	" not aborted
536    Xpath 'b'
537    if result != 2
538	Xpath 'c'
539    endif
540    return 1
541endfunc
542
543func G()		" no abort attribute
544    Xpath 'd'
545    if H() != -1	" aborted
546	Xpath 'e'
547    endif
548    Xpath 'f'
549    return 2
550endfunc
551
552func H() abort
553    Xpath 'g'
554    call I()		" aborted
555    Xpath 'h'
556    return 4
557endfunc
558
559func I() abort
560    Xpath 'i'
561    asdf		" error
562    Xpath 'j'
563    return 8
564endfunc
565
566if F() != 1
567    Xpath 'k'
568endif
569
570let g:test9_result = g:Xpath
571
572delfunction F
573delfunction G
574delfunction H
575delfunction I
576
577func Test_func_abort()
578    call assert_equal('adgifb', g:test9_result)
579endfunc
580
581
582"-------------------------------------------------------------------------------
583" Test 10:  :if, :elseif, :while argument parsing			    {{{1
584"
585"	    A '"' or '|' in an argument expression must not be mixed up with
586"	    a comment or a next command after a bar.  Parsing errors should
587"	    be recognized.
588"-------------------------------------------------------------------------------
589
590XpathINIT
591
592func MSG(enr, emsg)
593    let english = v:lang == "C" || v:lang =~ '^[Ee]n'
594    if a:enr == ""
595	Xout "TODO: Add message number for:" a:emsg
596	let v:errmsg = ":" . v:errmsg
597    endif
598    let match = 1
599    if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
600	let match = 0
601	if v:errmsg == ""
602	    Xout "Message missing."
603	else
604	    let v:errmsg = v:errmsg->escape('"')
605	    Xout "Unexpected message:" v:errmsg
606	endif
607    endif
608    return match
609endfunc
610
611if 1 || strlen("\"") | Xpath 'a'
612    Xpath 'b'
613endif
614Xpath 'c'
615
616if 0
617elseif 1 || strlen("\"") | Xpath 'd'
618    Xpath 'e'
619endif
620Xpath 'f'
621
622while 1 || strlen("\"") | Xpath 'g'
623    Xpath 'h'
624    break
625endwhile
626Xpath 'i'
627
628let v:errmsg = ""
629if 1 ||| strlen("\"") | Xpath 'j'
630    Xpath 'k'
631endif
632Xpath 'l'
633if !MSG('E15', "Invalid expression")
634    Xpath 'm'
635endif
636
637let v:errmsg = ""
638if 0
639elseif 1 ||| strlen("\"") | Xpath 'n'
640    Xpath 'o'
641endif
642Xpath 'p'
643if !MSG('E15', "Invalid expression")
644    Xpath 'q'
645endif
646
647let v:errmsg = ""
648while 1 ||| strlen("\"") | Xpath 'r'
649    Xpath 's'
650    break
651endwhile
652Xpath 't'
653if !MSG('E15', "Invalid expression")
654    Xpath 'u'
655endif
656
657let g:test10_result = g:Xpath
658delfunction MSG
659
660func Test_expr_parsing()
661    call assert_equal('abcdefghilpt', g:test10_result)
662endfunc
663
664
665"-------------------------------------------------------------------------------
666" Test 11:  :if, :elseif, :while argument evaluation after abort	    {{{1
667"
668"	    When code is skipped over due to an error, the boolean argument to
669"	    an :if, :elseif, or :while must not be evaluated.
670"-------------------------------------------------------------------------------
671
672XpathINIT
673
674let calls = 0
675
676func P(num)
677    let g:calls = g:calls + a:num   " side effect on call
678    return 0
679endfunc
680
681if 1
682    Xpath 'a'
683    asdf		" error
684    Xpath 'b'
685    if P(1)		" should not be called
686	Xpath 'c'
687    elseif !P(2)	" should not be called
688	Xpath 'd'
689    else
690	Xpath 'e'
691    endif
692    Xpath 'f'
693    while P(4)		" should not be called
694	Xpath 'g'
695    endwhile
696    Xpath 'h'
697endif
698Xpath 'x'
699
700let g:test11_calls = calls
701let g:test11_result = g:Xpath
702
703unlet calls
704delfunction P
705
706func Test_arg_abort()
707    call assert_equal(0, g:test11_calls)
708    call assert_equal('ax', g:test11_result)
709endfunc
710
711
712"-------------------------------------------------------------------------------
713" Test 12:  Expressions in braces in skipped code			    {{{1
714"
715"	    In code skipped over due to an error or inactive conditional,
716"	    an expression in braces as part of a variable or function name
717"	    should not be evaluated.
718"-------------------------------------------------------------------------------
719
720XpathINIT
721
722function! NULL()
723    Xpath 'a'
724    return 0
725endfunction
726
727function! ZERO()
728    Xpath 'b'
729    return 0
730endfunction
731
732function! F0()
733    Xpath 'c'
734endfunction
735
736function! F1(arg)
737    Xpath 'e'
738endfunction
739
740let V0 = 1
741
742Xpath 'f'
743echo 0 ? F{NULL() + V{ZERO()}}() : 1
744
745Xpath 'g'
746if 0
747    Xpath 'h'
748    call F{NULL() + V{ZERO()}}()
749endif
750
751Xpath 'i'
752if 1
753    asdf		" error
754    Xpath 'j'
755    call F1(F{NULL() + V{ZERO()}}())
756endif
757
758Xpath 'k'
759if 1
760    asdf		" error
761    Xpath 'l'
762    call F{NULL() + V{ZERO()}}()
763endif
764
765let g:test12_result = g:Xpath
766
767func Test_braces_skipped()
768    call assert_equal('fgik', g:test12_result)
769endfunc
770
771
772"-------------------------------------------------------------------------------
773" Test 13:  Failure in argument evaluation for :while			    {{{1
774"
775"	    A failure in the expression evaluation for the condition of a :while
776"	    causes the whole :while loop until the matching :endwhile being
777"	    ignored.  Continuation is at the next following line.
778"-------------------------------------------------------------------------------
779
780XpathINIT
781
782Xpath 'a'
783while asdf
784    Xpath 'b'
785    while 1
786	Xpath 'c'
787	break
788    endwhile
789    Xpath 'd'
790    break
791endwhile
792Xpath 'e'
793
794while asdf | Xpath 'f' | endwhile | Xpath 'g'
795Xpath 'h'
796let g:test13_result = g:Xpath
797
798func Test_while_fail()
799    call assert_equal('aeh', g:test13_result)
800endfunc
801
802
803"-------------------------------------------------------------------------------
804" Test 14:  Failure in argument evaluation for :if			    {{{1
805"
806"	    A failure in the expression evaluation for the condition of an :if
807"	    does not cause the corresponding :else or :endif being matched to
808"	    a previous :if/:elseif.  Neither of both branches of the failed :if
809"	    are executed.
810"-------------------------------------------------------------------------------
811
812XpathINIT
813
814function! F()
815    Xpath 'a'
816    let x = 0
817    if x		" false
818	Xpath 'b'
819    elseif !x		" always true
820	Xpath 'c'
821	let x = 1
822	if g:boolvar	" possibly undefined
823	    Xpath 'd'
824	else
825	    Xpath 'e'
826	endif
827	Xpath 'f'
828    elseif x		" never executed
829	Xpath 'g'
830    endif
831    Xpath 'h'
832endfunction
833
834let boolvar = 1
835call F()
836Xpath '-'
837
838unlet boolvar
839call F()
840let g:test14_result = g:Xpath
841
842delfunction F
843
844func Test_if_fail()
845    call assert_equal('acdfh-acfh', g:test14_result)
846endfunc
847
848
849"-------------------------------------------------------------------------------
850" Test 15:  Failure in argument evaluation for :if (bar)		    {{{1
851"
852"	    Like previous test, except that the failing :if ... | ... | :endif
853"	    is in a single line.
854"-------------------------------------------------------------------------------
855
856XpathINIT
857
858function! F()
859    Xpath 'a'
860    let x = 0
861    if x		" false
862	Xpath 'b'
863    elseif !x		" always true
864	Xpath 'c'
865	let x = 1
866	if g:boolvar | Xpath 'd' | else | Xpath 'e' | endif
867	Xpath 'f'
868    elseif x		" never executed
869	Xpath 'g'
870    endif
871    Xpath 'h'
872endfunction
873
874let boolvar = 1
875call F()
876Xpath '-'
877
878unlet boolvar
879call F()
880let g:test15_result = g:Xpath
881
882delfunction F
883
884func Test_if_bar_fail()
885    call assert_equal('acdfh-acfh', g:test15_result)
886endfunc
887
888"-------------------------------------------------------------------------------
889" Test 16:  Double :else or :elseif after :else				    {{{1
890"
891"	    Multiple :elses or an :elseif after an :else are forbidden.
892"-------------------------------------------------------------------------------
893
894func T16_F() abort
895  if 0
896    Xpath 'a'
897  else
898    Xpath 'b'
899  else		" aborts function
900    Xpath 'c'
901  endif
902  Xpath 'd'
903endfunc
904
905func T16_G() abort
906  if 0
907    Xpath 'a'
908  else
909    Xpath 'b'
910  elseif 1		" aborts function
911    Xpath 'c'
912  else
913    Xpath 'd'
914  endif
915  Xpath 'e'
916endfunc
917
918func T16_H() abort
919  if 0
920    Xpath 'a'
921  elseif 0
922    Xpath 'b'
923  else
924    Xpath 'c'
925  else		" aborts function
926    Xpath 'd'
927  endif
928  Xpath 'e'
929endfunc
930
931func T16_I() abort
932  if 0
933    Xpath 'a'
934  elseif 0
935    Xpath 'b'
936  else
937    Xpath 'c'
938  elseif 1		" aborts function
939    Xpath 'd'
940  else
941    Xpath 'e'
942  endif
943  Xpath 'f'
944endfunc
945
946func Test_Multi_Else()
947  XpathINIT
948  try
949    call T16_F()
950  catch /E583:/
951    Xpath 'e'
952  endtry
953  call assert_equal('be', g:Xpath)
954
955  XpathINIT
956  try
957    call T16_G()
958  catch /E584:/
959    Xpath 'f'
960  endtry
961  call assert_equal('bf', g:Xpath)
962
963  XpathINIT
964  try
965    call T16_H()
966  catch /E583:/
967    Xpath 'f'
968  endtry
969  call assert_equal('cf', g:Xpath)
970
971  XpathINIT
972  try
973    call T16_I()
974  catch /E584:/
975    Xpath 'g'
976  endtry
977  call assert_equal('cg', g:Xpath)
978endfunc
979
980"-------------------------------------------------------------------------------
981" Test 17:  Nesting of unmatched :if or :endif inside a :while		    {{{1
982"
983"	    The :while/:endwhile takes precedence in nesting over an unclosed
984"	    :if or an unopened :endif.
985"-------------------------------------------------------------------------------
986
987" While loops inside a function are continued on error.
988func T17_F()
989  let loops = 3
990  while loops > 0
991    let loops -= 1
992    Xpath 'a' . loops
993    if (loops == 1)
994      Xpath 'b' . loops
995      continue
996    elseif (loops == 0)
997      Xpath 'c' . loops
998      break
999    elseif 1
1000      Xpath 'd' . loops
1001    " endif missing!
1002  endwhile	" :endwhile after :if 1
1003  Xpath 'e'
1004endfunc
1005
1006func T17_G()
1007  let loops = 2
1008  while loops > 0
1009    let loops -= 1
1010    Xpath 'a' . loops
1011    if 0
1012      Xpath 'b' . loops
1013    " endif missing
1014  endwhile	" :endwhile after :if 0
1015endfunc
1016
1017func T17_H()
1018  let loops = 2
1019  while loops > 0
1020    let loops -= 1
1021    Xpath 'a' . loops
1022    " if missing!
1023    endif	" :endif without :if in while
1024    Xpath 'b' . loops
1025  endwhile
1026endfunc
1027
1028" Error continuation outside a function is at the outermost :endwhile or :endif.
1029XpathINIT
1030let v:errmsg = ''
1031let loops = 2
1032while loops > 0
1033    let loops -= 1
1034    Xpath 'a' . loops
1035    if 0
1036	Xpath 'b' . loops
1037    " endif missing! Following :endwhile fails.
1038endwhile | Xpath 'c'
1039Xpath 'd'
1040call assert_match('E171:', v:errmsg)
1041call assert_equal('a1d', g:Xpath)
1042
1043func Test_unmatched_if_in_while()
1044  XpathINIT
1045  call assert_fails('call T17_F()', 'E171:')
1046  call assert_equal('a2d2a1b1a0c0e', g:Xpath)
1047
1048  XpathINIT
1049  call assert_fails('call T17_G()', 'E171:')
1050  call assert_equal('a1a0', g:Xpath)
1051
1052  XpathINIT
1053  call assert_fails('call T17_H()', 'E580:')
1054  call assert_equal('a1b1a0b0', g:Xpath)
1055endfunc
1056
1057"-------------------------------------------------------------------------------
1058" Test 18:  Interrupt (Ctrl-C pressed)					    {{{1
1059"
1060"	    On an interrupt, the script processing is terminated immediately.
1061"-------------------------------------------------------------------------------
1062
1063func Test_interrupt_while_if()
1064  let test =<< trim [CODE]
1065    try
1066      if 1
1067        Xpath 'a'
1068        while 1
1069          Xpath 'b'
1070          if 1
1071            Xpath 'c'
1072            call interrupt()
1073            call assert_report('should not get here')
1074            break
1075            finish
1076          endif | call assert_report('should not get here')
1077          call assert_report('should not get here')
1078        endwhile | call assert_report('should not get here')
1079        call assert_report('should not get here')
1080      endif | call assert_report('should not get here')
1081      call assert_report('should not get here')
1082    catch /^Vim:Interrupt$/
1083      Xpath 'd'
1084    endtry | Xpath 'e'
1085    Xpath 'f'
1086  [CODE]
1087  let verify =<< trim [CODE]
1088    call assert_equal('abcdef', g:Xpath)
1089  [CODE]
1090  call RunInNewVim(test, verify)
1091endfunc
1092
1093func Test_interrupt_try()
1094  let test =<< trim [CODE]
1095    try
1096      try
1097        Xpath 'a'
1098        call interrupt()
1099        call assert_report('should not get here')
1100      endtry | call assert_report('should not get here')
1101      call assert_report('should not get here')
1102    catch /^Vim:Interrupt$/
1103      Xpath 'b'
1104    endtry | Xpath 'c'
1105    Xpath 'd'
1106  [CODE]
1107  let verify =<< trim [CODE]
1108    call assert_equal('abcd', g:Xpath)
1109  [CODE]
1110  call RunInNewVim(test, verify)
1111endfunc
1112
1113func Test_interrupt_func_while_if()
1114  let test =<< trim [CODE]
1115    func F()
1116      if 1
1117        Xpath 'a'
1118        while 1
1119          Xpath 'b'
1120          if 1
1121            Xpath 'c'
1122            call interrupt()
1123            call assert_report('should not get here')
1124            break
1125            return
1126          endif | call assert_report('should not get here')
1127          call assert_report('should not get here')
1128        endwhile | call assert_report('should not get here')
1129        call assert_report('should not get here')
1130      endif | call assert_report('should not get here')
1131      call assert_report('should not get here')
1132    endfunc
1133
1134    Xpath 'd'
1135    try
1136      call F() | call assert_report('should not get here')
1137    catch /^Vim:Interrupt$/
1138      Xpath 'e'
1139    endtry | Xpath 'f'
1140    Xpath 'g'
1141  [CODE]
1142  let verify =<< trim [CODE]
1143    call assert_equal('dabcefg', g:Xpath)
1144  [CODE]
1145  call RunInNewVim(test, verify)
1146endfunc
1147
1148func Test_interrupt_func_try()
1149  let test =<< trim [CODE]
1150    func G()
1151      try
1152        Xpath 'a'
1153        call interrupt()
1154        call assert_report('should not get here')
1155      endtry | call assert_report('should not get here')
1156      call assert_report('should not get here')
1157    endfunc
1158
1159    Xpath 'b'
1160    try
1161      call G() | call assert_report('should not get here')
1162    catch /^Vim:Interrupt$/
1163      Xpath 'c'
1164    endtry | Xpath 'd'
1165    Xpath 'e'
1166  [CODE]
1167  let verify =<< trim [CODE]
1168    call assert_equal('bacde', g:Xpath)
1169  [CODE]
1170  call RunInNewVim(test, verify)
1171endfunc
1172
1173"-------------------------------------------------------------------------------
1174" Test 19:  Aborting on errors inside :try/:endtry			    {{{1
1175"
1176"	    An error in a command dynamically enclosed in a :try/:endtry region
1177"	    aborts script processing immediately.  It does not matter whether
1178"	    the failing command is outside or inside a function and whether a
1179"	    function has an "abort" attribute.
1180"-------------------------------------------------------------------------------
1181
1182func Test_try_error_abort_1()
1183  let test =<< trim [CODE]
1184    func F() abort
1185      Xpath 'a'
1186      asdf
1187      call assert_report('should not get here')
1188    endfunc
1189
1190    try
1191      Xpath 'b'
1192      call F()
1193      call assert_report('should not get here')
1194    endtry | call assert_report('should not get here')
1195    call assert_report('should not get here')
1196  [CODE]
1197  let verify =<< trim [CODE]
1198    call assert_equal('ba', g:Xpath)
1199  [CODE]
1200  call RunInNewVim(test, verify)
1201endfunc
1202
1203func Test_try_error_abort_2()
1204  let test =<< trim [CODE]
1205    func G()
1206      Xpath 'a'
1207      asdf
1208      call assert_report('should not get here')
1209    endfunc
1210
1211    try
1212      Xpath 'b'
1213      call G()
1214      call assert_report('should not get here')
1215    endtry | call assert_report('should not get here')
1216    call assert_report('should not get here')
1217  [CODE]
1218  let verify =<< trim [CODE]
1219    call assert_equal('ba', g:Xpath)
1220  [CODE]
1221  call RunInNewVim(test, verify)
1222endfunc
1223
1224func Test_try_error_abort_3()
1225  let test =<< trim [CODE]
1226    try
1227      Xpath 'a'
1228      asdf
1229      call assert_report('should not get here')
1230    endtry | call assert_report('should not get here')
1231    call assert_report('should not get here')
1232  [CODE]
1233  let verify =<< trim [CODE]
1234    call assert_equal('a', g:Xpath)
1235  [CODE]
1236  call RunInNewVim(test, verify)
1237endfunc
1238
1239func Test_try_error_abort_4()
1240  let test =<< trim [CODE]
1241    if 1
1242      try
1243        Xpath 'a'
1244        asdf
1245        call assert_report('should not get here')
1246      endtry | call assert_report('should not get here')
1247    endif | call assert_report('should not get here')
1248    call assert_report('should not get here')
1249  [CODE]
1250  let verify =<< trim [CODE]
1251    call assert_equal('a', g:Xpath)
1252  [CODE]
1253  call RunInNewVim(test, verify)
1254endfunc
1255
1256func Test_try_error_abort_5()
1257  let test =<< trim [CODE]
1258    let p = 1
1259    while p
1260      let p = 0
1261      try
1262        Xpath 'a'
1263        asdf
1264        call assert_report('should not get here')
1265      endtry | call assert_report('should not get here')
1266    endwhile | call assert_report('should not get here')
1267    call assert_report('should not get here')
1268  [CODE]
1269  let verify =<< trim [CODE]
1270    call assert_equal('a', g:Xpath)
1271  [CODE]
1272  call RunInNewVim(test, verify)
1273endfunc
1274
1275func Test_try_error_abort_6()
1276  let test =<< trim [CODE]
1277    let p = 1
1278    Xpath 'a'
1279    while p
1280      Xpath 'b'
1281      let p = 0
1282      try
1283        Xpath 'c'
1284    endwhile | call assert_report('should not get here')
1285    call assert_report('should not get here')
1286  [CODE]
1287  let verify =<< trim [CODE]
1288    call assert_equal('abc', g:Xpath)
1289  [CODE]
1290  call RunInNewVim(test, verify)
1291endfunc
1292
1293"-------------------------------------------------------------------------------
1294" Test 20:  Aborting on errors after :try/:endtry			    {{{1
1295"
1296"	    When an error occurs after the last active :try/:endtry region has
1297"	    been left, termination behavior is as if no :try/:endtry has been
1298"	    seen.
1299"-------------------------------------------------------------------------------
1300
1301func Test_error_after_try_1()
1302  let test =<< trim [CODE]
1303    let p = 1
1304    while p
1305      let p = 0
1306      Xpath 'a'
1307      try
1308        Xpath 'b'
1309      endtry
1310      asdf
1311      call assert_report('should not get here')
1312    endwhile | call assert_report('should not get here')
1313    Xpath 'c'
1314  [CODE]
1315  let verify =<< trim [CODE]
1316    call assert_equal('abc', g:Xpath)
1317  [CODE]
1318  call RunInNewVim(test, verify)
1319endfunc
1320
1321func Test_error_after_try_2()
1322  let test =<< trim [CODE]
1323    while 1
1324      try
1325        Xpath 'a'
1326        break
1327        call assert_report('should not get here')
1328      endtry
1329    endwhile
1330    Xpath 'b'
1331    asdf
1332    Xpath 'c'
1333  [CODE]
1334  let verify =<< trim [CODE]
1335    call assert_equal('abc', g:Xpath)
1336  [CODE]
1337  call RunInNewVim(test, verify)
1338endfunc
1339
1340func Test_error_after_try_3()
1341  let test =<< trim [CODE]
1342    while 1
1343      try
1344        Xpath 'a'
1345        break
1346        call assert_report('should not get here')
1347      finally
1348        Xpath 'b'
1349      endtry
1350    endwhile
1351    Xpath 'c'
1352    asdf
1353    Xpath 'd'
1354  [CODE]
1355  let verify =<< trim [CODE]
1356    call assert_equal('abcd', g:Xpath)
1357  [CODE]
1358  call RunInNewVim(test, verify)
1359endfunc
1360
1361func Test_error_after_try_4()
1362  let test =<< trim [CODE]
1363    while 1
1364      try
1365        Xpath 'a'
1366      finally
1367        Xpath 'b'
1368        break
1369        call assert_report('should not get here')
1370      endtry
1371    endwhile
1372    Xpath 'c'
1373    asdf
1374    Xpath 'd'
1375  [CODE]
1376  let verify =<< trim [CODE]
1377    call assert_equal('abcd', g:Xpath)
1378  [CODE]
1379  call RunInNewVim(test, verify)
1380endfunc
1381
1382func Test_error_after_try_5()
1383  let test =<< trim [CODE]
1384    let p = 1
1385    while p
1386      let p = 0
1387      try
1388        Xpath 'a'
1389        continue
1390        call assert_report('should not get here')
1391      endtry
1392    endwhile
1393    Xpath 'b'
1394    asdf
1395    Xpath 'c'
1396  [CODE]
1397  let verify =<< trim [CODE]
1398    call assert_equal('abc', g:Xpath)
1399  [CODE]
1400  call RunInNewVim(test, verify)
1401endfunc
1402
1403func Test_error_after_try_6()
1404  let test =<< trim [CODE]
1405    let p = 1
1406    while p
1407      let p = 0
1408      try
1409        Xpath 'a'
1410        continue
1411        call assert_report('should not get here')
1412      finally
1413        Xpath 'b'
1414      endtry
1415    endwhile
1416    Xpath 'c'
1417    asdf
1418    Xpath 'd'
1419  [CODE]
1420  let verify =<< trim [CODE]
1421    call assert_equal('abcd', g:Xpath)
1422  [CODE]
1423  call RunInNewVim(test, verify)
1424endfunc
1425
1426func Test_error_after_try_7()
1427  let test =<< trim [CODE]
1428    let p = 1
1429    while p
1430      let p = 0
1431      try
1432        Xpath 'a'
1433      finally
1434        Xpath 'b'
1435        continue
1436        call assert_report('should not get here')
1437      endtry
1438    endwhile
1439    Xpath 'c'
1440    asdf
1441    Xpath 'd'
1442  [CODE]
1443  let verify =<< trim [CODE]
1444    call assert_equal('abcd', g:Xpath)
1445  [CODE]
1446  call RunInNewVim(test, verify)
1447endfunc
1448
1449"-------------------------------------------------------------------------------
1450" Test 21:  :finally for :try after :continue/:break/:return/:finish	    {{{1
1451"
1452"	    If a :try conditional stays inactive due to a preceding :continue,
1453"	    :break, :return, or :finish, its :finally clause should not be
1454"	    executed.
1455"-------------------------------------------------------------------------------
1456
1457func Test_finally_after_loop_ctrl_statement()
1458  let test =<< trim [CODE]
1459    func F()
1460      let loops = 2
1461      while loops > 0
1462        XloopNEXT
1463        let loops = loops - 1
1464        try
1465          if loops == 1
1466            Xloop 'a'
1467            continue
1468            call assert_report('should not get here')
1469          elseif loops == 0
1470            Xloop 'b'
1471            break
1472            call assert_report('should not get here')
1473          endif
1474
1475          try		" inactive
1476            call assert_report('should not get here')
1477          finally
1478            call assert_report('should not get here')
1479          endtry
1480        finally
1481          Xloop 'c'
1482        endtry
1483        call assert_report('should not get here')
1484      endwhile
1485
1486      try
1487        Xpath 'd'
1488        return
1489        call assert_report('should not get here')
1490        try		    " inactive
1491          call assert_report('should not get here')
1492        finally
1493          call assert_report('should not get here')
1494        endtry
1495      finally
1496        Xpath 'e'
1497      endtry
1498      call assert_report('should not get here')
1499    endfunc
1500
1501    try
1502      Xpath 'f'
1503      call F()
1504      Xpath 'g'
1505      finish
1506      call assert_report('should not get here')
1507      try		" inactive
1508        call assert_report('should not get here')
1509      finally
1510        call assert_report('should not get here')
1511      endtry
1512    finally
1513      Xpath 'h'
1514    endtry
1515    call assert_report('should not get here')
1516  [CODE]
1517  let verify =<< trim [CODE]
1518    call assert_equal('fa2c2b3c3degh', g:Xpath)
1519  [CODE]
1520  call RunInNewVim(test, verify)
1521endfunc
1522
1523"-------------------------------------------------------------------------------
1524" Test 22:  :finally for a :try after an error/interrupt/:throw		    {{{1
1525"
1526"	    If a :try conditional stays inactive due to a preceding error or
1527"	    interrupt or :throw, its :finally clause should not be executed.
1528"-------------------------------------------------------------------------------
1529
1530func Test_finally_after_error_in_func()
1531  let test =<< trim [CODE]
1532    func Error()
1533      try
1534        Xpath 'b'
1535        asdf    " aborting error, triggering error exception
1536        call assert_report('should not get here')
1537      endtry
1538      call assert_report('should not get here')
1539    endfunc
1540
1541    Xpath 'a'
1542    call Error()
1543    call assert_report('should not get here')
1544
1545    if 1	" not active due to error
1546      try	" not active since :if inactive
1547        call assert_report('should not get here')
1548      finally
1549        call assert_report('should not get here')
1550      endtry
1551    endif
1552
1553    try		" not active due to error
1554      call assert_report('should not get here')
1555    finally
1556      call assert_report('should not get here')
1557    endtry
1558  [CODE]
1559  let verify =<< trim [CODE]
1560    call assert_equal('ab', g:Xpath)
1561  [CODE]
1562  call RunInNewVim(test, verify)
1563endfunc
1564
1565func Test_finally_after_interrupt()
1566  let test =<< trim [CODE]
1567    func Interrupt()
1568      try
1569        Xpath 'a'
1570        call interrupt()            " triggering interrupt exception
1571        call assert_report('should not get here')
1572      endtry
1573    endfunc
1574
1575    Xpath 'b'
1576    try
1577      call Interrupt()
1578    catch /^Vim:Interrupt$/
1579      Xpath 'c'
1580      finish
1581    endtry
1582    call assert_report('should not get here')
1583
1584    if 1	" not active due to interrupt
1585      try	" not active since :if inactive
1586        call assert_report('should not get here')
1587      finally
1588        call assert_report('should not get here')
1589      endtry
1590    endif
1591
1592    try		" not active due to interrupt
1593      call assert_report('should not get here')
1594    finally
1595      call assert_report('should not get here')
1596    endtry
1597  [CODE]
1598  let verify =<< trim [CODE]
1599    call assert_equal('bac', g:Xpath)
1600  [CODE]
1601  call RunInNewVim(test, verify)
1602endfunc
1603
1604func Test_finally_after_throw()
1605  let test =<< trim [CODE]
1606    func Throw()
1607      Xpath 'a'
1608      throw 'xyz'
1609    endfunc
1610
1611    Xpath 'b'
1612    call Throw()
1613    call assert_report('should not get here')
1614
1615    if 1	" not active due to :throw
1616      try	" not active since :if inactive
1617        call assert_report('should not get here')
1618      finally
1619        call assert_report('should not get here')
1620      endtry
1621    endif
1622
1623    try		" not active due to :throw
1624      call assert_report('should not get here')
1625    finally
1626      call assert_report('should not get here')
1627    endtry
1628  [CODE]
1629  let verify =<< trim [CODE]
1630    call assert_equal('ba', g:Xpath)
1631  [CODE]
1632  call RunInNewVim(test, verify)
1633endfunc
1634
1635"-------------------------------------------------------------------------------
1636" Test 23:  :catch clauses for a :try after a :throw			    {{{1
1637"
1638"	    If a :try conditional stays inactive due to a preceding :throw,
1639"	    none of its :catch clauses should be executed.
1640"-------------------------------------------------------------------------------
1641
1642func Test_catch_after_throw()
1643  let test =<< trim [CODE]
1644    try
1645      Xpath 'a'
1646      throw "xyz"
1647      call assert_report('should not get here')
1648
1649      if 1	" not active due to :throw
1650        try	" not active since :if inactive
1651          call assert_report('should not get here')
1652        catch /xyz/
1653          call assert_report('should not get here')
1654        endtry
1655      endif
1656    catch /xyz/
1657      Xpath 'b'
1658    endtry
1659
1660    Xpath 'c'
1661    throw "abc"
1662    call assert_report('should not get here')
1663
1664    try		" not active due to :throw
1665      call assert_report('should not get here')
1666    catch /abc/
1667      call assert_report('should not get here')
1668    endtry
1669  [CODE]
1670  let verify =<< trim [CODE]
1671    call assert_equal('abc', g:Xpath)
1672  [CODE]
1673  call RunInNewVim(test, verify)
1674endfunc
1675
1676"-------------------------------------------------------------------------------
1677" Test 24:  :endtry for a :try after a :throw				    {{{1
1678"
1679"	    If a :try conditional stays inactive due to a preceding :throw,
1680"	    its :endtry should not rethrow the exception to the next surrounding
1681"	    active :try conditional.
1682"-------------------------------------------------------------------------------
1683
1684func Test_endtry_after_throw()
1685  let test =<< trim [CODE]
1686    try			" try 1
1687      try		" try 2
1688        Xpath 'a'
1689        throw "xyz"	" makes try 2 inactive
1690        call assert_report('should not get here')
1691
1692        try		" try 3
1693          call assert_report('should not get here')
1694        endtry	" no rethrow to try 1
1695      catch /xyz/	" should catch although try 2 inactive
1696        Xpath 'b'
1697      endtry
1698    catch /xyz/		" try 1 active, but exception already caught
1699      call assert_report('should not get here')
1700    endtry
1701    Xpath 'c'
1702  [CODE]
1703  let verify =<< trim [CODE]
1704    call assert_equal('abc', g:Xpath)
1705  [CODE]
1706  call RunInNewVim(test, verify)
1707endfunc
1708
1709"-------------------------------------------------------------------------------
1710" Test 27:  Executing :finally clauses after :return			    {{{1
1711"
1712"	    For a :return command dynamically enclosed in a :try/:endtry region,
1713"	    :finally clauses are executed and the called function is ended.
1714"-------------------------------------------------------------------------------
1715
1716func T27_F()
1717  try
1718    Xpath 'a'
1719    try
1720      Xpath 'b'
1721      return
1722      call assert_report('should not get here')
1723    finally
1724      Xpath 'c'
1725    endtry
1726    Xpath 'd'
1727  finally
1728    Xpath 'e'
1729  endtry
1730  call assert_report('should not get here')
1731endfunc
1732
1733func T27_G()
1734  try
1735    Xpath 'f'
1736    return
1737    call assert_report('should not get here')
1738  finally
1739    Xpath 'g'
1740    call T27_F()
1741    Xpath 'h'
1742  endtry
1743  call assert_report('should not get here')
1744endfunc
1745
1746func T27_H()
1747  try
1748    Xpath 'i'
1749    call T27_G()
1750    Xpath 'j'
1751  finally
1752    Xpath 'k'
1753    return
1754    call assert_report('should not get here')
1755  endtry
1756  call assert_report('should not get here')
1757endfunction
1758
1759func Test_finally_after_return()
1760  XpathINIT
1761  try
1762      Xpath 'l'
1763      call T27_H()
1764      Xpath 'm'
1765  finally
1766      Xpath 'n'
1767  endtry
1768  call assert_equal('lifgabcehjkmn', g:Xpath)
1769endfunc
1770
1771"-------------------------------------------------------------------------------
1772" Test 28:  Executing :finally clauses after :finish			    {{{1
1773"
1774"	    For a :finish command dynamically enclosed in a :try/:endtry region,
1775"	    :finally clauses are executed and the sourced file is finished.
1776"
1777"	    This test executes the bodies of the functions F, G, and H from the
1778"	    previous test as script files (:return replaced by :finish).
1779"-------------------------------------------------------------------------------
1780
1781func Test_finally_after_finish()
1782  XpathINIT
1783
1784  let scriptF = MakeScript("T27_F")
1785  let scriptG = MakeScript("T27_G", scriptF)
1786  let scriptH = MakeScript("T27_H", scriptG)
1787
1788  try
1789    Xpath 'A'
1790    exec "source" scriptH
1791    Xpath 'B'
1792  finally
1793    Xpath 'C'
1794  endtry
1795  Xpath 'D'
1796  call assert_equal('AifgabcehjkBCD', g:Xpath)
1797  call delete(scriptF)
1798  call delete(scriptG)
1799  call delete(scriptH)
1800endfunc
1801
1802"-------------------------------------------------------------------------------
1803" Test 29:  Executing :finally clauses on errors			    {{{1
1804"
1805"	    After an error in a command dynamically enclosed in a :try/:endtry
1806"	    region, :finally clauses are executed and the script processing is
1807"	    terminated.
1808"-------------------------------------------------------------------------------
1809
1810func Test_finally_after_error_1()
1811  let test =<< trim [CODE]
1812    func F()
1813      while 1
1814        try
1815          Xpath 'a'
1816          while 1
1817            try
1818              Xpath 'b'
1819              asdf	    " error
1820              call assert_report('should not get here')
1821            finally
1822              Xpath 'c'
1823            endtry | call assert_report('should not get here')
1824            call assert_report('should not get here')
1825            break
1826          endwhile
1827          call assert_report('should not get here')
1828        finally
1829          Xpath 'd'
1830        endtry | call assert_report('should not get here')
1831        call assert_report('should not get here')
1832        break
1833      endwhile
1834      call assert_report('should not get here')
1835    endfunc
1836
1837    while 1
1838      try
1839        Xpath 'e'
1840        while 1
1841          call F()
1842          call assert_report('should not get here')
1843          break
1844        endwhile  | call assert_report('should not get here')
1845        call assert_report('should not get here')
1846      finally
1847        Xpath 'f'
1848      endtry | call assert_report('should not get here')
1849    endwhile | call assert_report('should not get here')
1850    call assert_report('should not get here')
1851  [CODE]
1852  let verify =<< trim [CODE]
1853    call assert_equal('eabcdf', g:Xpath)
1854  [CODE]
1855  call RunInNewVim(test, verify)
1856endfunc
1857
1858func Test_finally_after_error_2()
1859  let test =<< trim [CODE]
1860    func G() abort
1861      if 1
1862        try
1863          Xpath 'a'
1864          asdf	    " error
1865          call assert_report('should not get here')
1866        finally
1867          Xpath 'b'
1868        endtry | Xpath 'c'
1869      endif | Xpath 'd'
1870      call assert_report('should not get here')
1871    endfunc
1872
1873    if 1
1874      try
1875        Xpath 'e'
1876        call G()
1877        call assert_report('should not get here')
1878      finally
1879        Xpath 'f'
1880      endtry | call assert_report('should not get here')
1881    endif | call assert_report('should not get here')
1882    call assert_report('should not get here')
1883  [CODE]
1884  let verify =<< trim [CODE]
1885    call assert_equal('eabf', g:Xpath)
1886  [CODE]
1887  call RunInNewVim(test, verify)
1888endfunc
1889
1890"-------------------------------------------------------------------------------
1891" Test 30:  Executing :finally clauses on interrupt			    {{{1
1892"
1893"	    After an interrupt in a command dynamically enclosed in
1894"	    a :try/:endtry region, :finally clauses are executed and the
1895"	    script processing is terminated.
1896"-------------------------------------------------------------------------------
1897
1898func Test_finally_on_interrupt()
1899  let test =<< trim [CODE]
1900    func F()
1901      try
1902        Xloop 'a'
1903        call interrupt()
1904        call assert_report('should not get here')
1905      finally
1906        Xloop 'b'
1907      endtry
1908      call assert_report('should not get here')
1909    endfunc
1910
1911    try
1912      try
1913        Xpath 'c'
1914        try
1915          Xpath 'd'
1916          call interrupt()
1917          call assert_report('should not get here')
1918        finally
1919          Xpath 'e'
1920          try
1921            Xpath 'f'
1922            try
1923              Xpath 'g'
1924            finally
1925              Xpath 'h'
1926              try
1927                Xpath 'i'
1928                call interrupt()
1929                call assert_report('should not get here')
1930              endtry
1931              call assert_report('should not get here')
1932            endtry
1933            call assert_report('should not get here')
1934          endtry
1935          call assert_report('should not get here')
1936        endtry
1937        call assert_report('should not get here')
1938      finally
1939        Xpath 'j'
1940        try
1941          Xpath 'k'
1942          call F()
1943          call assert_report('should not get here')
1944        finally
1945          Xpath 'l'
1946          try
1947            Xpath 'm'
1948            XloopNEXT
1949            ExecAsScript F
1950            call assert_report('should not get here')
1951          finally
1952            Xpath 'n'
1953          endtry
1954          call assert_report('should not get here')
1955        endtry
1956        call assert_report('should not get here')
1957      endtry
1958      call assert_report('should not get here')
1959    catch /^Vim:Interrupt$/
1960      Xpath 'o'
1961    endtry
1962  [CODE]
1963  let verify =<< trim [CODE]
1964    call assert_equal('cdefghijka1b1lma2b2no', g:Xpath)
1965  [CODE]
1966  call RunInNewVim(test, verify)
1967endfunc
1968
1969"-------------------------------------------------------------------------------
1970" Test 31:  Executing :finally clauses after :throw			    {{{1
1971"
1972"	    After a :throw dynamically enclosed in a :try/:endtry region,
1973"	    :finally clauses are executed and the script processing is
1974"	    terminated.
1975"-------------------------------------------------------------------------------
1976
1977func Test_finally_after_throw_2()
1978  let test =<< trim [CODE]
1979    func F()
1980      try
1981        Xloop 'a'
1982        throw "exception"
1983        call assert_report('should not get here')
1984      finally
1985        Xloop 'b'
1986      endtry
1987      call assert_report('should not get here')
1988    endfunc
1989
1990    try
1991      Xpath 'c'
1992      try
1993        Xpath 'd'
1994        throw "exception"
1995        call assert_report('should not get here')
1996      finally
1997        Xpath 'e'
1998        try
1999          Xpath 'f'
2000          try
2001            Xpath 'g'
2002          finally
2003            Xpath 'h'
2004            try
2005              Xpath 'i'
2006              throw "exception"
2007              call assert_report('should not get here')
2008            endtry
2009            call assert_report('should not get here')
2010          endtry
2011          call assert_report('should not get here')
2012        endtry
2013        call assert_report('should not get here')
2014      endtry
2015      call assert_report('should not get here')
2016    finally
2017      Xpath 'j'
2018      try
2019        Xpath 'k'
2020        call F()
2021        call assert_report('should not get here')
2022      finally
2023        Xpath 'l'
2024        try
2025          Xpath 'm'
2026          XloopNEXT
2027          ExecAsScript F
2028          call assert_report('should not get here')
2029        finally
2030          Xpath 'n'
2031        endtry
2032        call assert_report('should not get here')
2033      endtry
2034      call assert_report('should not get here')
2035    endtry
2036    call assert_report('should not get here')
2037  [CODE]
2038  let verify =<< trim [CODE]
2039    call assert_equal('cdefghijka1b1lma2b2n', g:Xpath)
2040  [CODE]
2041  call RunInNewVim(test, verify)
2042endfunc
2043
2044"-------------------------------------------------------------------------------
2045" Test 34:  :finally reason discarded by :continue			    {{{1
2046"
2047"	    When a :finally clause is executed due to a :continue, :break,
2048"	    :return, :finish, error, interrupt or :throw, the jump reason is
2049"	    discarded by a :continue in the finally clause.
2050"-------------------------------------------------------------------------------
2051
2052func Test_finally_after_continue()
2053  let test =<< trim [CODE]
2054    func C(jump)
2055      XloopNEXT
2056      let loop = 0
2057      while loop < 2
2058        let loop = loop + 1
2059        if loop == 1
2060          try
2061            if a:jump == "continue"
2062              continue
2063            elseif a:jump == "break"
2064              break
2065            elseif a:jump == "return" || a:jump == "finish"
2066              return
2067            elseif a:jump == "error"
2068              asdf
2069            elseif a:jump == "interrupt"
2070              call interrupt()
2071              let dummy = 0
2072            elseif a:jump == "throw"
2073              throw "abc"
2074            endif
2075          finally
2076            continue	" discards jump that caused the :finally
2077            call assert_report('should not get here')
2078          endtry
2079          call assert_report('should not get here')
2080        elseif loop == 2
2081          Xloop 'a'
2082        endif
2083      endwhile
2084    endfunc
2085
2086    call C("continue")
2087    Xpath 'b'
2088    call C("break")
2089    Xpath 'c'
2090    call C("return")
2091    Xpath 'd'
2092    let g:jump = "finish"
2093    ExecAsScript C
2094    unlet g:jump
2095    Xpath 'e'
2096    try
2097      call C("error")
2098      Xpath 'f'
2099    finally
2100      Xpath 'g'
2101      try
2102        call C("interrupt")
2103        Xpath 'h'
2104      finally
2105        Xpath 'i'
2106        call C("throw")
2107        Xpath 'j'
2108      endtry
2109    endtry
2110    Xpath 'k'
2111  [CODE]
2112  let verify =<< trim [CODE]
2113    call assert_equal('a2ba3ca4da5ea6fga7hia8jk', g:Xpath)
2114  [CODE]
2115  call RunInNewVim(test, verify)
2116endfunc
2117
2118"-------------------------------------------------------------------------------
2119" Test 35:  :finally reason discarded by :break				    {{{1
2120"
2121"	    When a :finally clause is executed due to a :continue, :break,
2122"	    :return, :finish, error, interrupt or :throw, the jump reason is
2123"	    discarded by a :break in the finally clause.
2124"-------------------------------------------------------------------------------
2125
2126func Test_finally_discard_by_break()
2127  let test =<< trim [CODE]
2128    func B(jump)
2129      XloopNEXT
2130      let loop = 0
2131      while loop < 2
2132        let loop = loop + 1
2133        if loop == 1
2134          try
2135            if a:jump == "continue"
2136              continue
2137            elseif a:jump == "break"
2138              break
2139            elseif a:jump == "return" || a:jump == "finish"
2140              return
2141            elseif a:jump == "error"
2142              asdf
2143            elseif a:jump == "interrupt"
2144              call interrupt()
2145              let dummy = 0
2146            elseif a:jump == "throw"
2147              throw "abc"
2148            endif
2149          finally
2150            break	" discards jump that caused the :finally
2151            call assert_report('should not get here')
2152          endtry
2153        elseif loop == 2
2154          call assert_report('should not get here')
2155        endif
2156      endwhile
2157      Xloop 'a'
2158    endfunc
2159
2160    call B("continue")
2161    Xpath 'b'
2162    call B("break")
2163    Xpath 'c'
2164    call B("return")
2165    Xpath 'd'
2166    let g:jump = "finish"
2167    ExecAsScript B
2168    unlet g:jump
2169    Xpath 'e'
2170    try
2171      call B("error")
2172      Xpath 'f'
2173    finally
2174      Xpath 'g'
2175      try
2176        call B("interrupt")
2177        Xpath 'h'
2178      finally
2179        Xpath 'i'
2180        call B("throw")
2181        Xpath 'j'
2182      endtry
2183    endtry
2184    Xpath 'k'
2185  [CODE]
2186  let verify =<< trim [CODE]
2187    call assert_equal('a2ba3ca4da5ea6fga7hia8jk', g:Xpath)
2188  [CODE]
2189  call RunInNewVim(test, verify)
2190endfunc
2191
2192"-------------------------------------------------------------------------------
2193" Test 36:  :finally reason discarded by :return			    {{{1
2194"
2195"	    When a :finally clause is executed due to a :continue, :break,
2196"	    :return, :finish, error, interrupt or :throw, the jump reason is
2197"	    discarded by a :return in the finally clause.
2198"-------------------------------------------------------------------------------
2199
2200func Test_finally_discard_by_return()
2201  let test =<< trim [CODE]
2202    func R(jump, retval) abort
2203      let loop = 0
2204      while loop < 2
2205        let loop = loop + 1
2206        if loop == 1
2207          try
2208            if a:jump == "continue"
2209              continue
2210            elseif a:jump == "break"
2211              break
2212            elseif a:jump == "return"
2213              return
2214            elseif a:jump == "error"
2215              asdf
2216            elseif a:jump == "interrupt"
2217              call interrupt()
2218              let dummy = 0
2219            elseif a:jump == "throw"
2220              throw "abc"
2221            endif
2222          finally
2223            return a:retval	" discards jump that caused the :finally
2224            call assert_report('should not get here')
2225          endtry
2226        elseif loop == 2
2227          call assert_report('should not get here')
2228        endif
2229      endwhile
2230      call assert_report('should not get here')
2231    endfunc
2232
2233    let sum =  -R("continue", -8)
2234    Xpath 'a'
2235    let sum = sum - R("break", -16)
2236    Xpath 'b'
2237    let sum = sum - R("return", -32)
2238    Xpath 'c'
2239    try
2240      let sum = sum - R("error", -64)
2241      Xpath 'd'
2242    finally
2243      Xpath 'e'
2244      try
2245        let sum = sum - R("interrupt", -128)
2246        Xpath 'f'
2247      finally
2248        Xpath 'g'
2249        let sum = sum - R("throw", -256)
2250        Xpath 'h'
2251      endtry
2252    endtry
2253    Xpath 'i'
2254
2255    let expected = 8 + 16 + 32 + 64 + 128 + 256
2256    call assert_equal(sum, expected)
2257  [CODE]
2258  let verify =<< trim [CODE]
2259    call assert_equal('abcdefghi', g:Xpath)
2260  [CODE]
2261  call RunInNewVim(test, verify)
2262endfunc
2263
2264"-------------------------------------------------------------------------------
2265" Test 37:  :finally reason discarded by :finish			    {{{1
2266"
2267"	    When a :finally clause is executed due to a :continue, :break,
2268"	    :return, :finish, error, interrupt or :throw, the jump reason is
2269"	    discarded by a :finish in the finally clause.
2270"-------------------------------------------------------------------------------
2271
2272func Test_finally_discard_by_finish()
2273  let test =<< trim [CODE]
2274    func F(jump)	" not executed as function, transformed to a script
2275      let loop = 0
2276      while loop < 2
2277        let loop = loop + 1
2278        if loop == 1
2279          try
2280            if a:jump == "continue"
2281              continue
2282            elseif a:jump == "break"
2283              break
2284            elseif a:jump == "finish"
2285              finish
2286            elseif a:jump == "error"
2287              asdf
2288            elseif a:jump == "interrupt"
2289              call interrupt()
2290              let dummy = 0
2291            elseif a:jump == "throw"
2292              throw "abc"
2293            endif
2294          finally
2295            finish	" discards jump that caused the :finally
2296            call assert_report('should not get here')
2297          endtry
2298        elseif loop == 2
2299          call assert_report('should not get here')
2300        endif
2301      endwhile
2302      call assert_report('should not get here')
2303    endfunc
2304
2305    let scriptF = MakeScript("F")
2306    delfunction F
2307
2308    let g:jump = "continue"
2309    exec "source" scriptF
2310    Xpath 'a'
2311    let g:jump = "break"
2312    exec "source" scriptF
2313    Xpath 'b'
2314    let g:jump = "finish"
2315    exec "source" scriptF
2316    Xpath 'c'
2317    try
2318      let g:jump = "error"
2319      exec "source" scriptF
2320      Xpath 'd'
2321    finally
2322      Xpath 'e'
2323      try
2324        let g:jump = "interrupt"
2325        exec "source" scriptF
2326        Xpath 'f'
2327      finally
2328        Xpath 'g'
2329        try
2330          let g:jump = "throw"
2331          exec "source" scriptF
2332          Xpath 'h'
2333        finally
2334          Xpath 'i'
2335        endtry
2336      endtry
2337    endtry
2338    unlet g:jump
2339    call delete(scriptF)
2340  [CODE]
2341  let verify =<< trim [CODE]
2342    call assert_equal('abcdefghi', g:Xpath)
2343  [CODE]
2344  call RunInNewVim(test, verify)
2345endfunc
2346
2347"-------------------------------------------------------------------------------
2348" Test 38:  :finally reason discarded by an error			    {{{1
2349"
2350"	    When a :finally clause is executed due to a :continue, :break,
2351"	    :return, :finish, error, interrupt or :throw, the jump reason is
2352"	    discarded by an error in the finally clause.
2353"-------------------------------------------------------------------------------
2354
2355func Test_finally_discard_by_error()
2356  let test =<< trim [CODE]
2357    func E(jump)
2358      let loop = 0
2359      while loop < 2
2360        let loop = loop + 1
2361        if loop == 1
2362          try
2363            if a:jump == "continue"
2364              continue
2365            elseif a:jump == "break"
2366              break
2367            elseif a:jump == "return" || a:jump == "finish"
2368              return
2369            elseif a:jump == "error"
2370              asdf
2371            elseif a:jump == "interrupt"
2372              call interrupt()
2373              let dummy = 0
2374            elseif a:jump == "throw"
2375              throw "abc"
2376            endif
2377          finally
2378            asdf	" error; discards jump that caused the :finally
2379          endtry
2380        elseif loop == 2
2381          call assert_report('should not get here')
2382        endif
2383      endwhile
2384      call assert_report('should not get here')
2385    endfunc
2386
2387    try
2388      Xpath 'a'
2389      call E("continue")
2390      call assert_report('should not get here')
2391    finally
2392      try
2393        Xpath 'b'
2394        call E("break")
2395        call assert_report('should not get here')
2396      finally
2397        try
2398          Xpath 'c'
2399          call E("return")
2400          call assert_report('should not get here')
2401        finally
2402          try
2403            Xpath 'd'
2404            let g:jump = "finish"
2405            ExecAsScript E
2406            call assert_report('should not get here')
2407          finally
2408            unlet g:jump
2409            try
2410              Xpath 'e'
2411              call E("error")
2412              call assert_report('should not get here')
2413            finally
2414              try
2415                Xpath 'f'
2416                call E("interrupt")
2417                call assert_report('should not get here')
2418              finally
2419                try
2420                  Xpath 'g'
2421                  call E("throw")
2422                  call assert_report('should not get here')
2423                finally
2424                  Xpath 'h'
2425                  delfunction E
2426                endtry
2427              endtry
2428            endtry
2429          endtry
2430        endtry
2431      endtry
2432    endtry
2433    call assert_report('should not get here')
2434  [CODE]
2435  let verify =<< trim [CODE]
2436    call assert_equal('abcdefgh', g:Xpath)
2437  [CODE]
2438  call RunInNewVim(test, verify)
2439endfunc
2440
2441"-------------------------------------------------------------------------------
2442" Test 39:  :finally reason discarded by an interrupt			    {{{1
2443"
2444"	    When a :finally clause is executed due to a :continue, :break,
2445"	    :return, :finish, error, interrupt or :throw, the jump reason is
2446"	    discarded by an interrupt in the finally clause.
2447"-------------------------------------------------------------------------------
2448
2449func Test_finally_discarded_by_interrupt()
2450  let test =<< trim [CODE]
2451    func I(jump)
2452      let loop = 0
2453      while loop < 2
2454        let loop = loop + 1
2455        if loop == 1
2456          try
2457            if a:jump == "continue"
2458              continue
2459            elseif a:jump == "break"
2460              break
2461            elseif a:jump == "return" || a:jump == "finish"
2462              return
2463            elseif a:jump == "error"
2464              asdf
2465            elseif a:jump == "interrupt"
2466              call interrupt()
2467              let dummy = 0
2468            elseif a:jump == "throw"
2469              throw "abc"
2470            endif
2471          finally
2472            call interrupt()
2473            let dummy = 0
2474          endtry
2475        elseif loop == 2
2476          call assert_report('should not get here')
2477        endif
2478      endwhile
2479      call assert_report('should not get here')
2480    endfunc
2481
2482    try
2483      try
2484        Xpath 'a'
2485        call I("continue")
2486        call assert_report('should not get here')
2487      finally
2488        try
2489          Xpath 'b'
2490          call I("break")
2491          call assert_report('should not get here')
2492        finally
2493          try
2494            Xpath 'c'
2495            call I("return")
2496            call assert_report('should not get here')
2497          finally
2498            try
2499              Xpath 'd'
2500              let g:jump = "finish"
2501              ExecAsScript I
2502              call assert_report('should not get here')
2503            finally
2504              unlet g:jump
2505              try
2506                Xpath 'e'
2507                call I("error")
2508                call assert_report('should not get here')
2509              finally
2510                try
2511                  Xpath 'f'
2512                  call I("interrupt")
2513                  call assert_report('should not get here')
2514                finally
2515                  try
2516                    Xpath 'g'
2517                    call I("throw")
2518                    call assert_report('should not get here')
2519                  finally
2520                    Xpath 'h'
2521                    delfunction I
2522                  endtry
2523                endtry
2524              endtry
2525            endtry
2526          endtry
2527        endtry
2528      endtry
2529      call assert_report('should not get here')
2530    catch /^Vim:Interrupt$/
2531      Xpath 'A'
2532    endtry
2533  [CODE]
2534  let verify =<< trim [CODE]
2535    call assert_equal('abcdefghA', g:Xpath)
2536  [CODE]
2537  call RunInNewVim(test, verify)
2538endfunc
2539
2540"-------------------------------------------------------------------------------
2541" Test 40:  :finally reason discarded by :throw				    {{{1
2542"
2543"	    When a :finally clause is executed due to a :continue, :break,
2544"	    :return, :finish, error, interrupt or :throw, the jump reason is
2545"	    discarded by a :throw in the finally clause.
2546"-------------------------------------------------------------------------------
2547
2548func Test_finally_discard_by_throw()
2549  let test =<< trim [CODE]
2550    func T(jump)
2551      let loop = 0
2552      while loop < 2
2553        let loop = loop + 1
2554        if loop == 1
2555          try
2556            if a:jump == "continue"
2557              continue
2558            elseif a:jump == "break"
2559              break
2560            elseif a:jump == "return" || a:jump == "finish"
2561              return
2562            elseif a:jump == "error"
2563              asdf
2564            elseif a:jump == "interrupt"
2565              call interrupt()
2566              let dummy = 0
2567            elseif a:jump == "throw"
2568              throw "abc"
2569            endif
2570          finally
2571            throw "xyz"	" discards jump that caused the :finally
2572          endtry
2573        elseif loop == 2
2574          call assert_report('should not get here')
2575        endif
2576      endwhile
2577      call assert_report('should not get here')
2578    endfunc
2579
2580    try
2581      Xpath 'a'
2582      call T("continue")
2583      call assert_report('should not get here')
2584    finally
2585      try
2586        Xpath 'b'
2587        call T("break")
2588        call assert_report('should not get here')
2589      finally
2590        try
2591          Xpath 'c'
2592          call T("return")
2593          call assert_report('should not get here')
2594        finally
2595          try
2596            Xpath 'd'
2597            let g:jump = "finish"
2598            ExecAsScript T
2599            call assert_report('should not get here')
2600          finally
2601            unlet g:jump
2602            try
2603              Xpath 'e'
2604              call T("error")
2605              call assert_report('should not get here')
2606            finally
2607              try
2608                Xpath 'f'
2609                call T("interrupt")
2610                call assert_report('should not get here')
2611              finally
2612                try
2613                  Xpath 'g'
2614                  call T("throw")
2615                  call assert_report('should not get here')
2616                finally
2617                  Xpath 'h'
2618                  delfunction T
2619                endtry
2620              endtry
2621            endtry
2622          endtry
2623        endtry
2624      endtry
2625    endtry
2626    call assert_report('should not get here')
2627  [CODE]
2628  let verify =<< trim [CODE]
2629    call assert_equal('abcdefgh', g:Xpath)
2630  [CODE]
2631  call RunInNewVim(test, verify)
2632endfunc
2633
2634"-------------------------------------------------------------------------------
2635" Test 49:  Throwing exceptions across functions			    {{{1
2636"
2637"	    When an exception is thrown but not caught inside a function, the
2638"	    caller is checked for a matching :catch clause.
2639"-------------------------------------------------------------------------------
2640
2641func T49_C()
2642  try
2643    Xpath 'a'
2644    throw "arrgh"
2645    call assert_report('should not get here')
2646  catch /arrgh/
2647    Xpath 'b'
2648  endtry
2649  Xpath 'c'
2650endfunc
2651
2652func T49_T1()
2653  XloopNEXT
2654  try
2655    Xloop 'd'
2656    throw "arrgh"
2657    call assert_report('should not get here')
2658  finally
2659    Xloop 'e'
2660  endtry
2661  Xloop 'f'
2662endfunc
2663
2664func T49_T2()
2665  try
2666    Xpath 'g'
2667    call T49_T1()
2668    call assert_report('should not get here')
2669  finally
2670    Xpath 'h'
2671  endtry
2672  call assert_report('should not get here')
2673endfunc
2674
2675func Test_throw_exception_across_funcs()
2676  XpathINIT
2677  XloopINIT
2678  try
2679    Xpath 'i'
2680    call T49_C()            " throw and catch
2681    Xpath 'j'
2682  catch /.*/
2683    call assert_report('should not get here')
2684  endtry
2685
2686  try
2687    Xpath 'k'
2688    call T49_T1()  " throw, one level
2689    call assert_report('should not get here')
2690  catch /arrgh/
2691    Xpath 'l'
2692  catch /.*/
2693    call assert_report('should not get here')
2694  endtry
2695
2696  try
2697    Xpath 'm'
2698    call T49_T2()	" throw, two levels
2699    call assert_report('should not get here')
2700  catch /arrgh/
2701    Xpath 'n'
2702  catch /.*/
2703    call assert_report('should not get here')
2704  endtry
2705  Xpath 'o'
2706
2707  call assert_equal('iabcjkd2e2lmgd3e3hno', g:Xpath)
2708endfunc
2709
2710"-------------------------------------------------------------------------------
2711" Test 50:  Throwing exceptions across script files			    {{{1
2712"
2713"	    When an exception is thrown but not caught inside a script file,
2714"	    the sourcing script or function is checked for a matching :catch
2715"	    clause.
2716"
2717"	    This test executes the bodies of the functions C, T1, and T2 from
2718"	    the previous test as script files (:return replaced by :finish).
2719"-------------------------------------------------------------------------------
2720
2721func T50_F()
2722  try
2723    Xpath 'A'
2724    exec "source" g:scriptC
2725    Xpath 'B'
2726  catch /.*/
2727    call assert_report('should not get here')
2728  endtry
2729
2730  try
2731    Xpath 'C'
2732    exec "source" g:scriptT1
2733    call assert_report('should not get here')
2734  catch /arrgh/
2735    Xpath 'D'
2736  catch /.*/
2737    call assert_report('should not get here')
2738  endtry
2739endfunc
2740
2741func Test_throw_across_script()
2742  XpathINIT
2743  XloopINIT
2744  let g:scriptC = MakeScript("T49_C")
2745  let g:scriptT1 = MakeScript("T49_T1")
2746  let scriptT2 = MakeScript("T49_T2", g:scriptT1)
2747
2748  try
2749    Xpath 'E'
2750    call T50_F()
2751    Xpath 'F'
2752    exec "source" scriptT2
2753    call assert_report('should not get here')
2754  catch /arrgh/
2755    Xpath 'G'
2756  catch /.*/
2757    call assert_report('should not get here')
2758  endtry
2759  Xpath 'H'
2760  call assert_equal('EAabcBCd2e2DFgd3e3hGH', g:Xpath)
2761
2762  call delete(g:scriptC)
2763  call delete(g:scriptT1)
2764  call delete(scriptT2)
2765  unlet g:scriptC g:scriptT1 scriptT2
2766endfunc
2767
2768"-------------------------------------------------------------------------------
2769" Test 52:  Uncaught exceptions						    {{{1
2770"
2771"	    When an exception is thrown but not caught, an error message is
2772"	    displayed when the script is terminated.  In case of an interrupt
2773"	    or error exception, the normal interrupt or error message(s) are
2774"	    displayed.
2775"-------------------------------------------------------------------------------
2776
2777func Test_uncaught_exception_1()
2778  CheckEnglish
2779
2780  let test =<< trim [CODE]
2781    Xpath 'a'
2782    throw "arrgh"
2783    call assert_report('should not get here')`
2784  [CODE]
2785  let verify =<< trim [CODE]
2786    call assert_equal('E605: Exception not caught: arrgh', v:errmsg)
2787    call assert_equal('a', g:Xpath)
2788  [CODE]
2789  call RunInNewVim(test, verify)
2790endfunc
2791
2792func Test_uncaught_exception_2()
2793  CheckEnglish
2794
2795  let test =<< trim [CODE]
2796    try
2797      Xpath 'a'
2798      throw "oops"
2799      call assert_report('should not get here')`
2800    catch /arrgh/
2801      call assert_report('should not get here')`
2802    endtry
2803    call assert_report('should not get here')`
2804  [CODE]
2805  let verify =<< trim [CODE]
2806    call assert_equal('E605: Exception not caught: oops', v:errmsg)
2807    call assert_equal('a', g:Xpath)
2808  [CODE]
2809  call RunInNewVim(test, verify)
2810endfunc
2811
2812func Test_uncaught_exception_3()
2813  CheckEnglish
2814
2815  let test =<< trim [CODE]
2816    func T()
2817      Xpath 'c'
2818      throw "brrr"
2819      call assert_report('should not get here')`
2820    endfunc
2821
2822    try
2823      Xpath 'a'
2824      throw "arrgh"
2825      call assert_report('should not get here')`
2826    catch /.*/
2827      Xpath 'b'
2828      call T()
2829      call assert_report('should not get here')`
2830    endtry
2831    call assert_report('should not get here')`
2832  [CODE]
2833  let verify =<< trim [CODE]
2834    call assert_equal('E605: Exception not caught: brrr', v:errmsg)
2835    call assert_equal('abc', g:Xpath)
2836  [CODE]
2837  call RunInNewVim(test, verify)
2838endfunc
2839
2840func Test_uncaught_exception_4()
2841  CheckEnglish
2842
2843  let test =<< trim [CODE]
2844    try
2845      Xpath 'a'
2846      throw "arrgh"
2847      call assert_report('should not get here')`
2848    finally
2849      Xpath 'b'
2850      throw "brrr"
2851      call assert_report('should not get here')`
2852    endtry
2853    call assert_report('should not get here')`
2854  [CODE]
2855  let verify =<< trim [CODE]
2856    call assert_equal('E605: Exception not caught: brrr', v:errmsg)
2857    call assert_equal('ab', g:Xpath)
2858  [CODE]
2859  call RunInNewVim(test, verify)
2860endfunc
2861
2862func Test_uncaught_exception_5()
2863  CheckEnglish
2864
2865  " Need to catch and handle interrupt, otherwise the test will wait for the
2866  " user to press <Enter> to continue
2867  let test =<< trim [CODE]
2868    try
2869      try
2870        Xpath 'a'
2871        call interrupt()
2872        call assert_report('should not get here')
2873      endtry
2874      call assert_report('should not get here')
2875    catch /^Vim:Interrupt$/
2876      Xpath 'b'
2877    endtry
2878  [CODE]
2879  let verify =<< trim [CODE]
2880    call assert_equal('ab', g:Xpath)
2881  [CODE]
2882  call RunInNewVim(test, verify)
2883endfunc
2884
2885func Test_uncaught_exception_6()
2886  CheckEnglish
2887
2888  let test =<< trim [CODE]
2889    try
2890      Xpath 'a'
2891      let x = novar	" error E121; exception: E121
2892    catch /E15:/	" should not catch
2893      call assert_report('should not get here')
2894    endtry
2895    call assert_report('should not get here')
2896  [CODE]
2897  let verify =<< trim [CODE]
2898    call assert_equal('a', g:Xpath)
2899    call assert_equal('E121: Undefined variable: novar', v:errmsg)
2900  [CODE]
2901  call RunInNewVim(test, verify)
2902endfunc
2903
2904func Test_uncaught_exception_7()
2905  CheckEnglish
2906
2907  let test =<< trim [CODE]
2908    try
2909      Xpath 'a'
2910      " error E108/E488; exception: E488
2911      unlet novar #
2912    catch /E108:/       " should not catch
2913      call assert_report('should not get here')
2914    endtry
2915    call assert_report('should not get here')
2916  [CODE]
2917  let verify =<< trim [CODE]
2918    call assert_equal('a', g:Xpath)
2919    call assert_equal('E488: Trailing characters: #', v:errmsg)
2920  [CODE]
2921  call RunInNewVim(test, verify)
2922endfunc
2923
2924"-------------------------------------------------------------------------------
2925" Test 53:  Nesting errors: :endif/:else/:elseif			    {{{1
2926"
2927"	    For nesting errors of :if conditionals the correct error messages
2928"	    should be given.
2929"-------------------------------------------------------------------------------
2930
2931func Test_nested_if_else_errors()
2932  CheckEnglish
2933
2934  " :endif without :if
2935  let code =<< trim END
2936    endif
2937  END
2938  call writefile(code, 'Xtest')
2939  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
2940
2941  " :endif without :if
2942  let code =<< trim END
2943    while 1
2944      endif
2945    endwhile
2946  END
2947  call writefile(code, 'Xtest')
2948  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
2949
2950  " :endif without :if
2951  let code =<< trim END
2952    try
2953    finally
2954      endif
2955    endtry
2956  END
2957  call writefile(code, 'Xtest')
2958  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
2959
2960  " :endif without :if
2961  let code =<< trim END
2962    try
2963      endif
2964    endtry
2965  END
2966  call writefile(code, 'Xtest')
2967  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
2968
2969  " :endif without :if
2970  let code =<< trim END
2971    try
2972      throw "a"
2973    catch /a/
2974      endif
2975    endtry
2976  END
2977  call writefile(code, 'Xtest')
2978  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
2979
2980  " :else without :if
2981  let code =<< trim END
2982    else
2983  END
2984  call writefile(code, 'Xtest')
2985  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
2986
2987  " :else without :if
2988  let code =<< trim END
2989    while 1
2990      else
2991    endwhile
2992  END
2993  call writefile(code, 'Xtest')
2994  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
2995
2996  " :else without :if
2997  let code =<< trim END
2998    try
2999    finally
3000      else
3001    endtry
3002  END
3003  call writefile(code, 'Xtest')
3004  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
3005
3006  " :else without :if
3007  let code =<< trim END
3008    try
3009      else
3010    endtry
3011  END
3012  call writefile(code, 'Xtest')
3013  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
3014
3015  " :else without :if
3016  let code =<< trim END
3017    try
3018      throw "a"
3019    catch /a/
3020      else
3021    endtry
3022  END
3023  call writefile(code, 'Xtest')
3024  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
3025
3026  " :elseif without :if
3027  let code =<< trim END
3028    elseif
3029  END
3030  call writefile(code, 'Xtest')
3031  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
3032
3033  " :elseif without :if
3034  let code =<< trim END
3035    while 1
3036      elseif
3037    endwhile
3038  END
3039  call writefile(code, 'Xtest')
3040  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
3041
3042  " :elseif without :if
3043  let code =<< trim END
3044    try
3045    finally
3046      elseif
3047    endtry
3048  END
3049  call writefile(code, 'Xtest')
3050  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
3051
3052  " :elseif without :if
3053  let code =<< trim END
3054    try
3055      elseif
3056    endtry
3057  END
3058  call writefile(code, 'Xtest')
3059  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
3060
3061  " :elseif without :if
3062  let code =<< trim END
3063    try
3064      throw "a"
3065    catch /a/
3066      elseif
3067    endtry
3068  END
3069  call writefile(code, 'Xtest')
3070  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
3071
3072  " multiple :else
3073  let code =<< trim END
3074    if 1
3075    else
3076    else
3077    endif
3078  END
3079  call writefile(code, 'Xtest')
3080  call AssertException(['source Xtest'], 'Vim(else):E583: multiple :else')
3081
3082  " :elseif after :else
3083  let code =<< trim END
3084    if 1
3085    else
3086    elseif 1
3087    endif
3088  END
3089  call writefile(code, 'Xtest')
3090  call AssertException(['source Xtest'], 'Vim(elseif):E584: :elseif after :else')
3091
3092  call delete('Xtest')
3093endfunc
3094
3095"-------------------------------------------------------------------------------
3096" Test 54:  Nesting errors: :while/:endwhile				    {{{1
3097"
3098"	    For nesting errors of :while conditionals the correct error messages
3099"	    should be given.
3100"
3101"	    This test reuses the function MESSAGES() from the previous test.
3102"	    This functions checks the messages in g:msgfile.
3103"-------------------------------------------------------------------------------
3104
3105func Test_nested_while_error()
3106  CheckEnglish
3107
3108  " :endwhile without :while
3109  let code =<< trim END
3110    endwhile
3111  END
3112  call writefile(code, 'Xtest')
3113  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3114
3115  " :endwhile without :while
3116  let code =<< trim END
3117    if 1
3118      endwhile
3119    endif
3120  END
3121  call writefile(code, 'Xtest')
3122  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3123
3124  " Missing :endif
3125  let code =<< trim END
3126    while 1
3127      if 1
3128    endwhile
3129  END
3130  call writefile(code, 'Xtest')
3131  call AssertException(['source Xtest'], 'Vim(endwhile):E171: Missing :endif')
3132
3133  " :endwhile without :while
3134  let code =<< trim END
3135    try
3136    finally
3137      endwhile
3138    endtry
3139  END
3140  call writefile(code, 'Xtest')
3141  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3142
3143  " Missing :endtry
3144  let code =<< trim END
3145    while 1
3146      try
3147      finally
3148    endwhile
3149  END
3150  call writefile(code, 'Xtest')
3151  call AssertException(['source Xtest'], 'Vim(endwhile):E600: Missing :endtry')
3152
3153  " Missing :endtry
3154  let code =<< trim END
3155    while 1
3156      if 1
3157        try
3158        finally
3159    endwhile
3160  END
3161  call writefile(code, 'Xtest')
3162  call AssertException(['source Xtest'], 'Vim(endwhile):E600: Missing :endtry')
3163
3164  " Missing :endif
3165  let code =<< trim END
3166    while 1
3167      try
3168      finally
3169        if 1
3170    endwhile
3171  END
3172  call writefile(code, 'Xtest')
3173  call AssertException(['source Xtest'], 'Vim(endwhile):E171: Missing :endif')
3174
3175  " :endwhile without :while
3176  let code =<< trim END
3177    try
3178      endwhile
3179    endtry
3180  END
3181  call writefile(code, 'Xtest')
3182  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3183
3184  " :endwhile without :while
3185  let code =<< trim END
3186    while 1
3187      try
3188        endwhile
3189      endtry
3190    endwhile
3191  END
3192  call writefile(code, 'Xtest')
3193  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3194
3195  " :endwhile without :while
3196  let code =<< trim END
3197    try
3198      throw "a"
3199    catch /a/
3200      endwhile
3201    endtry
3202  END
3203  call writefile(code, 'Xtest')
3204  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3205
3206  " :endwhile without :while
3207  let code =<< trim END
3208    while 1
3209      try
3210        throw "a"
3211      catch /a/
3212        endwhile
3213      endtry
3214    endwhile
3215  END
3216  call writefile(code, 'Xtest')
3217  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
3218
3219  call delete('Xtest')
3220endfunc
3221
3222"-------------------------------------------------------------------------------
3223" Test 55:  Nesting errors: :continue/:break				    {{{1
3224"
3225"	    For nesting errors of :continue and :break commands the correct
3226"	    error messages should be given.
3227"
3228"	    This test reuses the function MESSAGES() from the previous test.
3229"	    This functions checks the messages in g:msgfile.
3230"-------------------------------------------------------------------------------
3231
3232func Test_nested_cont_break_error()
3233  CheckEnglish
3234
3235  " :continue without :while
3236  let code =<< trim END
3237    continue
3238  END
3239  call writefile(code, 'Xtest')
3240  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
3241
3242  " :continue without :while
3243  let code =<< trim END
3244    if 1
3245      continue
3246    endif
3247  END
3248  call writefile(code, 'Xtest')
3249  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
3250
3251  " :continue without :while
3252  let code =<< trim END
3253    try
3254    finally
3255      continue
3256    endtry
3257  END
3258  call writefile(code, 'Xtest')
3259  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
3260
3261  " :continue without :while
3262  let code =<< trim END
3263    try
3264      continue
3265    endtry
3266  END
3267  call writefile(code, 'Xtest')
3268  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
3269
3270  " :continue without :while
3271  let code =<< trim END
3272    try
3273      throw "a"
3274    catch /a/
3275      continue
3276    endtry
3277  END
3278  call writefile(code, 'Xtest')
3279  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
3280
3281  " :break without :while
3282  let code =<< trim END
3283    break
3284  END
3285  call writefile(code, 'Xtest')
3286  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
3287
3288  " :break without :while
3289  let code =<< trim END
3290    if 1
3291      break
3292    endif
3293  END
3294  call writefile(code, 'Xtest')
3295  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
3296
3297  " :break without :while
3298  let code =<< trim END
3299    try
3300    finally
3301      break
3302    endtry
3303  END
3304  call writefile(code, 'Xtest')
3305  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
3306
3307  " :break without :while
3308  let code =<< trim END
3309    try
3310      break
3311    endtry
3312  END
3313  call writefile(code, 'Xtest')
3314  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
3315
3316  " :break without :while
3317  let code =<< trim END
3318    try
3319      throw "a"
3320    catch /a/
3321      break
3322    endtry
3323  END
3324  call writefile(code, 'Xtest')
3325  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
3326
3327  call delete('Xtest')
3328endfunc
3329
3330"-------------------------------------------------------------------------------
3331" Test 56:  Nesting errors: :endtry					    {{{1
3332"
3333"	    For nesting errors of :try conditionals the correct error messages
3334"	    should be given.
3335"
3336"	    This test reuses the function MESSAGES() from the previous test.
3337"	    This functions checks the messages in g:msgfile.
3338"-------------------------------------------------------------------------------
3339
3340func Test_nested_endtry_error()
3341  CheckEnglish
3342
3343  " :endtry without :try
3344  let code =<< trim END
3345    endtry
3346  END
3347  call writefile(code, 'Xtest')
3348  call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try')
3349
3350  " :endtry without :try
3351  let code =<< trim END
3352    if 1
3353      endtry
3354    endif
3355  END
3356  call writefile(code, 'Xtest')
3357  call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try')
3358
3359  " :endtry without :try
3360  let code =<< trim END
3361    while 1
3362      endtry
3363    endwhile
3364  END
3365  call writefile(code, 'Xtest')
3366  call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try')
3367
3368  " Missing :endif
3369  let code =<< trim END
3370    try
3371        if 1
3372    endtry
3373  END
3374  call writefile(code, 'Xtest')
3375  call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif')
3376
3377  " Missing :endwhile
3378  let code =<< trim END
3379    try
3380      while 1
3381    endtry
3382  END
3383  call writefile(code, 'Xtest')
3384  call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile')
3385
3386  " Missing :endif
3387  let code =<< trim END
3388    try
3389    finally
3390      if 1
3391    endtry
3392  END
3393  call writefile(code, 'Xtest')
3394  call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif')
3395
3396  " Missing :endwhile
3397  let code =<< trim END
3398    try
3399    finally
3400      while 1
3401    endtry
3402  END
3403  call writefile(code, 'Xtest')
3404  call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile')
3405
3406  " Missing :endif
3407  let code =<< trim END
3408    try
3409      throw "a"
3410    catch /a/
3411      if 1
3412    endtry
3413  END
3414  call writefile(code, 'Xtest')
3415  call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif')
3416
3417  " Missing :endwhile
3418  let code =<< trim END
3419    try
3420      throw "a"
3421    catch /a/
3422      while 1
3423    endtry
3424  END
3425  call writefile(code, 'Xtest')
3426  call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile')
3427
3428  call delete('Xtest')
3429endfunc
3430
3431"-------------------------------------------------------------------------------
3432" Test 57:  v:exception and v:throwpoint for user exceptions		    {{{1
3433"
3434"	    v:exception evaluates to the value of the exception that was caught
3435"	    most recently and is not finished.  (A caught exception is finished
3436"	    when the next ":catch", ":finally", or ":endtry" is reached.)
3437"	    v:throwpoint evaluates to the script/function name and line number
3438"	    where that exception has been thrown.
3439"-------------------------------------------------------------------------------
3440
3441func Test_user_exception_info()
3442  CheckEnglish
3443
3444  XpathINIT
3445  XloopINIT
3446
3447  func FuncException()
3448    let g:exception = v:exception
3449  endfunc
3450
3451  func FuncThrowpoint()
3452    let g:throwpoint = v:throwpoint
3453  endfunc
3454
3455  let scriptException  = MakeScript("FuncException")
3456  let scriptThrowPoint = MakeScript("FuncThrowpoint")
3457
3458  command! CmdException  let g:exception  = v:exception
3459  command! CmdThrowpoint let g:throwpoint = v:throwpoint
3460
3461  func T(arg, line)
3462    if a:line == 2
3463      throw a:arg		" in line 2
3464    elseif a:line == 4
3465      throw a:arg		" in line 4
3466    elseif a:line == 6
3467      throw a:arg		" in line 6
3468    elseif a:line == 8
3469      throw a:arg		" in line 8
3470    endif
3471  endfunc
3472
3473  func G(arg, line)
3474    call T(a:arg, a:line)
3475  endfunc
3476
3477  func F(arg, line)
3478    call G(a:arg, a:line)
3479  endfunc
3480
3481  let scriptT = MakeScript("T")
3482  let scriptG = MakeScript("G", scriptT)
3483  let scriptF = MakeScript("F", scriptG)
3484
3485  try
3486    Xpath 'a'
3487    call F("oops", 2)
3488  catch /.*/
3489    Xpath 'b'
3490    let exception  = v:exception
3491    let throwpoint = v:throwpoint
3492    call assert_equal("oops", v:exception)
3493    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3494    call assert_match('\<2\>', v:throwpoint)
3495
3496    exec "let exception  = v:exception"
3497    exec "let throwpoint = v:throwpoint"
3498    call assert_equal("oops", v:exception)
3499    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3500    call assert_match('\<2\>', v:throwpoint)
3501
3502    CmdException
3503    CmdThrowpoint
3504    call assert_equal("oops", v:exception)
3505    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3506    call assert_match('\<2\>', v:throwpoint)
3507
3508    call FuncException()
3509    call FuncThrowpoint()
3510    call assert_equal("oops", v:exception)
3511    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3512    call assert_match('\<2\>', v:throwpoint)
3513
3514    exec "source" scriptException
3515    exec "source" scriptThrowPoint
3516    call assert_equal("oops", v:exception)
3517    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3518    call assert_match('\<2\>', v:throwpoint)
3519
3520    try
3521      Xpath 'c'
3522      call G("arrgh", 4)
3523    catch /.*/
3524      Xpath 'd'
3525      let exception  = v:exception
3526      let throwpoint = v:throwpoint
3527      call assert_equal("arrgh", v:exception)
3528      call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
3529      call assert_match('\<4\>', v:throwpoint)
3530
3531      try
3532        Xpath 'e'
3533        let g:arg = "autsch"
3534        let g:line = 6
3535        exec "source" scriptF
3536      catch /.*/
3537        Xpath 'f'
3538        let exception  = v:exception
3539        let throwpoint = v:throwpoint
3540        call assert_equal("autsch", v:exception)
3541        call assert_match(fnamemodify(scriptT, ':t'), v:throwpoint)
3542        call assert_match('\<6\>', v:throwpoint)
3543      finally
3544        Xpath 'g'
3545        let exception  = v:exception
3546        let throwpoint = v:throwpoint
3547        call assert_equal("arrgh", v:exception)
3548        call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
3549        call assert_match('\<4\>', v:throwpoint)
3550        try
3551          Xpath 'h'
3552          let g:arg = "brrrr"
3553          let g:line = 8
3554          exec "source" scriptG
3555        catch /.*/
3556          Xpath 'i'
3557          let exception  = v:exception
3558          let throwpoint = v:throwpoint
3559          " Resolve scriptT for matching it against v:throwpoint.
3560          call assert_equal("brrrr", v:exception)
3561          call assert_match(fnamemodify(scriptT, ':t'), v:throwpoint)
3562          call assert_match('\<8\>', v:throwpoint)
3563        finally
3564          Xpath 'j'
3565          let exception  = v:exception
3566          let throwpoint = v:throwpoint
3567          call assert_equal("arrgh", v:exception)
3568          call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
3569          call assert_match('\<4\>', v:throwpoint)
3570        endtry
3571        Xpath 'k'
3572        let exception  = v:exception
3573        let throwpoint = v:throwpoint
3574        call assert_equal("arrgh", v:exception)
3575        call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
3576        call assert_match('\<4\>', v:throwpoint)
3577      endtry
3578      Xpath 'l'
3579      let exception  = v:exception
3580      let throwpoint = v:throwpoint
3581      call assert_equal("arrgh", v:exception)
3582      call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
3583      call assert_match('\<4\>', v:throwpoint)
3584    finally
3585      Xpath 'm'
3586      let exception  = v:exception
3587      let throwpoint = v:throwpoint
3588      call assert_equal("oops", v:exception)
3589      call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3590      call assert_match('\<2\>', v:throwpoint)
3591    endtry
3592    Xpath 'n'
3593    let exception  = v:exception
3594    let throwpoint = v:throwpoint
3595    call assert_equal("oops", v:exception)
3596    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
3597    call assert_match('\<2\>', v:throwpoint)
3598  finally
3599    Xpath 'o'
3600    let exception  = v:exception
3601    let throwpoint = v:throwpoint
3602    call assert_equal("", v:exception)
3603    call assert_match('^$', v:throwpoint)
3604    call assert_match('^$', v:throwpoint)
3605  endtry
3606
3607  call assert_equal('abcdefghijklmno', g:Xpath)
3608
3609  unlet exception throwpoint
3610  delfunction FuncException
3611  delfunction FuncThrowpoint
3612  call delete(scriptException)
3613  call delete(scriptThrowPoint)
3614  unlet scriptException scriptThrowPoint
3615  delcommand CmdException
3616  delcommand CmdThrowpoint
3617  delfunction T
3618  delfunction G
3619  delfunction F
3620  call delete(scriptT)
3621  call delete(scriptG)
3622  call delete(scriptF)
3623  unlet scriptT scriptG scriptF
3624endfunc
3625
3626"-------------------------------------------------------------------------------
3627"
3628" Test 58:  v:exception and v:throwpoint for error/interrupt exceptions	    {{{1
3629"
3630"	    v:exception and v:throwpoint work also for error and interrupt
3631"	    exceptions.
3632"-------------------------------------------------------------------------------
3633
3634func Test_execption_info_for_error()
3635  CheckEnglish
3636
3637  let test =<< trim [CODE]
3638    func T(line)
3639      if a:line == 2
3640        delfunction T		" error (function in use) in line 2
3641      elseif a:line == 4
3642        call interrupt()
3643      endif
3644    endfunc
3645
3646    while 1
3647      try
3648        Xpath 'a'
3649        call T(2)
3650        call assert_report('should not get here')
3651      catch /.*/
3652        Xpath 'b'
3653        if v:exception !~ 'Vim(delfunction):'
3654          call assert_report('should not get here')
3655        endif
3656        if v:throwpoint !~ '\<T\>'
3657          call assert_report('should not get here')
3658        endif
3659        if v:throwpoint !~ '\<2\>'
3660          call assert_report('should not get here')
3661        endif
3662      finally
3663        Xpath 'c'
3664        if v:exception != ""
3665          call assert_report('should not get here')
3666        endif
3667        if v:throwpoint != ""
3668          call assert_report('should not get here')
3669        endif
3670        break
3671      endtry
3672    endwhile
3673
3674    Xpath 'd'
3675    if v:exception != ""
3676      call assert_report('should not get here')
3677    endif
3678    if v:throwpoint != ""
3679      call assert_report('should not get here')
3680    endif
3681
3682    while 1
3683      try
3684        Xpath 'e'
3685        call T(4)
3686        call assert_report('should not get here')
3687      catch /.*/
3688        Xpath 'f'
3689        if v:exception != 'Vim:Interrupt'
3690          call assert_report('should not get here')
3691        endif
3692        if v:throwpoint !~ 'function T'
3693          call assert_report('should not get here')
3694        endif
3695        if v:throwpoint !~ '\<4\>'
3696          call assert_report('should not get here')
3697        endif
3698      finally
3699        Xpath 'g'
3700        if v:exception != ""
3701          call assert_report('should not get here')
3702        endif
3703        if v:throwpoint != ""
3704          call assert_report('should not get here')
3705        endif
3706        break
3707      endtry
3708    endwhile
3709
3710    Xpath 'h'
3711    if v:exception != ""
3712      call assert_report('should not get here')
3713    endif
3714    if v:throwpoint != ""
3715      call assert_report('should not get here')
3716    endif
3717  [CODE]
3718  let verify =<< trim [CODE]
3719    call assert_equal('abcdefgh', g:Xpath)
3720  [CODE]
3721  call RunInNewVim(test, verify)
3722endfunc
3723
3724"-------------------------------------------------------------------------------
3725"
3726" Test 59:  v:exception and v:throwpoint when discarding exceptions	    {{{1
3727"
3728"	    When a :catch clause is left by a ":break" etc or an error or
3729"	    interrupt exception, v:exception and v:throwpoint are reset.  They
3730"	    are not affected by an exception that is discarded before being
3731"	    caught.
3732"-------------------------------------------------------------------------------
3733func Test_exception_info_on_discard()
3734  CheckEnglish
3735
3736  let test =<< trim [CODE]
3737    let sfile = expand("<sfile>")
3738
3739    while 1
3740      try
3741        throw "x1"
3742      catch /.*/
3743        break
3744      endtry
3745    endwhile
3746    call assert_equal('', v:exception)
3747    call assert_equal('', v:throwpoint)
3748
3749    while 1
3750      try
3751        throw "x2"
3752      catch /.*/
3753        break
3754      finally
3755        call assert_equal('', v:exception)
3756        call assert_equal('', v:throwpoint)
3757      endtry
3758      break
3759    endwhile
3760    call assert_equal('', v:exception)
3761    call assert_equal('', v:throwpoint)
3762
3763    while 1
3764      try
3765        let errcaught = 0
3766        try
3767          try
3768            throw "x3"
3769          catch /.*/
3770            let lnum = expand("<sflnum>")
3771            asdf
3772          endtry
3773        catch /.*/
3774          let errcaught = 1
3775          call assert_match('Vim:E492: Not an editor command:', v:exception)
3776          call assert_match('line ' .. (lnum + 1), v:throwpoint)
3777        endtry
3778      finally
3779        call assert_equal(1, errcaught)
3780        break
3781      endtry
3782    endwhile
3783    call assert_equal('', v:exception)
3784    call assert_equal('', v:throwpoint)
3785
3786    Xpath 'a'
3787
3788    while 1
3789      try
3790        let intcaught = 0
3791        try
3792          try
3793            throw "x4"
3794          catch /.*/
3795            let lnum = expand("<sflnum>")
3796            call interrupt()
3797          endtry
3798        catch /.*/
3799          let intcaught = 1
3800          call assert_match('Vim:Interrupt', v:exception)
3801          call assert_match('line ' .. (lnum + 1), v:throwpoint)
3802        endtry
3803      finally
3804        call assert_equal(1, intcaught)
3805        break
3806      endtry
3807    endwhile
3808    call assert_equal('', v:exception)
3809    call assert_equal('', v:throwpoint)
3810
3811    Xpath 'b'
3812
3813    while 1
3814      try
3815        let errcaught = 0
3816        try
3817          try
3818            if 1
3819              let lnum = expand("<sflnum>")
3820              throw "x5"
3821            " missing endif
3822          catch /.*/
3823            call assert_report('should not get here')
3824          endtry
3825        catch /.*/
3826          let errcaught = 1
3827          call assert_match('Vim(catch):E171: Missing :endif:', v:exception)
3828          call assert_match('line ' .. (lnum + 3), v:throwpoint)
3829        endtry
3830      finally
3831        call assert_equal(1, errcaught)
3832        break
3833      endtry
3834    endwhile
3835    call assert_equal('', v:exception)
3836    call assert_equal('', v:throwpoint)
3837
3838    Xpath 'c'
3839
3840    try
3841      while 1
3842        try
3843          throw "x6"
3844        finally
3845          break
3846        endtry
3847        break
3848      endwhile
3849    catch /.*/
3850      call assert_report('should not get here')
3851    endtry
3852    call assert_equal('', v:exception)
3853    call assert_equal('', v:throwpoint)
3854
3855    try
3856      while 1
3857        try
3858          throw "x7"
3859        finally
3860          break
3861        endtry
3862        break
3863      endwhile
3864    catch /.*/
3865      call assert_report('should not get here')
3866    finally
3867      call assert_equal('', v:exception)
3868      call assert_equal('', v:throwpoint)
3869    endtry
3870    call assert_equal('', v:exception)
3871    call assert_equal('', v:throwpoint)
3872
3873    while 1
3874      try
3875        let errcaught = 0
3876        try
3877          try
3878            throw "x8"
3879          finally
3880            let lnum = expand("<sflnum>")
3881            asdf
3882          endtry
3883        catch /.*/
3884          let errcaught = 1
3885          call assert_match('Vim:E492: Not an editor command:', v:exception)
3886          call assert_match('line ' .. (lnum + 1), v:throwpoint)
3887        endtry
3888      finally
3889        call assert_equal(1, errcaught)
3890        break
3891      endtry
3892    endwhile
3893    call assert_equal('', v:exception)
3894    call assert_equal('', v:throwpoint)
3895
3896    Xpath 'd'
3897
3898    while 1
3899      try
3900        let intcaught = 0
3901        try
3902          try
3903            throw "x9"
3904          finally
3905            let lnum = expand("<sflnum>")
3906            call interrupt()
3907          endtry
3908        catch /.*/
3909          let intcaught = 1
3910          call assert_match('Vim:Interrupt', v:exception)
3911          call assert_match('line ' .. (lnum + 1), v:throwpoint)
3912        endtry
3913      finally
3914        call assert_equal(1, intcaught)
3915        break
3916      endtry
3917    endwhile
3918    call assert_equal('', v:exception)
3919    call assert_equal('', v:throwpoint)
3920
3921    Xpath 'e'
3922
3923    while 1
3924      try
3925        let errcaught = 0
3926        try
3927          try
3928            if 1
3929              let lnum = expand("<sflnum>")
3930              throw "x10"
3931            " missing endif
3932          finally
3933            call assert_equal('', v:exception)
3934            call assert_equal('', v:throwpoint)
3935          endtry
3936        catch /.*/
3937          let errcaught = 1
3938          call assert_match('Vim(finally):E171: Missing :endif:', v:exception)
3939          call assert_match('line ' .. (lnum + 3), v:throwpoint)
3940        endtry
3941      finally
3942        call assert_equal(1, errcaught)
3943        break
3944      endtry
3945    endwhile
3946    call assert_equal('', v:exception)
3947    call assert_equal('', v:throwpoint)
3948
3949    Xpath 'f'
3950
3951    while 1
3952      try
3953        let errcaught = 0
3954        try
3955          try
3956            if 1
3957              let lnum = expand("<sflnum>")
3958              throw "x11"
3959            " missing endif
3960          endtry
3961        catch /.*/
3962          let errcaught = 1
3963          call assert_match('Vim(endtry):E171: Missing :endif:', v:exception)
3964          call assert_match('line ' .. (lnum + 3), v:throwpoint)
3965        endtry
3966      finally
3967        call assert_equal(1, errcaught)
3968        break
3969      endtry
3970    endwhile
3971    call assert_equal('', v:exception)
3972    call assert_equal('', v:throwpoint)
3973
3974    Xpath 'g'
3975  [CODE]
3976  let verify =<< trim [CODE]
3977    call assert_equal('abcdefg', g:Xpath)
3978  [CODE]
3979  call RunInNewVim(test, verify)
3980endfunc
3981
3982"-------------------------------------------------------------------------------
3983"
3984" Test 60:  (Re)throwing v:exception; :echoerr.				    {{{1
3985"
3986"	    A user exception can be rethrown after catching by throwing
3987"	    v:exception.  An error or interrupt exception cannot be rethrown
3988"	    because Vim exceptions cannot be faked.  A Vim exception using the
3989"	    value of v:exception can, however, be triggered by the :echoerr
3990"	    command.
3991"-------------------------------------------------------------------------------
3992
3993func Test_rethrow_exception_1()
3994  XpathINIT
3995  try
3996    try
3997      Xpath 'a'
3998      throw "oops"
3999    catch /oops/
4000      Xpath 'b'
4001      throw v:exception	" rethrow user exception
4002    catch /.*/
4003      call assert_report('should not get here')
4004    endtry
4005  catch /^oops$/			" catches rethrown user exception
4006    Xpath 'c'
4007  catch /.*/
4008    call assert_report('should not get here')
4009  endtry
4010  call assert_equal('abc', g:Xpath)
4011endfunc
4012
4013func Test_rethrow_exception_2()
4014  XpathINIT
4015  try
4016    let caught = 0
4017    try
4018      Xpath 'a'
4019      write /n/o/n/w/r/i/t/a/b/l/e/_/f/i/l/e
4020      call assert_report('should not get here')
4021    catch /^Vim(write):/
4022      let caught = 1
4023      throw v:exception	" throw error: cannot fake Vim exception
4024    catch /.*/
4025      call assert_report('should not get here')
4026    finally
4027      Xpath 'b'
4028      call assert_equal(1, caught)
4029    endtry
4030  catch /^Vim(throw):/	" catches throw error
4031    let caught = caught + 1
4032  catch /.*/
4033    call assert_report('should not get here')
4034  finally
4035    Xpath 'c'
4036    call assert_equal(2, caught)
4037  endtry
4038  call assert_equal('abc', g:Xpath)
4039endfunc
4040
4041func Test_rethrow_exception_3()
4042  XpathINIT
4043  try
4044    let caught = 0
4045    try
4046      Xpath 'a'
4047      asdf
4048    catch /^Vim/		" catch error exception
4049      let caught = 1
4050      " Trigger Vim error exception with value specified after :echoerr
4051      let value = substitute(v:exception, '^Vim\((.*)\)\=:', '', "")
4052      echoerr value
4053    catch /.*/
4054      call assert_report('should not get here')
4055    finally
4056      Xpath 'b'
4057      call assert_equal(1, caught)
4058    endtry
4059  catch /^Vim(echoerr):/
4060    let caught = caught + 1
4061    call assert_match(value, v:exception)
4062  catch /.*/
4063    call assert_report('should not get here')
4064  finally
4065    Xpath 'c'
4066    call assert_equal(2, caught)
4067  endtry
4068  call assert_equal('abc', g:Xpath)
4069endfunc
4070
4071func Test_rethrow_exception_3()
4072  XpathINIT
4073  try
4074    let errcaught = 0
4075    try
4076      Xpath 'a'
4077      let intcaught = 0
4078      call interrupt()
4079    catch /^Vim:/		" catch interrupt exception
4080      let intcaught = 1
4081      " Trigger Vim error exception with value specified after :echoerr
4082      echoerr substitute(v:exception, '^Vim\((.*)\)\=:', '', "")
4083    catch /.*/
4084      call assert_report('should not get here')
4085    finally
4086      Xpath 'b'
4087      call assert_equal(1, intcaught)
4088    endtry
4089  catch /^Vim(echoerr):/
4090    let errcaught = 1
4091    call assert_match('Interrupt', v:exception)
4092  finally
4093    Xpath 'c'
4094    call assert_equal(1, errcaught)
4095  endtry
4096  call assert_equal('abc', g:Xpath)
4097endfunc
4098
4099"-------------------------------------------------------------------------------
4100" Test 61:  Catching interrupt exceptions				    {{{1
4101"
4102"	    When an interrupt occurs inside a :try/:endtry region, an
4103"	    interrupt exception is thrown and can be caught.  Its value is
4104"	    "Vim:Interrupt".  If the interrupt occurs after an error or a :throw
4105"	    but before a matching :catch is reached, all following :catches of
4106"	    that try block are ignored, but the interrupt exception can be
4107"	    caught by the next surrounding try conditional.  An interrupt is
4108"	    ignored when there is a previous interrupt that has not been caught
4109"	    or causes a :finally clause to be executed.
4110"-------------------------------------------------------------------------------
4111
4112func Test_catch_intr_exception()
4113  let test =<< trim [CODE]
4114    while 1
4115      try
4116        try
4117          Xpath 'a'
4118          call interrupt()
4119          call assert_report('should not get here')
4120        catch /^Vim:Interrupt$/
4121          Xpath 'b'
4122        finally
4123          Xpath 'c'
4124        endtry
4125      catch /.*/
4126        call assert_report('should not get here')
4127      finally
4128        Xpath 'd'
4129        break
4130      endtry
4131    endwhile
4132
4133    while 1
4134      try
4135        try
4136          try
4137            Xpath 'e'
4138            asdf
4139            call assert_report('should not get here')
4140          catch /do_not_catch/
4141            call assert_report('should not get here')
4142          catch /.*/
4143            Xpath 'f'
4144            call interrupt()
4145            call assert_report('should not get here')
4146          catch /.*/
4147            call assert_report('should not get here')
4148          finally
4149            Xpath 'g'
4150            call interrupt()
4151            call assert_report('should not get here')
4152          endtry
4153        catch /^Vim:Interrupt$/
4154          Xpath 'h'
4155        finally
4156          Xpath 'i'
4157        endtry
4158      catch /.*/
4159        call assert_report('should not get here')
4160      finally
4161        Xpath 'j'
4162        break
4163      endtry
4164    endwhile
4165
4166    while 1
4167      try
4168        try
4169          try
4170            Xpath 'k'
4171            throw "x"
4172            call assert_report('should not get here')
4173          catch /do_not_catch/
4174            call assert_report('should not get here')
4175          catch /x/
4176            Xpath 'l'
4177            call interrupt()
4178            call assert_report('should not get here')
4179          catch /.*/
4180            call assert_report('should not get here')
4181          endtry
4182        catch /^Vim:Interrupt$/
4183          Xpath 'm'
4184        finally
4185          Xpath 'n'
4186        endtry
4187      catch /.*/
4188        call assert_report('should not get here')
4189      finally
4190        Xpath 'o'
4191        break
4192      endtry
4193    endwhile
4194
4195    while 1
4196      try
4197        try
4198          Xpath 'p'
4199          call interrupt()
4200          call assert_report('should not get here')
4201        catch /do_not_catch/
4202          call interrupt()
4203          call assert_report('should not get here')
4204        catch /^Vim:Interrupt$/
4205          Xpath 'q'
4206        finally
4207          Xpath 'r'
4208        endtry
4209      catch /.*/
4210        call assert_report('should not get here')
4211      finally
4212        Xpath 's'
4213        break
4214      endtry
4215    endwhile
4216
4217    Xpath 't'
4218  [CODE]
4219  let verify =<< trim [CODE]
4220    call assert_equal('abcdefghijklmnopqrst', g:Xpath)
4221  [CODE]
4222  call RunInNewVim(test, verify)
4223endfunc
4224
4225"-------------------------------------------------------------------------------
4226" Test 62:  Catching error exceptions					    {{{1
4227"
4228"	    An error inside a :try/:endtry region is converted to an exception
4229"	    and can be caught.  The error exception has a "Vim(cmdname):" prefix
4230"	    where cmdname is the name of the failing command, or a "Vim:" prefix
4231"	    if no command name is known.  The "Vim" prefixes cannot be faked.
4232"-------------------------------------------------------------------------------
4233
4234func Test_catch_err_exception_1()
4235  XpathINIT
4236  while 1
4237    try
4238      try
4239        let caught = 0
4240        unlet novar
4241      catch /^Vim(unlet):/
4242        Xpath 'a'
4243        let caught = 1
4244        let v:errmsg = substitute(v:exception, '^Vim(unlet):', '', "")
4245      finally
4246        Xpath 'b'
4247        call assert_equal(1, caught)
4248        call assert_match('E108: No such variable: "novar"', v:errmsg)
4249      endtry
4250    catch /.*/
4251      call assert_report('should not get here')
4252    finally
4253      Xpath 'c'
4254      break
4255    endtry
4256    call assert_report('should not get here')
4257  endwhile
4258  call assert_equal('abc', g:Xpath)
4259endfunc
4260
4261func Test_catch_err_exception_2()
4262  XpathINIT
4263  while 1
4264    try
4265      try
4266        let caught = 0
4267        throw novar			" error in :throw
4268      catch /^Vim(throw):/
4269        Xpath 'a'
4270        let caught = 1
4271        let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "")
4272      finally
4273        Xpath 'b'
4274        call assert_equal(1, caught)
4275        call assert_match('E121: Undefined variable: novar', v:errmsg)
4276      endtry
4277    catch /.*/
4278      call assert_report('should not get here')
4279    finally
4280      Xpath 'c'
4281      break
4282    endtry
4283    call assert_report('should not get here')
4284  endwhile
4285  call assert_equal('abc', g:Xpath)
4286endfunc
4287
4288func Test_catch_err_exception_3()
4289  XpathINIT
4290  while 1
4291    try
4292      try
4293        let caught = 0
4294        throw "Vim:faked"		" error: cannot fake Vim exception
4295      catch /^Vim(throw):/
4296        Xpath 'a'
4297        let caught = 1
4298        let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "")
4299      finally
4300        Xpath 'b'
4301        call assert_equal(1, caught)
4302        call assert_match("E608: Cannot :throw exceptions with 'Vim' prefix",
4303              \ v:errmsg)
4304      endtry
4305    catch /.*/
4306      call assert_report('should not get here')
4307    finally
4308      Xpath 'c'
4309      break
4310    endtry
4311    call assert_report('should not get here')
4312  endwhile
4313  call assert_equal('abc', g:Xpath)
4314endfunc
4315
4316func Test_catch_err_exception_4()
4317  XpathINIT
4318  func F()
4319    while 1
4320    " Missing :endwhile
4321  endfunc
4322
4323  while 1
4324    try
4325      try
4326        let caught = 0
4327        call F()
4328      catch /^Vim(endfunction):/
4329        Xpath 'a'
4330        let caught = 1
4331        let v:errmsg = substitute(v:exception, '^Vim(endfunction):', '', "")
4332      finally
4333        Xpath 'b'
4334        call assert_equal(1, caught)
4335        call assert_match("E170: Missing :endwhile", v:errmsg)
4336      endtry
4337    catch /.*/
4338      call assert_report('should not get here')
4339    finally
4340      Xpath 'c'
4341      break
4342    endtry
4343    call assert_report('should not get here')
4344  endwhile
4345  call assert_equal('abc', g:Xpath)
4346  delfunc F
4347endfunc
4348
4349func Test_catch_err_exception_5()
4350  XpathINIT
4351  func F()
4352    while 1
4353    " Missing :endwhile
4354  endfunc
4355
4356  while 1
4357    try
4358      try
4359        let caught = 0
4360        ExecAsScript F
4361      catch /^Vim:/
4362        Xpath 'a'
4363        let caught = 1
4364        let v:errmsg = substitute(v:exception, '^Vim:', '', "")
4365      finally
4366        Xpath 'b'
4367        call assert_equal(1, caught)
4368        call assert_match("E170: Missing :endwhile", v:errmsg)
4369      endtry
4370    catch /.*/
4371      call assert_report('should not get here')
4372    finally
4373      Xpath 'c'
4374      break
4375    endtry
4376    call assert_report('should not get here')
4377  endwhile
4378  call assert_equal('abc', g:Xpath)
4379  delfunc F
4380endfunc
4381
4382func Test_catch_err_exception_6()
4383  XpathINIT
4384  func G()
4385    call G()
4386  endfunc
4387
4388  while 1
4389    try
4390      let mfd_save = &mfd
4391      set mfd=3
4392      try
4393        let caught = 0
4394        call G()
4395      catch /^Vim(call):/
4396        Xpath 'a'
4397        let caught = 1
4398        let v:errmsg = substitute(v:exception, '^Vim(call):', '', "")
4399      finally
4400        Xpath 'b'
4401        call assert_equal(1, caught)
4402        call assert_match("E132: Function call depth is higher than 'maxfuncdepth'", v:errmsg)
4403      endtry
4404    catch /.*/
4405      call assert_report('should not get here')
4406    finally
4407      Xpath 'c'
4408      let &mfd = mfd_save
4409      break
4410    endtry
4411    call assert_report('should not get here')
4412  endwhile
4413  call assert_equal('abc', g:Xpath)
4414  delfunc G
4415endfunc
4416
4417func Test_catch_err_exception_7()
4418  XpathINIT
4419  func H()
4420    return H()
4421  endfunc
4422
4423  while 1
4424    try
4425      let mfd_save = &mfd
4426      set mfd=3
4427      try
4428        let caught = 0
4429        call H()
4430      catch /^Vim(return):/
4431        Xpath 'a'
4432        let caught = 1
4433        let v:errmsg = substitute(v:exception, '^Vim(return):', '', "")
4434      finally
4435        Xpath 'b'
4436        call assert_equal(1, caught)
4437        call assert_match("E132: Function call depth is higher than 'maxfuncdepth'", v:errmsg)
4438      endtry
4439    catch /.*/
4440      call assert_report('should not get here')
4441    finally
4442      Xpath 'c'
4443      let &mfd = mfd_save
4444      break		" discard error for $VIMNOERRTHROW
4445    endtry
4446    call assert_report('should not get here')
4447  endwhile
4448
4449  call assert_equal('abc', g:Xpath)
4450  delfunc H
4451endfunc
4452
4453"-------------------------------------------------------------------------------
4454" Test 63:  Suppressing error exceptions by :silent!.			    {{{1
4455"
4456"	    A :silent! command inside a :try/:endtry region suppresses the
4457"	    conversion of errors to an exception and the immediate abortion on
4458"	    error.  When the commands executed by the :silent! themselves open
4459"	    a new :try/:endtry region, conversion of errors to exception and
4460"	    immediate abortion is switched on again - until the next :silent!
4461"	    etc.  The :silent! has the effect of setting v:errmsg to the error
4462"	    message text (without displaying it) and continuing with the next
4463"	    script line.
4464"
4465"	    When a command triggering autocommands is executed by :silent!
4466"	    inside a :try/:endtry, the autocommand execution is not suppressed
4467"	    on error.
4468"
4469"	    This test reuses the function MSG() from the previous test.
4470"-------------------------------------------------------------------------------
4471
4472func Test_silent_exception()
4473  XpathINIT
4474  XloopINIT
4475  let g:taken = ""
4476
4477  func S(n) abort
4478    XloopNEXT
4479    let g:taken = g:taken . "E" . a:n
4480    let v:errmsg = ""
4481    exec "asdf" . a:n
4482
4483    " Check that ":silent!" continues:
4484    Xloop 'a'
4485
4486    " Check that ":silent!" sets "v:errmsg":
4487    call assert_match("E492: Not an editor command", v:errmsg)
4488  endfunc
4489
4490  func Foo()
4491    while 1
4492      try
4493        try
4494          let caught = 0
4495          " This is not silent:
4496          call S(3)
4497        catch /^Vim:/
4498          Xpath 'b'
4499          let caught = 1
4500          let errmsg3 = substitute(v:exception, '^Vim:', '', "")
4501          silent! call S(4)
4502        finally
4503          call assert_equal(1, caught)
4504          Xpath 'c'
4505          call assert_match("E492: Not an editor command", errmsg3)
4506          silent! call S(5)
4507          " Break out of try conditionals that cover ":silent!".  This also
4508          " discards the aborting error when $VIMNOERRTHROW is non-zero.
4509          break
4510        endtry
4511      catch /.*/
4512        call assert_report('should not get here')
4513      endtry
4514    endwhile
4515    " This is a double ":silent!" (see caller).
4516    silent! call S(6)
4517  endfunc
4518
4519  func Bar()
4520    try
4521      silent! call S(2)
4522      silent! execute "call Foo() | call S(7)"
4523      silent! call S(8)
4524    endtry	" normal end of try cond that covers ":silent!"
4525    " This has a ":silent!" from the caller:
4526    call S(9)
4527  endfunc
4528
4529  silent! call S(1)
4530  silent! call Bar()
4531  silent! call S(10)
4532
4533  call assert_equal("E1E2E3E4E5E6E7E8E9E10", g:taken)
4534
4535  augroup TMP
4536    au!
4537    autocmd BufWritePost * Xpath 'd'
4538  augroup END
4539
4540  Xpath 'e'
4541  silent! write /i/m/p/o/s/s/i/b/l/e
4542  Xpath 'f'
4543
4544  call assert_equal('a2a3ba5ca6a7a8a9a10a11edf', g:Xpath)
4545
4546  augroup TMP
4547    au!
4548  augroup END
4549  augroup! TMP
4550  delfunction S
4551  delfunction Foo
4552  delfunction Bar
4553endfunc
4554
4555"-------------------------------------------------------------------------------
4556" Test 64:  Error exceptions after error, interrupt or :throw		    {{{1
4557"
4558"	    When an error occurs after an interrupt or a :throw but before
4559"	    a matching :catch is reached, all following :catches of that try
4560"	    block are ignored, but the error exception can be caught by the next
4561"	    surrounding try conditional.  Any previous error exception is
4562"	    discarded.  An error is ignored when there is a previous error that
4563"	    has not been caught.
4564"-------------------------------------------------------------------------------
4565
4566func Test_exception_after_error_1()
4567  XpathINIT
4568  while 1
4569    try
4570      try
4571        Xpath 'a'
4572        let caught = 0
4573        while 1
4574          if 1
4575          " Missing :endif
4576        endwhile	" throw error exception
4577      catch /^Vim(/
4578        Xpath 'b'
4579        let caught = 1
4580      finally
4581        Xpath 'c'
4582        call assert_equal(1, caught)
4583      endtry
4584    catch /.*/
4585      call assert_report('should not get here')
4586    finally
4587      Xpath 'd'
4588      break
4589    endtry
4590    call assert_report('should not get here')
4591  endwhile
4592  call assert_equal('abcd', g:Xpath)
4593endfunc
4594
4595func Test_exception_after_error_2()
4596  XpathINIT
4597  while 1
4598    try
4599      try
4600        Xpath 'a'
4601        let caught = 0
4602        try
4603          if 1
4604          " Missing :endif
4605        catch /.*/	" throw error exception
4606          call assert_report('should not get here')
4607        catch /.*/
4608          call assert_report('should not get here')
4609        endtry
4610      catch /^Vim(/
4611        Xpath 'b'
4612        let caught = 1
4613      finally
4614        Xpath 'c'
4615        call assert_equal(1, caught)
4616      endtry
4617    catch /.*/
4618      call assert_report('should not get here')
4619    finally
4620      Xpath 'd'
4621      break
4622    endtry
4623    call assert_report('should not get here')
4624  endwhile
4625  call assert_equal('abcd', g:Xpath)
4626endfunc
4627
4628func Test_exception_after_error_3()
4629  XpathINIT
4630  while 1
4631    try
4632      try
4633        let caught = 0
4634        try
4635          Xpath 'a'
4636          call interrupt()
4637        catch /do_not_catch/
4638          call assert_report('should not get here')
4639          if 1
4640          " Missing :endif
4641        catch /.*/	" throw error exception
4642          call assert_report('should not get here')
4643        catch /.*/
4644          call assert_report('should not get here')
4645        endtry
4646      catch /^Vim(/
4647        Xpath 'b'
4648        let caught = 1
4649      finally
4650        Xpath 'c'
4651        call assert_equal(1, caught)
4652      endtry
4653    catch /.*/
4654      call assert_report('should not get here')
4655    finally
4656      Xpath 'd'
4657      break
4658    endtry
4659    call assert_report('should not get here')
4660  endwhile
4661  call assert_equal('abcd', g:Xpath)
4662endfunc
4663
4664func Test_exception_after_error_4()
4665  XpathINIT
4666  while 1
4667    try
4668      try
4669        let caught = 0
4670        try
4671          Xpath 'a'
4672          throw "x"
4673        catch /do_not_catch/
4674          call assert_report('should not get here')
4675          if 1
4676          " Missing :endif
4677        catch /x/	" throw error exception
4678          call assert_report('should not get here')
4679        catch /.*/
4680          call assert_report('should not get here')
4681        endtry
4682      catch /^Vim(/
4683        Xpath 'b'
4684        let caught = 1
4685      finally
4686        Xpath 'c'
4687        call assert_equal(1, caught)
4688      endtry
4689    catch /.*/
4690      call assert_report('should not get here')
4691    finally
4692      Xpath 'd'
4693      break
4694    endtry
4695    call assert_report('should not get here')
4696  endwhile
4697  call assert_equal('abcd', g:Xpath)
4698endfunc
4699
4700func Test_exception_after_error_5()
4701  XpathINIT
4702  while 1
4703    try
4704      try
4705        let caught = 0
4706        Xpath 'a'
4707        endif		" :endif without :if; throw error exception
4708        if 1
4709        " Missing :endif
4710      catch /do_not_catch/ " ignore new error
4711        call assert_report('should not get here')
4712      catch /^Vim(endif):/
4713        Xpath 'b'
4714        let caught = 1
4715      catch /^Vim(/
4716        call assert_report('should not get here')
4717      finally
4718        Xpath 'c'
4719        call assert_equal(1, caught)
4720      endtry
4721    catch /.*/
4722      call assert_report('should not get here')
4723    finally
4724      Xpath 'd'
4725      break
4726    endtry
4727    call assert_report('should not get here')
4728  endwhile
4729  call assert_equal('abcd', g:Xpath)
4730endfunc
4731
4732"-------------------------------------------------------------------------------
4733" Test 65:  Errors in the /pattern/ argument of a :catch		    {{{1
4734"
4735"	    On an error in the /pattern/ argument of a :catch, the :catch does
4736"	    not match.  Any following :catches of the same :try/:endtry don't
4737"	    match either.  Finally clauses are executed.
4738"-------------------------------------------------------------------------------
4739
4740func Test_catch_pattern_error()
4741  CheckEnglish
4742  XpathINIT
4743
4744  try
4745    try
4746      Xpath 'a'
4747      throw "oops"
4748    catch /^oops$/
4749      Xpath 'b'
4750    catch /\)/		" not checked; exception has already been caught
4751      call assert_report('should not get here')
4752    endtry
4753    Xpath 'c'
4754  catch /.*/
4755    call assert_report('should not get here')
4756  endtry
4757  call assert_equal('abc', g:Xpath)
4758
4759  XpathINIT
4760  func F()
4761    try
4762      try
4763        try
4764          Xpath 'a'
4765          throw "ab"
4766        catch /abc/	" does not catch
4767          call assert_report('should not get here')
4768        catch /\)/	" error; discards exception
4769          call assert_report('should not get here')
4770        catch /.*/	" not checked
4771          call assert_report('should not get here')
4772        finally
4773          Xpath 'b'
4774        endtry
4775        call assert_report('should not get here')
4776      catch /^ab$/	" checked, but original exception is discarded
4777        call assert_report('should not get here')
4778      catch /^Vim(catch):/
4779        Xpath 'c'
4780        call assert_match('Vim(catch):E475: Invalid argument:', v:exception)
4781      finally
4782        Xpath 'd'
4783      endtry
4784      Xpath 'e'
4785    catch /.*/
4786      call assert_report('should not get here')
4787    endtry
4788    Xpath 'f'
4789  endfunc
4790
4791  call F()
4792  call assert_equal('abcdef', g:Xpath)
4793
4794  delfunc F
4795endfunc
4796
4797"-------------------------------------------------------------------------------
4798" Test 66:  Stop range :call on error, interrupt, or :throw		    {{{1
4799"
4800"	    When a function which is multiply called for a range since it
4801"	    doesn't handle the range itself has an error in a command
4802"	    dynamically enclosed by :try/:endtry or gets an interrupt or
4803"	    executes a :throw, no more calls for the remaining lines in the
4804"	    range are made.  On an error in a command not dynamically enclosed
4805"	    by :try/:endtry, the function is executed again for the remaining
4806"	    lines in the range.
4807"-------------------------------------------------------------------------------
4808
4809func Test_stop_range_on_error()
4810  let test =<< trim [CODE]
4811    let file = tempname()
4812    exec "edit" file
4813    call setline(1, ['line 1', 'line 2', 'line 3'])
4814    let taken = ""
4815    let expected = "G1EF1E(1)F1E(2)F1E(3)G2EF2E(1)G3IF3I(1)G4TF4T(1)G5AF5A(1)"
4816
4817    func F(reason, n) abort
4818      let g:taken = g:taken .. "F" .. a:n ..
4819                          \ substitute(a:reason, '\(\l\).*', '\u\1', "") ..
4820                          \ "(" .. line(".") .. ")"
4821
4822      if a:reason == "error"
4823        asdf
4824      elseif a:reason == "interrupt"
4825        call interrupt()
4826      elseif a:reason == "throw"
4827        throw "xyz"
4828      elseif a:reason == "aborting error"
4829        XloopNEXT
4830        call assert_equal(g:taken, g:expected)
4831        try
4832          bwipeout!
4833          call delete(g:file)
4834          asdf
4835        endtry
4836      endif
4837    endfunc
4838
4839    func G(reason, n)
4840      let g:taken = g:taken .. "G" .. a:n ..
4841                              \ substitute(a:reason, '\(\l\).*', '\u\1', "")
4842      1,3call F(a:reason, a:n)
4843    endfunc
4844
4845    Xpath 'a'
4846    call G("error", 1)
4847    try
4848      Xpath 'b'
4849      try
4850        call G("error", 2)
4851        call assert_report('should not get here')
4852      finally
4853        Xpath 'c'
4854        try
4855          call G("interrupt", 3)
4856          call assert_report('should not get here')
4857        finally
4858          Xpath 'd'
4859          try
4860            call G("throw", 4)
4861            call assert_report('should not get here')
4862          endtry
4863        endtry
4864      endtry
4865    catch /xyz/
4866      Xpath 'e'
4867    catch /.*/
4868      call assert_report('should not get here')
4869    endtry
4870    Xpath 'f'
4871    call G("aborting error", 5)
4872    call assert_report('should not get here')
4873  [CODE]
4874  let verify =<< trim [CODE]
4875    call assert_equal('abcdef', g:Xpath)
4876  [CODE]
4877  call RunInNewVim(test, verify)
4878endfunc
4879
4880"-------------------------------------------------------------------------------
4881" Test 67:  :throw across :call command					    {{{1
4882"
4883"	    On a call command, an exception might be thrown when evaluating the
4884"	    function name, during evaluation of the arguments, or when the
4885"	    function is being executed.  The exception can be caught by the
4886"	    caller.
4887"-------------------------------------------------------------------------------
4888
4889func THROW(x, n)
4890  if a:n == 1
4891    Xpath 'A'
4892  elseif a:n == 2
4893    Xpath 'B'
4894  elseif a:n == 3
4895    Xpath 'C'
4896  endif
4897  throw a:x
4898endfunc
4899
4900func NAME(x, n)
4901  if a:n == 1
4902    call assert_report('should not get here')
4903  elseif a:n == 2
4904    Xpath 'D'
4905  elseif a:n == 3
4906    Xpath 'E'
4907  elseif a:n == 4
4908    Xpath 'F'
4909  endif
4910  return a:x
4911endfunc
4912
4913func ARG(x, n)
4914  if a:n == 1
4915    call assert_report('should not get here')
4916  elseif a:n == 2
4917    call assert_report('should not get here')
4918  elseif a:n == 3
4919    Xpath 'G'
4920  elseif a:n == 4
4921    Xpath 'I'
4922  endif
4923  return a:x
4924endfunc
4925
4926func Test_throw_across_call_cmd()
4927  XpathINIT
4928
4929  func F(x, n)
4930    if a:n == 2
4931      call assert_report('should not get here')
4932    elseif a:n == 4
4933      Xpath 'a'
4934    endif
4935  endfunc
4936
4937  while 1
4938    try
4939      let v:errmsg = ""
4940
4941      while 1
4942        try
4943          Xpath 'b'
4944          call {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1)
4945          call assert_report('should not get here')
4946        catch /^name$/
4947          Xpath 'c'
4948        catch /.*/
4949          call assert_report('should not get here')
4950        finally
4951          call assert_equal("", v:errmsg)
4952          let v:errmsg = ""
4953          break
4954        endtry
4955      endwhile
4956
4957      while 1
4958        try
4959          Xpath 'd'
4960          call {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2)
4961          call assert_report('should not get here')
4962        catch /^arg$/
4963          Xpath 'e'
4964        catch /.*/
4965          call assert_report('should not get here')
4966        finally
4967          call assert_equal("", v:errmsg)
4968          let v:errmsg = ""
4969          break
4970        endtry
4971      endwhile
4972
4973      while 1
4974        try
4975          Xpath 'f'
4976          call {NAME("THROW", 3)}(ARG("call", 3), 3)
4977          call assert_report('should not get here')
4978        catch /^call$/
4979          Xpath 'g'
4980        catch /^0$/	    " default return value
4981          call assert_report('should not get here')
4982        catch /.*/
4983          call assert_report('should not get here')
4984        finally
4985          call assert_equal("", v:errmsg)
4986          let v:errmsg = ""
4987          break
4988        endtry
4989      endwhile
4990
4991      while 1
4992        try
4993          Xpath 'h'
4994          call {NAME("F", 4)}(ARG(4711, 4), 4)
4995          Xpath 'i'
4996        catch /.*/
4997          call assert_report('should not get here')
4998        finally
4999          call assert_equal("", v:errmsg)
5000          let v:errmsg = ""
5001          break
5002        endtry
5003      endwhile
5004
5005    catch /^0$/	    " default return value
5006      call assert_report('should not get here')
5007    catch /.*/
5008      call assert_report('should not get here')
5009    finally
5010      call assert_equal("", v:errmsg)
5011      let v:errmsg = ""
5012      break
5013    endtry
5014  endwhile
5015
5016  call assert_equal('bAcdDBefEGCghFIai', g:Xpath)
5017  delfunction F
5018endfunc
5019
5020"-------------------------------------------------------------------------------
5021" Test 68:  :throw across function calls in expressions			    {{{1
5022"
5023"	    On a function call within an expression, an exception might be
5024"	    thrown when evaluating the function name, during evaluation of the
5025"	    arguments, or when the function is being executed.  The exception
5026"	    can be caught by the caller.
5027"
5028"	    This test reuses the functions THROW(), NAME(), and ARG() from the
5029"	    previous test.
5030"-------------------------------------------------------------------------------
5031
5032func Test_throw_across_call_expr()
5033  XpathINIT
5034
5035  func F(x, n)
5036    if a:n == 2
5037      call assert_report('should not get here')
5038    elseif a:n == 4
5039      Xpath 'a'
5040    endif
5041    return a:x
5042  endfunction
5043
5044  while 1
5045    try
5046      let error = 0
5047      let v:errmsg = ""
5048
5049      while 1
5050        try
5051          Xpath 'b'
5052          let var1 = {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1)
5053          call assert_report('should not get here')
5054        catch /^name$/
5055          Xpath 'c'
5056        catch /.*/
5057          call assert_report('should not get here')
5058        finally
5059          call assert_equal("", v:errmsg)
5060          let v:errmsg = ""
5061          break
5062        endtry
5063      endwhile
5064      call assert_true(!exists('var1'))
5065
5066      while 1
5067        try
5068          Xpath 'd'
5069          let var2 = {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2)
5070          call assert_report('should not get here')
5071        catch /^arg$/
5072          Xpath 'e'
5073        catch /.*/
5074          call assert_report('should not get here')
5075        finally
5076          call assert_equal("", v:errmsg)
5077          let v:errmsg = ""
5078          break
5079        endtry
5080      endwhile
5081      call assert_true(!exists('var2'))
5082
5083      while 1
5084        try
5085          Xpath 'f'
5086          let var3 = {NAME("THROW", 3)}(ARG("call", 3), 3)
5087          call assert_report('should not get here')
5088        catch /^call$/
5089          Xpath 'g'
5090        catch /^0$/	    " default return value
5091          call assert_report('should not get here')
5092        catch /.*/
5093          call assert_report('should not get here')
5094        finally
5095          call assert_equal("", v:errmsg)
5096          let v:errmsg = ""
5097          break
5098        endtry
5099      endwhile
5100      call assert_true(!exists('var3'))
5101
5102      while 1
5103        try
5104          Xpath 'h'
5105          let var4 = {NAME("F", 4)}(ARG(4711, 4), 4)
5106          Xpath 'i'
5107        catch /.*/
5108          call assert_report('should not get here')
5109        finally
5110          call assert_equal("", v:errmsg)
5111          let v:errmsg = ""
5112          break
5113        endtry
5114      endwhile
5115      call assert_true(exists('var4') && var4 == 4711)
5116
5117    catch /^0$/	    " default return value
5118      call assert_report('should not get here')
5119    catch /.*/
5120      call assert_report('should not get here')
5121    finally
5122      call assert_equal("", v:errmsg)
5123      break
5124    endtry
5125  endwhile
5126
5127  call assert_equal('bAcdDBefEGCghFIai', g:Xpath)
5128  delfunc F
5129endfunc
5130
5131"-------------------------------------------------------------------------------
5132" Test 76:  Errors, interrupts, :throw during expression evaluation	    {{{1
5133"
5134"	    When a function call made during expression evaluation is aborted
5135"	    due to an error inside a :try/:endtry region or due to an interrupt
5136"	    or a :throw, the expression evaluation is aborted as well.	No
5137"	    message is displayed for the cancelled expression evaluation.  On an
5138"	    error not inside :try/:endtry, the expression evaluation continues.
5139"-------------------------------------------------------------------------------
5140
5141func Test_expr_eval_error()
5142  let test =<< trim [CODE]
5143    let taken = ""
5144
5145    func ERR(n)
5146      let g:taken = g:taken .. "E" .. a:n
5147      asdf
5148    endfunc
5149
5150    func ERRabort(n) abort
5151      let g:taken = g:taken .. "A" .. a:n
5152      asdf
5153    endfunc	" returns -1; may cause follow-up msg for illegal var/func name
5154
5155    func WRAP(n, arg)
5156      let g:taken = g:taken .. "W" .. a:n
5157      let g:saved_errmsg = v:errmsg
5158      return arg
5159    endfunc
5160
5161    func INT(n)
5162      let g:taken = g:taken .. "I" .. a:n
5163      call interrupt()
5164    endfunc
5165
5166    func THR(n)
5167      let g:taken = g:taken .. "T" .. a:n
5168      throw "should not be caught"
5169    endfunc
5170
5171    func CONT(n)
5172      let g:taken = g:taken .. "C" .. a:n
5173    endfunc
5174
5175    func MSG(n)
5176      let g:taken = g:taken .. "M" .. a:n
5177      let errmsg = (a:n >= 37 && a:n <= 44) ? g:saved_errmsg : v:errmsg
5178      let msgptn = (a:n >= 10 && a:n <= 27) ? "^$" : "asdf"
5179      call assert_match(msgptn, errmsg)
5180      let v:errmsg = ""
5181      let g:saved_errmsg = ""
5182    endfunc
5183
5184    let v:errmsg = ""
5185
5186    try
5187      let t = 1
5188      while t <= 9
5189        Xloop 'a'
5190        try
5191          if t == 1
5192            let v{ERR(t) + CONT(t)} = 0
5193          elseif t == 2
5194            let v{ERR(t) + CONT(t)}
5195          elseif t == 3
5196            let var = exists('v{ERR(t) + CONT(t)}')
5197          elseif t == 4
5198            unlet v{ERR(t) + CONT(t)}
5199          elseif t == 5
5200            function F{ERR(t) + CONT(t)}()
5201            endfunction
5202          elseif t == 6
5203            function F{ERR(t) + CONT(t)}
5204          elseif t == 7
5205            let var = exists('*F{ERR(t) + CONT(t)}')
5206          elseif t == 8
5207            delfunction F{ERR(t) + CONT(t)}
5208          elseif t == 9
5209            let var = ERR(t) + CONT(t)
5210          endif
5211        catch /asdf/
5212          " v:errmsg is not set when the error message is converted to an
5213          " exception.  Set it to the original error message.
5214          let v:errmsg = substitute(v:exception, '^Vim:', '', "")
5215        catch /^Vim\((\a\+)\)\=:/
5216          " An error exception has been thrown after the original error.
5217          let v:errmsg = ""
5218        finally
5219          call MSG(t)
5220          let t = t + 1
5221          XloopNEXT
5222          continue	" discard an aborting error
5223        endtry
5224      endwhile
5225    catch /.*/
5226      call assert_report('should not get here')
5227    endtry
5228
5229    try
5230      let t = 10
5231      while t <= 18
5232        Xloop 'b'
5233        try
5234          if t == 10
5235            let v{INT(t) + CONT(t)} = 0
5236          elseif t == 11
5237            let v{INT(t) + CONT(t)}
5238          elseif t == 12
5239            let var = exists('v{INT(t) + CONT(t)}')
5240          elseif t == 13
5241            unlet v{INT(t) + CONT(t)}
5242          elseif t == 14
5243            function F{INT(t) + CONT(t)}()
5244            endfunction
5245          elseif t == 15
5246            function F{INT(t) + CONT(t)}
5247          elseif t == 16
5248            let var = exists('*F{INT(t) + CONT(t)}')
5249          elseif t == 17
5250            delfunction F{INT(t) + CONT(t)}
5251          elseif t == 18
5252            let var = INT(t) + CONT(t)
5253          endif
5254        catch /^Vim\((\a\+)\)\=:\(Interrupt\)\@!/
5255          " An error exception has been triggered after the interrupt.
5256          let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
5257        finally
5258          call MSG(t)
5259          let t = t + 1
5260          XloopNEXT
5261          continue	" discard interrupt
5262        endtry
5263      endwhile
5264    catch /.*/
5265      call assert_report('should not get here')
5266    endtry
5267
5268    try
5269      let t = 19
5270      while t <= 27
5271        Xloop 'c'
5272        try
5273          if t == 19
5274            let v{THR(t) + CONT(t)} = 0
5275          elseif t == 20
5276            let v{THR(t) + CONT(t)}
5277          elseif t == 21
5278            let var = exists('v{THR(t) + CONT(t)}')
5279          elseif t == 22
5280            unlet v{THR(t) + CONT(t)}
5281          elseif t == 23
5282            function F{THR(t) + CONT(t)}()
5283            endfunction
5284          elseif t == 24
5285            function F{THR(t) + CONT(t)}
5286          elseif t == 25
5287            let var = exists('*F{THR(t) + CONT(t)}')
5288          elseif t == 26
5289            delfunction F{THR(t) + CONT(t)}
5290          elseif t == 27
5291            let var = THR(t) + CONT(t)
5292          endif
5293        catch /^Vim\((\a\+)\)\=:/
5294          " An error exception has been triggered after the :throw.
5295          let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
5296        finally
5297          call MSG(t)
5298          let t = t + 1
5299          XloopNEXT
5300          continue	" discard exception
5301        endtry
5302      endwhile
5303    catch /.*/
5304      call assert_report('should not get here')
5305    endtry
5306
5307    let v{ERR(28) + CONT(28)} = 0
5308    call MSG(28)
5309    let v{ERR(29) + CONT(29)}
5310    call MSG(29)
5311    let var = exists('v{ERR(30) + CONT(30)}')
5312    call MSG(30)
5313    unlet v{ERR(31) + CONT(31)}
5314    call MSG(31)
5315    function F{ERR(32) + CONT(32)}()
5316    endfunction
5317    call MSG(32)
5318    function F{ERR(33) + CONT(33)}
5319    call MSG(33)
5320    let var = exists('*F{ERR(34) + CONT(34)}')
5321    call MSG(34)
5322    delfunction F{ERR(35) + CONT(35)}
5323    call MSG(35)
5324    let var = ERR(36) + CONT(36)
5325    call MSG(36)
5326
5327    let saved_errmsg = ""
5328
5329    let v{WRAP(37, ERRabort(37)) + CONT(37)} = 0
5330    call MSG(37)
5331    let v{WRAP(38, ERRabort(38)) + CONT(38)}
5332    call MSG(38)
5333    let var = exists('v{WRAP(39, ERRabort(39)) + CONT(39)}')
5334    call MSG(39)
5335    unlet v{WRAP(40, ERRabort(40)) + CONT(40)}
5336    call MSG(40)
5337    function F{WRAP(41, ERRabort(41)) + CONT(41)}()
5338    endfunction
5339    call MSG(41)
5340    function F{WRAP(42, ERRabort(42)) + CONT(42)}
5341    call MSG(42)
5342    let var = exists('*F{WRAP(43, ERRabort(43)) + CONT(43)}')
5343    call MSG(43)
5344    delfunction F{WRAP(44, ERRabort(44)) + CONT(44)}
5345    call MSG(44)
5346    let var = ERRabort(45) + CONT(45)
5347    call MSG(45)
5348    Xpath 'd'
5349
5350    let expected = ""
5351          \ .. "E1M1E2M2E3M3E4M4E5M5E6M6E7M7E8M8E9M9"
5352          \ .. "I10M10I11M11I12M12I13M13I14M14I15M15I16M16I17M17I18M18"
5353          \ .. "T19M19T20M20T21M21T22M22T23M23T24M24T25M25T26M26T27M27"
5354          \ .. "E28C28M28E29C29M29E30C30M30E31C31M31E32C32M32E33C33M33"
5355          \ .. "E34C34M34E35C35M35E36C36M36"
5356          \ .. "A37W37C37M37A38W38C38M38A39W39C39M39A40W40C40M40A41W41C41M41"
5357          \ .. "A42W42C42M42A43W43C43M43A44W44C44M44A45C45M45"
5358    call assert_equal(expected, taken)
5359  [CODE]
5360  let verify =<< trim [CODE]
5361    let expected = "a1a2a3a4a5a6a7a8a9"
5362                      \ .. "b10b11b12b13b14b15b16b17b18"
5363                      \ .. "c19c20c21c22c23c24c25c26c27d"
5364    call assert_equal(expected, g:Xpath)
5365  [CODE]
5366  call RunInNewVim(test, verify)
5367endfunc
5368
5369"-------------------------------------------------------------------------------
5370" Test 77:  Errors, interrupts, :throw in name{brace-expression}	    {{{1
5371"
5372"	    When a function call made during evaluation of an expression in
5373"	    braces as part of a function name after ":function" is aborted due
5374"	    to an error inside a :try/:endtry region or due to an interrupt or
5375"	    a :throw, the expression evaluation is aborted as well, and the
5376"	    function definition is ignored, skipping all commands to the
5377"	    ":endfunction".  On an error not inside :try/:endtry, the expression
5378"	    evaluation continues and the function gets defined, and can be
5379"	    called and deleted.
5380"-------------------------------------------------------------------------------
5381func Test_brace_expr_error()
5382  let test =<< trim [CODE]
5383    func ERR() abort
5384      Xloop 'a'
5385      asdf
5386    endfunc					" returns -1
5387
5388    func OK()
5389      Xloop 'b'
5390      let v:errmsg = ""
5391      return 0
5392    endfunc
5393
5394    let v:errmsg = ""
5395
5396    Xpath 'c'
5397    func F{1 + ERR() + OK()}(arg)
5398      " F0 should be defined.
5399      if exists("a:arg") && a:arg == "calling"
5400        Xpath 'd'
5401      else
5402        call assert_report('should not get here')
5403      endif
5404    endfunction
5405    call assert_equal("", v:errmsg)
5406    XloopNEXT
5407
5408    Xpath 'e'
5409    call F{1 + ERR() + OK()}("calling")
5410    call assert_equal("", v:errmsg)
5411    XloopNEXT
5412
5413    Xpath 'f'
5414    delfunction F{1 + ERR() + OK()}
5415    call assert_equal("", v:errmsg)
5416    XloopNEXT
5417
5418    try
5419      while 1
5420        try
5421          Xpath 'g'
5422          func G{1 + ERR() + OK()}(arg)
5423            " G0 should not be defined, and the function body should be
5424            " skipped.
5425            call assert_report('should not get here')
5426            " Use an unmatched ":finally" to check whether the body is
5427            " skipped when an error occurs in ERR().  This works whether or
5428            " not the exception is converted to an exception.
5429            finally
5430              call assert_report('should not get here')
5431            endtry
5432          try
5433            call assert_report('should not get here')
5434          endfunction
5435
5436          call assert_report('should not get here')
5437        catch /asdf/
5438          " Jumped to when the function is not defined and the body is
5439          " skipped.
5440          Xpath 'h'
5441        catch /.*/
5442          call assert_report('should not get here')
5443        finally
5444          Xpath 'i'
5445          break
5446        endtry			" jumped to when the body is not skipped
5447      endwhile
5448    catch /.*/
5449      call assert_report('should not get here')
5450    endtry
5451  [CODE]
5452  let verify =<< trim [CODE]
5453    call assert_equal('ca1b1ea2b2dfa3b3ga4hi', g:Xpath)
5454  [CODE]
5455  call RunInNewVim(test, verify)
5456endfunc
5457
5458"-------------------------------------------------------------------------------
5459" Test 78:  Messages on parsing errors in expression evaluation		    {{{1
5460"
5461"	    When an expression evaluation detects a parsing error, an error
5462"	    message is given and converted to an exception, and the expression
5463"	    evaluation is aborted.
5464"-------------------------------------------------------------------------------
5465func Test_expr_eval_error_msg()
5466  CheckEnglish
5467
5468  let test =<< trim [CODE]
5469    let taken = ""
5470
5471    func F(n)
5472      let g:taken = g:taken . "F" . a:n
5473    endfunc
5474
5475    func MSG(n, enr, emsg)
5476      let g:taken = g:taken . "M" . a:n
5477      call assert_match('^' .. a:enr .. ':', v:errmsg)
5478      call assert_match(a:emsg, v:errmsg)
5479    endfunc
5480
5481    func CONT(n)
5482      let g:taken = g:taken . "C" . a:n
5483    endfunc
5484
5485    let v:errmsg = ""
5486    try
5487      let t = 1
5488      while t <= 14
5489        let g:taken = g:taken . "T" . t
5490        let v:errmsg = ""
5491        try
5492          if t == 1
5493            let v{novar + CONT(t)} = 0
5494          elseif t == 2
5495            let v{novar + CONT(t)}
5496          elseif t == 3
5497            let var = exists('v{novar + CONT(t)}')
5498          elseif t == 4
5499            unlet v{novar + CONT(t)}
5500          elseif t == 5
5501            function F{novar + CONT(t)}()
5502            endfunction
5503          elseif t == 6
5504            function F{novar + CONT(t)}
5505          elseif t == 7
5506            let var = exists('*F{novar + CONT(t)}')
5507          elseif t == 8
5508            delfunction F{novar + CONT(t)}
5509          elseif t == 9
5510            echo novar + CONT(t)
5511          elseif t == 10
5512            echo v{novar + CONT(t)}
5513          elseif t == 11
5514            echo F{novar + CONT(t)}
5515          elseif t == 12
5516            let var = novar + CONT(t)
5517          elseif t == 13
5518            let var = v{novar + CONT(t)}
5519          elseif t == 14
5520            let var = F{novar + CONT(t)}()
5521          endif
5522        catch /^Vim\((\a\+)\)\=:/
5523          Xloop 'a'
5524          " v:errmsg is not set when the error message is converted to an
5525          " exception.  Set it to the original error message.
5526          let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
5527        finally
5528          Xloop 'b'
5529          if t <= 8 && t != 3 && t != 7
5530            call MSG(t, 'E475', 'Invalid argument\>')
5531          else
5532            call MSG(t, 'E121', "Undefined variable")
5533          endif
5534          let t = t + 1
5535          XloopNEXT
5536          continue	" discard an aborting error
5537        endtry
5538      endwhile
5539    catch /.*/
5540      call assert_report('should not get here')
5541    endtry
5542
5543    func T(n, expr, enr, emsg)
5544      try
5545        let g:taken = g:taken . "T" . a:n
5546        let v:errmsg = ""
5547        try
5548          execute "let var = " . a:expr
5549        catch /^Vim\((\a\+)\)\=:/
5550          Xloop 'c'
5551          " v:errmsg is not set when the error message is converted to an
5552          " exception.  Set it to the original error message.
5553          let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
5554        finally
5555          Xloop 'd'
5556          call MSG(a:n, a:enr, a:emsg)
5557          XloopNEXT
5558          " Discard an aborting error:
5559          return
5560        endtry
5561      catch /.*/
5562        call assert_report('should not get here')
5563      endtry
5564    endfunc
5565
5566    call T(15, 'Nofunc() + CONT(15)',	'E117',	"Unknown function")
5567    call T(16, 'F(1 2 + CONT(16))',	'E116',	"Invalid arguments")
5568    call T(17, 'F(1, 2) + CONT(17)',	'E118',	"Too many arguments")
5569    call T(18, 'F() + CONT(18)',	'E119',	"Not enough arguments")
5570    call T(19, '{(1} + CONT(19)',	'E110',	"Missing ')'")
5571    call T(20, '("abc"[1) + CONT(20)',	'E111',	"Missing ']'")
5572    call T(21, '(1 +) + CONT(21)',	'E15',	"Invalid expression")
5573    call T(22, '1 2 + CONT(22)',	'E15',	"Invalid expression")
5574    call T(23, '(1 ? 2) + CONT(23)',	'E109',	"Missing ':' after '?'")
5575    call T(24, '("abc) + CONT(24)',	'E114',	"Missing quote")
5576    call T(25, "('abc) + CONT(25)",	'E115',	"Missing quote")
5577    call T(26, '& + CONT(26)',		'E112', "Option name missing")
5578    call T(27, '&asdf + CONT(27)',	'E113', "Unknown option")
5579
5580    let expected = ""
5581      \ .. "T1M1T2M2T3M3T4M4T5M5T6M6T7M7T8M8T9M9T10M10T11M11T12M12T13M13T14M14"
5582      \ .. "T15M15T16M16T17M17T18M18T19M19T20M20T21M21T22M22T23M23T24M24T25M25"
5583      \ .. "T26M26T27M27"
5584
5585    call assert_equal(expected, taken)
5586  [CODE]
5587  let verify =<< trim [CODE]
5588    let expected = "a1b1a2b2a3b3a4b4a5b5a6b6a7b7a8b8a9b9a10b10a11b11a12b12"
5589                  \ .. "a13b13a14b14c15d15c16d16c17d17c18d18c19d19c20d20"
5590                  \ .. "c21d21c22d22c23d23c24d24c25d25c26d26c27d27"
5591    call assert_equal(expected, g:Xpath)
5592  [CODE]
5593  call RunInNewVim(test, verify)
5594endfunc
5595
5596"-------------------------------------------------------------------------------
5597" Test 79:  Throwing one of several errors for the same command		    {{{1
5598"
5599"	    When several errors appear in a row (for instance during expression
5600"	    evaluation), the first as the most specific one is used when
5601"	    throwing an error exception.  If, however, a syntax error is
5602"	    detected afterwards, this one is used for the error exception.
5603"	    On a syntax error, the next command is not executed, on a normal
5604"	    error, however, it is (relevant only in a function without the
5605"	    "abort" flag).  v:errmsg is not set.
5606"
5607"	    If throwing error exceptions is configured off, v:errmsg is always
5608"	    set to the latest error message, that is, to the more general
5609"	    message or the syntax error, respectively.
5610"-------------------------------------------------------------------------------
5611func Test_throw_multi_error()
5612  CheckEnglish
5613
5614  let test =<< trim [CODE]
5615    func NEXT(cmd)
5616      exec a:cmd . " | Xloop 'a'"
5617    endfun
5618
5619    call NEXT('echo novar')			" (checks nextcmd)
5620    XloopNEXT
5621    call NEXT('let novar #')			" (skips nextcmd)
5622    XloopNEXT
5623    call NEXT('unlet novar #')			" (skips nextcmd)
5624    XloopNEXT
5625    call NEXT('let {novar}')			" (skips nextcmd)
5626    XloopNEXT
5627    call NEXT('unlet{ novar}')			" (skips nextcmd)
5628
5629    call assert_equal('a1', g:Xpath)
5630    XpathINIT
5631    XloopINIT
5632
5633    func EXEC(cmd)
5634      exec a:cmd
5635    endfunc
5636
5637    try
5638      while 1				" dummy loop
5639        try
5640          let v:errmsg = ""
5641          call EXEC('echo novar')	" normal error
5642        catch /^Vim\((\a\+)\)\=:/
5643          Xpath 'b'
5644          call assert_match('E121: Undefined variable: novar', v:exception)
5645        finally
5646          Xpath 'c'
5647          call assert_equal("", v:errmsg)
5648          break
5649        endtry
5650      endwhile
5651
5652      Xpath 'd'
5653      let cmd = "let"
5654      while cmd != ""
5655        try
5656          let v:errmsg = ""
5657          call EXEC(cmd . ' novar #')		" normal plus syntax error
5658        catch /^Vim\((\a\+)\)\=:/
5659          Xloop 'e'
5660          call assert_match('E488: Trailing characters', v:exception)
5661        finally
5662          Xloop 'f'
5663          call assert_equal("", v:errmsg)
5664          if cmd == "let"
5665            let cmd = "unlet"
5666          else
5667            let cmd = ""
5668          endif
5669          XloopNEXT
5670          continue
5671        endtry
5672      endwhile
5673
5674      Xpath 'g'
5675      let cmd = "let"
5676      while cmd != ""
5677        try
5678          let v:errmsg = ""
5679          call EXEC(cmd . ' {novar}')		" normal plus syntax error
5680        catch /^Vim\((\a\+)\)\=:/
5681          Xloop 'h'
5682          call assert_match('E475: Invalid argument: {novar}', v:exception)
5683        finally
5684          Xloop 'i'
5685          call assert_equal("", v:errmsg)
5686          if cmd == "let"
5687            let cmd = "unlet"
5688          else
5689            let cmd = ""
5690          endif
5691          XloopNEXT
5692          continue
5693        endtry
5694      endwhile
5695    catch /.*/
5696      call assert_report('should not get here')
5697    endtry
5698    Xpath 'j'
5699  [CODE]
5700  let verify =<< trim [CODE]
5701    call assert_equal('bcde1f1e2f2gh3i3h4i4j', g:Xpath)
5702  [CODE]
5703  call RunInNewVim(test, verify)
5704endfunc
5705
5706"-------------------------------------------------------------------------------
5707" Test 80:  Syntax error in expression for illegal :elseif		    {{{1
5708"
5709"	    If there is a syntax error in the expression after an illegal
5710"	    :elseif, an error message is given (or an error exception thrown)
5711"	    for the illegal :elseif rather than the expression error.
5712"-------------------------------------------------------------------------------
5713func Test_if_syntax_error()
5714  CheckEnglish
5715
5716  let test =<< trim [CODE]
5717    let v:errmsg = ""
5718    if 0
5719    else
5720    elseif 1 ||| 2
5721    endif
5722    Xpath 'a'
5723    call assert_match('E584: :elseif after :else', v:errmsg)
5724
5725    let v:errmsg = ""
5726    if 1
5727    else
5728    elseif 1 ||| 2
5729    endif
5730    Xpath 'b'
5731    call assert_match('E584: :elseif after :else', v:errmsg)
5732
5733    let v:errmsg = ""
5734    elseif 1 ||| 2
5735    Xpath 'c'
5736    call assert_match('E582: :elseif without :if', v:errmsg)
5737
5738    let v:errmsg = ""
5739    while 1
5740      elseif 1 ||| 2
5741    endwhile
5742    Xpath 'd'
5743    call assert_match('E582: :elseif without :if', v:errmsg)
5744
5745    while 1
5746      try
5747        try
5748          let v:errmsg = ""
5749          if 0
5750          else
5751          elseif 1 ||| 2
5752          endif
5753        catch /^Vim\((\a\+)\)\=:/
5754          Xpath 'e'
5755          call assert_match('E584: :elseif after :else', v:exception)
5756        finally
5757          Xpath 'f'
5758          call assert_equal("", v:errmsg)
5759        endtry
5760      catch /.*/
5761      call assert_report('should not get here')
5762      finally
5763        Xpath 'g'
5764        break
5765      endtry
5766    endwhile
5767
5768    while 1
5769      try
5770        try
5771          let v:errmsg = ""
5772          if 1
5773          else
5774          elseif 1 ||| 2
5775          endif
5776        catch /^Vim\((\a\+)\)\=:/
5777          Xpath 'h'
5778          call assert_match('E584: :elseif after :else', v:exception)
5779        finally
5780          Xpath 'i'
5781          call assert_equal("", v:errmsg)
5782        endtry
5783      catch /.*/
5784        call assert_report('should not get here')
5785      finally
5786        Xpath 'j'
5787        break
5788      endtry
5789    endwhile
5790
5791    while 1
5792      try
5793        try
5794          let v:errmsg = ""
5795          elseif 1 ||| 2
5796        catch /^Vim\((\a\+)\)\=:/
5797          Xpath 'k'
5798          call assert_match('E582: :elseif without :if', v:exception)
5799        finally
5800          Xpath 'l'
5801          call assert_equal("", v:errmsg)
5802        endtry
5803      catch /.*/
5804        call assert_report('should not get here')
5805      finally
5806        Xpath 'm'
5807        break
5808      endtry
5809    endwhile
5810
5811    while 1
5812      try
5813        try
5814          let v:errmsg = ""
5815          while 1
5816              elseif 1 ||| 2
5817          endwhile
5818        catch /^Vim\((\a\+)\)\=:/
5819          Xpath 'n'
5820          call assert_match('E582: :elseif without :if', v:exception)
5821        finally
5822          Xpath 'o'
5823          call assert_equal("", v:errmsg)
5824        endtry
5825      catch /.*/
5826        call assert_report('should not get here')
5827      finally
5828        Xpath 'p'
5829        break
5830      endtry
5831    endwhile
5832    Xpath 'q'
5833  [CODE]
5834  let verify =<< trim [CODE]
5835    call assert_equal('abcdefghijklmnopq', g:Xpath)
5836  [CODE]
5837  call RunInNewVim(test, verify)
5838endfunc
5839
5840"-------------------------------------------------------------------------------
5841" Test 81:  Discarding exceptions after an error or interrupt		    {{{1
5842"
5843"	    When an exception is thrown from inside a :try conditional without
5844"	    :catch and :finally clauses and an error or interrupt occurs before
5845"	    the :endtry is reached, the exception is discarded.
5846"-------------------------------------------------------------------------------
5847
5848func Test_discard_exception_after_error_1()
5849  let test =<< trim [CODE]
5850    try
5851      Xpath 'a'
5852      try
5853        Xpath 'b'
5854        throw "arrgh"
5855        call assert_report('should not get here')
5856        if 1
5857        call assert_report('should not get here')
5858        " error after :throw: missing :endif
5859      endtry
5860      call assert_report('should not get here')
5861    catch /arrgh/
5862      call assert_report('should not get here')
5863    endtry
5864    call assert_report('should not get here')
5865  [CODE]
5866  let verify =<< trim [CODE]
5867    call assert_equal('ab', g:Xpath)
5868  [CODE]
5869  call RunInNewVim(test, verify)
5870endfunc
5871
5872" interrupt the code before the endtry is invoked
5873func Test_discard_exception_after_error_2()
5874  XpathINIT
5875  let lines =<< trim [CODE]
5876    try
5877      Xpath 'a'
5878      try
5879        Xpath 'b'
5880        throw "arrgh"
5881        call assert_report('should not get here')
5882      endtry                      " interrupt here
5883      call assert_report('should not get here')
5884    catch /arrgh/
5885      call assert_report('should not get here')
5886    endtry
5887    call assert_report('should not get here')
5888  [CODE]
5889  call writefile(lines, 'Xscript')
5890
5891  breakadd file 7 Xscript
5892  try
5893    let caught_intr = 0
5894    debuggreedy
5895    call feedkeys(":source Xscript\<CR>quit\<CR>", "xt")
5896  catch /^Vim:Interrupt$/
5897    call assert_match('Xscript, line 7', v:throwpoint)
5898    let caught_intr = 1
5899  endtry
5900  0debuggreedy
5901  call assert_equal(1, caught_intr)
5902  call assert_equal('ab', g:Xpath)
5903  breakdel *
5904  call delete('Xscript')
5905endfunc
5906
5907"-------------------------------------------------------------------------------
5908" Test 82:  Ignoring :catch clauses after an error or interrupt		    {{{1
5909"
5910"	    When an exception is thrown and an error or interrupt occurs before
5911"	    the matching :catch clause is reached, the exception is discarded
5912"	    and the :catch clause is ignored (also for the error or interrupt
5913"	    exception being thrown then).
5914"-------------------------------------------------------------------------------
5915
5916func Test_ignore_catch_after_error_1()
5917  let test =<< trim [CODE]
5918    try
5919      try
5920        Xpath 'a'
5921        throw "arrgh"
5922        call assert_report('should not get here')
5923        if 1
5924        call assert_report('should not get here')
5925        " error after :throw: missing :endif
5926      catch /.*/
5927        call assert_report('should not get here')
5928      catch /.*/
5929        call assert_report('should not get here')
5930      endtry
5931      call assert_report('should not get here')
5932    catch /arrgh/
5933      call assert_report('should not get here')
5934    endtry
5935    call assert_report('should not get here')
5936  [CODE]
5937  let verify =<< trim [CODE]
5938    call assert_equal('a', g:Xpath)
5939  [CODE]
5940  call RunInNewVim(test, verify)
5941endfunc
5942
5943func Test_ignore_catch_after_error_2()
5944  let test =<< trim [CODE]
5945    func E()
5946      try
5947        try
5948          Xpath 'a'
5949          throw "arrgh"
5950          call assert_report('should not get here')
5951          if 1
5952          call assert_report('should not get here')
5953          " error after :throw: missing :endif
5954        catch /.*/
5955          call assert_report('should not get here')
5956        catch /.*/
5957          call assert_report('should not get here')
5958        endtry
5959        call assert_report('should not get here')
5960      catch /arrgh/
5961        call assert_report('should not get here')
5962      endtry
5963    endfunc
5964
5965    call E()
5966    call assert_report('should not get here')
5967  [CODE]
5968  let verify =<< trim [CODE]
5969    call assert_equal('a', g:Xpath)
5970  [CODE]
5971  call RunInNewVim(test, verify)
5972endfunc
5973
5974" interrupt right before a catch is invoked in a script
5975func Test_ignore_catch_after_intr_1()
5976  XpathINIT
5977  let lines =<< trim [CODE]
5978    try
5979      try
5980        Xpath 'a'
5981        throw "arrgh"
5982        call assert_report('should not get here')
5983      catch /.*/              " interrupt here
5984        call assert_report('should not get here')
5985      catch /.*/
5986        call assert_report('should not get here')
5987      endtry
5988      call assert_report('should not get here')
5989    catch /arrgh/
5990      call assert_report('should not get here')
5991    endtry
5992    call assert_report('should not get here')
5993  [CODE]
5994  call writefile(lines, 'Xscript')
5995
5996  breakadd file 6 Xscript
5997  try
5998    let caught_intr = 0
5999    debuggreedy
6000    call feedkeys(":source Xscript\<CR>quit\<CR>", "xt")
6001  catch /^Vim:Interrupt$/
6002    call assert_match('Xscript, line 6', v:throwpoint)
6003    let caught_intr = 1
6004  endtry
6005  0debuggreedy
6006  call assert_equal(1, caught_intr)
6007  call assert_equal('a', g:Xpath)
6008  breakdel *
6009  call delete('Xscript')
6010endfunc
6011
6012" interrupt right before a catch is invoked inside a function.
6013func Test_ignore_catch_after_intr_2()
6014  XpathINIT
6015  func F()
6016    try
6017      try
6018        Xpath 'a'
6019        throw "arrgh"
6020        call assert_report('should not get here')
6021      catch /.*/              " interrupt here
6022        call assert_report('should not get here')
6023      catch /.*/
6024        call assert_report('should not get here')
6025      endtry
6026      call assert_report('should not get here')
6027    catch /arrgh/
6028      call assert_report('should not get here')
6029    endtry
6030    call assert_report('should not get here')
6031  endfunc
6032
6033  breakadd func 6 F
6034  try
6035    let caught_intr = 0
6036    debuggreedy
6037    call feedkeys(":call F()\<CR>quit\<CR>", "xt")
6038  catch /^Vim:Interrupt$/
6039    call assert_match('\.F, line 6', v:throwpoint)
6040    let caught_intr = 1
6041  endtry
6042  0debuggreedy
6043  call assert_equal(1, caught_intr)
6044  call assert_equal('a', g:Xpath)
6045  breakdel *
6046  delfunc F
6047endfunc
6048
6049"-------------------------------------------------------------------------------
6050" Test 83:  Executing :finally clauses after an error or interrupt	    {{{1
6051"
6052"	    When an exception is thrown and an error or interrupt occurs before
6053"	    the :finally of the innermost :try is reached, the exception is
6054"	    discarded and the :finally clause is executed.
6055"-------------------------------------------------------------------------------
6056
6057func Test_finally_after_error()
6058  let test =<< trim [CODE]
6059    try
6060      Xpath 'a'
6061      try
6062        Xpath 'b'
6063        throw "arrgh"
6064        call assert_report('should not get here')
6065        if 1
6066        call assert_report('should not get here')
6067        " error after :throw: missing :endif
6068      finally
6069        Xpath 'c'
6070      endtry
6071      call assert_report('should not get here')
6072    catch /arrgh/
6073      call assert_report('should not get here')
6074    endtry
6075    call assert_report('should not get here')
6076  [CODE]
6077  let verify =<< trim [CODE]
6078    call assert_equal('abc', g:Xpath)
6079  [CODE]
6080  call RunInNewVim(test, verify)
6081endfunc
6082
6083" interrupt the code right before the finally is invoked
6084func Test_finally_after_intr()
6085  XpathINIT
6086  let lines =<< trim [CODE]
6087    try
6088      Xpath 'a'
6089      try
6090        Xpath 'b'
6091        throw "arrgh"
6092        call assert_report('should not get here')
6093      finally		" interrupt here
6094        Xpath 'c'
6095      endtry
6096      call assert_report('should not get here')
6097    catch /arrgh/
6098      call assert_report('should not get here')
6099    endtry
6100    call assert_report('should not get here')
6101  [CODE]
6102  call writefile(lines, 'Xscript')
6103
6104  breakadd file 7 Xscript
6105  try
6106    let caught_intr = 0
6107    debuggreedy
6108    call feedkeys(":source Xscript\<CR>quit\<CR>", "xt")
6109  catch /^Vim:Interrupt$/
6110    call assert_match('Xscript, line 7', v:throwpoint)
6111    let caught_intr = 1
6112  endtry
6113  0debuggreedy
6114  call assert_equal(1, caught_intr)
6115  call assert_equal('abc', g:Xpath)
6116  breakdel *
6117  call delete('Xscript')
6118endfunc
6119
6120"-------------------------------------------------------------------------------
6121" Test 84:  Exceptions in autocommand sequences.			    {{{1
6122"
6123"	    When an exception occurs in a sequence of autocommands for
6124"	    a specific event, the rest of the sequence is not executed.  The
6125"	    command that triggered the autocommand execution aborts, and the
6126"	    exception is propagated to the caller.
6127"
6128"	    For the FuncUndefined event under a function call expression or
6129"	    :call command, the function is not executed, even when it has
6130"	    been defined by the autocommands before the exception occurred.
6131"-------------------------------------------------------------------------------
6132
6133func Test_autocmd_exception()
6134  let test =<< trim [CODE]
6135    func INT()
6136      call interrupt()
6137    endfunc
6138
6139    aug TMP
6140      autocmd!
6141
6142      autocmd User x1 Xpath 'a'
6143      autocmd User x1 throw "x1"
6144      autocmd User x1 call assert_report('should not get here')
6145
6146      autocmd User x2 Xpath 'b'
6147      autocmd User x2 asdf
6148      autocmd User x2 call assert_report('should not get here')
6149
6150      autocmd User x3 Xpath 'c'
6151      autocmd User x3 call INT()
6152      autocmd User x3 call assert_report('should not get here')
6153
6154      autocmd FuncUndefined U1 func U1()
6155      autocmd FuncUndefined U1   call assert_report('should not get here')
6156      autocmd FuncUndefined U1 endfunc
6157      autocmd FuncUndefined U1 Xpath 'd'
6158      autocmd FuncUndefined U1 throw "U1"
6159      autocmd FuncUndefined U1 call assert_report('should not get here')
6160
6161      autocmd FuncUndefined U2 func U2()
6162      autocmd FuncUndefined U2   call assert_report('should not get here')
6163      autocmd FuncUndefined U2 endfunc
6164      autocmd FuncUndefined U2 Xpath 'e'
6165      autocmd FuncUndefined U2 ASDF
6166      autocmd FuncUndefined U2 call assert_report('should not get here')
6167
6168      autocmd FuncUndefined U3 func U3()
6169      autocmd FuncUndefined U3   call assert_report('should not get here')
6170      autocmd FuncUndefined U3 endfunc
6171      autocmd FuncUndefined U3 Xpath 'f'
6172      autocmd FuncUndefined U3 call INT()
6173      autocmd FuncUndefined U3 call assert_report('should not get here')
6174    aug END
6175
6176    try
6177      try
6178        Xpath 'g'
6179        doautocmd User x1
6180      catch /x1/
6181        Xpath 'h'
6182      endtry
6183
6184      while 1
6185        try
6186          Xpath 'i'
6187          doautocmd User x2
6188        catch /asdf/
6189          Xpath 'j'
6190        finally
6191          Xpath 'k'
6192          break
6193        endtry
6194      endwhile
6195
6196      while 1
6197        try
6198          Xpath 'l'
6199          doautocmd User x3
6200        catch /Vim:Interrupt/
6201          Xpath 'm'
6202        finally
6203          Xpath 'n'
6204          " ... but break loop for caught interrupt exception,
6205          " or discard interrupt and break loop if $VIMNOINTTHROW
6206          break
6207        endtry
6208      endwhile
6209
6210      if exists("*U1") | delfunction U1 | endif
6211      if exists("*U2") | delfunction U2 | endif
6212      if exists("*U3") | delfunction U3 | endif
6213
6214      try
6215        Xpath 'o'
6216        call U1()
6217      catch /U1/
6218        Xpath 'p'
6219      endtry
6220
6221      while 1
6222        try
6223          Xpath 'q'
6224          call U2()
6225        catch /ASDF/
6226          Xpath 'r'
6227        finally
6228          Xpath 's'
6229          " ... but break loop for caught error exception,
6230          " or discard error and break loop if $VIMNOERRTHROW
6231          break
6232        endtry
6233      endwhile
6234
6235      while 1
6236        try
6237          Xpath 't'
6238          call U3()
6239        catch /Vim:Interrupt/
6240          Xpath 'u'
6241        finally
6242          Xpath 'v'
6243          " ... but break loop for caught interrupt exception,
6244          " or discard interrupt and break loop if $VIMNOINTTHROW
6245          break
6246        endtry
6247      endwhile
6248    catch /.*/
6249      call assert_report('should not get here')
6250    endtry
6251    Xpath 'w'
6252  [CODE]
6253  let verify =<< trim [CODE]
6254    call assert_equal('gahibjklcmnodpqerstfuvw', g:Xpath)
6255  [CODE]
6256  call RunInNewVim(test, verify)
6257endfunc
6258
6259"-------------------------------------------------------------------------------
6260" Test 85:  Error exceptions in autocommands for I/O command events	    {{{1
6261"
6262"	    When an I/O command is inside :try/:endtry, autocommands to be
6263"	    executed after it should be skipped on an error (exception) in the
6264"	    command itself or in autocommands to be executed before the command.
6265"	    In the latter case, the I/O command should not be executed either.
6266"	    Example 1: BufWritePre, :write, BufWritePost
6267"	    Example 2: FileReadPre, :read, FileReadPost.
6268"-------------------------------------------------------------------------------
6269
6270func Test_autocmd_error_io_exception()
6271  let test =<< trim [CODE]
6272    " Remove the autocommands for the events specified as arguments in all used
6273    " autogroups.
6274    func Delete_autocommands(...)
6275      let augfile = tempname()
6276      while 1
6277        try
6278          exec "redir >" . augfile
6279          aug
6280          redir END
6281          exec "edit" augfile
6282          g/^$/d
6283          norm G$
6284          let wrap = "w"
6285          while search('\%(  \|^\)\@<=.\{-}\%(  \)\@=', wrap) > 0
6286            let wrap = "W"
6287            exec "norm y/  \n"
6288            let argno = 1
6289            while argno <= a:0
6290              exec "au!" escape(@", " ") a:{argno}
6291              let argno = argno + 1
6292            endwhile
6293          endwhile
6294        catch /.*/
6295        finally
6296          bwipeout!
6297          call delete(augfile)
6298          break
6299        endtry
6300      endwhile
6301    endfunc
6302
6303    call Delete_autocommands("BufWritePre", "BufWritePost")
6304
6305    while 1
6306      try
6307        try
6308          let post = 0
6309          aug TMP
6310            au! BufWritePost * let post = 1
6311          aug END
6312          write /n/o/n/e/x/i/s/t/e/n/t
6313        catch /^Vim(write):/
6314          Xpath 'a'
6315          call assert_match("E212: Can't open file for writing", v:exception)
6316        finally
6317          Xpath 'b'
6318          call assert_equal(0, post)
6319          au! TMP
6320          aug! TMP
6321        endtry
6322      catch /.*/
6323        call assert_report('should not get here')
6324      finally
6325        Xpath 'c'
6326        break
6327      endtry
6328    endwhile
6329
6330    while 1
6331      try
6332        try
6333          let post = 0
6334          aug TMP
6335            au! BufWritePre  * asdf
6336            au! BufWritePost * let post = 1
6337          aug END
6338          let tmpfile = tempname()
6339          exec "write" tmpfile
6340        catch /^Vim\((write)\)\=:/
6341          Xpath 'd'
6342          call assert_match('E492: Not an editor command', v:exception)
6343        finally
6344          Xpath 'e'
6345          if filereadable(tmpfile)
6346            call assert_report('should not get here')
6347          endif
6348          call assert_equal(0, post)
6349          au! TMP
6350          aug! TMP
6351        endtry
6352      catch /.*/
6353        call assert_report('should not get here')
6354      finally
6355        Xpath 'f'
6356        break
6357      endtry
6358    endwhile
6359
6360    call delete(tmpfile)
6361
6362    call Delete_autocommands("BufWritePre", "BufWritePost",
6363          \ "BufReadPre", "BufReadPost", "FileReadPre", "FileReadPost")
6364
6365    while 1
6366      try
6367        try
6368          let post = 0
6369          aug TMP
6370            au! FileReadPost * let post = 1
6371          aug END
6372          let caught = 0
6373          read /n/o/n/e/x/i/s/t/e/n/t
6374        catch /^Vim(read):/
6375          Xpath 'g'
6376          call assert_match("E484: Can't open file", v:exception)
6377        finally
6378          Xpath 'h'
6379          call assert_equal(0, post)
6380          au! TMP
6381          aug! TMP
6382        endtry
6383      catch /.*/
6384        call assert_report('should not get here')
6385      finally
6386        Xpath 'i'
6387        break
6388      endtry
6389    endwhile
6390
6391    while 1
6392      try
6393        let infile = tempname()
6394        let tmpfile = tempname()
6395        call writefile(["XYZ"], infile)
6396        exec "edit" tmpfile
6397        try
6398          Xpath 'j'
6399          try
6400            let post = 0
6401            aug TMP
6402              au! FileReadPre  * asdf
6403              au! FileReadPost * let post = 1
6404            aug END
6405            exec "0read" infile
6406          catch /^Vim\((read)\)\=:/
6407            Xpath 'k'
6408            call assert_match('E492: Not an editor command', v:exception)
6409          finally
6410            Xpath 'l'
6411            if getline("1") == "XYZ"
6412              call assert_report('should not get here')
6413            endif
6414            call assert_equal(0, post)
6415            au! TMP
6416            aug! TMP
6417          endtry
6418        finally
6419          Xpath 'm'
6420          bwipeout!
6421        endtry
6422      catch /.*/
6423        call assert_report('should not get here')
6424      finally
6425        Xpath 'n'
6426        break
6427      endtry
6428    endwhile
6429
6430    call delete(infile)
6431    call delete(tmpfile)
6432  [CODE]
6433  let verify =<< trim [CODE]
6434    call assert_equal('abcdefghijklmn', g:Xpath)
6435  [CODE]
6436  call RunInNewVim(test, verify)
6437endfunc
6438
6439"-------------------------------------------------------------------------------
6440" Test 87   using (expr) ? funcref : funcref				    {{{1
6441"
6442"	    Vim needs to correctly parse the funcref and even when it does
6443"	    not execute the funcref, it needs to consume the trailing ()
6444"-------------------------------------------------------------------------------
6445
6446func Add2(x1, x2)
6447  return a:x1 + a:x2
6448endfu
6449
6450func GetStr()
6451  return "abcdefghijklmnopqrstuvwxyp"
6452endfu
6453
6454func Test_funcref_with_condexpr()
6455  call assert_equal(5, function('Add2')(2,3))
6456
6457  call assert_equal(3, 1 ? function('Add2')(1,2) : function('Add2')(2,3))
6458  call assert_equal(5, 0 ? function('Add2')(1,2) : function('Add2')(2,3))
6459  " Make sure, GetStr() still works.
6460  call assert_equal('abcdefghijk', GetStr()[0:10])
6461endfunc
6462
6463" Test 90:  Recognizing {} in variable name.			    {{{1
6464"-------------------------------------------------------------------------------
6465
6466func Test_curlies()
6467    let s:var = 66
6468    let ns = 's'
6469    call assert_equal(66, {ns}:var)
6470
6471    let g:a = {}
6472    let g:b = 't'
6473    let g:a[g:b] = 77
6474    call assert_equal(77, g:a['t'])
6475endfunc
6476
6477"-------------------------------------------------------------------------------
6478" Test 91:  using type().					    {{{1
6479"-------------------------------------------------------------------------------
6480
6481func Test_type()
6482    call assert_equal(0, type(0))
6483    call assert_equal(1, type(""))
6484    call assert_equal(2, type(function("tr")))
6485    call assert_equal(2, type(function("tr", [8])))
6486    call assert_equal(3, type([]))
6487    call assert_equal(4, type({}))
6488    if has('float')
6489      call assert_equal(5, type(0.0))
6490    endif
6491    call assert_equal(6, type(v:false))
6492    call assert_equal(6, type(v:true))
6493    call assert_equal(7, type(v:none))
6494    call assert_equal(7, type(v:null))
6495    call assert_equal(8, v:t_job)
6496    call assert_equal(9, v:t_channel)
6497    call assert_equal(v:t_number, type(0))
6498    call assert_equal(v:t_string, type(""))
6499    call assert_equal(v:t_func, type(function("tr")))
6500    call assert_equal(v:t_func, type(function("tr", [8])))
6501    call assert_equal(v:t_list, type([]))
6502    call assert_equal(v:t_dict, type({}))
6503    if has('float')
6504      call assert_equal(v:t_float, type(0.0))
6505    endif
6506    call assert_equal(v:t_bool, type(v:false))
6507    call assert_equal(v:t_bool, type(v:true))
6508    call assert_equal(v:t_none, type(v:none))
6509    call assert_equal(v:t_none, type(v:null))
6510    call assert_equal(v:t_string, type(test_null_string()))
6511    call assert_equal(v:t_func, type(test_null_function()))
6512    call assert_equal(v:t_func, type(test_null_partial()))
6513    call assert_equal(v:t_list, type(test_null_list()))
6514    call assert_equal(v:t_dict, type(test_null_dict()))
6515    if has('job')
6516      call assert_equal(v:t_job, type(test_null_job()))
6517    endif
6518    if has('channel')
6519      call assert_equal(v:t_channel, type(test_null_channel()))
6520    endif
6521    call assert_equal(v:t_blob, type(test_null_blob()))
6522
6523    call assert_fails("call type(test_void())", 'E685:')
6524    call assert_fails("call type(test_unknown())", 'E685:')
6525
6526    call assert_equal(0, 0 + v:false)
6527    call assert_equal(1, 0 + v:true)
6528    call assert_equal(0, 0 + v:none)
6529    call assert_equal(0, 0 + v:null)
6530
6531    call assert_equal('v:false', '' . v:false)
6532    call assert_equal('v:true', '' . v:true)
6533    call assert_equal('v:none', '' . v:none)
6534    call assert_equal('v:null', '' . v:null)
6535
6536    call assert_true(v:false == 0)
6537    call assert_false(v:false != 0)
6538    call assert_true(v:true == 1)
6539    call assert_false(v:true != 1)
6540    call assert_false(v:true == v:false)
6541    call assert_true(v:true != v:false)
6542
6543    call assert_true(v:null == 0)
6544    call assert_false(v:null != 0)
6545    call assert_true(v:none == 0)
6546    call assert_false(v:none != 0)
6547
6548    call assert_true(v:false is v:false)
6549    call assert_true(v:true is v:true)
6550    call assert_true(v:none is v:none)
6551    call assert_true(v:null is v:null)
6552
6553    call assert_false(v:false isnot v:false)
6554    call assert_false(v:true isnot v:true)
6555    call assert_false(v:none isnot v:none)
6556    call assert_false(v:null isnot v:null)
6557
6558    call assert_false(v:false is 0)
6559    call assert_false(v:true is 1)
6560    call assert_false(v:true is v:false)
6561    call assert_false(v:none is 0)
6562    call assert_false(v:null is 0)
6563    call assert_false(v:null is v:none)
6564
6565    call assert_true(v:false isnot 0)
6566    call assert_true(v:true isnot 1)
6567    call assert_true(v:true isnot v:false)
6568    call assert_true(v:none isnot 0)
6569    call assert_true(v:null isnot 0)
6570    call assert_true(v:null isnot v:none)
6571
6572    call assert_equal(v:false, eval(string(v:false)))
6573    call assert_equal(v:true, eval(string(v:true)))
6574    call assert_equal(v:none, eval(string(v:none)))
6575    call assert_equal(v:null, eval(string(v:null)))
6576
6577    call assert_equal(v:false, copy(v:false))
6578    call assert_equal(v:true, copy(v:true))
6579    call assert_equal(v:none, copy(v:none))
6580    call assert_equal(v:null, copy(v:null))
6581
6582    call assert_equal([v:false], deepcopy([v:false]))
6583    call assert_equal([v:true], deepcopy([v:true]))
6584    call assert_equal([v:none], deepcopy([v:none]))
6585    call assert_equal([v:null], deepcopy([v:null]))
6586
6587    call assert_true(empty(v:false))
6588    call assert_false(empty(v:true))
6589    call assert_true(empty(v:null))
6590    call assert_true(empty(v:none))
6591
6592    func ChangeYourMind()
6593	try
6594	    return v:true
6595	finally
6596	    return 'something else'
6597	endtry
6598    endfunc
6599
6600    call ChangeYourMind()
6601endfunc
6602
6603func Test_typename()
6604  call assert_equal('number', typename(123))
6605  call assert_equal('string', typename('x'))
6606  call assert_equal('list<number>', typename([123]))
6607  call assert_equal('dict<number>', typename(#{key: 123}))
6608  call assert_equal('list<dict<number>>', typename([#{key: 123}]))
6609
6610  let l = []
6611  let d = #{a: 0}
6612  let l = [d]
6613  let l[0].e = #{b: l}
6614  call assert_equal('list<dict<any>>', typename(l))
6615  call assert_equal('dict<any>', typename(d))
6616endfunc
6617
6618"-------------------------------------------------------------------------------
6619" Test 92:  skipping code					    {{{1
6620"-------------------------------------------------------------------------------
6621
6622func Test_skip()
6623    let Fn = function('Test_type')
6624    call assert_false(0 && Fn[1])
6625    call assert_false(0 && string(Fn))
6626    call assert_false(0 && len(Fn))
6627    let l = []
6628    call assert_false(0 && l[1])
6629    call assert_false(0 && string(l))
6630    call assert_false(0 && len(l))
6631    let f = 1.0
6632    call assert_false(0 && f[1])
6633    call assert_false(0 && string(f))
6634    call assert_false(0 && len(f))
6635    let sp = v:null
6636    call assert_false(0 && sp[1])
6637    call assert_false(0 && string(sp))
6638    call assert_false(0 && len(sp))
6639
6640endfunc
6641
6642"-------------------------------------------------------------------------------
6643" Test 93:  :echo and string()					    {{{1
6644"-------------------------------------------------------------------------------
6645
6646func Test_echo_and_string()
6647    " String
6648    let a = 'foo bar'
6649    redir => result
6650    echo a
6651    echo string(a)
6652    redir END
6653    let l = split(result, "\n")
6654    call assert_equal(["foo bar",
6655		     \ "'foo bar'"], l)
6656
6657    " Float
6658    if has('float')
6659	let a = -1.2e0
6660	redir => result
6661	echo a
6662	echo string(a)
6663	redir END
6664	let l = split(result, "\n")
6665	call assert_equal(["-1.2",
6666			 \ "-1.2"], l)
6667    endif
6668
6669    " Funcref
6670    redir => result
6671    echo function('string')
6672    echo string(function('string'))
6673    redir END
6674    let l = split(result, "\n")
6675    call assert_equal(["string",
6676		     \ "function('string')"], l)
6677
6678    " Recursive dictionary
6679    let a = {}
6680    let a["a"] = a
6681    redir => result
6682    echo a
6683    echo string(a)
6684    redir END
6685    let l = split(result, "\n")
6686    call assert_equal(["{'a': {...}}",
6687		     \ "{'a': {...}}"], l)
6688
6689    " Recursive list
6690    let a = [0]
6691    let a[0] = a
6692    redir => result
6693    echo a
6694    echo string(a)
6695    redir END
6696    let l = split(result, "\n")
6697    call assert_equal(["[[...]]",
6698		     \ "[[...]]"], l)
6699
6700    " Empty dictionaries in a list
6701    let a = {}
6702    redir => result
6703    echo [a, a, a]
6704    echo string([a, a, a])
6705    redir END
6706    let l = split(result, "\n")
6707    call assert_equal(["[{}, {}, {}]",
6708		     \ "[{}, {}, {}]"], l)
6709
6710    " Empty dictionaries in a dictionary
6711    let a = {}
6712    let b = {"a": a, "b": a}
6713    redir => result
6714    echo b
6715    echo string(b)
6716    redir END
6717    let l = split(result, "\n")
6718    call assert_equal(["{'a': {}, 'b': {}}",
6719		     \ "{'a': {}, 'b': {}}"], l)
6720
6721    " Empty lists in a list
6722    let a = []
6723    redir => result
6724    echo [a, a, a]
6725    echo string([a, a, a])
6726    redir END
6727    let l = split(result, "\n")
6728    call assert_equal(["[[], [], []]",
6729		     \ "[[], [], []]"], l)
6730
6731    " Empty lists in a dictionary
6732    let a = []
6733    let b = {"a": a, "b": a}
6734    redir => result
6735    echo b
6736    echo string(b)
6737    redir END
6738    let l = split(result, "\n")
6739    call assert_equal(["{'a': [], 'b': []}",
6740		     \ "{'a': [], 'b': []}"], l)
6741
6742    " Dictionaries in a list
6743    let a = {"one": "yes", "two": "yes", "three": "yes"}
6744    redir => result
6745    echo [a, a, a]
6746    echo string([a, a, a])
6747    redir END
6748    let l = split(result, "\n")
6749    call assert_equal(["[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {...}, {...}]",
6750		     \ "[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}]"], l)
6751
6752    " Dictionaries in a dictionary
6753    let a = {"one": "yes", "two": "yes", "three": "yes"}
6754    let b = {"a": a, "b": a}
6755    redir => result
6756    echo b
6757    echo string(b)
6758    redir END
6759    let l = split(result, "\n")
6760    call assert_equal(["{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {...}}",
6761		     \ "{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {'one': 'yes', 'two': 'yes', 'three': 'yes'}}"], l)
6762
6763    " Lists in a list
6764    let a = [1, 2, 3]
6765    redir => result
6766    echo [a, a, a]
6767    echo string([a, a, a])
6768    redir END
6769    let l = split(result, "\n")
6770    call assert_equal(["[[1, 2, 3], [...], [...]]",
6771		     \ "[[1, 2, 3], [1, 2, 3], [1, 2, 3]]"], l)
6772
6773    " Lists in a dictionary
6774    let a = [1, 2, 3]
6775    let b = {"a": a, "b": a}
6776    redir => result
6777    echo b
6778    echo string(b)
6779    redir END
6780    let l = split(result, "\n")
6781    call assert_equal(["{'a': [1, 2, 3], 'b': [...]}",
6782		     \ "{'a': [1, 2, 3], 'b': [1, 2, 3]}"], l)
6783
6784    call assert_fails('echo &:', 'E112:')
6785    call assert_fails('echo &g:', 'E112:')
6786    call assert_fails('echo &l:', 'E112:')
6787
6788endfunc
6789
6790"-------------------------------------------------------------------------------
6791" Test 94:  64-bit Numbers					    {{{1
6792"-------------------------------------------------------------------------------
6793
6794func Test_num64()
6795    call assert_notequal( 4294967296, 0)
6796    call assert_notequal(-4294967296, 0)
6797    call assert_equal( 4294967296,  0xFFFFffff + 1)
6798    call assert_equal(-4294967296, -0xFFFFffff - 1)
6799
6800    call assert_equal( 9223372036854775807,  1 / 0)
6801    call assert_equal(-9223372036854775807, -1 / 0)
6802    call assert_equal(-9223372036854775807 - 1,  0 / 0)
6803
6804    if has('float')
6805      call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150))
6806      call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150))
6807    endif
6808
6809    let rng = range(0xFFFFffff, 0x100000001)
6810    call assert_equal([0xFFFFffff, 0x100000000, 0x100000001], rng)
6811    call assert_equal(0x100000001, max(rng))
6812    call assert_equal(0xFFFFffff, min(rng))
6813    call assert_equal(rng, sort(range(0x100000001, 0xFFFFffff, -1), 'N'))
6814endfunc
6815
6816"-------------------------------------------------------------------------------
6817" Test 95:  lines of :append, :change, :insert			    {{{1
6818"-------------------------------------------------------------------------------
6819
6820function! DefineFunction(name, body)
6821    let func = join(['function! ' . a:name . '()'] + a:body + ['endfunction'], "\n")
6822    exec func
6823endfunction
6824
6825func Test_script_lines()
6826    " :append
6827    try
6828	call DefineFunction('T_Append', [
6829		    \ 'append',
6830		    \ 'py <<EOS',
6831		    \ '.',
6832		    \ ])
6833    catch
6834	call assert_report("Can't define function")
6835    endtry
6836    try
6837	call DefineFunction('T_Append', [
6838		    \ 'append',
6839		    \ 'abc',
6840		    \ ])
6841	call assert_report("Shouldn't be able to define function")
6842    catch
6843	call assert_exception('Vim(function):E1145: Missing heredoc end marker: .')
6844    endtry
6845
6846    " :change
6847    try
6848	call DefineFunction('T_Change', [
6849		    \ 'change',
6850		    \ 'py <<EOS',
6851		    \ '.',
6852		    \ ])
6853    catch
6854	call assert_report("Can't define function")
6855    endtry
6856    try
6857	call DefineFunction('T_Change', [
6858		    \ 'change',
6859		    \ 'abc',
6860		    \ ])
6861	call assert_report("Shouldn't be able to define function")
6862    catch
6863	call assert_exception('Vim(function):E1145: Missing heredoc end marker: .')
6864    endtry
6865
6866    " :insert
6867    try
6868	call DefineFunction('T_Insert', [
6869		    \ 'insert',
6870		    \ 'py <<EOS',
6871		    \ '.',
6872		    \ ])
6873    catch
6874	call assert_report("Can't define function")
6875    endtry
6876    try
6877	call DefineFunction('T_Insert', [
6878		    \ 'insert',
6879		    \ 'abc',
6880		    \ ])
6881	call assert_report("Shouldn't be able to define function")
6882    catch
6883	call assert_exception('Vim(function):E1145: Missing heredoc end marker: .')
6884    endtry
6885endfunc
6886
6887"-------------------------------------------------------------------------------
6888" Test 96:  line continuation						    {{{1
6889"
6890"	    Undefined behavior was detected by ubsan with line continuation
6891"	    after an empty line.
6892"-------------------------------------------------------------------------------
6893func Test_script_emty_line_continuation()
6894
6895    \
6896endfunc
6897
6898"-------------------------------------------------------------------------------
6899" Test 97:  bitwise functions						    {{{1
6900"-------------------------------------------------------------------------------
6901func Test_bitwise_functions()
6902    " and
6903    call assert_equal(127, and(127, 127))
6904    call assert_equal(16, and(127, 16))
6905    eval 127->and(16)->assert_equal(16)
6906    call assert_equal(0, and(127, 128))
6907    call assert_fails("call and([], 1)", 'E745:')
6908    call assert_fails("call and({}, 1)", 'E728:')
6909    if has('float')
6910      call assert_fails("call and(1.0, 1)", 'E805:')
6911      call assert_fails("call and(1, 1.0)", 'E805:')
6912    endif
6913    call assert_fails("call and(1, [])", 'E745:')
6914    call assert_fails("call and(1, {})", 'E728:')
6915    " or
6916    call assert_equal(23, or(16, 7))
6917    call assert_equal(15, or(8, 7))
6918    eval 8->or(7)->assert_equal(15)
6919    call assert_equal(123, or(0, 123))
6920    call assert_fails("call or([], 1)", 'E745:')
6921    call assert_fails("call or({}, 1)", 'E728:')
6922    if has('float')
6923      call assert_fails("call or(1.0, 1)", 'E805:')
6924      call assert_fails("call or(1, 1.0)", 'E805:')
6925    endif
6926    call assert_fails("call or(1, [])", 'E745:')
6927    call assert_fails("call or(1, {})", 'E728:')
6928    " xor
6929    call assert_equal(0, xor(127, 127))
6930    call assert_equal(111, xor(127, 16))
6931    eval 127->xor(16)->assert_equal(111)
6932    call assert_equal(255, xor(127, 128))
6933    if has('float')
6934      call assert_fails("call xor(1.0, 1)", 'E805:')
6935      call assert_fails("call xor(1, 1.0)", 'E805:')
6936    endif
6937    call assert_fails("call xor([], 1)", 'E745:')
6938    call assert_fails("call xor({}, 1)", 'E728:')
6939    call assert_fails("call xor(1, [])", 'E745:')
6940    call assert_fails("call xor(1, {})", 'E728:')
6941    " invert
6942    call assert_equal(65408, and(invert(127), 65535))
6943    eval 127->invert()->and(65535)->assert_equal(65408)
6944    call assert_equal(65519, and(invert(16), 65535))
6945    call assert_equal(65407, and(invert(128), 65535))
6946    if has('float')
6947      call assert_fails("call invert(1.0)", 'E805:')
6948    endif
6949    call assert_fails("call invert([])", 'E745:')
6950    call assert_fails("call invert({})", 'E728:')
6951endfunc
6952
6953" Test using bang after user command				    {{{1
6954func Test_user_command_with_bang()
6955    command -bang Nieuw let nieuw = 1
6956    Ni!
6957    call assert_equal(1, nieuw)
6958    unlet nieuw
6959    delcommand Nieuw
6960endfunc
6961
6962func Test_script_expand_sfile()
6963  let lines =<< trim END
6964    func s:snr()
6965      return expand('<sfile>')
6966    endfunc
6967    let g:result = s:snr()
6968  END
6969  call writefile(lines, 'Xexpand')
6970  source Xexpand
6971  call assert_match('<SNR>\d\+_snr', g:result)
6972  source Xexpand
6973  call assert_match('<SNR>\d\+_snr', g:result)
6974
6975  call delete('Xexpand')
6976  unlet g:result
6977endfunc
6978
6979func Test_compound_assignment_operators()
6980    " Test for number
6981    let x = 1
6982    let x += 10
6983    call assert_equal(11, x)
6984    let x -= 5
6985    call assert_equal(6, x)
6986    let x *= 4
6987    call assert_equal(24, x)
6988    let x /= 3
6989    call assert_equal(8, x)
6990    let x %= 3
6991    call assert_equal(2, x)
6992    let x .= 'n'
6993    call assert_equal('2n', x)
6994
6995    " Test special cases: division or modulus with 0.
6996    let x = 1
6997    let x /= 0
6998    call assert_equal(0x7FFFFFFFFFFFFFFF, x)
6999
7000    let x = -1
7001    let x /= 0
7002    call assert_equal(-0x7FFFFFFFFFFFFFFF, x)
7003
7004    let x = 0
7005    let x /= 0
7006    call assert_equal(-0x7FFFFFFFFFFFFFFF - 1, x)
7007
7008    let x = 1
7009    let x %= 0
7010    call assert_equal(0, x)
7011
7012    let x = -1
7013    let x %= 0
7014    call assert_equal(0, x)
7015
7016    let x = 0
7017    let x %= 0
7018    call assert_equal(0, x)
7019
7020    " Test for string
7021    let x = 'str'
7022    let x .= 'ing'
7023    call assert_equal('string', x)
7024    let x += 1
7025    call assert_equal(1, x)
7026
7027    if has('float')
7028      " Test for float
7029      let x -= 1.5
7030      call assert_equal(-0.5, x)
7031      let x = 0.5
7032      let x += 4.5
7033      call assert_equal(5.0, x)
7034      let x -= 1.5
7035      call assert_equal(3.5, x)
7036      let x *= 3.0
7037      call assert_equal(10.5, x)
7038      let x /= 2.5
7039      call assert_equal(4.2, x)
7040      call assert_fails('let x %= 0.5', 'E734:')
7041      call assert_fails('let x .= "f"', 'E734:')
7042      let x = !3.14
7043      call assert_equal(0.0, x)
7044
7045      " integer and float operations
7046      let x = 1
7047      let x *= 2.1
7048      call assert_equal(2.1, x)
7049      let x = 1
7050      let x /= 0.25
7051      call assert_equal(4.0, x)
7052      let x = 1
7053      call assert_fails('let x %= 0.25', 'E734:')
7054      let x = 1
7055      call assert_fails('let x .= 0.25', 'E734:')
7056      let x = 1.0
7057      call assert_fails('let x += [1.1]', 'E734:')
7058    endif
7059
7060    " Test for environment variable
7061    let $FOO = 1
7062    call assert_fails('let $FOO += 1', 'E734:')
7063    call assert_fails('let $FOO -= 1', 'E734:')
7064    call assert_fails('let $FOO *= 1', 'E734:')
7065    call assert_fails('let $FOO /= 1', 'E734:')
7066    call assert_fails('let $FOO %= 1', 'E734:')
7067    let $FOO .= 's'
7068    call assert_equal('1s', $FOO)
7069    unlet $FOO
7070
7071    " Test for option variable (type: number)
7072    let &scrolljump = 1
7073    let &scrolljump += 5
7074    call assert_equal(6, &scrolljump)
7075    let &scrolljump -= 2
7076    call assert_equal(4, &scrolljump)
7077    let &scrolljump *= 3
7078    call assert_equal(12, &scrolljump)
7079    let &scrolljump /= 2
7080    call assert_equal(6, &scrolljump)
7081    let &scrolljump %= 5
7082    call assert_equal(1, &scrolljump)
7083    call assert_fails('let &scrolljump .= "j"', 'E734:')
7084    set scrolljump&vim
7085
7086    " Test for register
7087    let @/ = 1
7088    call assert_fails('let @/ += 1', 'E734:')
7089    call assert_fails('let @/ -= 1', 'E734:')
7090    call assert_fails('let @/ *= 1', 'E734:')
7091    call assert_fails('let @/ /= 1', 'E734:')
7092    call assert_fails('let @/ %= 1', 'E734:')
7093    let @/ .= 's'
7094    call assert_equal('1s', @/)
7095    let @/ = ''
7096endfunc
7097
7098func Test_unlet_env()
7099  let $TESTVAR = 'yes'
7100  call assert_equal('yes', $TESTVAR)
7101  call assert_fails('lockvar $TESTVAR', 'E940:')
7102  call assert_fails('unlockvar $TESTVAR', 'E940:')
7103  call assert_equal('yes', $TESTVAR)
7104  if 0
7105    unlet $TESTVAR
7106  endif
7107  call assert_equal('yes', $TESTVAR)
7108  unlet $TESTVAR
7109  call assert_equal('', $TESTVAR)
7110endfunc
7111
7112func Test_refcount()
7113    " Immediate values
7114    call assert_equal(-1, test_refcount(1))
7115    call assert_equal(-1, test_refcount('s'))
7116    call assert_equal(-1, test_refcount(v:true))
7117    call assert_equal(0, test_refcount([]))
7118    call assert_equal(0, test_refcount({}))
7119    call assert_equal(0, test_refcount(0zff))
7120    call assert_equal(0, test_refcount({-> line('.')}))
7121    if has('float')
7122        call assert_equal(-1, test_refcount(0.1))
7123    endif
7124    if has('job')
7125        call assert_equal(0, test_refcount(job_start([&shell, &shellcmdflag, 'echo .'])))
7126    endif
7127
7128    " No refcount types
7129    let x = 1
7130    call assert_equal(-1, test_refcount(x))
7131    let x = 's'
7132    call assert_equal(-1, test_refcount(x))
7133    let x = v:true
7134    call assert_equal(-1, test_refcount(x))
7135    if has('float')
7136        let x = 0.1
7137        call assert_equal(-1, test_refcount(x))
7138    endif
7139
7140    " Check refcount
7141    let x = []
7142    call assert_equal(1, test_refcount(x))
7143
7144    let x = {}
7145    call assert_equal(1, x->test_refcount())
7146
7147    let x = 0zff
7148    call assert_equal(1, test_refcount(x))
7149
7150    let X = {-> line('.')}
7151    call assert_equal(1, test_refcount(X))
7152    let Y = X
7153    call assert_equal(2, test_refcount(X))
7154
7155    if has('job')
7156        let job = job_start([&shell, &shellcmdflag, 'echo .'])
7157        call assert_equal(1, test_refcount(job))
7158        call assert_equal(1, test_refcount(job_getchannel(job)))
7159        call assert_equal(1, test_refcount(job))
7160    endif
7161
7162    " Function arguments, copying and unassigning
7163    func ExprCheck(x, i)
7164        let i = a:i + 1
7165        call assert_equal(i, test_refcount(a:x))
7166        let Y = a:x
7167        call assert_equal(i + 1, test_refcount(a:x))
7168        call assert_equal(test_refcount(a:x), test_refcount(Y))
7169        let Y = 0
7170        call assert_equal(i, test_refcount(a:x))
7171    endfunc
7172    call ExprCheck([], 0)
7173    call ExprCheck({}, 0)
7174    call ExprCheck(0zff, 0)
7175    call ExprCheck({-> line('.')}, 0)
7176    if has('job')
7177	call ExprCheck(job, 1)
7178	call ExprCheck(job_getchannel(job), 1)
7179	call job_stop(job)
7180    endif
7181    delfunc ExprCheck
7182
7183    " Regarding function
7184    func Func(x) abort
7185        call assert_equal(2, test_refcount(function('Func')))
7186        call assert_equal(0, test_refcount(funcref('Func')))
7187    endfunc
7188    call assert_equal(1, test_refcount(function('Func')))
7189    call assert_equal(0, test_refcount(function('Func', [1])))
7190    call assert_equal(0, test_refcount(funcref('Func')))
7191    call assert_equal(0, test_refcount(funcref('Func', [1])))
7192    let X = function('Func')
7193    let Y = X
7194    call assert_equal(1, test_refcount(X))
7195    let X = function('Func', [1])
7196    let Y = X
7197    call assert_equal(2, test_refcount(X))
7198    let X = funcref('Func')
7199    let Y = X
7200    call assert_equal(2, test_refcount(X))
7201    let X = funcref('Func', [1])
7202    let Y = X
7203    call assert_equal(2, test_refcount(X))
7204    unlet X
7205    unlet Y
7206    call Func(1)
7207    delfunc Func
7208
7209    " Function with dict
7210    func DictFunc() dict
7211        call assert_equal(3, test_refcount(self))
7212    endfunc
7213    let d = {'Func': function('DictFunc')}
7214    call assert_equal(1, test_refcount(d))
7215    call assert_equal(0, test_refcount(d.Func))
7216    call d.Func()
7217    unlet d
7218    delfunc DictFunc
7219endfunc
7220
7221" Test for missing :endif, :endfor, :endwhile and :endtry           {{{1
7222func Test_missing_end()
7223  call writefile(['if 2 > 1', 'echo ">"'], 'Xscript')
7224  call assert_fails('source Xscript', 'E171:')
7225  call writefile(['for i in range(5)', 'echo i'], 'Xscript')
7226  call assert_fails('source Xscript', 'E170:')
7227  call writefile(['while v:true', 'echo "."'], 'Xscript')
7228  call assert_fails('source Xscript', 'E170:')
7229  call writefile(['try', 'echo "."'], 'Xscript')
7230  call assert_fails('source Xscript', 'E600:')
7231  call delete('Xscript')
7232
7233  " Using endfor with :while
7234  let caught_e732 = 0
7235  try
7236    while v:true
7237    endfor
7238  catch /E732:/
7239    let caught_e732 = 1
7240  endtry
7241  call assert_equal(1, caught_e732)
7242
7243  " Using endwhile with :for
7244  let caught_e733 = 0
7245  try
7246    for i in range(1)
7247    endwhile
7248  catch /E733:/
7249    let caught_e733 = 1
7250  endtry
7251  call assert_equal(1, caught_e733)
7252
7253  " Using endfunc with :if
7254  call assert_fails('exe "if 1 | endfunc | endif"', 'E193:')
7255
7256  " Missing 'in' in a :for statement
7257  call assert_fails('for i range(1) | endfor', 'E690:')
7258
7259  " Incorrect number of variables in for
7260  call assert_fails('for [i,] in range(3) | endfor', 'E475:')
7261endfunc
7262
7263" Test for deep nesting of if/for/while/try statements              {{{1
7264func Test_deep_nest()
7265  CheckRunVimInTerminal
7266
7267  let lines =<< trim [SCRIPT]
7268    " Deep nesting of if ... endif
7269    func Test1()
7270      let @a = join(repeat(['if v:true'], 51), "\n")
7271      let @a ..= "\n"
7272      let @a ..= join(repeat(['endif'], 51), "\n")
7273      @a
7274      let @a = ''
7275    endfunc
7276
7277    " Deep nesting of for ... endfor
7278    func Test2()
7279      let @a = join(repeat(['for i in [1]'], 51), "\n")
7280      let @a ..= "\n"
7281      let @a ..= join(repeat(['endfor'], 51), "\n")
7282      @a
7283      let @a = ''
7284    endfunc
7285
7286    " Deep nesting of while ... endwhile
7287    func Test3()
7288      let @a = join(repeat(['while v:true'], 51), "\n")
7289      let @a ..= "\n"
7290      let @a ..= join(repeat(['endwhile'], 51), "\n")
7291      @a
7292      let @a = ''
7293    endfunc
7294
7295    " Deep nesting of try ... endtry
7296    func Test4()
7297      let @a = join(repeat(['try'], 51), "\n")
7298      let @a ..= "\necho v:true\n"
7299      let @a ..= join(repeat(['endtry'], 51), "\n")
7300      @a
7301      let @a = ''
7302    endfunc
7303
7304    " Deep nesting of function ... endfunction
7305    func Test5()
7306      let @a = join(repeat(['function X()'], 51), "\n")
7307      let @a ..= "\necho v:true\n"
7308      let @a ..= join(repeat(['endfunction'], 51), "\n")
7309      @a
7310      let @a = ''
7311    endfunc
7312  [SCRIPT]
7313  call writefile(lines, 'Xscript')
7314
7315  let buf = RunVimInTerminal('-S Xscript', {'rows': 6})
7316
7317  " Deep nesting of if ... endif
7318  call term_sendkeys(buf, ":call Test1()\n")
7319  call TermWait(buf)
7320  call WaitForAssert({-> assert_match('^E579:', term_getline(buf, 5))})
7321
7322  " Deep nesting of for ... endfor
7323  call term_sendkeys(buf, ":call Test2()\n")
7324  call TermWait(buf)
7325  call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))})
7326
7327  " Deep nesting of while ... endwhile
7328  call term_sendkeys(buf, ":call Test3()\n")
7329  call TermWait(buf)
7330  call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))})
7331
7332  " Deep nesting of try ... endtry
7333  call term_sendkeys(buf, ":call Test4()\n")
7334  call TermWait(buf)
7335  call WaitForAssert({-> assert_match('^E601:', term_getline(buf, 5))})
7336
7337  " Deep nesting of function ... endfunction
7338  call term_sendkeys(buf, ":call Test5()\n")
7339  call TermWait(buf)
7340  call WaitForAssert({-> assert_match('^E1058:', term_getline(buf, 4))})
7341  call term_sendkeys(buf, "\<C-C>\n")
7342  call TermWait(buf)
7343
7344  "let l = ''
7345  "for i in range(1, 6)
7346  "  let l ..= term_getline(buf, i) . "\n"
7347  "endfor
7348  "call assert_report(l)
7349
7350  call StopVimInTerminal(buf)
7351  call delete('Xscript')
7352endfunc
7353
7354" Test for errors in converting to float from various types         {{{1
7355func Test_float_conversion_errors()
7356  if has('float')
7357    call assert_fails('let x = 4.0 % 2.0', 'E804:')
7358    call assert_fails('echo 1.1[0]', 'E806:')
7359    call assert_fails('echo sort([function("min"), 1], "f")', 'E891:')
7360    call assert_fails('echo 3.2 == "vim"', 'E892:')
7361    call assert_fails('echo sort([[], 1], "f")', 'E893:')
7362    call assert_fails('echo sort([{}, 1], "f")', 'E894:')
7363    call assert_fails('echo 3.2 == v:true', 'E362:')
7364    call assert_fails('echo 3.2 == v:none', 'E907:')
7365  endif
7366endfunc
7367
7368" invalid function names               {{{1
7369func Test_invalid_function_names()
7370  " function name not starting with capital
7371  let caught_e128 = 0
7372  try
7373    func! g:test()
7374      echo "test"
7375    endfunc
7376  catch /E128:/
7377    let caught_e128 = 1
7378  endtry
7379  call assert_equal(1, caught_e128)
7380
7381  " function name includes a colon
7382  let caught_e884 = 0
7383  try
7384    func! b:test()
7385      echo "test"
7386    endfunc
7387  catch /E884:/
7388    let caught_e884 = 1
7389  endtry
7390  call assert_equal(1, caught_e884)
7391
7392  " function name followed by #
7393  let caught_e128 = 0
7394  try
7395    func! test2() "#
7396      echo "test2"
7397    endfunc
7398  catch /E128:/
7399    let caught_e128 = 1
7400  endtry
7401  call assert_equal(1, caught_e128)
7402
7403  " function name starting with/without "g:", buffer-local funcref.
7404  function! g:Foo(n)
7405    return 'called Foo(' . a:n . ')'
7406  endfunction
7407  let b:my_func = function('Foo')
7408  call assert_equal('called Foo(1)', b:my_func(1))
7409  call assert_equal('called Foo(2)', g:Foo(2))
7410  call assert_equal('called Foo(3)', Foo(3))
7411  delfunc g:Foo
7412
7413  " script-local function used in Funcref must exist.
7414  let lines =<< trim END
7415    func s:Testje()
7416      return "foo"
7417    endfunc
7418    let Bar = function('s:Testje')
7419    call assert_equal(0, exists('s:Testje'))
7420    call assert_equal(1, exists('*s:Testje'))
7421    call assert_equal(1, exists('Bar'))
7422    call assert_equal(1, exists('*Bar'))
7423  END
7424  call writefile(lines, 'Xscript')
7425  source Xscript
7426  call delete('Xscript')
7427endfunc
7428
7429" substring and variable name              {{{1
7430func Test_substring_var()
7431  let str = 'abcdef'
7432  let n = 3
7433  call assert_equal('def', str[n:])
7434  call assert_equal('abcd', str[:n])
7435  call assert_equal('d', str[n:n])
7436  unlet n
7437  let nn = 3
7438  call assert_equal('def', str[nn:])
7439  call assert_equal('abcd', str[:nn])
7440  call assert_equal('d', str[nn:nn])
7441  unlet nn
7442  let b:nn = 4
7443  call assert_equal('ef', str[b:nn:])
7444  call assert_equal('abcde', str[:b:nn])
7445  call assert_equal('e', str[b:nn:b:nn])
7446  unlet b:nn
7447endfunc
7448
7449" Test using s: with a typed command              {{{1
7450func Test_typed_script_var()
7451  CheckRunVimInTerminal
7452
7453  let buf = RunVimInTerminal('', {'rows': 6})
7454
7455  " Deep nesting of if ... endif
7456  call term_sendkeys(buf, ":echo get(s:, 'foo', 'x')\n")
7457  call TermWait(buf)
7458  call WaitForAssert({-> assert_match('^E116:', term_getline(buf, 5))})
7459
7460  call StopVimInTerminal(buf)
7461endfunc
7462
7463" Test for issue6776              {{{1
7464func Test_trinary_expression()
7465  try
7466    call eval('0 ? 0')
7467  catch
7468  endtry
7469  " previous failure should not cause next expression to fail
7470  call assert_equal(v:false, eval(string(v:false)))
7471
7472  try
7473    call eval('0 ? "burp')
7474  catch
7475  endtry
7476  " previous failure should not cause next expression to fail
7477  call assert_equal(v:false, eval(string(v:false)))
7478
7479  try
7480    call eval('1 ? 0 : "burp')
7481  catch
7482  endtry
7483  " previous failure should not cause next expression to fail
7484  call assert_equal(v:false, eval(string(v:false)))
7485endfunction
7486
7487func Test_for_over_string()
7488  let res = ''
7489  for c in 'aéc̀d'
7490    let res ..= c .. '-'
7491  endfor
7492  call assert_equal('a-é-c̀-d-', res)
7493
7494  let res = ''
7495  for c in ''
7496    let res ..= c .. '-'
7497  endfor
7498  call assert_equal('', res)
7499
7500  let res = ''
7501  for c in test_null_string()
7502    let res ..= c .. '-'
7503  endfor
7504  call assert_equal('', res)
7505endfunc
7506
7507"-------------------------------------------------------------------------------
7508" Modelines								    {{{1
7509" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
7510"-------------------------------------------------------------------------------
7511