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